1 //! Anything related to audio and media API.
2 
3 use bt_topshim::btif::{
4     BluetoothInterface, BtBondState, BtConnectionDirection, BtStatus, BtTransport, DisplayAddress,
5     RawAddress, ToggleableProfile,
6 };
7 use bt_topshim::profiles::a2dp::{
8     A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
9     A2dpCodecConfig, A2dpCodecIndex, A2dpCodecPriority, A2dpCodecSampleRate, BtavAudioState,
10     BtavConnectionState, PresentationPosition,
11 };
12 use bt_topshim::profiles::avrcp::{
13     Avrcp, AvrcpCallbacks, AvrcpCallbacksDispatcher, PlayerMetadata,
14 };
15 use bt_topshim::profiles::csis::{
16     BtCsisConnectionState, CsisClient, CsisClientCallbacks, CsisClientCallbacksDispatcher,
17 };
18 use bt_topshim::profiles::hfp::interop_insert_call_when_sco_start;
19 use bt_topshim::profiles::hfp::{
20     BthfAudioState, BthfConnectionState, CallHoldCommand, CallInfo, CallState, EscoCodingFormat,
21     Hfp, HfpCallbacks, HfpCallbacksDispatcher, HfpCodecBitId, HfpCodecFormat, HfpCodecId,
22     PhoneState, TelephonyDeviceStatus,
23 };
24 use bt_topshim::profiles::le_audio::{
25     BtLeAudioConnectionState, BtLeAudioContentType, BtLeAudioDirection, BtLeAudioGroupNodeStatus,
26     BtLeAudioGroupStatus, BtLeAudioGroupStreamStatus, BtLeAudioSource,
27     BtLeAudioUnicastMonitorModeStatus, BtLeAudioUsage, BtLePcmConfig, BtLeStreamStartedStatus,
28     LeAudioClient, LeAudioClientCallbacks, LeAudioClientCallbacksDispatcher, SinkMetadata,
29     SourceMetadata,
30 };
31 use bt_topshim::profiles::vc::{
32     BtVcConnectionState, VolumeControl, VolumeControlCallbacks, VolumeControlCallbacksDispatcher,
33 };
34 use bt_topshim::profiles::ProfileConnectionState;
35 use bt_topshim::{metrics, topstack};
36 use bt_utils::at_command_parser::{calculate_battery_percent, parse_at_command_data};
37 use bt_utils::features;
38 use bt_utils::uhid_hfp::{
39     OutputEvent, UHidHfp, BLUETOOTH_TELEPHONY_UHID_REPORT_ID, UHID_INPUT_DROP,
40     UHID_INPUT_HOOK_SWITCH, UHID_INPUT_NONE, UHID_INPUT_PHONE_MUTE, UHID_OUTPUT_MUTE,
41     UHID_OUTPUT_NONE, UHID_OUTPUT_OFF_HOOK, UHID_OUTPUT_RING,
42 };
43 use bt_utils::uinput::UInput;
44 
45 use itertools::Itertools;
46 use log::{debug, info, warn};
47 use std::collections::{HashMap, HashSet};
48 use std::convert::{TryFrom, TryInto};
49 use std::sync::Arc;
50 use std::sync::Mutex;
51 
52 use tokio::sync::mpsc::Sender;
53 use tokio::task::JoinHandle;
54 use tokio::time::{sleep, Duration, Instant};
55 
56 use crate::battery_manager::{Battery, BatterySet};
57 use crate::battery_provider_manager::{
58     BatteryProviderManager, IBatteryProviderCallback, IBatteryProviderManager,
59 };
60 use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth};
61 use crate::callbacks::Callbacks;
62 use crate::uuid;
63 use crate::uuid::{Profile, UuidHelper};
64 use crate::{Message, RPCProxy};
65 
66 use num_derive::FromPrimitive;
67 
68 // The timeout we have to wait for all supported profiles to connect after we
69 // receive the first profile connected event. The host shall disconnect or
70 // force connect the potentially partially connected device after this many
71 // seconds of timeout.
72 const PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 10;
73 // The timeout we have to wait for the initiator peer device to complete the
74 // initial profile connection. After this many seconds, we will begin to
75 // connect the missing profiles.
76 // 6s is set to align with Android's default. See "btservice/PhonePolicy".
77 const CONNECT_MISSING_PROFILES_TIMEOUT_SEC: u64 = 6;
78 // The duration we assume the role of the initiator, i.e. the side that starts
79 // the profile connection. If the profile is connected before this many seconds,
80 // we assume we are the initiator and can keep connecting the remaining
81 // profiles, otherwise we wait for the peer initiator.
82 // Set to 5s to align with default page timeout (BT spec vol 4 part E sec 6.6)
83 const CONNECT_AS_INITIATOR_TIMEOUT_SEC: u64 = 5;
84 
85 /// The list of profiles we consider as classic audio profiles for media.
86 const MEDIA_CLASSIC_AUDIO_PROFILES: &[Profile] =
87     &[Profile::A2dpSink, Profile::Hfp, Profile::AvrcpController];
88 
89 /// The list of profiles we consider as LE audio profiles for media.
90 const MEDIA_LE_AUDIO_PROFILES: &[Profile] =
91     &[Profile::LeAudio, Profile::VolumeControl, Profile::CoordinatedSet];
92 
93 /// Group ID used to identify unknown/non-existent groups.
94 pub const LEA_UNKNOWN_GROUP_ID: i32 = -1;
95 
96 /// Refer to |pairDeviceByCsip| in |CachedBluetoothDeviceManager.java|.
97 /// Number of attempts for CSIS to bond set members of a connected group.
98 const CSIS_BONDING_NUM_ATTEMPTS: u32 = 30;
99 /// The delay for bonding retries when pairing is busy, in milliseconds.
100 const CSIS_BONDING_RETRY_DELAY_MS: u64 = 500;
101 
102 pub trait IBluetoothMedia {
103     ///
register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool104     fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool;
105 
106     /// initializes media (both A2dp and AVRCP) stack
initialize(&mut self) -> bool107     fn initialize(&mut self) -> bool;
108 
109     /// clean up media stack
cleanup(&mut self) -> bool110     fn cleanup(&mut self) -> bool;
111 
112     /// connect to available but missing classic media profiles
connect(&mut self, address: RawAddress)113     fn connect(&mut self, address: RawAddress);
114 
115     /// disconnect all profiles from the device
116     /// NOTE: do not call this function from outside unless `is_complete_profiles_required`
disconnect(&mut self, address: RawAddress)117     fn disconnect(&mut self, address: RawAddress);
118 
connect_lea_group_by_member_address(&mut self, address: RawAddress)119     fn connect_lea_group_by_member_address(&mut self, address: RawAddress);
disconnect_lea_group_by_member_address(&mut self, address: RawAddress)120     fn disconnect_lea_group_by_member_address(&mut self, address: RawAddress);
121 
connect_lea(&mut self, address: RawAddress)122     fn connect_lea(&mut self, address: RawAddress);
disconnect_lea(&mut self, address: RawAddress)123     fn disconnect_lea(&mut self, address: RawAddress);
connect_vc(&mut self, address: RawAddress)124     fn connect_vc(&mut self, address: RawAddress);
disconnect_vc(&mut self, address: RawAddress)125     fn disconnect_vc(&mut self, address: RawAddress);
connect_csis(&mut self, address: RawAddress)126     fn connect_csis(&mut self, address: RawAddress);
disconnect_csis(&mut self, address: RawAddress)127     fn disconnect_csis(&mut self, address: RawAddress);
128 
129     // Set the device as the active A2DP device
set_active_device(&mut self, address: RawAddress)130     fn set_active_device(&mut self, address: RawAddress);
131 
132     // Reset the active A2DP device
reset_active_device(&mut self)133     fn reset_active_device(&mut self);
134 
135     // Set the device as the active HFP device
set_hfp_active_device(&mut self, address: RawAddress)136     fn set_hfp_active_device(&mut self, address: RawAddress);
137 
set_audio_config( &mut self, address: RawAddress, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool138     fn set_audio_config(
139         &mut self,
140         address: RawAddress,
141         codec_type: A2dpCodecIndex,
142         sample_rate: A2dpCodecSampleRate,
143         bits_per_sample: A2dpCodecBitsPerSample,
144         channel_mode: A2dpCodecChannelMode,
145     ) -> bool;
146 
147     // Set the A2DP/AVRCP volume. Valid volume specified by the spec should be
148     // in the range of 0-127.
set_volume(&mut self, volume: u8)149     fn set_volume(&mut self, volume: u8);
150 
151     // Set the HFP speaker volume. Valid volume specified by the HFP spec should
152     // be in the range of 0-15.
set_hfp_volume(&mut self, volume: u8, address: RawAddress)153     fn set_hfp_volume(&mut self, volume: u8, address: RawAddress);
start_audio_request(&mut self) -> bool154     fn start_audio_request(&mut self) -> bool;
stop_audio_request(&mut self)155     fn stop_audio_request(&mut self);
156 
157     /// Returns true iff A2DP audio has started.
get_a2dp_audio_started(&mut self, address: RawAddress) -> bool158     fn get_a2dp_audio_started(&mut self, address: RawAddress) -> bool;
159 
160     /// Returns the negotiated codec (CVSD=1, mSBC=2, LC3=4) to use if HFP audio has started.
161     /// Returns 0 if HFP audio hasn't started.
get_hfp_audio_final_codecs(&mut self, address: RawAddress) -> u8162     fn get_hfp_audio_final_codecs(&mut self, address: RawAddress) -> u8;
163 
get_presentation_position(&mut self) -> PresentationPosition164     fn get_presentation_position(&mut self) -> PresentationPosition;
165 
166     /// Start the SCO setup to connect audio
start_sco_call( &mut self, address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, ) -> bool167     fn start_sco_call(
168         &mut self,
169         address: RawAddress,
170         sco_offload: bool,
171         disabled_codecs: HfpCodecBitId,
172     ) -> bool;
stop_sco_call(&mut self, address: RawAddress)173     fn stop_sco_call(&mut self, address: RawAddress);
174 
175     /// Set the current playback status: e.g., playing, paused, stopped, etc. The method is a copy
176     /// of the existing CRAS API, hence not following Floss API conventions.
set_player_playback_status(&mut self, status: String)177     fn set_player_playback_status(&mut self, status: String);
178     /// Set the position of the current media in microseconds. The method is a copy of the existing
179     /// CRAS API, hence not following Floss API conventions.
set_player_position(&mut self, position: i64)180     fn set_player_position(&mut self, position: i64);
181     /// Set the media metadata, including title, artist, album, and length. The method is a
182     /// copy of the existing CRAS API, hence not following Floss API conventions. PlayerMetadata is
183     /// a custom data type that requires special handlng.
set_player_metadata(&mut self, metadata: PlayerMetadata)184     fn set_player_metadata(&mut self, metadata: PlayerMetadata);
185 
186     // Trigger a debug log dump.
trigger_debug_dump(&mut self)187     fn trigger_debug_dump(&mut self);
188 
189     /// LE Audio Commands
group_set_active(&mut self, group_id: i32)190     fn group_set_active(&mut self, group_id: i32);
host_start_audio_request(&mut self) -> bool191     fn host_start_audio_request(&mut self) -> bool;
host_stop_audio_request(&mut self)192     fn host_stop_audio_request(&mut self);
peer_start_audio_request(&mut self) -> bool193     fn peer_start_audio_request(&mut self) -> bool;
peer_stop_audio_request(&mut self)194     fn peer_stop_audio_request(&mut self);
get_host_pcm_config(&mut self) -> BtLePcmConfig195     fn get_host_pcm_config(&mut self) -> BtLePcmConfig;
get_peer_pcm_config(&mut self) -> BtLePcmConfig196     fn get_peer_pcm_config(&mut self) -> BtLePcmConfig;
get_host_stream_started(&mut self) -> BtLeStreamStartedStatus197     fn get_host_stream_started(&mut self) -> BtLeStreamStartedStatus;
get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus198     fn get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus;
source_metadata_changed( &mut self, usage: BtLeAudioUsage, content_type: BtLeAudioContentType, gain: f64, ) -> bool199     fn source_metadata_changed(
200         &mut self,
201         usage: BtLeAudioUsage,
202         content_type: BtLeAudioContentType,
203         gain: f64,
204     ) -> bool;
sink_metadata_changed(&mut self, source: BtLeAudioSource, gain: f64) -> bool205     fn sink_metadata_changed(&mut self, source: BtLeAudioSource, gain: f64) -> bool;
get_unicast_monitor_mode_status( &mut self, direction: BtLeAudioDirection, ) -> BtLeAudioUnicastMonitorModeStatus206     fn get_unicast_monitor_mode_status(
207         &mut self,
208         direction: BtLeAudioDirection,
209     ) -> BtLeAudioUnicastMonitorModeStatus;
get_group_stream_status(&mut self, group_id: i32) -> BtLeAudioGroupStreamStatus210     fn get_group_stream_status(&mut self, group_id: i32) -> BtLeAudioGroupStreamStatus;
get_group_status(&mut self, group_id: i32) -> BtLeAudioGroupStatus211     fn get_group_status(&mut self, group_id: i32) -> BtLeAudioGroupStatus;
212 
213     /// Valid volume range is [0, 255], see 2.3.1.1, VCS v1.
set_group_volume(&mut self, group_id: i32, volume: u8)214     fn set_group_volume(&mut self, group_id: i32, volume: u8);
215 }
216 
217 pub trait IBluetoothMediaCallback: RPCProxy {
218     /// Triggered when a Bluetooth audio device is ready to be used. This should
219     /// only be triggered once for a device and send an event to clients. If the
220     /// device supports both HFP and A2DP, both should be ready when this is
221     /// triggered.
on_bluetooth_audio_device_added(&mut self, device: BluetoothAudioDevice)222     fn on_bluetooth_audio_device_added(&mut self, device: BluetoothAudioDevice);
223 
224     ///
on_bluetooth_audio_device_removed(&mut self, addr: RawAddress)225     fn on_bluetooth_audio_device_removed(&mut self, addr: RawAddress);
226 
227     ///
on_absolute_volume_supported_changed(&mut self, supported: bool)228     fn on_absolute_volume_supported_changed(&mut self, supported: bool);
229 
230     /// Triggered when a Bluetooth device triggers an AVRCP/A2DP volume change
231     /// event. We need to notify audio client to reflect the change on the audio
232     /// stack. The volume should be in the range of 0 to 127.
on_absolute_volume_changed(&mut self, volume: u8)233     fn on_absolute_volume_changed(&mut self, volume: u8);
234 
235     /// Triggered when a Bluetooth device triggers a HFP AT command (AT+VGS) to
236     /// notify AG about its speaker volume change. We need to notify audio
237     /// client to reflect the change on the audio stack. The volume should be
238     /// in the range of 0 to 15.
on_hfp_volume_changed(&mut self, volume: u8, addr: RawAddress)239     fn on_hfp_volume_changed(&mut self, volume: u8, addr: RawAddress);
240 
241     /// Triggered when HFP audio is disconnected, in which case it could be
242     /// waiting for the audio client to issue a reconnection request. We need
243     /// to notify audio client of this event for it to do appropriate handling.
on_hfp_audio_disconnected(&mut self, addr: RawAddress)244     fn on_hfp_audio_disconnected(&mut self, addr: RawAddress);
245 
246     /// Triggered when there is a HFP dump is received. This should only be used
247     /// for debugging and testing purpose.
on_hfp_debug_dump( &mut self, active: bool, codec_id: u16, total_num_decoded_frames: i32, pkt_loss_ratio: f64, begin_ts: u64, end_ts: u64, pkt_status_in_hex: String, pkt_status_in_binary: String, )248     fn on_hfp_debug_dump(
249         &mut self,
250         active: bool,
251         codec_id: u16,
252         total_num_decoded_frames: i32,
253         pkt_loss_ratio: f64,
254         begin_ts: u64,
255         end_ts: u64,
256         pkt_status_in_hex: String,
257         pkt_status_in_binary: String,
258     );
259 
260     /// Triggered when the first member of the specified LEA group has connected
261     /// the LE audio profile. This is the earliest meaningful timing to notify
262     /// the audio server that the group as an audio device is available.
on_lea_group_connected(&mut self, group_id: i32, name: String)263     fn on_lea_group_connected(&mut self, group_id: i32, name: String);
264 
265     /// Triggered when the last connected member of the specified LEA group has
266     /// disconnected the LE audio profile. This is when we should notify the
267     /// audio server that the group is no longer available as an audio device.
on_lea_group_disconnected(&mut self, group_id: i32)268     fn on_lea_group_disconnected(&mut self, group_id: i32);
269 
on_lea_group_status(&mut self, group_id: i32, status: BtLeAudioGroupStatus)270     fn on_lea_group_status(&mut self, group_id: i32, status: BtLeAudioGroupStatus);
271 
on_lea_group_node_status( &mut self, addr: RawAddress, group_id: i32, status: BtLeAudioGroupNodeStatus, )272     fn on_lea_group_node_status(
273         &mut self,
274         addr: RawAddress,
275         group_id: i32,
276         status: BtLeAudioGroupNodeStatus,
277     );
278 
on_lea_audio_conf( &mut self, direction: u8, group_id: i32, snk_audio_location: u32, src_audio_location: u32, avail_cont: u16, )279     fn on_lea_audio_conf(
280         &mut self,
281         direction: u8,
282         group_id: i32,
283         snk_audio_location: u32,
284         src_audio_location: u32,
285         avail_cont: u16,
286     );
287 
on_lea_unicast_monitor_mode_status( &mut self, direction: BtLeAudioDirection, status: BtLeAudioUnicastMonitorModeStatus, )288     fn on_lea_unicast_monitor_mode_status(
289         &mut self,
290         direction: BtLeAudioDirection,
291         status: BtLeAudioUnicastMonitorModeStatus,
292     );
293 
on_lea_group_stream_status(&mut self, group_id: i32, status: BtLeAudioGroupStreamStatus)294     fn on_lea_group_stream_status(&mut self, group_id: i32, status: BtLeAudioGroupStreamStatus);
295 
on_lea_vc_connected(&mut self, addr: RawAddress, group_id: i32)296     fn on_lea_vc_connected(&mut self, addr: RawAddress, group_id: i32);
297 
on_lea_group_volume_changed(&mut self, group_id: i32, volume: u8)298     fn on_lea_group_volume_changed(&mut self, group_id: i32, volume: u8);
299 }
300 
301 pub trait IBluetoothTelephony {
302     ///
register_telephony_callback( &mut self, callback: Box<dyn IBluetoothTelephonyCallback + Send>, ) -> bool303     fn register_telephony_callback(
304         &mut self,
305         callback: Box<dyn IBluetoothTelephonyCallback + Send>,
306     ) -> bool;
307 
308     /// Sets whether the device is connected to the cellular network.
set_network_available(&mut self, network_available: bool)309     fn set_network_available(&mut self, network_available: bool);
310     /// Sets whether the device is roaming.
set_roaming(&mut self, roaming: bool)311     fn set_roaming(&mut self, roaming: bool);
312     /// Sets the device signal strength, 0 to 5.
set_signal_strength(&mut self, signal_strength: i32) -> bool313     fn set_signal_strength(&mut self, signal_strength: i32) -> bool;
314     /// Sets the device battery level, 0 to 5.
set_battery_level(&mut self, battery_level: i32) -> bool315     fn set_battery_level(&mut self, battery_level: i32) -> bool;
316     /// Enables/disables phone operations.
set_phone_ops_enabled(&mut self, enable: bool)317     fn set_phone_ops_enabled(&mut self, enable: bool);
318     /// Enables/disables phone operations for mps qualification.
319     /// The call state is fully reset whenever this is called.
set_mps_qualification_enabled(&mut self, enable: bool)320     fn set_mps_qualification_enabled(&mut self, enable: bool);
321     /// Acts like the AG received an incoming call.
incoming_call(&mut self, number: String) -> bool322     fn incoming_call(&mut self, number: String) -> bool;
323     /// Acts like dialing a call from the AG.
dialing_call(&mut self, number: String) -> bool324     fn dialing_call(&mut self, number: String) -> bool;
325     /// Acts like answering an incoming/dialing call from the AG.
answer_call(&mut self) -> bool326     fn answer_call(&mut self) -> bool;
327     /// Acts like hanging up an active/incoming/dialing call from the AG.
hangup_call(&mut self) -> bool328     fn hangup_call(&mut self) -> bool;
329     /// Sets/unsets the memory slot. Note that we store at most one memory
330     /// number and return it regardless of which slot is specified by HF.
set_memory_call(&mut self, number: Option<String>) -> bool331     fn set_memory_call(&mut self, number: Option<String>) -> bool;
332     /// Sets/unsets the last call.
set_last_call(&mut self, number: Option<String>) -> bool333     fn set_last_call(&mut self, number: Option<String>) -> bool;
334     /// Releases all of the held calls.
release_held(&mut self) -> bool335     fn release_held(&mut self) -> bool;
336     /// Releases the active call and accepts a held call.
release_active_accept_held(&mut self) -> bool337     fn release_active_accept_held(&mut self) -> bool;
338     /// Holds the active call and accepts a held call.
hold_active_accept_held(&mut self) -> bool339     fn hold_active_accept_held(&mut self) -> bool;
340     /// Establishes an audio connection to <address>.
audio_connect(&mut self, address: RawAddress) -> bool341     fn audio_connect(&mut self, address: RawAddress) -> bool;
342     /// Stops the audio connection to <address>.
audio_disconnect(&mut self, address: RawAddress)343     fn audio_disconnect(&mut self, address: RawAddress);
344 }
345 
346 pub trait IBluetoothTelephonyCallback: RPCProxy {
on_telephony_event(&mut self, addr: RawAddress, event: u8, state: u8)347     fn on_telephony_event(&mut self, addr: RawAddress, event: u8, state: u8);
348 }
349 
350 /// Serializable device used in.
351 #[derive(Debug, Default, Clone)]
352 pub struct BluetoothAudioDevice {
353     pub address: RawAddress,
354     pub name: String,
355     pub a2dp_caps: Vec<A2dpCodecConfig>,
356     pub hfp_cap: HfpCodecFormat,
357     pub absolute_volume: bool,
358 }
359 
360 impl BluetoothAudioDevice {
new( address: RawAddress, name: String, a2dp_caps: Vec<A2dpCodecConfig>, hfp_cap: HfpCodecFormat, absolute_volume: bool, ) -> Self361     pub(crate) fn new(
362         address: RawAddress,
363         name: String,
364         a2dp_caps: Vec<A2dpCodecConfig>,
365         hfp_cap: HfpCodecFormat,
366         absolute_volume: bool,
367     ) -> Self {
368         Self { address, name, a2dp_caps, hfp_cap, absolute_volume }
369     }
370 }
371 /// Actions that `BluetoothMedia` can take on behalf of the stack.
372 pub enum MediaActions {
373     Connect(RawAddress),
374     Disconnect(RawAddress),
375     ForceEnterConnected(RawAddress), // Only used for qualification.
376 
377     ConnectLeaGroupByMemberAddress(RawAddress),
378     DisconnectLeaGroupByMemberAddress(RawAddress),
379     ConnectLea(RawAddress),
380     DisconnectLea(RawAddress),
381     ConnectVc(RawAddress),
382     DisconnectVc(RawAddress),
383     ConnectCsis(RawAddress),
384     DisconnectCsis(RawAddress),
385 }
386 
387 #[derive(Debug, Clone, PartialEq)]
388 enum DeviceConnectionStates {
389     Initiating,            // Some profile is connected, initiated from host side
390     ConnectingBeforeRetry, // Some profile is connected, probably initiated from peer side
391     ConnectingAfterRetry,  // Host initiated requests to missing profiles after timeout
392     FullyConnected,        // All profiles (excluding AVRCP) are connected
393     Disconnecting,         // Working towards disconnection of each connected profile
394     WaitingConnection,     // Waiting for new connections initiated by peer
395 }
396 
397 struct UHid {
398     pub handle: UHidHfp,
399     pub volume: u8,
400     pub muted: bool,
401     pub is_open: bool,
402 }
403 
404 struct LEAAudioConf {
405     pub direction: u8,
406     pub group_id: i32,
407     pub snk_audio_location: u32,
408     pub src_audio_location: u32,
409     pub avail_cont: u16,
410 }
411 
412 #[derive(Default, Clone)]
413 struct LeAudioGroup {
414     pub devices: HashSet<RawAddress>,
415     pub status: BtLeAudioGroupStatus,
416     pub stream_status: BtLeAudioGroupStreamStatus,
417     pub volume: Option<u8>,
418 }
419 
420 #[derive(Debug, Copy, Clone, FromPrimitive)]
421 #[repr(u8)]
422 enum TelephonyEvent {
423     UHidCreate = 0,
424     UHidDestroy,
425     UHidOpen,
426     UHidClose,
427     UHidIncomingCall,
428     UHidAnswerCall,
429     UHidHangupCall,
430     UHidPlaceActiveCall,
431     UHidMicMute,
432     UHidMicUnmute,
433     CRASPlaceActiveCall,
434     CRASRemoveActiveCall,
435     HFAnswerCall,
436     HFHangupCall,
437     HFMicMute,
438     HFMicUnmute,
439     HFCurrentCallsQuery,
440 }
441 
442 impl From<TelephonyEvent> for u8 {
from(telephony_event: TelephonyEvent) -> Self443     fn from(telephony_event: TelephonyEvent) -> Self {
444         telephony_event as u8
445     }
446 }
447 
448 pub struct BluetoothMedia {
449     intf: Arc<Mutex<BluetoothInterface>>,
450     battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
451     battery_provider_id: u32,
452     initialized: bool,
453     callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>,
454     telephony_callbacks: Arc<Mutex<Callbacks<dyn IBluetoothTelephonyCallback + Send>>>,
455     tx: Sender<Message>,
456     adapter: Option<Arc<Mutex<Box<Bluetooth>>>>,
457     a2dp: Option<A2dp>,
458     avrcp: Option<Avrcp>,
459     avrcp_direction: BtConnectionDirection,
460     a2dp_states: HashMap<RawAddress, BtavConnectionState>,
461     a2dp_audio_state: HashMap<RawAddress, BtavAudioState>,
462     a2dp_has_interrupted_stream: bool, // Only used for qualification.
463     hfp: Option<Hfp>,
464     hfp_states: HashMap<RawAddress, BthfConnectionState>,
465     hfp_audio_state: HashMap<RawAddress, BthfAudioState>,
466     a2dp_caps: HashMap<RawAddress, Vec<A2dpCodecConfig>>,
467     hfp_cap: HashMap<RawAddress, HfpCodecFormat>,
468     fallback_tasks: Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
469     absolute_volume: bool,
470     uinput: UInput,
471     delay_enable_profiles: HashSet<Profile>,
472     connected_profiles: HashMap<RawAddress, HashSet<Profile>>,
473     device_states: Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
474     delay_volume_update: HashMap<Profile, u8>,
475     telephony_device_status: TelephonyDeviceStatus,
476     phone_state: PhoneState,
477     call_list: Vec<CallInfo>,
478     phone_ops_enabled: bool,
479     mps_qualification_enabled: bool,
480     memory_dialing_number: Option<String>,
481     last_dialing_number: Option<String>,
482     uhid: HashMap<RawAddress, UHid>,
483     le_audio: Option<LeAudioClient>,
484     le_audio_groups: HashMap<i32, LeAudioGroup>,
485     le_audio_node_to_group: HashMap<RawAddress, i32>,
486     le_audio_states: HashMap<RawAddress, BtLeAudioConnectionState>,
487     le_audio_unicast_monitor_mode_status: HashMap<i32, BtLeAudioUnicastMonitorModeStatus>,
488     le_audio_delayed_audio_conf_updates: HashMap<i32, LEAAudioConf>,
489     le_audio_delayed_vc_connection_updates: HashSet<RawAddress>,
490     vc: Option<VolumeControl>,
491     vc_states: HashMap<RawAddress, BtVcConnectionState>,
492     csis: Option<CsisClient>,
493     csis_states: HashMap<RawAddress, BtCsisConnectionState>,
494     is_le_audio_only_enabled: bool, // TODO: remove this once there is dual mode.
495 }
496 
497 impl BluetoothMedia {
new( tx: Sender<Message>, intf: Arc<Mutex<BluetoothInterface>>, battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, ) -> BluetoothMedia498     pub fn new(
499         tx: Sender<Message>,
500         intf: Arc<Mutex<BluetoothInterface>>,
501         battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
502     ) -> BluetoothMedia {
503         let battery_provider_id = battery_provider_manager
504             .lock()
505             .unwrap()
506             .register_battery_provider(Box::new(BatteryProviderCallback::new()));
507         BluetoothMedia {
508             intf,
509             battery_provider_manager,
510             battery_provider_id,
511             initialized: false,
512             callbacks: Arc::new(Mutex::new(Callbacks::new(
513                 tx.clone(),
514                 Message::MediaCallbackDisconnected,
515             ))),
516             telephony_callbacks: Arc::new(Mutex::new(Callbacks::new(
517                 tx.clone(),
518                 Message::TelephonyCallbackDisconnected,
519             ))),
520             tx,
521             adapter: None,
522             a2dp: None,
523             avrcp: None,
524             avrcp_direction: BtConnectionDirection::Unknown,
525             a2dp_states: HashMap::new(),
526             a2dp_audio_state: HashMap::new(),
527             a2dp_has_interrupted_stream: false,
528             hfp: None,
529             hfp_states: HashMap::new(),
530             hfp_audio_state: HashMap::new(),
531             a2dp_caps: HashMap::new(),
532             hfp_cap: HashMap::new(),
533             fallback_tasks: Arc::new(Mutex::new(HashMap::new())),
534             absolute_volume: false,
535             uinput: UInput::new(),
536             delay_enable_profiles: HashSet::new(),
537             connected_profiles: HashMap::new(),
538             device_states: Arc::new(Mutex::new(HashMap::new())),
539             delay_volume_update: HashMap::new(),
540             telephony_device_status: TelephonyDeviceStatus::new(),
541             phone_state: PhoneState { num_active: 0, num_held: 0, state: CallState::Idle },
542             call_list: vec![],
543             phone_ops_enabled: false,
544             mps_qualification_enabled: false,
545             memory_dialing_number: None,
546             last_dialing_number: None,
547             uhid: HashMap::new(),
548             le_audio: None,
549             le_audio_groups: HashMap::new(),
550             le_audio_node_to_group: HashMap::new(),
551             le_audio_states: HashMap::new(),
552             le_audio_unicast_monitor_mode_status: HashMap::new(),
553             le_audio_delayed_audio_conf_updates: HashMap::new(),
554             le_audio_delayed_vc_connection_updates: HashSet::new(),
555             vc: None,
556             vc_states: HashMap::new(),
557             csis: None,
558             csis_states: HashMap::new(),
559             is_le_audio_only_enabled: false,
560         }
561     }
562 
is_profile_connected(&self, addr: &RawAddress, profile: &Profile) -> bool563     fn is_profile_connected(&self, addr: &RawAddress, profile: &Profile) -> bool {
564         self.is_any_profile_connected(addr, &[profile.clone()])
565     }
566 
is_any_profile_connected(&self, addr: &RawAddress, profiles: &[Profile]) -> bool567     fn is_any_profile_connected(&self, addr: &RawAddress, profiles: &[Profile]) -> bool {
568         if let Some(connected_profiles) = self.connected_profiles.get(addr) {
569             return profiles.iter().any(|p| connected_profiles.contains(&p));
570         }
571 
572         return false;
573     }
574 
add_connected_profile(&mut self, addr: RawAddress, profile: Profile)575     fn add_connected_profile(&mut self, addr: RawAddress, profile: Profile) {
576         if self.is_profile_connected(&addr, &profile) {
577             warn!("[{}]: profile is already connected", DisplayAddress(&addr));
578             return;
579         }
580 
581         self.connected_profiles.entry(addr).or_insert_with(HashSet::new).insert(profile);
582 
583         self.notify_media_capability_updated(addr);
584     }
585 
rm_connected_profile( &mut self, addr: RawAddress, profile: Profile, is_profile_critical: bool, )586     fn rm_connected_profile(
587         &mut self,
588         addr: RawAddress,
589         profile: Profile,
590         is_profile_critical: bool,
591     ) {
592         if !self.is_profile_connected(&addr, &profile) {
593             warn!("[{}]: profile is already disconnected", DisplayAddress(&addr));
594             return;
595         }
596 
597         self.connected_profiles.entry(addr).or_insert_with(HashSet::new).remove(&profile);
598         self.delay_volume_update.remove(&profile);
599 
600         if is_profile_critical && self.is_complete_profiles_required() {
601             BluetoothMedia::disconnect_device(self.tx.clone(), addr);
602             self.notify_critical_profile_disconnected(addr);
603         }
604 
605         self.notify_media_capability_updated(addr);
606     }
607 
is_group_connected(&self, group: &LeAudioGroup) -> bool608     fn is_group_connected(&self, group: &LeAudioGroup) -> bool {
609         group.devices.iter().any(|&addr| {
610             *self.le_audio_states.get(&addr).unwrap_or(&BtLeAudioConnectionState::Disconnected)
611                 == BtLeAudioConnectionState::Connected
612         })
613     }
614 
remove_device_from_group(&mut self, addr: RawAddress)615     fn remove_device_from_group(&mut self, addr: RawAddress) {
616         let group_id = match self.le_audio_node_to_group.get(&addr) {
617             Some(group_id) => group_id,
618             None => {
619                 warn!("Cannot remove device {} that belongs to no group", DisplayAddress(&addr));
620                 return;
621             }
622         };
623 
624         match self.le_audio_groups.get_mut(&group_id) {
625             Some(group) => {
626                 group.devices.remove(&addr);
627                 if group.devices.is_empty() {
628                     self.le_audio_groups.remove(&group_id);
629                 }
630             }
631             None => {
632                 warn!(
633                     "{} claims to be in group {} which does not exist",
634                     DisplayAddress(&addr),
635                     group_id
636                 );
637                 return;
638             }
639         }
640     }
641 
set_adapter(&mut self, adapter: Arc<Mutex<Box<Bluetooth>>>)642     pub fn set_adapter(&mut self, adapter: Arc<Mutex<Box<Bluetooth>>>) {
643         self.adapter = Some(adapter);
644     }
645 
enable_profile(&mut self, profile: &Profile)646     pub fn enable_profile(&mut self, profile: &Profile) {
647         match profile {
648             Profile::A2dpSource | Profile::AvrcpTarget | Profile::Hfp => {
649                 if self.is_le_audio_only_enabled {
650                     info!("LeAudioEnableLeAudioOnly is set, skip enabling {:?}", profile);
651                     return;
652                 }
653             }
654             Profile::LeAudio | Profile::VolumeControl | Profile::CoordinatedSet => {
655                 if !self.is_le_audio_only_enabled {
656                     info!("LeAudioEnableLeAudioOnly is not set, skip enabling {:?}", profile);
657                     return;
658                 }
659             }
660             _ => {}
661         }
662 
663         match profile {
664             &Profile::A2dpSource => {
665                 if let Some(a2dp) = &mut self.a2dp {
666                     a2dp.enable();
667                 }
668             }
669             &Profile::AvrcpTarget => {
670                 if let Some(avrcp) = &mut self.avrcp {
671                     avrcp.enable();
672                 }
673             }
674             &Profile::Hfp => {
675                 if let Some(hfp) = &mut self.hfp {
676                     hfp.enable();
677                 }
678             }
679             &Profile::LeAudio => {
680                 if let Some(le_audio) = &mut self.le_audio {
681                     le_audio.enable();
682                 }
683             }
684             &Profile::VolumeControl => {
685                 if let Some(vc) = &mut self.vc {
686                     vc.enable();
687                 }
688             }
689             &Profile::CoordinatedSet => {
690                 if let Some(csis) = &mut self.csis {
691                     csis.enable();
692                 }
693             }
694             _ => {
695                 warn!("Tried to enable {} in bluetooth_media", profile);
696                 return;
697             }
698         }
699 
700         if self.is_profile_enabled(profile).unwrap() {
701             self.delay_enable_profiles.remove(profile);
702         } else {
703             self.delay_enable_profiles.insert(profile.clone());
704         }
705     }
706 
disable_profile(&mut self, profile: &Profile)707     pub fn disable_profile(&mut self, profile: &Profile) {
708         match profile {
709             &Profile::A2dpSource => {
710                 if let Some(a2dp) = &mut self.a2dp {
711                     a2dp.disable();
712                 }
713             }
714             &Profile::AvrcpTarget => {
715                 if let Some(avrcp) = &mut self.avrcp {
716                     avrcp.disable();
717                 }
718             }
719             &Profile::Hfp => {
720                 if let Some(hfp) = &mut self.hfp {
721                     hfp.disable();
722                 }
723             }
724             &Profile::LeAudio => {
725                 if let Some(le_audio) = &mut self.le_audio {
726                     le_audio.disable();
727                 }
728             }
729             &Profile::VolumeControl => {
730                 if let Some(vc) = &mut self.vc {
731                     vc.disable();
732                 }
733             }
734             &Profile::CoordinatedSet => {
735                 if let Some(csis) = &mut self.csis {
736                     csis.disable();
737                 }
738             }
739             _ => {
740                 warn!("Tried to disable {} in bluetooth_media", profile);
741                 return;
742             }
743         }
744 
745         self.delay_enable_profiles.remove(profile);
746     }
747 
is_profile_enabled(&self, profile: &Profile) -> Option<bool>748     pub fn is_profile_enabled(&self, profile: &Profile) -> Option<bool> {
749         match profile {
750             &Profile::A2dpSource => {
751                 Some(self.a2dp.as_ref().map_or(false, |a2dp| a2dp.is_enabled()))
752             }
753             &Profile::AvrcpTarget => {
754                 Some(self.avrcp.as_ref().map_or(false, |avrcp| avrcp.is_enabled()))
755             }
756             &Profile::Hfp => Some(self.hfp.as_ref().map_or(false, |hfp| hfp.is_enabled())),
757             &Profile::LeAudio => {
758                 Some(self.le_audio.as_ref().map_or(false, |le_audio| le_audio.is_enabled()))
759             }
760             &Profile::VolumeControl => Some(self.vc.as_ref().map_or(false, |vc| vc.is_enabled())),
761             &Profile::CoordinatedSet => {
762                 Some(self.csis.as_ref().map_or(false, |csis| csis.is_enabled()))
763             }
764             _ => {
765                 warn!("Tried to query enablement status of {} in bluetooth_media", profile);
766                 None
767             }
768         }
769     }
770 
dispatch_csis_callbacks(&mut self, cb: CsisClientCallbacks)771     pub fn dispatch_csis_callbacks(&mut self, cb: CsisClientCallbacks) {
772         match cb {
773             CsisClientCallbacks::ConnectionState(addr, state) => {
774                 if !self.csis_states.get(&addr).is_none()
775                     && state == *self.csis_states.get(&addr).unwrap()
776                 {
777                     return;
778                 }
779 
780                 info!(
781                     "CsisClientCallbacks::ConnectionState: [{}]: state={:?}",
782                     DisplayAddress(&addr),
783                     state
784                 );
785 
786                 match state {
787                     BtCsisConnectionState::Connected => {
788                         self.csis_states.insert(addr, state);
789                     }
790                     BtCsisConnectionState::Disconnected => {
791                         self.csis_states.remove(&addr);
792                     }
793                     _ => {
794                         self.csis_states.insert(addr, state);
795                     }
796                 }
797             }
798             CsisClientCallbacks::DeviceAvailable(addr, group_id, group_size, rank, uuid) => {
799                 info!(
800                     "CsisClientCallbacks::DeviceAvailable: [{}]: group_id={}, group_size={}, rank={}, uuid={:?}",
801                     DisplayAddress(&addr),
802                     group_id,
803                     group_size,
804                     rank,
805                     uuid,
806                 );
807             }
808             CsisClientCallbacks::SetMemberAvailable(addr, group_id) => {
809                 info!(
810                     "CsisClientCallbacks::SetMemberAvailable: [{}]: group_id={}",
811                     DisplayAddress(&addr),
812                     group_id
813                 );
814                 let device = BluetoothDevice::new(addr, "".to_string());
815                 let txl = self.tx.clone();
816                 topstack::get_runtime().spawn(async move {
817                     let _ = txl
818                         .send(Message::CreateBondWithRetry(
819                             device,
820                             BtTransport::Le,
821                             CSIS_BONDING_NUM_ATTEMPTS,
822                             Duration::from_millis(CSIS_BONDING_RETRY_DELAY_MS),
823                         ))
824                         .await;
825                 });
826             }
827             CsisClientCallbacks::GroupLockChanged(group_id, locked, status) => {
828                 info!(
829                     "CsisClientCallbacks::GroupLockChanged: group_id={}, locked={}, status={:?}",
830                     group_id, locked, status
831                 );
832             }
833         }
834     }
835 
dispatch_vc_callbacks(&mut self, cb: VolumeControlCallbacks)836     pub fn dispatch_vc_callbacks(&mut self, cb: VolumeControlCallbacks) {
837         match cb {
838             VolumeControlCallbacks::ConnectionState(state, addr) => {
839                 if !self.vc_states.get(&addr).is_none()
840                     && state == *self.vc_states.get(&addr).unwrap()
841                 {
842                     return;
843                 }
844 
845                 info!(
846                     "VolumeControlCallbacks::ConnectionState: [{}]: state={:?}",
847                     DisplayAddress(&addr),
848                     state
849                 );
850 
851                 match state {
852                     BtVcConnectionState::Connected => {
853                         self.vc_states.insert(addr, state);
854 
855                         let group_id = self.get_group_id(addr);
856                         match self.le_audio_groups.get(&group_id) {
857                             Some(group) if self.is_group_connected(group) => {
858                                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
859                                     callback.on_lea_vc_connected(addr, group_id);
860                                 });
861 
862                                 // Sync group volume in case this new member has not been adjusted.
863                                 if let Some(volume) = group.volume {
864                                     self.set_group_volume(group_id, volume);
865                                 }
866                             }
867                             _ => {
868                                 self.le_audio_delayed_vc_connection_updates.insert(addr);
869                             }
870                         }
871                     }
872                     BtVcConnectionState::Disconnected => {
873                         self.vc_states.remove(&addr);
874                     }
875                     _ => {
876                         self.vc_states.insert(addr, state);
877                     }
878                 }
879             }
880             VolumeControlCallbacks::VolumeState(addr, volume, mute, is_autonomous) => {
881                 info!(
882                     "VolumeControlCallbacks::VolumeState: [{}]: volume={}, mute={}, is_autonomous={}",
883                     DisplayAddress(&addr),
884                     volume,
885                     mute,
886                     is_autonomous
887                 );
888             }
889             VolumeControlCallbacks::GroupVolumeState(group_id, volume, mute, is_autonomous) => {
890                 info!(
891                     "VolumeControlCallbacks::GroupVolumeState: group_id={}, volume={}, mute={}, is_autonomous={}",
892                     group_id, volume, mute, is_autonomous
893                 );
894 
895                 // This can come with ~300ms delay, thus notify only when
896                 // triggered by the headset. Otherwise expect the audio server
897                 // to know the expected volume.
898                 if is_autonomous {
899                     self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
900                         callback.on_lea_group_volume_changed(group_id, volume);
901                     });
902                 }
903 
904                 self.le_audio_groups.entry(group_id).or_default().volume = Some(volume);
905             }
906             VolumeControlCallbacks::DeviceAvailable(addr, num_offset) => {
907                 info!(
908                     "VolumeControlCallbacks::DeviceAvailable: [{}]: num_offset={}",
909                     DisplayAddress(&addr),
910                     num_offset
911                 );
912             }
913             VolumeControlCallbacks::ExtAudioOutVolume(addr, ext_output_id, offset) => {
914                 info!(
915                     "VolumeControlCallbacks::ExtAudioOutVolume: [{}]: ext_output_id={}, offset={}",
916                     DisplayAddress(&addr),
917                     ext_output_id,
918                     offset
919                 );
920             }
921             VolumeControlCallbacks::ExtAudioOutLocation(addr, ext_output_id, location) => {
922                 info!(
923                     "VolumeControlCallbacks::ExtAudioOutLocation: [{}]: ext_output_id={}, location={}",
924                     DisplayAddress(&addr),
925                     ext_output_id,
926                     location
927                 );
928             }
929             VolumeControlCallbacks::ExtAudioOutDescription(addr, ext_output_id, descr) => {
930                 info!(
931                     "VolumeControlCallbacks::ExtAudioOutDescription: [{}]: ext_output_id={}, descr={}",
932                     DisplayAddress(&addr),
933                     ext_output_id,
934                     descr
935                 );
936             }
937         }
938     }
939 
dispatch_le_audio_callbacks(&mut self, cb: LeAudioClientCallbacks)940     pub fn dispatch_le_audio_callbacks(&mut self, cb: LeAudioClientCallbacks) {
941         match cb {
942             LeAudioClientCallbacks::Initialized() => {
943                 info!("LeAudioClientCallbacks::Initialized: ");
944             }
945             LeAudioClientCallbacks::ConnectionState(state, addr) => {
946                 if !self.le_audio_states.get(&addr).is_none()
947                     && state == *self.le_audio_states.get(&addr).unwrap()
948                 {
949                     return;
950                 }
951 
952                 let group_id = self.get_group_id(addr);
953                 if group_id == LEA_UNKNOWN_GROUP_ID {
954                     warn!(
955                         "LeAudioClientCallbacks::ConnectionState: [{}] Ignored dispatching of LeAudio callback on a device with no group",
956                         DisplayAddress(&addr)
957                     );
958                     return;
959                 }
960 
961                 let is_only_connected_member = match self.le_audio_groups.get(&group_id) {
962                     Some(group) => group.devices.iter().all(|&member_addr| {
963                         member_addr == addr
964                             || *self
965                                 .le_audio_states
966                                 .get(&member_addr)
967                                 .unwrap_or(&BtLeAudioConnectionState::Disconnected)
968                                 != BtLeAudioConnectionState::Connected
969                     }),
970                     _ => true,
971                 };
972 
973                 info!(
974                     "LeAudioClientCallbacks::ConnectionState: [{}]: state={:?}, group_id={}, is_only_connected_member={}",
975                     DisplayAddress(&addr),
976                     state,
977                     group_id,
978                     is_only_connected_member
979                 );
980 
981                 match state {
982                     BtLeAudioConnectionState::Connected => {
983                         if is_only_connected_member {
984                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
985                                 callback.on_lea_group_connected(
986                                     group_id,
987                                     self.adapter_get_remote_name(addr),
988                                 );
989                             });
990 
991                             match self.le_audio_delayed_audio_conf_updates.remove(&group_id) {
992                                 Some(conf) => {
993                                     self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
994                                         callback.on_lea_audio_conf(
995                                             conf.direction,
996                                             conf.group_id,
997                                             conf.snk_audio_location,
998                                             conf.src_audio_location,
999                                             conf.avail_cont,
1000                                         );
1001                                     });
1002                                 }
1003                                 _ => {}
1004                             }
1005                         }
1006 
1007                         if self.le_audio_delayed_vc_connection_updates.remove(&addr) {
1008                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1009                                 callback.on_lea_vc_connected(addr, group_id);
1010                             });
1011                         }
1012 
1013                         self.le_audio_states.insert(addr, state);
1014                     }
1015                     BtLeAudioConnectionState::Disconnected => {
1016                         if self.le_audio_states.remove(&addr).is_some() {
1017                             if is_only_connected_member {
1018                                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1019                                     callback.on_lea_group_disconnected(group_id);
1020                                 });
1021                             }
1022                         }
1023 
1024                         // In anticipation that it could possibly never be connected.
1025                         self.le_audio_delayed_vc_connection_updates.remove(&addr);
1026                     }
1027                     _ => {
1028                         self.le_audio_states.insert(addr, state);
1029                     }
1030                 }
1031             }
1032             LeAudioClientCallbacks::GroupStatus(group_id, status) => {
1033                 if !self.le_audio_groups.get(&group_id).is_none()
1034                     && status == self.le_audio_groups.get(&group_id).unwrap().status
1035                 {
1036                     return;
1037                 }
1038 
1039                 info!(
1040                     "LeAudioClientCallbacks::GroupStatus: group_id={}, status={:?}",
1041                     group_id, status
1042                 );
1043 
1044                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1045                     callback.on_lea_group_status(group_id, status);
1046                 });
1047 
1048                 self.le_audio_groups.entry(group_id).or_default().status = status;
1049             }
1050             LeAudioClientCallbacks::GroupNodeStatus(addr, group_id, status) => {
1051                 info!(
1052                     "LeAudioClientCallbacks::GroupNodeStatus: [{}]: group_id={}, status={:?}",
1053                     DisplayAddress(&addr),
1054                     group_id,
1055                     status
1056                 );
1057 
1058                 match status {
1059                     BtLeAudioGroupNodeStatus::Added => {
1060                         match self.le_audio_node_to_group.get(&addr) {
1061                             Some(old_group_id) if *old_group_id != group_id => {
1062                                 warn!(
1063                                     "LeAudioClientCallbacks::GroupNodeStatus: [{}]: node already belongs to another group {}",
1064                                     DisplayAddress(&addr),
1065                                     old_group_id,
1066                                 );
1067 
1068                                 self.remove_device_from_group(addr);
1069                             }
1070                             _ => {}
1071                         }
1072 
1073                         self.le_audio_node_to_group.insert(addr, group_id);
1074 
1075                         let group = self.le_audio_groups.entry(group_id).or_default();
1076 
1077                         group.devices.insert(addr);
1078 
1079                         if let Some(volume) = group.volume {
1080                             self.set_group_volume(group_id, volume);
1081                         }
1082                     }
1083                     BtLeAudioGroupNodeStatus::Removed => {
1084                         match self.le_audio_node_to_group.get(&addr) {
1085                             Some(old_group_id) if *old_group_id == group_id => {
1086                                 self.remove_device_from_group(addr);
1087                             }
1088                             Some(old_group_id) if *old_group_id != group_id => {
1089                                 warn!(
1090                                     "LeAudioClientCallbacks::GroupNodeStatus: [{}]: cannot remove node from group {} because it is in group {}",
1091                                     DisplayAddress(&addr),
1092                                     group_id,
1093                                     old_group_id,
1094                                 );
1095 
1096                                 return;
1097                             }
1098                             _ => {}
1099                         }
1100 
1101                         self.le_audio_node_to_group.remove(&addr);
1102                     }
1103                     _ => {
1104                         warn!("LeAudioClientCallbacks::GroupNodeStatus: Unknown status for GroupNodeStatus {:?}", status);
1105                     }
1106                 }
1107 
1108                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1109                     callback.on_lea_group_node_status(addr, group_id, status);
1110                 });
1111             }
1112             LeAudioClientCallbacks::AudioConf(
1113                 direction,
1114                 group_id,
1115                 snk_audio_location,
1116                 src_audio_location,
1117                 avail_cont,
1118             ) => {
1119                 info!(
1120                     "LeAudioClientCallbacks::AudioConf: direction={}, group_id={}, snk_audio_location={}, src_audio_location={}, avail_cont={}",
1121                     direction, group_id, snk_audio_location, src_audio_location, avail_cont,
1122                 );
1123 
1124                 match self.le_audio_groups.get(&group_id) {
1125                     Some(group) if self.is_group_connected(group) => {
1126                         self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1127                             callback.on_lea_audio_conf(
1128                                 direction,
1129                                 group_id,
1130                                 snk_audio_location,
1131                                 src_audio_location,
1132                                 avail_cont,
1133                             );
1134                         });
1135                     }
1136                     _ => {
1137                         self.le_audio_delayed_audio_conf_updates.insert(
1138                             group_id,
1139                             LEAAudioConf {
1140                                 direction,
1141                                 group_id,
1142                                 snk_audio_location,
1143                                 src_audio_location,
1144                                 avail_cont,
1145                             },
1146                         );
1147                     }
1148                 }
1149             }
1150             LeAudioClientCallbacks::SinkAudioLocationAvailable(addr, snk_audio_locations) => {
1151                 info!("LeAudioClientCallbacks::SinkAudioLocationAvailable: [{}]: snk_audio_locations={:?}", DisplayAddress(&addr), snk_audio_locations);
1152             }
1153             LeAudioClientCallbacks::AudioLocalCodecCapabilities(
1154                 local_input_codec_conf,
1155                 local_output_codec_conf,
1156             ) => {
1157                 info!(
1158                     "LeAudioClientCallbacks::AudioLocalCodecCapabilities: local_input_codec_conf={:?}, local_output_codec_conf={:?}",
1159                     local_input_codec_conf, local_output_codec_conf
1160                 );
1161             }
1162             LeAudioClientCallbacks::AudioGroupCodecConf(
1163                 group_id,
1164                 input_codec_conf,
1165                 output_codec_conf,
1166                 input_caps,
1167                 output_caps,
1168             ) => {
1169                 info!("LeAudioClientCallbacks::AudioGroupCodecConf: group_id={}, input_codec_conf={:?}, output_codec_conf={:?}, input_caps={:?}, output_caps={:?}",
1170                       group_id, input_codec_conf, output_codec_conf, input_caps, output_caps);
1171             }
1172             LeAudioClientCallbacks::UnicastMonitorModeStatus(direction, status) => {
1173                 if !self.le_audio_unicast_monitor_mode_status.get(&direction.into()).is_none()
1174                     && status
1175                         == *self
1176                             .le_audio_unicast_monitor_mode_status
1177                             .get(&direction.into())
1178                             .unwrap()
1179                 {
1180                     return;
1181                 }
1182 
1183                 info!(
1184                     "LeAudioClientCallbacks::UnicastMonitorModeStatus: direction={:?}, status={:?}",
1185                     direction, status
1186                 );
1187 
1188                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1189                     callback.on_lea_unicast_monitor_mode_status(direction, status);
1190                 });
1191 
1192                 self.le_audio_unicast_monitor_mode_status.insert(direction.into(), status);
1193             }
1194             LeAudioClientCallbacks::GroupStreamStatus(group_id, status) => {
1195                 if !self.le_audio_groups.get(&group_id).is_none()
1196                     && status == self.le_audio_groups.get(&group_id).unwrap().stream_status
1197                 {
1198                     return;
1199                 }
1200 
1201                 info!(
1202                     "LeAudioClientCallbacks::GroupStreamStatus: group_id={} status {:?}",
1203                     group_id, status
1204                 );
1205 
1206                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1207                     callback.on_lea_group_stream_status(group_id, status);
1208                 });
1209 
1210                 self.le_audio_groups.entry(group_id).or_default().stream_status = status;
1211             }
1212         }
1213     }
1214 
dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks)1215     pub fn dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks) {
1216         match cb {
1217             A2dpCallbacks::ConnectionState(addr, state, error) => {
1218                 if !self.a2dp_states.get(&addr).is_none()
1219                     && state == *self.a2dp_states.get(&addr).unwrap()
1220                 {
1221                     return;
1222                 }
1223                 metrics::profile_connection_state_changed(
1224                     addr,
1225                     Profile::A2dpSink as u32,
1226                     error.status,
1227                     state.clone() as u32,
1228                 );
1229                 match state {
1230                     BtavConnectionState::Connected => {
1231                         info!("[{}]: a2dp connected.", DisplayAddress(&addr));
1232                         self.a2dp_states.insert(addr, state);
1233                         self.add_connected_profile(addr, Profile::A2dpSink);
1234                     }
1235                     BtavConnectionState::Disconnected => {
1236                         info!("[{}]: a2dp disconnected.", DisplayAddress(&addr));
1237                         self.a2dp_states.remove(&addr);
1238                         self.a2dp_caps.remove(&addr);
1239                         self.a2dp_audio_state.remove(&addr);
1240                         self.rm_connected_profile(addr, Profile::A2dpSink, true);
1241                     }
1242                     _ => {
1243                         self.a2dp_states.insert(addr, state);
1244                     }
1245                 }
1246             }
1247             A2dpCallbacks::AudioState(addr, state) => {
1248                 info!("[{}]: a2dp audio state: {:?}", DisplayAddress(&addr), state);
1249                 self.a2dp_audio_state.insert(addr, state);
1250             }
1251             A2dpCallbacks::AudioConfig(addr, _config, _local_caps, a2dp_caps) => {
1252                 debug!("[{}]: a2dp updated audio config: {:?}", DisplayAddress(&addr), a2dp_caps);
1253                 self.a2dp_caps.insert(addr, a2dp_caps);
1254             }
1255             A2dpCallbacks::MandatoryCodecPreferred(_addr) => {}
1256         }
1257     }
1258 
disconnect_device(txl: Sender<Message>, addr: RawAddress)1259     fn disconnect_device(txl: Sender<Message>, addr: RawAddress) {
1260         let device = BluetoothDevice::new(addr, "".to_string());
1261         topstack::get_runtime().spawn(async move {
1262             let _ = txl.send(Message::DisconnectDevice(device)).await;
1263         });
1264     }
1265 
dispatch_avrcp_callbacks(&mut self, cb: AvrcpCallbacks)1266     pub fn dispatch_avrcp_callbacks(&mut self, cb: AvrcpCallbacks) {
1267         match cb {
1268             AvrcpCallbacks::AvrcpDeviceConnected(addr, supported) => {
1269                 info!(
1270                     "[{}]: avrcp connected. Absolute volume support: {}.",
1271                     DisplayAddress(&addr),
1272                     supported
1273                 );
1274 
1275                 match self.uinput.create(self.adapter_get_remote_name(addr), addr.to_string()) {
1276                     Ok(()) => info!("uinput device created for: {}", DisplayAddress(&addr)),
1277                     Err(e) => warn!("{}", e),
1278                 }
1279 
1280                 // Notify change via callback if device is added.
1281                 if self.absolute_volume != supported {
1282                     let guard = self.fallback_tasks.lock().unwrap();
1283                     if let Some(task) = guard.get(&addr) {
1284                         if task.is_none() {
1285                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1286                                 callback.on_absolute_volume_supported_changed(supported);
1287                             });
1288                         }
1289                     }
1290                 }
1291 
1292                 self.absolute_volume = supported;
1293 
1294                 // If is device initiated the AVRCP connection, emit a fake connecting state as
1295                 // stack don't receive one.
1296                 if self.avrcp_direction != BtConnectionDirection::Outgoing {
1297                     metrics::profile_connection_state_changed(
1298                         addr,
1299                         Profile::AvrcpController as u32,
1300                         BtStatus::Success,
1301                         BtavConnectionState::Connecting as u32,
1302                     );
1303                 }
1304                 metrics::profile_connection_state_changed(
1305                     addr,
1306                     Profile::AvrcpController as u32,
1307                     BtStatus::Success,
1308                     BtavConnectionState::Connected as u32,
1309                 );
1310                 // Reset direction to unknown.
1311                 self.avrcp_direction = BtConnectionDirection::Unknown;
1312 
1313                 self.add_connected_profile(addr, Profile::AvrcpController);
1314             }
1315             AvrcpCallbacks::AvrcpDeviceDisconnected(addr) => {
1316                 info!("[{}]: avrcp disconnected.", DisplayAddress(&addr));
1317 
1318                 self.uinput.close(addr.to_string());
1319 
1320                 // TODO: better support for multi-device
1321                 self.absolute_volume = false;
1322 
1323                 // This may be considered a critical profile in the extreme case
1324                 // where only AVRCP was connected.
1325                 let is_profile_critical = match self.connected_profiles.get(&addr) {
1326                     Some(profiles) => *profiles == HashSet::from([Profile::AvrcpController]),
1327                     None => false,
1328                 };
1329 
1330                 // If the peer device initiated the AVRCP disconnection, emit a fake connecting
1331                 // state as stack don't receive one.
1332                 if self.avrcp_direction != BtConnectionDirection::Outgoing {
1333                     metrics::profile_connection_state_changed(
1334                         addr,
1335                         Profile::AvrcpController as u32,
1336                         BtStatus::Success,
1337                         BtavConnectionState::Disconnecting as u32,
1338                     );
1339                 }
1340                 metrics::profile_connection_state_changed(
1341                     addr,
1342                     Profile::AvrcpController as u32,
1343                     BtStatus::Success,
1344                     BtavConnectionState::Disconnected as u32,
1345                 );
1346                 // Reset direction to unknown.
1347                 self.avrcp_direction = BtConnectionDirection::Unknown;
1348 
1349                 self.rm_connected_profile(addr, Profile::AvrcpController, is_profile_critical);
1350             }
1351             AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => {
1352                 for (addr, state) in self.device_states.lock().unwrap().iter() {
1353                     info!("[{}]: state {:?}", DisplayAddress(&addr), state);
1354                     match state {
1355                         DeviceConnectionStates::ConnectingBeforeRetry
1356                         | DeviceConnectionStates::ConnectingAfterRetry
1357                         | DeviceConnectionStates::WaitingConnection => {
1358                             self.delay_volume_update.insert(Profile::AvrcpController, volume);
1359                         }
1360                         DeviceConnectionStates::FullyConnected => {
1361                             self.delay_volume_update.remove(&Profile::AvrcpController);
1362                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1363                                 callback.on_absolute_volume_changed(volume);
1364                             });
1365                             return;
1366                         }
1367                         _ => {}
1368                     }
1369                 }
1370             }
1371             AvrcpCallbacks::AvrcpSendKeyEvent(key, value) => {
1372                 match self.uinput.send_key(key, value) {
1373                     Ok(()) => (),
1374                     Err(e) => warn!("{}", e),
1375                 }
1376 
1377                 const AVRCP_ID_PAUSE: u8 = 0x46;
1378                 const AVRCP_STATE_PRESS: u8 = 0;
1379 
1380                 // Per MPS v1.0, on receiving a pause key through AVRCP,
1381                 // central should pause the A2DP stream with an AVDTP suspend command.
1382                 if self.mps_qualification_enabled
1383                     && key == AVRCP_ID_PAUSE
1384                     && value == AVRCP_STATE_PRESS
1385                 {
1386                     self.suspend_audio_request_impl();
1387                 }
1388             }
1389             AvrcpCallbacks::AvrcpSetActiveDevice(addr) => {
1390                 self.uinput.set_active_device(addr.to_string());
1391             }
1392         }
1393     }
1394 
dispatch_media_actions(&mut self, action: MediaActions)1395     pub fn dispatch_media_actions(&mut self, action: MediaActions) {
1396         match action {
1397             MediaActions::Connect(address) => self.connect(address),
1398             MediaActions::Disconnect(address) => self.disconnect(address),
1399             MediaActions::ForceEnterConnected(address) => self.force_enter_connected(address),
1400 
1401             MediaActions::ConnectLea(address) => self.connect_lea(address),
1402             MediaActions::DisconnectLea(address) => self.disconnect_lea(address),
1403             MediaActions::ConnectVc(address) => self.connect_vc(address),
1404             MediaActions::DisconnectVc(address) => self.disconnect_vc(address),
1405             MediaActions::ConnectCsis(address) => self.connect_csis(address),
1406             MediaActions::DisconnectCsis(address) => self.disconnect_csis(address),
1407 
1408             MediaActions::ConnectLeaGroupByMemberAddress(address) => {
1409                 self.connect_lea_group_by_member_address(address)
1410             }
1411             MediaActions::DisconnectLeaGroupByMemberAddress(address) => {
1412                 self.disconnect_lea_group_by_member_address(address)
1413             }
1414         }
1415     }
1416 
dispatch_hfp_callbacks(&mut self, cb: HfpCallbacks)1417     pub fn dispatch_hfp_callbacks(&mut self, cb: HfpCallbacks) {
1418         match cb {
1419             HfpCallbacks::ConnectionState(state, addr) => {
1420                 if !self.hfp_states.get(&addr).is_none()
1421                     && state == *self.hfp_states.get(&addr).unwrap()
1422                 {
1423                     return;
1424                 }
1425                 metrics::profile_connection_state_changed(
1426                     addr,
1427                     Profile::Hfp as u32,
1428                     BtStatus::Success,
1429                     state.clone() as u32,
1430                 );
1431                 match state {
1432                     BthfConnectionState::Connected => {
1433                         info!("[{}]: hfp connected.", DisplayAddress(&addr));
1434                     }
1435                     BthfConnectionState::SlcConnected => {
1436                         info!("[{}]: hfp slc connected.", DisplayAddress(&addr));
1437                         // The device may not support codec-negotiation,
1438                         // in which case we shall assume it supports CVSD at this point.
1439                         if !self.hfp_cap.contains_key(&addr) {
1440                             self.hfp_cap.insert(addr, HfpCodecFormat::CVSD);
1441                         }
1442                         self.add_connected_profile(addr, Profile::Hfp);
1443 
1444                         // Connect SCO if phone operations are enabled and an active call exists.
1445                         // This is only used for Bluetooth HFP qualification.
1446                         if self.mps_qualification_enabled && self.phone_state.num_active > 0 {
1447                             debug!("[{}]: Connect SCO due to active call.", DisplayAddress(&addr));
1448                             self.start_sco_call_impl(addr, false, HfpCodecBitId::NONE);
1449                         }
1450 
1451                         if self.phone_ops_enabled {
1452                             self.uhid_create(addr);
1453                         }
1454                     }
1455                     BthfConnectionState::Disconnected => {
1456                         info!("[{}]: hfp disconnected.", DisplayAddress(&addr));
1457                         self.uhid_destroy(&addr);
1458                         self.hfp_states.remove(&addr);
1459                         self.hfp_cap.remove(&addr);
1460                         self.hfp_audio_state.remove(&addr);
1461                         self.rm_connected_profile(addr, Profile::Hfp, true);
1462                     }
1463                     BthfConnectionState::Connecting => {
1464                         info!("[{}]: hfp connecting.", DisplayAddress(&addr));
1465                     }
1466                     BthfConnectionState::Disconnecting => {
1467                         info!("[{}]: hfp disconnecting.", DisplayAddress(&addr));
1468                     }
1469                 }
1470 
1471                 self.hfp_states.insert(addr, state);
1472             }
1473             HfpCallbacks::AudioState(state, addr) => {
1474                 if self.hfp_states.get(&addr).is_none()
1475                     || BthfConnectionState::SlcConnected != *self.hfp_states.get(&addr).unwrap()
1476                 {
1477                     warn!("[{}]: Unknown address hfp or slc not ready", DisplayAddress(&addr));
1478                     return;
1479                 }
1480 
1481                 match state {
1482                     BthfAudioState::Connected => {
1483                         info!("[{}]: hfp audio connected.", DisplayAddress(&addr));
1484 
1485                         self.hfp_audio_state.insert(addr, state);
1486 
1487                         if self.should_insert_call_when_sco_start(addr) {
1488                             // This triggers a +CIEV command to set the call status for HFP devices.
1489                             // It is required for some devices to provide sound.
1490                             self.place_active_call();
1491                             self.notify_telephony_event(&addr, TelephonyEvent::CRASPlaceActiveCall);
1492                         }
1493                     }
1494                     BthfAudioState::Disconnected => {
1495                         info!("[{}]: hfp audio disconnected.", DisplayAddress(&addr));
1496 
1497                         // Ignore disconnected -> disconnected
1498                         if let Some(BthfAudioState::Connected) =
1499                             self.hfp_audio_state.insert(addr, state)
1500                         {
1501                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1502                                 callback.on_hfp_audio_disconnected(addr);
1503                             });
1504                         }
1505 
1506                         if self.should_insert_call_when_sco_start(addr) {
1507                             // Remove the only call related to the one added for devices requesting to force +CIEV command
1508                             self.call_list = vec![];
1509                             self.phone_state.num_active = 0;
1510                             self.phone_state_change("".into());
1511                             self.notify_telephony_event(
1512                                 &addr,
1513                                 TelephonyEvent::CRASRemoveActiveCall,
1514                             );
1515                         }
1516 
1517                         // Resume the A2DP stream when a phone call ended (per MPS v1.0).
1518                         self.try_a2dp_resume();
1519                     }
1520                     BthfAudioState::Connecting => {
1521                         info!("[{}]: hfp audio connecting.", DisplayAddress(&addr));
1522                     }
1523                     BthfAudioState::Disconnecting => {
1524                         info!("[{}]: hfp audio disconnecting.", DisplayAddress(&addr));
1525                     }
1526                 }
1527             }
1528             HfpCallbacks::VolumeUpdate(volume, addr) => {
1529                 if self.hfp_states.get(&addr).is_none()
1530                     || BthfConnectionState::SlcConnected != *self.hfp_states.get(&addr).unwrap()
1531                 {
1532                     warn!("[{}]: Unknown address hfp or slc not ready", DisplayAddress(&addr));
1533                     return;
1534                 }
1535 
1536                 let states = self.device_states.lock().unwrap();
1537                 info!(
1538                     "[{}]: VolumeUpdate state: {:?}",
1539                     DisplayAddress(&addr),
1540                     states.get(&addr).unwrap()
1541                 );
1542                 match states.get(&addr).unwrap() {
1543                     DeviceConnectionStates::ConnectingBeforeRetry
1544                     | DeviceConnectionStates::ConnectingAfterRetry
1545                     | DeviceConnectionStates::WaitingConnection => {
1546                         self.delay_volume_update.insert(Profile::Hfp, volume);
1547                     }
1548                     DeviceConnectionStates::FullyConnected => {
1549                         self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1550                             callback.on_hfp_volume_changed(volume, addr);
1551                         });
1552                     }
1553                     _ => {}
1554                 }
1555             }
1556             HfpCallbacks::MicVolumeUpdate(volume, addr) => {
1557                 if !self.phone_ops_enabled {
1558                     return;
1559                 }
1560 
1561                 if self.hfp_states.get(&addr).is_none()
1562                     || BthfConnectionState::SlcConnected != *self.hfp_states.get(&addr).unwrap()
1563                 {
1564                     warn!("[{}]: Unknown address hfp or slc not ready", DisplayAddress(&addr));
1565                     return;
1566                 }
1567 
1568                 if let Some(uhid) = self.uhid.get_mut(&addr) {
1569                     if volume == 0 && !uhid.muted {
1570                         // We expect the application to send back UHID output report and
1571                         // update uhid.mute in dispatch_uhid_hfp_output_callback later.
1572                         self.uhid_send_phone_mute_input_report(&addr, true);
1573                         self.notify_telephony_event(&addr, TelephonyEvent::HFMicMute);
1574                     } else if volume > 0 {
1575                         uhid.volume = volume;
1576                         if uhid.muted {
1577                             // We expect the application to send back UHID output report and
1578                             // update uhid.mute in dispatch_uhid_hfp_output_callback later.
1579                             self.uhid_send_phone_mute_input_report(&addr, false);
1580                             self.notify_telephony_event(&addr, TelephonyEvent::HFMicUnmute);
1581                         }
1582                     }
1583                 }
1584             }
1585             HfpCallbacks::VendorSpecificAtCommand(at_string, addr) => {
1586                 let at_command = match parse_at_command_data(at_string) {
1587                     Ok(command) => command,
1588                     Err(e) => {
1589                         debug!("{}", e);
1590                         return;
1591                     }
1592                 };
1593                 let battery_level = match calculate_battery_percent(at_command.clone()) {
1594                     Ok(level) => level,
1595                     Err(e) => {
1596                         debug!("{}", e);
1597                         return;
1598                     }
1599                 };
1600                 let source_info = match at_command.vendor {
1601                     Some(vendor) => format!("HFP - {}", vendor),
1602                     _ => "HFP - UnknownAtCommand".to_string(),
1603                 };
1604                 self.battery_provider_manager.lock().unwrap().set_battery_info(
1605                     self.battery_provider_id,
1606                     BatterySet::new(
1607                         addr,
1608                         uuid::HFP.to_string(),
1609                         source_info,
1610                         vec![Battery { percentage: battery_level, variant: "".to_string() }],
1611                     ),
1612                 );
1613             }
1614             HfpCallbacks::BatteryLevelUpdate(battery_level, addr) => {
1615                 let battery_set = BatterySet::new(
1616                     addr,
1617                     uuid::HFP.to_string(),
1618                     "HFP".to_string(),
1619                     vec![Battery { percentage: battery_level as u32, variant: "".to_string() }],
1620                 );
1621                 self.battery_provider_manager
1622                     .lock()
1623                     .unwrap()
1624                     .set_battery_info(self.battery_provider_id, battery_set);
1625             }
1626             HfpCallbacks::WbsCapsUpdate(wbs_supported, addr) => {
1627                 let is_transparent_coding_format_supported = match &self.adapter {
1628                     Some(adapter) => adapter
1629                         .lock()
1630                         .unwrap()
1631                         .is_coding_format_supported(EscoCodingFormat::TRANSPARENT),
1632                     _ => false,
1633                 };
1634 
1635                 let is_msbc_coding_format_supported = match &self.adapter {
1636                     Some(adapter) => {
1637                         adapter.lock().unwrap().is_coding_format_supported(EscoCodingFormat::MSBC)
1638                     }
1639                     _ => false,
1640                 };
1641 
1642                 let mut codec_diff = HfpCodecFormat::NONE;
1643                 if is_transparent_coding_format_supported {
1644                     codec_diff |= HfpCodecFormat::MSBC_TRANSPARENT;
1645                 }
1646                 if is_msbc_coding_format_supported {
1647                     codec_diff |= HfpCodecFormat::MSBC;
1648                 }
1649 
1650                 if let Some(cur_hfp_cap) = self.hfp_cap.get_mut(&addr) {
1651                     if wbs_supported {
1652                         *cur_hfp_cap |= codec_diff;
1653                     } else {
1654                         *cur_hfp_cap &= !codec_diff;
1655                     }
1656                 } else {
1657                     let new_hfp_cap = match wbs_supported {
1658                         true => HfpCodecFormat::CVSD | codec_diff,
1659                         false => HfpCodecFormat::CVSD,
1660                     };
1661                     self.hfp_cap.insert(addr, new_hfp_cap);
1662                 }
1663             }
1664             HfpCallbacks::SwbCapsUpdate(swb_supported, addr) => {
1665                 // LC3 can be propagated to this point only if adapter supports transparent mode.
1666                 if let Some(cur_hfp_cap) = self.hfp_cap.get_mut(&addr) {
1667                     if swb_supported {
1668                         *cur_hfp_cap |= HfpCodecFormat::LC3_TRANSPARENT;
1669                     } else {
1670                         *cur_hfp_cap &= !HfpCodecFormat::LC3_TRANSPARENT;
1671                     }
1672                 } else {
1673                     let new_hfp_cap = match swb_supported {
1674                         true => HfpCodecFormat::CVSD | HfpCodecFormat::LC3_TRANSPARENT,
1675                         false => HfpCodecFormat::CVSD,
1676                     };
1677                     self.hfp_cap.insert(addr, new_hfp_cap);
1678                 }
1679             }
1680             HfpCallbacks::IndicatorQuery(addr) => {
1681                 match self.hfp.as_mut() {
1682                     Some(hfp) => {
1683                         debug!(
1684                             "[{}]: Responding CIND query with device={:?} phone={:?}",
1685                             DisplayAddress(&addr),
1686                             self.telephony_device_status,
1687                             self.phone_state,
1688                         );
1689                         let status = hfp.indicator_query_response(
1690                             self.telephony_device_status,
1691                             self.phone_state,
1692                             addr,
1693                         );
1694                         if status != BtStatus::Success {
1695                             warn!(
1696                                 "[{}]: CIND response failed, status={:?}",
1697                                 DisplayAddress(&addr),
1698                                 status
1699                             );
1700                         }
1701                     }
1702                     None => warn!("Uninitialized HFP to notify telephony status"),
1703                 };
1704             }
1705             HfpCallbacks::CurrentCallsQuery(addr) => {
1706                 match self.hfp.as_mut() {
1707                     Some(hfp) => {
1708                         debug!(
1709                             "[{}]: Responding CLCC query with call_list={:?}",
1710                             DisplayAddress(&addr),
1711                             self.call_list,
1712                         );
1713                         let status = hfp.current_calls_query_response(&self.call_list, addr);
1714                         if status != BtStatus::Success {
1715                             warn!(
1716                                 "[{}]: CLCC response failed, status={:?}",
1717                                 DisplayAddress(&addr),
1718                                 status
1719                             );
1720                         }
1721                         self.notify_telephony_event(&addr, TelephonyEvent::HFCurrentCallsQuery);
1722                     }
1723                     None => warn!("Uninitialized HFP to notify telephony status"),
1724                 };
1725             }
1726             HfpCallbacks::AnswerCall(addr) => {
1727                 if !self.phone_ops_enabled && !self.mps_qualification_enabled {
1728                     warn!("Unexpected answer call. phone_ops_enabled and mps_qualification_enabled does not enabled.");
1729                     return;
1730                 }
1731                 if self.mps_qualification_enabled {
1732                     // In qualification mode we expect no application to interact with.
1733                     // So we just jump right in to the telephony ops implementation.
1734                     let id = BLUETOOTH_TELEPHONY_UHID_REPORT_ID;
1735                     let mut data = UHID_OUTPUT_NONE;
1736                     data |= UHID_OUTPUT_OFF_HOOK;
1737                     self.dispatch_uhid_hfp_output_callback(addr, id, data);
1738                 } else {
1739                     // We expect the application to send back UHID output report and
1740                     // trigger dispatch_uhid_hfp_output_callback later.
1741                     self.uhid_send_hook_switch_input_report(&addr, true);
1742                     self.notify_telephony_event(&addr, TelephonyEvent::HFAnswerCall);
1743                 }
1744             }
1745             HfpCallbacks::HangupCall(addr) => {
1746                 if !self.phone_ops_enabled && !self.mps_qualification_enabled {
1747                     warn!("Unexpected hangup call. phone_ops_enabled and mps_qualification_enabled does not enabled.");
1748                     return;
1749                 }
1750                 if self.mps_qualification_enabled {
1751                     // In qualification mode we expect no application to interact with.
1752                     // So we just jump right in to the telephony ops implementation.
1753                     let id = BLUETOOTH_TELEPHONY_UHID_REPORT_ID;
1754                     let mut data = UHID_OUTPUT_NONE;
1755                     data &= !UHID_OUTPUT_OFF_HOOK;
1756                     self.dispatch_uhid_hfp_output_callback(addr, id, data);
1757                 } else {
1758                     // We expect the application to send back UHID output report and
1759                     // trigger dispatch_uhid_hfp_output_callback later.
1760                     self.uhid_send_hook_switch_input_report(&addr, false);
1761                     self.notify_telephony_event(&addr, TelephonyEvent::HFHangupCall);
1762                 }
1763             }
1764             HfpCallbacks::DialCall(number, addr) => {
1765                 if !self.mps_qualification_enabled {
1766                     warn!("Unexpected dail call. mps_qualification_enabled does not enabled.");
1767                     self.simple_at_response(false, addr);
1768                     return;
1769                 }
1770                 let number = if number == "" {
1771                     self.last_dialing_number.clone()
1772                 } else if number.starts_with(">") {
1773                     self.memory_dialing_number.clone()
1774                 } else {
1775                     Some(number)
1776                 };
1777 
1778                 if let Some(number) = number {
1779                     self.dialing_call_impl(number, Some(addr));
1780                 } else {
1781                     self.simple_at_response(false, addr);
1782                 }
1783             }
1784             HfpCallbacks::CallHold(command, addr) => {
1785                 if !self.mps_qualification_enabled {
1786                     warn!("Unexpected call hold. mps_qualification_enabled does not enabled.");
1787                     self.simple_at_response(false, addr);
1788                     return;
1789                 }
1790                 let success = match command {
1791                     CallHoldCommand::ReleaseHeld => self.release_held_impl(Some(addr)),
1792                     CallHoldCommand::ReleaseActiveAcceptHeld => {
1793                         self.release_active_accept_held_impl(Some(addr))
1794                     }
1795                     CallHoldCommand::HoldActiveAcceptHeld => {
1796                         self.hold_active_accept_held_impl(Some(addr))
1797                     }
1798                     _ => false, // We only support the 3 operations above.
1799                 };
1800                 if !success {
1801                     warn!(
1802                         "[{}]: Unexpected or unsupported CHLD command {:?} from HF",
1803                         DisplayAddress(&addr),
1804                         command
1805                     );
1806                 }
1807             }
1808             HfpCallbacks::DebugDump(
1809                 active,
1810                 codec_id,
1811                 total_num_decoded_frames,
1812                 pkt_loss_ratio,
1813                 begin_ts,
1814                 end_ts,
1815                 pkt_status_in_hex,
1816                 pkt_status_in_binary,
1817             ) => {
1818                 let is_wbs = codec_id == HfpCodecId::MSBC as u16;
1819                 let is_swb = codec_id == HfpCodecId::LC3 as u16;
1820                 debug!("[HFP] DebugDump: active:{}, codec_id:{}", active, codec_id);
1821                 if is_wbs || is_swb {
1822                     debug!(
1823                         "total_num_decoded_frames:{} pkt_loss_ratio:{}",
1824                         total_num_decoded_frames, pkt_loss_ratio
1825                     );
1826                     debug!("begin_ts:{} end_ts:{}", begin_ts, end_ts);
1827                     debug!(
1828                         "pkt_status_in_hex:{} pkt_status_in_binary:{}",
1829                         pkt_status_in_hex, pkt_status_in_binary
1830                     );
1831                 }
1832                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1833                     callback.on_hfp_debug_dump(
1834                         active,
1835                         codec_id,
1836                         total_num_decoded_frames,
1837                         pkt_loss_ratio,
1838                         begin_ts,
1839                         end_ts,
1840                         pkt_status_in_hex.clone(),
1841                         pkt_status_in_binary.clone(),
1842                     );
1843                 });
1844             }
1845         }
1846     }
1847 
remove_callback(&mut self, id: u32) -> bool1848     pub fn remove_callback(&mut self, id: u32) -> bool {
1849         self.callbacks.lock().unwrap().remove_callback(id)
1850     }
1851 
remove_telephony_callback(&mut self, id: u32) -> bool1852     pub fn remove_telephony_callback(&mut self, id: u32) -> bool {
1853         self.telephony_callbacks.lock().unwrap().remove_callback(id)
1854     }
1855 
uhid_create(&mut self, addr: RawAddress)1856     fn uhid_create(&mut self, addr: RawAddress) {
1857         debug!(
1858             "[{}]: UHID create: PhoneOpsEnabled {}",
1859             DisplayAddress(&addr),
1860             self.phone_ops_enabled,
1861         );
1862         // To change the value of phone_ops_enabled, you need to toggle the BluetoothFlossTelephony feature flag on chrome://flags.
1863         if !self.phone_ops_enabled {
1864             return;
1865         }
1866         if self.uhid.contains_key(&addr) {
1867             warn!("[{}]: UHID create: entry already created", DisplayAddress(&addr));
1868             return;
1869         }
1870         let adapter_addr = match &self.adapter {
1871             Some(adapter) => adapter.lock().unwrap().get_address().to_string().to_lowercase(),
1872             _ => "".to_string(),
1873         };
1874         let txl = self.tx.clone();
1875         self.uhid.insert(
1876             addr,
1877             UHid {
1878                 handle: UHidHfp::create(
1879                     adapter_addr,
1880                     addr.to_string(),
1881                     self.adapter_get_remote_name(addr),
1882                     move |m| {
1883                         match m {
1884                             OutputEvent::Close => {
1885                                 txl.blocking_send(Message::UHidTelephonyUseCallback(addr, false))
1886                                     .unwrap();
1887                             }
1888                             OutputEvent::Open => {
1889                                 txl.blocking_send(Message::UHidTelephonyUseCallback(addr, true))
1890                                     .unwrap();
1891                             }
1892                             OutputEvent::Output { data } => {
1893                                 txl.blocking_send(Message::UHidHfpOutputCallback(
1894                                     addr, data[0], data[1],
1895                                 ))
1896                                 .unwrap();
1897                             }
1898                             _ => (),
1899                         };
1900                     },
1901                 ),
1902                 volume: 15, // By default use maximum volume in case microphone gain has not been received
1903                 muted: false,
1904                 is_open: false,
1905             },
1906         );
1907         self.notify_telephony_event(&addr, TelephonyEvent::UHidCreate);
1908     }
1909 
uhid_destroy(&mut self, addr: &RawAddress)1910     fn uhid_destroy(&mut self, addr: &RawAddress) {
1911         if let Some(uhid) = self.uhid.get_mut(addr) {
1912             debug!("[{}]: UHID destroy", DisplayAddress(&addr));
1913             match uhid.handle.destroy() {
1914                 Err(e) => log::error!(
1915                     "[{}]: UHID destroy: Fail to destroy uhid {}",
1916                     DisplayAddress(&addr),
1917                     e
1918                 ),
1919                 Ok(_) => (),
1920             };
1921             self.uhid.remove(addr);
1922             self.notify_telephony_event(&addr, TelephonyEvent::UHidDestroy);
1923         } else {
1924             debug!("[{}]: UHID destroy: not a UHID device", DisplayAddress(&addr));
1925         }
1926     }
1927 
uhid_send_input_event_report(&mut self, addr: &RawAddress, data: u8)1928     fn uhid_send_input_event_report(&mut self, addr: &RawAddress, data: u8) {
1929         if !self.phone_ops_enabled {
1930             return;
1931         }
1932         if let Some(uhid) = self.uhid.get_mut(addr) {
1933             info!(
1934                 "[{}]: UHID: Send telephony hid input report. hook_switch({}), mute({}), drop({})",
1935                 DisplayAddress(&addr),
1936                 (data & UHID_INPUT_HOOK_SWITCH) != 0,
1937                 (data & UHID_INPUT_PHONE_MUTE) != 0,
1938                 (data & UHID_INPUT_DROP) != 0,
1939             );
1940             match uhid.handle.send_input(data) {
1941                 Err(e) => log::error!(
1942                     "[{}]: UHID: Fail to send hid input report. err:{}",
1943                     DisplayAddress(&addr),
1944                     e
1945                 ),
1946                 Ok(_) => (),
1947             };
1948         }
1949     }
1950 
uhid_send_hook_switch_input_report(&mut self, addr: &RawAddress, hook: bool)1951     fn uhid_send_hook_switch_input_report(&mut self, addr: &RawAddress, hook: bool) {
1952         if !self.phone_ops_enabled {
1953             return;
1954         }
1955         if let Some(uhid) = self.uhid.get(addr) {
1956             let mut data = UHID_INPUT_NONE;
1957             if hook {
1958                 data |= UHID_INPUT_HOOK_SWITCH;
1959             } else if self.phone_state.state == CallState::Incoming {
1960                 data |= UHID_INPUT_DROP;
1961             }
1962             // Preserve the muted state when sending the hook switch event.
1963             if uhid.muted {
1964                 data |= UHID_INPUT_PHONE_MUTE;
1965             }
1966             self.uhid_send_input_event_report(&addr, data);
1967         };
1968     }
uhid_send_phone_mute_input_report(&mut self, addr: &RawAddress, muted: bool)1969     fn uhid_send_phone_mute_input_report(&mut self, addr: &RawAddress, muted: bool) {
1970         if !self.phone_ops_enabled {
1971             return;
1972         }
1973         if self.uhid.get(addr).is_some() {
1974             let mut data = UHID_INPUT_NONE;
1975             // Preserve the hook switch state when sending the microphone mute event.
1976             let call_active = self.phone_state.num_active > 0;
1977             if call_active {
1978                 data |= UHID_INPUT_HOOK_SWITCH;
1979             }
1980             info!(
1981                 "[{}]: UHID: Send phone_mute({}) hid input report. hook-switch({})",
1982                 DisplayAddress(&addr),
1983                 muted,
1984                 call_active
1985             );
1986             if muted {
1987                 data |= UHID_INPUT_PHONE_MUTE;
1988                 self.uhid_send_input_event_report(&addr, data);
1989             } else {
1990                 // We follow the same pattern as the USB headset, which sends an
1991                 // additional phone mute=1 event when unmuting the microphone.
1992                 // Based on our testing, Some applications do not respond to phone
1993                 // mute=0 and treat the phone mute=1 event as a toggle rather than
1994                 // an on off control.
1995                 data |= UHID_INPUT_PHONE_MUTE;
1996                 self.uhid_send_input_event_report(&addr, data);
1997                 data &= !UHID_INPUT_PHONE_MUTE;
1998                 self.uhid_send_input_event_report(&addr, data);
1999             }
2000         };
2001     }
2002 
dispatch_uhid_hfp_output_callback(&mut self, addr: RawAddress, id: u8, data: u8)2003     pub fn dispatch_uhid_hfp_output_callback(&mut self, addr: RawAddress, id: u8, data: u8) {
2004         if !self.phone_ops_enabled {
2005             warn!("Unexpected dispatch_uhid_hfp_output_callback uhid output. phone_ops_enabled does not enabled.");
2006             return;
2007         }
2008 
2009         debug!(
2010             "[{}]: UHID: Received output report: id {}, data {}",
2011             DisplayAddress(&addr),
2012             id,
2013             data
2014         );
2015 
2016         let uhid = match self.uhid.get_mut(&addr) {
2017             Some(uhid) => uhid,
2018             None => {
2019                 warn!("[{}]: UHID: No valid UHID", DisplayAddress(&addr));
2020                 return;
2021             }
2022         };
2023 
2024         if id == BLUETOOTH_TELEPHONY_UHID_REPORT_ID {
2025             let mute = data & UHID_OUTPUT_MUTE;
2026             if mute == UHID_OUTPUT_MUTE && !uhid.muted {
2027                 uhid.muted = true;
2028                 self.set_hfp_mic_volume(0, addr);
2029                 self.notify_telephony_event(&addr, TelephonyEvent::UHidMicMute);
2030             } else if mute != UHID_OUTPUT_MUTE && uhid.muted {
2031                 uhid.muted = false;
2032                 let saved_volume = uhid.volume;
2033                 self.set_hfp_mic_volume(saved_volume, addr);
2034                 self.notify_telephony_event(&addr, TelephonyEvent::UHidMicUnmute);
2035             }
2036 
2037             let call_state = data & (UHID_OUTPUT_RING | UHID_OUTPUT_OFF_HOOK);
2038             if call_state == UHID_OUTPUT_NONE {
2039                 self.hangup_call_impl();
2040                 self.notify_telephony_event(&addr, TelephonyEvent::UHidHangupCall);
2041             } else if call_state == UHID_OUTPUT_RING {
2042                 self.incoming_call_impl("".into());
2043                 self.notify_telephony_event(&addr, TelephonyEvent::UHidIncomingCall);
2044             } else if call_state == UHID_OUTPUT_OFF_HOOK {
2045                 if self.phone_state.state == CallState::Incoming {
2046                     self.answer_call_impl();
2047                     self.notify_telephony_event(&addr, TelephonyEvent::UHidAnswerCall);
2048                 } else if self.phone_state.state == CallState::Idle {
2049                     self.place_active_call();
2050                     self.notify_telephony_event(&addr, TelephonyEvent::UHidPlaceActiveCall);
2051                 }
2052                 self.uhid_send_hook_switch_input_report(&addr, true);
2053             }
2054         }
2055     }
2056 
dispatch_uhid_telephony_use_callback(&mut self, addr: RawAddress, state: bool)2057     pub fn dispatch_uhid_telephony_use_callback(&mut self, addr: RawAddress, state: bool) {
2058         let uhid = match self.uhid.get_mut(&addr) {
2059             Some(uhid) => uhid,
2060             None => {
2061                 warn!("[{}]: UHID: No valid UHID", DisplayAddress(&addr));
2062                 return;
2063             }
2064         };
2065 
2066         uhid.is_open = state;
2067 
2068         info!("[{}]: UHID: floss telephony device is open: {}", DisplayAddress(&addr), state);
2069         // A hangup call is necessary both when opening and closing the UHID device,
2070         // although for different reasons:
2071         //  - On open: To prevent conflicts with existing SCO calls in CRAS and establish
2072         //             a clean environment for Bluetooth Telephony operations.
2073         //  - On close: As there's a HID call for each WebHID call, even if it has been
2074         //              answered in the app or pre-exists, and that an app which disconnects
2075         //              from WebHID may not have trigger the UHID_OUTPUT_NONE, we need to
2076         //              remove all pending HID calls on telephony use release to keep lower
2077         //              HF layer in sync and not prevent A2DP streaming.
2078         self.hangup_call_impl();
2079 
2080         if state {
2081             self.notify_telephony_event(&addr, TelephonyEvent::UHidOpen);
2082         } else {
2083             self.notify_telephony_event(&addr, TelephonyEvent::UHidClose);
2084         }
2085     }
2086 
notify_telephony_event(&mut self, addr: &RawAddress, event: TelephonyEvent)2087     fn notify_telephony_event(&mut self, addr: &RawAddress, event: TelephonyEvent) {
2088         // Simplified call status: Assumes at most one call in the list.
2089         // Defaults to Idle if no calls are present.
2090         // Revisit this logic if the system supports multiple concurrent calls in the future (e.g., three-way-call).
2091         let mut call_state = CallState::Idle;
2092         self.call_list.first().map(|c| call_state = c.state);
2093         self.telephony_callbacks.lock().unwrap().for_all_callbacks(|callback| {
2094             callback.on_telephony_event(*addr, u8::from(event), u8::from(call_state));
2095         });
2096     }
2097 
set_hfp_mic_volume(&mut self, volume: u8, addr: RawAddress)2098     fn set_hfp_mic_volume(&mut self, volume: u8, addr: RawAddress) {
2099         let vol = match i8::try_from(volume) {
2100             Ok(val) if val <= 15 => val,
2101             _ => {
2102                 warn!("[{}]: Ignore invalid mic volume {}", DisplayAddress(&addr), volume);
2103                 return;
2104             }
2105         };
2106 
2107         if self.hfp_states.get(&addr).is_none() {
2108             warn!(
2109                 "[{}]: Ignore mic volume event for unconnected or disconnected HFP device",
2110                 DisplayAddress(&addr)
2111             );
2112             return;
2113         }
2114 
2115         match self.hfp.as_mut() {
2116             Some(hfp) => {
2117                 let status = hfp.set_mic_volume(vol, addr);
2118                 if status != BtStatus::Success {
2119                     warn!("[{}]: Failed to set mic volume to {}", DisplayAddress(&addr), vol);
2120                 }
2121             }
2122             None => warn!("Uninitialized HFP to set mic volume"),
2123         };
2124     }
2125 
notify_critical_profile_disconnected(&mut self, addr: RawAddress)2126     fn notify_critical_profile_disconnected(&mut self, addr: RawAddress) {
2127         info!(
2128             "[{}]: Device connection state: {:?}.",
2129             DisplayAddress(&addr),
2130             DeviceConnectionStates::Disconnecting
2131         );
2132 
2133         let mut states = self.device_states.lock().unwrap();
2134         let prev_state = states.insert(addr, DeviceConnectionStates::Disconnecting).unwrap();
2135         if prev_state != DeviceConnectionStates::Disconnecting {
2136             let mut guard = self.fallback_tasks.lock().unwrap();
2137             if let Some(task) = guard.get(&addr) {
2138                 match task {
2139                     // Abort pending task if there is any.
2140                     Some((handler, _ts)) => {
2141                         warn!(
2142                             "[{}]: Device disconnected a critical profile before it was added.",
2143                             DisplayAddress(&addr)
2144                         );
2145                         handler.abort();
2146                         guard.insert(addr, None);
2147                     }
2148                     // Notify device removal if it has been added.
2149                     None => {
2150                         info!(
2151                             "[{}]: Device disconnected a critical profile, removing the device.",
2152                             DisplayAddress(&addr)
2153                         );
2154                         self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
2155                             callback.on_bluetooth_audio_device_removed(addr);
2156                         });
2157                     }
2158                 };
2159             }
2160             self.delay_volume_update.clear();
2161         }
2162     }
2163 
wait_retry( _fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>, device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>, txl: &Sender<Message>, addr: &RawAddress, first_conn_ts: Instant, )2164     async fn wait_retry(
2165         _fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
2166         device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
2167         txl: &Sender<Message>,
2168         addr: &RawAddress,
2169         first_conn_ts: Instant,
2170     ) {
2171         let now_ts = Instant::now();
2172         let total_duration = Duration::from_secs(CONNECT_MISSING_PROFILES_TIMEOUT_SEC);
2173         let sleep_duration = (first_conn_ts + total_duration).saturating_duration_since(now_ts);
2174         sleep(sleep_duration).await;
2175 
2176         device_states.lock().unwrap().insert(*addr, DeviceConnectionStates::ConnectingAfterRetry);
2177 
2178         info!(
2179             "[{}]: Device connection state: {:?}.",
2180             DisplayAddress(addr),
2181             DeviceConnectionStates::ConnectingAfterRetry
2182         );
2183 
2184         let _ = txl.send(Message::Media(MediaActions::Connect(*addr))).await;
2185     }
2186 
wait_disconnect( fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>, device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>, txl: &Sender<Message>, addr: &RawAddress, first_conn_ts: Instant, )2187     async fn wait_disconnect(
2188         fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
2189         device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
2190         txl: &Sender<Message>,
2191         addr: &RawAddress,
2192         first_conn_ts: Instant,
2193     ) {
2194         let now_ts = Instant::now();
2195         let total_duration = Duration::from_secs(PROFILE_DISCOVERY_TIMEOUT_SEC);
2196         let sleep_duration = (first_conn_ts + total_duration).saturating_duration_since(now_ts);
2197         sleep(sleep_duration).await;
2198 
2199         Self::async_disconnect(fallback_tasks, device_states, txl, addr).await;
2200     }
2201 
async_disconnect( fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>, device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>, txl: &Sender<Message>, addr: &RawAddress, )2202     async fn async_disconnect(
2203         fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
2204         device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
2205         txl: &Sender<Message>,
2206         addr: &RawAddress,
2207     ) {
2208         device_states.lock().unwrap().insert(*addr, DeviceConnectionStates::Disconnecting);
2209         fallback_tasks.lock().unwrap().insert(*addr, None);
2210 
2211         info!(
2212             "[{}]: Device connection state: {:?}.",
2213             DisplayAddress(addr),
2214             DeviceConnectionStates::Disconnecting
2215         );
2216 
2217         let _ = txl.send(Message::Media(MediaActions::Disconnect(*addr))).await;
2218     }
2219 
wait_force_enter_connected( txl: &Sender<Message>, addr: &RawAddress, first_conn_ts: Instant, )2220     async fn wait_force_enter_connected(
2221         txl: &Sender<Message>,
2222         addr: &RawAddress,
2223         first_conn_ts: Instant,
2224     ) {
2225         let now_ts = Instant::now();
2226         let total_duration = Duration::from_secs(PROFILE_DISCOVERY_TIMEOUT_SEC);
2227         let sleep_duration = (first_conn_ts + total_duration).saturating_duration_since(now_ts);
2228         sleep(sleep_duration).await;
2229         let _ = txl.send(Message::Media(MediaActions::ForceEnterConnected(*addr))).await;
2230     }
2231 
is_bonded(&self, addr: &RawAddress) -> bool2232     fn is_bonded(&self, addr: &RawAddress) -> bool {
2233         match &self.adapter {
2234             Some(adapter) => {
2235                 BtBondState::Bonded == adapter.lock().unwrap().get_bond_state_by_addr(&addr)
2236             }
2237             _ => false,
2238         }
2239     }
2240 
notify_media_capability_updated(&mut self, addr: RawAddress)2241     fn notify_media_capability_updated(&mut self, addr: RawAddress) {
2242         let mut guard = self.fallback_tasks.lock().unwrap();
2243         let mut states = self.device_states.lock().unwrap();
2244         let mut first_conn_ts = Instant::now();
2245 
2246         let is_profile_cleared = self.connected_profiles.get(&addr).unwrap().is_empty();
2247 
2248         if let Some(task) = guard.get(&addr) {
2249             if let Some((handler, ts)) = task {
2250                 // Abort the pending task. It may be updated or
2251                 // removed depending on whether all profiles are cleared.
2252                 handler.abort();
2253                 first_conn_ts = *ts;
2254                 guard.insert(addr, None);
2255             } else {
2256                 // The device is already added or is disconnecting.
2257                 // Ignore unless all profiles are cleared, where we need to do some clean up.
2258                 if !is_profile_cleared {
2259                     // Unbonded device is special, we need to reject the connection from them.
2260                     if !self.is_bonded(&addr) {
2261                         let tasks = self.fallback_tasks.clone();
2262                         let states = self.device_states.clone();
2263                         let txl = self.tx.clone();
2264                         let task = topstack::get_runtime().spawn(async move {
2265                             warn!(
2266                                 "[{}]: Rejecting an unbonded device's attempt to connect media",
2267                                 DisplayAddress(&addr)
2268                             );
2269                             BluetoothMedia::async_disconnect(&tasks, &states, &txl, &addr).await;
2270                         });
2271                         guard.insert(addr, Some((task, first_conn_ts)));
2272                     }
2273                     return;
2274                 }
2275             }
2276         }
2277 
2278         // Cleanup if transitioning to empty set.
2279         if is_profile_cleared {
2280             info!("[{}]: Device connection state: Disconnected.", DisplayAddress(&addr));
2281             self.connected_profiles.remove(&addr);
2282             states.remove(&addr);
2283             guard.remove(&addr);
2284             return;
2285         }
2286 
2287         let available_profiles = self.adapter_get_classic_audio_profiles(addr);
2288         let connected_profiles = self.connected_profiles.get(&addr).unwrap();
2289         let missing_profiles =
2290             available_profiles.difference(&connected_profiles).cloned().collect::<HashSet<_>>();
2291 
2292         // Update device states
2293         if states.get(&addr).is_none() {
2294             states.insert(addr, DeviceConnectionStates::ConnectingBeforeRetry);
2295         }
2296 
2297         if states.get(&addr).unwrap() != &DeviceConnectionStates::FullyConnected {
2298             if available_profiles.is_empty() {
2299                 // Some headsets may start initiating connections to audio profiles before they are
2300                 // exposed to the stack. In this case, wait for either all critical profiles have been
2301                 // connected or some timeout to enter the |FullyConnected| state.
2302                 if connected_profiles.contains(&Profile::Hfp)
2303                     && connected_profiles.contains(&Profile::A2dpSink)
2304                 {
2305                     info!(
2306                         "[{}]: Fully connected, available profiles: {:?}, connected profiles: {:?}.",
2307                         DisplayAddress(&addr),
2308                         available_profiles,
2309                         connected_profiles
2310                     );
2311 
2312                     states.insert(addr, DeviceConnectionStates::FullyConnected);
2313                 } else {
2314                     warn!(
2315                         "[{}]: Connected profiles: {:?}, waiting for peer to initiate remaining connections.",
2316                         DisplayAddress(&addr),
2317                         connected_profiles
2318                     );
2319 
2320                     states.insert(addr, DeviceConnectionStates::WaitingConnection);
2321                 }
2322             } else {
2323                 if missing_profiles.is_empty()
2324                     || missing_profiles == HashSet::from([Profile::AvrcpController])
2325                 {
2326                     info!(
2327                         "[{}]: Fully connected, available profiles: {:?}, connected profiles: {:?}.",
2328                         DisplayAddress(&addr),
2329                         available_profiles,
2330                         connected_profiles
2331                     );
2332 
2333                     states.insert(addr, DeviceConnectionStates::FullyConnected);
2334                 }
2335             }
2336         }
2337 
2338         info!(
2339             "[{}]: Device connection state: {:?}.",
2340             DisplayAddress(&addr),
2341             states.get(&addr).unwrap()
2342         );
2343 
2344         // React on updated device states
2345         let tasks = self.fallback_tasks.clone();
2346         let device_states = self.device_states.clone();
2347         let txl = self.tx.clone();
2348         let ts = first_conn_ts;
2349         let is_complete_profiles_required = self.is_complete_profiles_required();
2350         match states.get(&addr).unwrap() {
2351             DeviceConnectionStates::Initiating => {
2352                 let task = topstack::get_runtime().spawn(async move {
2353                     // As initiator we can just immediately start connecting
2354                     let _ = txl.send(Message::Media(MediaActions::Connect(addr))).await;
2355                     if !is_complete_profiles_required {
2356                         BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
2357                         return;
2358                     }
2359                     BluetoothMedia::wait_retry(&tasks, &device_states, &txl, &addr, ts).await;
2360                     BluetoothMedia::wait_disconnect(&tasks, &device_states, &txl, &addr, ts).await;
2361                 });
2362                 guard.insert(addr, Some((task, ts)));
2363             }
2364             DeviceConnectionStates::ConnectingBeforeRetry => {
2365                 let task = topstack::get_runtime().spawn(async move {
2366                     if !is_complete_profiles_required {
2367                         BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
2368                         return;
2369                     }
2370                     BluetoothMedia::wait_retry(&tasks, &device_states, &txl, &addr, ts).await;
2371                     BluetoothMedia::wait_disconnect(&tasks, &device_states, &txl, &addr, ts).await;
2372                 });
2373                 guard.insert(addr, Some((task, ts)));
2374             }
2375             DeviceConnectionStates::ConnectingAfterRetry => {
2376                 let task = topstack::get_runtime().spawn(async move {
2377                     if !is_complete_profiles_required {
2378                         BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
2379                         return;
2380                     }
2381                     BluetoothMedia::wait_disconnect(&tasks, &device_states, &txl, &addr, ts).await;
2382                 });
2383                 guard.insert(addr, Some((task, ts)));
2384             }
2385             DeviceConnectionStates::FullyConnected => {
2386                 // Rejecting the unbonded connection after we finished our profile
2387                 // reconnecting logic to avoid a collision.
2388                 if !self.is_bonded(&addr) {
2389                     warn!(
2390                         "[{}]: Rejecting a unbonded device's attempt to connect to media profiles",
2391                         DisplayAddress(&addr)
2392                     );
2393 
2394                     let task = topstack::get_runtime().spawn(async move {
2395                         BluetoothMedia::async_disconnect(&tasks, &device_states, &txl, &addr).await;
2396                     });
2397                     guard.insert(addr, Some((task, ts)));
2398                     return;
2399                 }
2400 
2401                 let cur_a2dp_caps = self.a2dp_caps.get(&addr);
2402                 let cur_hfp_cap = self.hfp_cap.get(&addr);
2403                 let name = self.adapter_get_remote_name(addr);
2404                 let absolute_volume = self.absolute_volume;
2405                 let device = BluetoothAudioDevice::new(
2406                     addr,
2407                     name.clone(),
2408                     cur_a2dp_caps.unwrap_or(&Vec::new()).to_vec(),
2409                     *cur_hfp_cap.unwrap_or(&HfpCodecFormat::NONE),
2410                     absolute_volume,
2411                 );
2412 
2413                 let hfp_volume = self.delay_volume_update.remove(&Profile::Hfp);
2414                 let avrcp_volume = self.delay_volume_update.remove(&Profile::AvrcpController);
2415 
2416                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
2417                     callback.on_bluetooth_audio_device_added(device.clone());
2418                     if let Some(volume) = hfp_volume {
2419                         info!("Trigger HFP volume update to {}", DisplayAddress(&addr));
2420                         callback.on_hfp_volume_changed(volume, addr);
2421                     }
2422 
2423                     if let Some(volume) = avrcp_volume {
2424                         info!("Trigger avrcp volume update");
2425                         callback.on_absolute_volume_changed(volume);
2426                     }
2427                 });
2428 
2429                 guard.insert(addr, None);
2430             }
2431             DeviceConnectionStates::Disconnecting => {}
2432             DeviceConnectionStates::WaitingConnection => {
2433                 let task = topstack::get_runtime().spawn(async move {
2434                     BluetoothMedia::wait_retry(&tasks, &device_states, &txl, &addr, ts).await;
2435                     BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
2436                 });
2437                 guard.insert(addr, Some((task, ts)));
2438             }
2439         }
2440     }
2441 
adapter_get_remote_name(&self, addr: RawAddress) -> String2442     fn adapter_get_remote_name(&self, addr: RawAddress) -> String {
2443         let device = BluetoothDevice::new(
2444             addr,
2445             // get_remote_name needs a BluetoothDevice just for its address, the
2446             // name field is unused so construct one with a fake name.
2447             "Classic Device".to_string(),
2448         );
2449         if let Some(adapter) = &self.adapter {
2450             match adapter.lock().unwrap().get_remote_name(device).as_str() {
2451                 "" => addr.to_string(),
2452                 name => name.into(),
2453             }
2454         } else {
2455             addr.to_string()
2456         }
2457     }
2458 
adapter_get_le_audio_profiles(&self, addr: RawAddress) -> HashSet<Profile>2459     fn adapter_get_le_audio_profiles(&self, addr: RawAddress) -> HashSet<Profile> {
2460         let device = BluetoothDevice::new(addr, "".to_string());
2461         if let Some(adapter) = &self.adapter {
2462             adapter
2463                 .lock()
2464                 .unwrap()
2465                 .get_remote_uuids(device)
2466                 .into_iter()
2467                 .filter_map(|u| UuidHelper::is_known_profile(&u))
2468                 .filter(|u| MEDIA_LE_AUDIO_PROFILES.contains(&u))
2469                 .collect()
2470         } else {
2471             HashSet::new()
2472         }
2473     }
2474 
adapter_get_classic_audio_profiles(&self, addr: RawAddress) -> HashSet<Profile>2475     fn adapter_get_classic_audio_profiles(&self, addr: RawAddress) -> HashSet<Profile> {
2476         let device = BluetoothDevice::new(addr, "".to_string());
2477         if let Some(adapter) = &self.adapter {
2478             adapter
2479                 .lock()
2480                 .unwrap()
2481                 .get_remote_uuids(device)
2482                 .into_iter()
2483                 .filter_map(|u| UuidHelper::is_known_profile(&u))
2484                 .filter(|u| MEDIA_CLASSIC_AUDIO_PROFILES.contains(&u))
2485                 .collect()
2486         } else {
2487             HashSet::new()
2488         }
2489     }
2490 
get_hfp_connection_state(&self) -> ProfileConnectionState2491     pub fn get_hfp_connection_state(&self) -> ProfileConnectionState {
2492         if self.hfp_audio_state.values().any(|state| *state == BthfAudioState::Connected) {
2493             ProfileConnectionState::Active
2494         } else {
2495             let mut winning_state = ProfileConnectionState::Disconnected;
2496             for state in self.hfp_states.values() {
2497                 // Grab any state higher than the current state.
2498                 match state {
2499                     // Any SLC completed state means the profile is connected.
2500                     BthfConnectionState::SlcConnected => {
2501                         winning_state = ProfileConnectionState::Connected;
2502                     }
2503 
2504                     // Connecting or Connected are both counted as connecting for profile state
2505                     // since it's not a complete connection.
2506                     BthfConnectionState::Connecting | BthfConnectionState::Connected
2507                         if winning_state != ProfileConnectionState::Connected =>
2508                     {
2509                         winning_state = ProfileConnectionState::Connecting;
2510                     }
2511 
2512                     BthfConnectionState::Disconnecting
2513                         if winning_state == ProfileConnectionState::Disconnected =>
2514                     {
2515                         winning_state = ProfileConnectionState::Disconnecting;
2516                     }
2517 
2518                     _ => (),
2519                 }
2520             }
2521 
2522             winning_state
2523         }
2524     }
2525 
get_a2dp_connection_state(&self) -> ProfileConnectionState2526     pub fn get_a2dp_connection_state(&self) -> ProfileConnectionState {
2527         if self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
2528             ProfileConnectionState::Active
2529         } else {
2530             let mut winning_state = ProfileConnectionState::Disconnected;
2531             for state in self.a2dp_states.values() {
2532                 // Grab any state higher than the current state.
2533                 match state {
2534                     BtavConnectionState::Connected => {
2535                         winning_state = ProfileConnectionState::Connected;
2536                     }
2537 
2538                     BtavConnectionState::Connecting
2539                         if winning_state != ProfileConnectionState::Connected =>
2540                     {
2541                         winning_state = ProfileConnectionState::Connecting;
2542                     }
2543 
2544                     BtavConnectionState::Disconnecting
2545                         if winning_state == ProfileConnectionState::Disconnected =>
2546                     {
2547                         winning_state = ProfileConnectionState::Disconnecting;
2548                     }
2549 
2550                     _ => (),
2551                 }
2552             }
2553 
2554             winning_state
2555         }
2556     }
2557 
filter_to_connected_audio_devices_from( &self, devices: &Vec<BluetoothDevice>, ) -> Vec<BluetoothDevice>2558     pub fn filter_to_connected_audio_devices_from(
2559         &self,
2560         devices: &Vec<BluetoothDevice>,
2561     ) -> Vec<BluetoothDevice> {
2562         devices
2563             .iter()
2564             .filter(|d| {
2565                 self.is_any_profile_connected(&d.address, &MEDIA_CLASSIC_AUDIO_PROFILES)
2566                     || self.is_any_profile_connected(&d.address, &MEDIA_LE_AUDIO_PROFILES)
2567             })
2568             .cloned()
2569             .collect()
2570     }
2571 
start_audio_request_impl(&mut self) -> bool2572     fn start_audio_request_impl(&mut self) -> bool {
2573         debug!("Start audio request");
2574 
2575         match self.a2dp.as_mut() {
2576             Some(a2dp) => a2dp.start_audio_request(),
2577             None => {
2578                 warn!("Uninitialized A2DP to start audio request");
2579                 false
2580             }
2581         }
2582     }
2583 
suspend_audio_request_impl(&mut self)2584     fn suspend_audio_request_impl(&mut self) {
2585         match self.a2dp.as_mut() {
2586             Some(a2dp) => a2dp.suspend_audio_request(),
2587             None => warn!("Uninitialized A2DP to suspend audio request"),
2588         };
2589     }
2590 
try_a2dp_resume(&mut self)2591     fn try_a2dp_resume(&mut self) {
2592         // Try resume the A2DP stream (per MPS v1.0) on rejecting an incoming call or an
2593         // outgoing call is rejected.
2594         // It may fail if a SCO connection is still active (terminate call case), in that
2595         // case we will retry on SCO disconnected.
2596         if !self.mps_qualification_enabled {
2597             return;
2598         }
2599         // Make sure there is no any SCO connection and then resume the A2DP stream.
2600         if self.a2dp_has_interrupted_stream
2601             && !self.hfp_audio_state.values().any(|state| *state == BthfAudioState::Connected)
2602         {
2603             self.a2dp_has_interrupted_stream = false;
2604             self.start_audio_request_impl();
2605         }
2606     }
2607 
try_a2dp_suspend(&mut self)2608     fn try_a2dp_suspend(&mut self) {
2609         // Try suspend the A2DP stream (per MPS v1.0) when receiving an incoming call
2610         if !self.mps_qualification_enabled {
2611             return;
2612         }
2613         // Suspend the A2DP stream if there is any.
2614         if self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
2615             self.a2dp_has_interrupted_stream = true;
2616             self.suspend_audio_request_impl();
2617         }
2618     }
2619 
start_sco_call_impl( &mut self, addr: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, ) -> bool2620     fn start_sco_call_impl(
2621         &mut self,
2622         addr: RawAddress,
2623         sco_offload: bool,
2624         disabled_codecs: HfpCodecBitId,
2625     ) -> bool {
2626         match (|| -> Result<(), &str> {
2627             info!("Start sco call for {}", DisplayAddress(&addr));
2628 
2629             let hfp = self.hfp.as_mut().ok_or("Uninitialized HFP to start the sco call")?;
2630             let disabled_codecs = disabled_codecs.try_into().expect("Can't parse disabled_codecs");
2631             if hfp.connect_audio(addr, sco_offload, disabled_codecs) != 0 {
2632                 return Err("SCO connect_audio status failed");
2633             }
2634             info!("SCO connect_audio status success");
2635             Ok(())
2636         })() {
2637             Ok(_) => true,
2638             Err(msg) => {
2639                 warn!("{}", msg);
2640                 false
2641             }
2642         }
2643     }
2644 
stop_sco_call_impl(&mut self, addr: RawAddress)2645     fn stop_sco_call_impl(&mut self, addr: RawAddress) {
2646         info!("Stop sco call for {}", DisplayAddress(&addr));
2647         if let Some(hfp) = self.hfp.as_mut() {
2648             hfp.disconnect_audio(addr);
2649         } else {
2650             warn!("Uninitialized HFP to stop the sco call");
2651         }
2652     }
2653 
device_status_notification(&mut self)2654     fn device_status_notification(&mut self) {
2655         match self.hfp.as_mut() {
2656             Some(hfp) => {
2657                 for (addr, state) in self.hfp_states.iter() {
2658                     if *state != BthfConnectionState::SlcConnected {
2659                         continue;
2660                     }
2661                     debug!(
2662                         "[{}]: Device status notification {:?}",
2663                         DisplayAddress(addr),
2664                         self.telephony_device_status
2665                     );
2666                     let status =
2667                         hfp.device_status_notification(self.telephony_device_status, *addr);
2668                     if status != BtStatus::Success {
2669                         warn!(
2670                             "[{}]: Device status notification failed, status={:?}",
2671                             DisplayAddress(addr),
2672                             status
2673                         );
2674                     }
2675                 }
2676             }
2677             None => warn!("Uninitialized HFP to notify telephony status"),
2678         }
2679     }
2680 
phone_state_change(&mut self, number: String)2681     fn phone_state_change(&mut self, number: String) {
2682         match self.hfp.as_mut() {
2683             Some(hfp) => {
2684                 for (addr, state) in self.hfp_states.iter() {
2685                     if *state != BthfConnectionState::SlcConnected {
2686                         continue;
2687                     }
2688                     debug!(
2689                         "[{}]: Phone state change state={:?} number={}",
2690                         DisplayAddress(addr),
2691                         self.phone_state,
2692                         number
2693                     );
2694                     let status = hfp.phone_state_change(self.phone_state, &number, *addr);
2695                     if status != BtStatus::Success {
2696                         warn!(
2697                             "[{}]: Device status notification failed, status={:?}",
2698                             DisplayAddress(addr),
2699                             status
2700                         );
2701                     }
2702                 }
2703             }
2704             None => warn!("Uninitialized HFP to notify telephony status"),
2705         }
2706     }
2707 
2708     // Returns the minimum unoccupied index starting from 1.
new_call_index(&self) -> i322709     fn new_call_index(&self) -> i32 {
2710         (1..)
2711             .find(|&index| self.call_list.iter().all(|x| x.index != index))
2712             .expect("There must be an unoccupied index")
2713     }
2714 
simple_at_response(&mut self, ok: bool, addr: RawAddress)2715     fn simple_at_response(&mut self, ok: bool, addr: RawAddress) {
2716         match self.hfp.as_mut() {
2717             Some(hfp) => {
2718                 let status = hfp.simple_at_response(ok, addr);
2719                 if status != BtStatus::Success {
2720                     warn!("[{}]: AT response failed, status={:?}", DisplayAddress(&addr), status);
2721                 }
2722             }
2723             None => warn!("Uninitialized HFP to send AT response"),
2724         }
2725     }
2726 
incoming_call_impl(&mut self, number: String) -> bool2727     fn incoming_call_impl(&mut self, number: String) -> bool {
2728         if self.phone_state.state != CallState::Idle {
2729             return false;
2730         }
2731 
2732         if self.phone_state.num_active > 0 {
2733             return false;
2734         }
2735 
2736         self.call_list.push(CallInfo {
2737             index: self.new_call_index(),
2738             dir_incoming: true,
2739             state: CallState::Incoming,
2740             number: number.clone(),
2741         });
2742         self.phone_state.state = CallState::Incoming;
2743         self.phone_state_change(number);
2744         self.try_a2dp_suspend();
2745         true
2746     }
2747 
answer_call_impl(&mut self) -> bool2748     fn answer_call_impl(&mut self) -> bool {
2749         if self.phone_state.state == CallState::Idle {
2750             return false;
2751         }
2752         // There must be exactly one incoming/dialing call in the list.
2753         for c in self.call_list.iter_mut() {
2754             match c.state {
2755                 CallState::Incoming | CallState::Dialing | CallState::Alerting => {
2756                     c.state = CallState::Active;
2757                     break;
2758                 }
2759                 _ => {}
2760             }
2761         }
2762         self.phone_state.state = CallState::Idle;
2763         self.phone_state.num_active += 1;
2764 
2765         self.phone_state_change("".into());
2766 
2767         if self.mps_qualification_enabled {
2768             // Find a connected HFP and try to establish an SCO.
2769             if let Some(addr) = self.hfp_states.iter().find_map(|(addr, state)| {
2770                 if *state == BthfConnectionState::SlcConnected {
2771                     Some(addr)
2772                 } else {
2773                     None
2774                 }
2775             }) {
2776                 info!("Start SCO call due to call answered");
2777                 self.start_sco_call_impl(*addr, false, HfpCodecBitId::NONE);
2778             }
2779         }
2780 
2781         true
2782     }
2783 
hangup_call_impl(&mut self) -> bool2784     fn hangup_call_impl(&mut self) -> bool {
2785         if !self.phone_ops_enabled && !self.mps_qualification_enabled {
2786             return false;
2787         }
2788 
2789         match self.phone_state.state {
2790             CallState::Idle if self.phone_state.num_active > 0 => {
2791                 self.phone_state.num_active -= 1;
2792             }
2793             CallState::Incoming | CallState::Dialing | CallState::Alerting => {
2794                 self.phone_state.state = CallState::Idle;
2795             }
2796             _ => return false,
2797         }
2798         // At this point, there must be exactly one incoming/dialing/alerting/active call to be
2799         // removed.
2800         self.call_list.retain(|x| match x.state {
2801             CallState::Active | CallState::Incoming | CallState::Dialing | CallState::Alerting => {
2802                 false
2803             }
2804             _ => true,
2805         });
2806 
2807         self.phone_state_change("".into());
2808         self.try_a2dp_resume();
2809 
2810         true
2811     }
2812 
dialing_call_impl(&mut self, number: String, addr: Option<RawAddress>) -> bool2813     fn dialing_call_impl(&mut self, number: String, addr: Option<RawAddress>) -> bool {
2814         if self.phone_state.num_active > 0 || self.phone_state.state != CallState::Idle {
2815             if let Some(addr) = addr {
2816                 self.simple_at_response(false, addr);
2817                 warn!("[{}]: Unexpected dialing command from HF", DisplayAddress(&addr));
2818             }
2819             return false;
2820         }
2821 
2822         self.call_list.push(CallInfo {
2823             index: self.new_call_index(),
2824             dir_incoming: false,
2825             state: CallState::Dialing,
2826             number: number.clone(),
2827         });
2828         self.phone_state.state = CallState::Dialing;
2829 
2830         if let Some(addr) = addr {
2831             self.simple_at_response(true, addr);
2832             warn!("[{}]: Unexpected dialing command from HF", DisplayAddress(&addr));
2833         }
2834 
2835         // Inform libbluetooth that the state has changed to dialing.
2836         self.phone_state_change("".into());
2837         self.try_a2dp_suspend();
2838         // Change to alerting state and inform libbluetooth.
2839         self.dialing_to_alerting();
2840         true
2841     }
2842 
dialing_to_alerting(&mut self) -> bool2843     fn dialing_to_alerting(&mut self) -> bool {
2844         if !(self.phone_ops_enabled || self.mps_qualification_enabled)
2845             || self.phone_state.state != CallState::Dialing
2846         {
2847             return false;
2848         }
2849         for c in self.call_list.iter_mut() {
2850             if c.state == CallState::Dialing {
2851                 c.state = CallState::Alerting;
2852                 break;
2853             }
2854         }
2855         self.phone_state.state = CallState::Alerting;
2856         self.phone_state_change("".into());
2857         true
2858     }
2859 
release_held_impl(&mut self, addr: Option<RawAddress>) -> bool2860     fn release_held_impl(&mut self, addr: Option<RawAddress>) -> bool {
2861         if self.phone_state.state != CallState::Idle {
2862             if let Some(addr) = addr {
2863                 // Respond ERROR to the HF which sent the command.
2864                 self.simple_at_response(false, addr);
2865             }
2866             return false;
2867         }
2868         self.call_list.retain(|x| x.state != CallState::Held);
2869         self.phone_state.num_held = 0;
2870 
2871         if let Some(addr) = addr {
2872             // This should be called before calling phone_state_change.
2873             self.simple_at_response(true, addr);
2874         }
2875         // Success means the call state has changed. Inform libbluetooth.
2876         self.phone_state_change("".into());
2877         true
2878     }
2879 
release_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool2880     fn release_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool {
2881         self.call_list.retain(|x| x.state != CallState::Active);
2882         self.phone_state.num_active = 0;
2883         // Activate the first held call
2884         if self.phone_state.state != CallState::Idle {
2885             if let Some(addr) = addr {
2886                 // Respond ERROR to the HF which sent the command.
2887                 self.simple_at_response(false, addr);
2888             }
2889             return false;
2890         }
2891         for c in self.call_list.iter_mut() {
2892             if c.state == CallState::Held {
2893                 c.state = CallState::Active;
2894                 self.phone_state.num_held -= 1;
2895                 self.phone_state.num_active += 1;
2896                 break;
2897             }
2898         }
2899         if let Some(addr) = addr {
2900             // This should be called before calling phone_state_change.
2901             self.simple_at_response(true, addr);
2902         }
2903         // Success means the call state has changed. Inform libbluetooth.
2904         self.phone_state_change("".into());
2905         true
2906     }
2907 
hold_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool2908     fn hold_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool {
2909         if self.phone_state.state != CallState::Idle {
2910             if let Some(addr) = addr {
2911                 // Respond ERROR to the HF which sent the command.
2912                 self.simple_at_response(false, addr);
2913             }
2914             return false;
2915         }
2916         self.phone_state.num_held += self.phone_state.num_active;
2917         self.phone_state.num_active = 0;
2918 
2919         for c in self.call_list.iter_mut() {
2920             match c.state {
2921                 // Activate at most one held call
2922                 CallState::Held if self.phone_state.num_active == 0 => {
2923                     c.state = CallState::Active;
2924                     self.phone_state.num_held -= 1;
2925                     self.phone_state.num_active = 1;
2926                 }
2927                 CallState::Active => {
2928                     c.state = CallState::Held;
2929                 }
2930                 _ => {}
2931             }
2932         }
2933         if let Some(addr) = addr {
2934             // This should be called before calling phone_state_change.
2935             self.simple_at_response(true, addr);
2936         }
2937         // Success means the call state has changed. Inform libbluetooth.
2938         self.phone_state_change("".into());
2939         true
2940     }
2941 
2942     // Per MPS v1.0 (Multi-Profile Specification), disconnecting or failing to connect
2943     // a profile should not affect the others.
2944     // Allow partial profiles connection during qualification (MPS qualification mode is enabled).
is_complete_profiles_required(&self) -> bool2945     fn is_complete_profiles_required(&self) -> bool {
2946         !self.mps_qualification_enabled
2947     }
2948 
2949     // Force the media enters the FullyConnected state and then triggers a retry.
2950     // When this function is used for qualification as a replacement of normal retry,
2951     // PTS could initiate the connection of the necessary profiles, and Floss should
2952     // notify CRAS of the new audio device regardless of the unconnected profiles.
2953     // Still retry in the end because some test cases require that.
force_enter_connected(&mut self, addr: RawAddress)2954     fn force_enter_connected(&mut self, addr: RawAddress) {
2955         self.device_states.lock().unwrap().insert(addr, DeviceConnectionStates::FullyConnected);
2956         self.notify_media_capability_updated(addr);
2957         self.connect(addr);
2958     }
add_player(&mut self, name: String, browsing_supported: bool)2959     pub fn add_player(&mut self, name: String, browsing_supported: bool) {
2960         self.avrcp.as_mut().unwrap().add_player(&name, browsing_supported);
2961     }
2962 
2963     // This function determines if it's safe to send a +CIEV command to an HFP device when SCO starts.
2964 
2965     // The +CIEV command should NOT be sent if:
2966     //  - MPS qualification mode is enabled, as it may cause qualification failures.
2967     //  - Uhid device is open, as it may conflict with ongoing telephony operations.
2968 
2969     // The +CIEV command is safe to send if:
2970     //  - Both MPS qualification and Bluetooth telephony are disabled.
2971     //  - Uhid device is closed, preventing any telephony conflicts.
2972     //  - The headset is listed in interop_database.conf, indicating it requires +CIEV for audio.
should_insert_call_when_sco_start(&self, address: RawAddress) -> bool2973     fn should_insert_call_when_sco_start(&self, address: RawAddress) -> bool {
2974         if self.mps_qualification_enabled {
2975             return false;
2976         }
2977         if !self.phone_ops_enabled {
2978             return true;
2979         }
2980 
2981         match self.uhid.get(&address) {
2982             Some(uhid) => {
2983                 if !uhid.is_open {
2984                     return true;
2985                 }
2986             }
2987             None => {
2988                 return true;
2989             }
2990         };
2991 
2992         return interop_insert_call_when_sco_start(address);
2993     }
2994     // Places an active call into the call list and triggers a headset update (+CIEV).
2995     // Preconditions:
2996     //   - No active calls in progress (phone_state.num_active == 0)
2997     //   - Phone state is idle (phone_state.state == CallState::Idle)
place_active_call(&mut self)2998     fn place_active_call(&mut self) {
2999         if self.phone_state.num_active != 0 {
3000             warn!("Unexpected usage. phone_state.num_active can only be 0 when calling place_active_call");
3001             return;
3002         }
3003 
3004         if self.phone_state.state != CallState::Idle {
3005             warn!("Unexpected usage. phone_state.state can only be idle when calling place_active_call");
3006             return;
3007         }
3008 
3009         self.call_list.push(CallInfo {
3010             index: 1,
3011             dir_incoming: false,
3012             state: CallState::Active,
3013             number: "".into(),
3014         });
3015         self.phone_state.num_active = 1;
3016         self.phone_state_change("".into());
3017     }
3018 
get_group_devices(&self, group_id: i32) -> HashSet<RawAddress>3019     pub fn get_group_devices(&self, group_id: i32) -> HashSet<RawAddress> {
3020         match self.le_audio_groups.get(&group_id) {
3021             Some(g) => g.devices.clone(),
3022             _ => HashSet::new(),
3023         }
3024     }
3025 
get_group_id(&self, addr: RawAddress) -> i323026     pub fn get_group_id(&self, addr: RawAddress) -> i32 {
3027         *self.le_audio_node_to_group.get(&addr).unwrap_or(&LEA_UNKNOWN_GROUP_ID)
3028     }
3029 }
3030 
get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher3031 fn get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher {
3032     A2dpCallbacksDispatcher {
3033         dispatch: Box::new(move |cb| {
3034             let txl = tx.clone();
3035             topstack::get_runtime().spawn(async move {
3036                 let _ = txl.send(Message::A2dp(cb)).await;
3037             });
3038         }),
3039     }
3040 }
3041 
get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher3042 fn get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher {
3043     AvrcpCallbacksDispatcher {
3044         dispatch: Box::new(move |cb| {
3045             let txl = tx.clone();
3046             topstack::get_runtime().spawn(async move {
3047                 let _ = txl.send(Message::Avrcp(cb)).await;
3048             });
3049         }),
3050     }
3051 }
3052 
get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher3053 fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher {
3054     HfpCallbacksDispatcher {
3055         dispatch: Box::new(move |cb| {
3056             let txl = tx.clone();
3057             topstack::get_runtime().spawn(async move {
3058                 let _ = txl.send(Message::Hfp(cb)).await;
3059             });
3060         }),
3061     }
3062 }
3063 
get_le_audio_dispatcher(tx: Sender<Message>) -> LeAudioClientCallbacksDispatcher3064 fn get_le_audio_dispatcher(tx: Sender<Message>) -> LeAudioClientCallbacksDispatcher {
3065     LeAudioClientCallbacksDispatcher {
3066         dispatch: Box::new(move |cb| {
3067             let txl = tx.clone();
3068             topstack::get_runtime().spawn(async move {
3069                 let _ = txl.send(Message::LeAudioClient(cb)).await;
3070             });
3071         }),
3072     }
3073 }
3074 
get_vc_dispatcher(tx: Sender<Message>) -> VolumeControlCallbacksDispatcher3075 fn get_vc_dispatcher(tx: Sender<Message>) -> VolumeControlCallbacksDispatcher {
3076     VolumeControlCallbacksDispatcher {
3077         dispatch: Box::new(move |cb| {
3078             let txl = tx.clone();
3079             topstack::get_runtime().spawn(async move {
3080                 let _ = txl.send(Message::VolumeControl(cb)).await;
3081             });
3082         }),
3083     }
3084 }
3085 
get_csis_dispatcher(tx: Sender<Message>) -> CsisClientCallbacksDispatcher3086 fn get_csis_dispatcher(tx: Sender<Message>) -> CsisClientCallbacksDispatcher {
3087     CsisClientCallbacksDispatcher {
3088         dispatch: Box::new(move |cb| {
3089             let txl = tx.clone();
3090             topstack::get_runtime().spawn(async move {
3091                 let _ = txl.send(Message::CsisClient(cb)).await;
3092             });
3093         }),
3094     }
3095 }
3096 
3097 impl IBluetoothMedia for BluetoothMedia {
register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool3098     fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool {
3099         let _id = self.callbacks.lock().unwrap().add_callback(callback);
3100         true
3101     }
3102 
initialize(&mut self) -> bool3103     fn initialize(&mut self) -> bool {
3104         if self.initialized {
3105             return false;
3106         }
3107         self.initialized = true;
3108 
3109         self.is_le_audio_only_enabled =
3110             features::is_feature_enabled("CrOSLateBootBluetoothAudioLEAudioOnly").unwrap_or(false);
3111 
3112         // A2DP
3113         let a2dp_dispatcher = get_a2dp_dispatcher(self.tx.clone());
3114         self.a2dp = Some(A2dp::new(&self.intf.lock().unwrap()));
3115         self.a2dp.as_mut().unwrap().initialize(a2dp_dispatcher);
3116 
3117         // AVRCP
3118         let avrcp_dispatcher = get_avrcp_dispatcher(self.tx.clone());
3119         self.avrcp = Some(Avrcp::new(&self.intf.lock().unwrap()));
3120         self.avrcp.as_mut().unwrap().initialize(avrcp_dispatcher);
3121 
3122         // HFP
3123         let hfp_dispatcher = get_hfp_dispatcher(self.tx.clone());
3124         self.hfp = Some(Hfp::new(&self.intf.lock().unwrap()));
3125         self.hfp.as_mut().unwrap().initialize(hfp_dispatcher);
3126 
3127         // LEA
3128         let le_audio_dispatcher = get_le_audio_dispatcher(self.tx.clone());
3129         self.le_audio = Some(LeAudioClient::new(&self.intf.lock().unwrap()));
3130         self.le_audio.as_mut().unwrap().initialize(le_audio_dispatcher);
3131 
3132         // VC
3133         let vc_dispatcher = get_vc_dispatcher(self.tx.clone());
3134         self.vc = Some(VolumeControl::new(&self.intf.lock().unwrap()));
3135         self.vc.as_mut().unwrap().initialize(vc_dispatcher);
3136 
3137         // CSIS
3138         let csis_dispatcher = get_csis_dispatcher(self.tx.clone());
3139         self.csis = Some(CsisClient::new(&self.intf.lock().unwrap()));
3140         self.csis.as_mut().unwrap().initialize(csis_dispatcher);
3141 
3142         // TODO(b/284811956) A2DP needs to be enabled before AVRCP otherwise AVRCP gets memset'd.
3143         // Iterate the delay_enable_profiles hashmap directly when this is fixed.
3144         let profile_order = vec![
3145             Profile::A2dpSource,
3146             Profile::AvrcpTarget,
3147             Profile::Hfp,
3148             Profile::LeAudio,
3149             Profile::VolumeControl,
3150             Profile::CoordinatedSet,
3151         ];
3152         for profile in profile_order {
3153             if self.delay_enable_profiles.contains(&profile) {
3154                 self.enable_profile(&profile);
3155             }
3156         }
3157         true
3158     }
3159 
connect_lea_group_by_member_address(&mut self, addr: RawAddress)3160     fn connect_lea_group_by_member_address(&mut self, addr: RawAddress) {
3161         // Note that at this point the scanning of profiles may be incomplete,
3162         // TODO(b/335780769): connect to available profiles and ensure
3163         // this function is invoked whenever there is an incremental
3164         // discovery of LE audio profiles.
3165         for profile in MEDIA_LE_AUDIO_PROFILES {
3166             match profile {
3167                 Profile::LeAudio => {
3168                     self.connect_lea(addr);
3169                 }
3170                 Profile::VolumeControl => {
3171                     self.connect_vc(addr);
3172                 }
3173                 Profile::CoordinatedSet => {
3174                     self.connect_csis(addr);
3175                 }
3176                 _ => {}
3177             }
3178         }
3179     }
3180 
disconnect_lea_group_by_member_address(&mut self, addr: RawAddress)3181     fn disconnect_lea_group_by_member_address(&mut self, addr: RawAddress) {
3182         let group_id = self.get_group_id(addr);
3183         if group_id == LEA_UNKNOWN_GROUP_ID {
3184             warn!(
3185                 "disconnect_lea_group_by_member_address: [{}]: address belongs to no group",
3186                 DisplayAddress(&addr)
3187             );
3188             return;
3189         }
3190 
3191         let group = self.le_audio_groups.entry(group_id).or_default().clone();
3192 
3193         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3194 
3195         info!(
3196             "disconnect_lea_group_by_member_address: [{}]: available profiles: {:?}.",
3197             DisplayAddress(&addr),
3198             available_profiles
3199         );
3200 
3201         for &member_addr in group.devices.iter() {
3202             for profile in self.adapter_get_le_audio_profiles(addr) {
3203                 match profile {
3204                     Profile::LeAudio => {
3205                         self.disconnect_lea(member_addr);
3206                     }
3207                     Profile::VolumeControl => {
3208                         self.disconnect_vc(member_addr);
3209                     }
3210                     Profile::CoordinatedSet => {
3211                         self.disconnect_csis(member_addr);
3212                     }
3213                     _ => {}
3214                 }
3215             }
3216         }
3217     }
3218 
connect_lea(&mut self, addr: RawAddress)3219     fn connect_lea(&mut self, addr: RawAddress) {
3220         if !self.is_le_audio_only_enabled {
3221             warn!("connect_lea: LeAudioEnableLeAudioOnly is not set");
3222             return;
3223         }
3224 
3225         if *self.le_audio_states.get(&addr).unwrap_or(&BtLeAudioConnectionState::Disconnected)
3226             == BtLeAudioConnectionState::Connected
3227         {
3228             info!("connect_lea: already connected.");
3229             return;
3230         }
3231 
3232         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3233 
3234         info!(
3235             "connect_lea: [{}]: connecting, available profiles: {:?}.",
3236             DisplayAddress(&addr),
3237             available_profiles
3238         );
3239 
3240         match self.le_audio.as_mut() {
3241             Some(le_audio) => {
3242                 le_audio.set_enable_state(addr, true);
3243                 le_audio.connect(addr);
3244             }
3245             None => {
3246                 warn!("connect_lea: [{}]: uninitialized LeAudio to connect", DisplayAddress(&addr));
3247             }
3248         };
3249     }
3250 
disconnect_lea(&mut self, addr: RawAddress)3251     fn disconnect_lea(&mut self, addr: RawAddress) {
3252         if *self.le_audio_states.get(&addr).unwrap_or(&BtLeAudioConnectionState::Disconnected)
3253             == BtLeAudioConnectionState::Disconnected
3254         {
3255             info!("disconnect_lea: [{}]: already disconnected", DisplayAddress(&addr));
3256             return;
3257         }
3258 
3259         info!("disconnect_lea: [{}]: disconnecting", DisplayAddress(&addr));
3260 
3261         match self.le_audio.as_mut() {
3262             Some(le_audio) => {
3263                 le_audio.set_enable_state(addr, false);
3264                 le_audio.disconnect(addr);
3265             }
3266             None => {
3267                 warn!(
3268                     "disconnect_lea: [{}]: uninitialized LeAudio to disconnect",
3269                     DisplayAddress(&addr)
3270                 );
3271             }
3272         };
3273     }
3274 
connect_vc(&mut self, addr: RawAddress)3275     fn connect_vc(&mut self, addr: RawAddress) {
3276         if !self.is_le_audio_only_enabled {
3277             warn!("connect_vc: LeAudioEnableLeAudioOnly is not set");
3278             return;
3279         }
3280 
3281         if *self.vc_states.get(&addr).unwrap_or(&BtVcConnectionState::Disconnected)
3282             == BtVcConnectionState::Connected
3283         {
3284             info!("connect_vc: already connected");
3285             return;
3286         }
3287 
3288         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3289 
3290         info!(
3291             "connect_vc: [{}]: connecting, available profiles: {:?}.",
3292             DisplayAddress(&addr),
3293             available_profiles
3294         );
3295 
3296         match self.vc.as_mut() {
3297             Some(vc) => {
3298                 vc.connect(addr);
3299             }
3300             None => {
3301                 warn!("connect_vc: [{}]: uninitialized VC to connect", DisplayAddress(&addr));
3302             }
3303         };
3304     }
3305 
disconnect_vc(&mut self, addr: RawAddress)3306     fn disconnect_vc(&mut self, addr: RawAddress) {
3307         if *self.vc_states.get(&addr).unwrap_or(&BtVcConnectionState::Disconnected)
3308             == BtVcConnectionState::Disconnected
3309         {
3310             info!("disconnect_vc: already disconnected");
3311             return;
3312         }
3313 
3314         info!("disconnect_vc: [{}]: disconnecting", DisplayAddress(&addr));
3315 
3316         match self.vc.as_mut() {
3317             Some(vc) => {
3318                 vc.disconnect(addr);
3319             }
3320             None => {
3321                 warn!("disconnect_vc: [{}]: uninitialized VC to disconnect", DisplayAddress(&addr));
3322             }
3323         };
3324     }
3325 
connect_csis(&mut self, addr: RawAddress)3326     fn connect_csis(&mut self, addr: RawAddress) {
3327         if !self.is_le_audio_only_enabled {
3328             warn!("connect_csis: LeAudioEnableLeAudioOnly is not set");
3329             return;
3330         }
3331 
3332         if *self.csis_states.get(&addr).unwrap_or(&BtCsisConnectionState::Disconnected)
3333             == BtCsisConnectionState::Connected
3334         {
3335             info!("connect_csis: already connected");
3336             return;
3337         }
3338 
3339         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3340 
3341         info!(
3342             "connect_csis: [{}]: connecting, available profiles: {:?}.",
3343             DisplayAddress(&addr),
3344             available_profiles
3345         );
3346 
3347         match self.csis.as_mut() {
3348             Some(csis) => {
3349                 csis.connect(addr);
3350             }
3351             None => {
3352                 warn!("connect_csis: [{}]: uninitialized Csis to connect", DisplayAddress(&addr));
3353             }
3354         };
3355     }
3356 
disconnect_csis(&mut self, addr: RawAddress)3357     fn disconnect_csis(&mut self, addr: RawAddress) {
3358         if *self.csis_states.get(&addr).unwrap_or(&BtCsisConnectionState::Disconnected)
3359             == BtCsisConnectionState::Disconnected
3360         {
3361             info!("disconnect_csis: already disconnected");
3362             return;
3363         }
3364 
3365         info!("disconnect_csis: [{}]: disconnecting", DisplayAddress(&addr));
3366 
3367         match self.csis.as_mut() {
3368             Some(csis) => {
3369                 csis.disconnect(addr);
3370             }
3371             None => {
3372                 warn!(
3373                     "disconnect_csis: [{}]: uninitialized CSIS to disconnect",
3374                     DisplayAddress(&addr)
3375                 );
3376             }
3377         };
3378     }
3379 
connect(&mut self, addr: RawAddress)3380     fn connect(&mut self, addr: RawAddress) {
3381         if self.is_le_audio_only_enabled {
3382             warn!("connect: LeAudioEnableLeAudioOnly is set");
3383             return;
3384         }
3385 
3386         let available_profiles = self.adapter_get_classic_audio_profiles(addr);
3387 
3388         info!(
3389             "[{}]: Connecting to device, available profiles: {:?}.",
3390             DisplayAddress(&addr),
3391             available_profiles
3392         );
3393 
3394         let connected_profiles = self.connected_profiles.entry(addr).or_insert_with(HashSet::new);
3395 
3396         // Sort here so the order of connection is always consistent
3397         let missing_profiles =
3398             available_profiles.difference(&connected_profiles).sorted().collect::<Vec<_>>();
3399 
3400         // Connect the profiles one-by-one so it won't stuck at the lower layer.
3401         // Therefore, just connect to one profile for now.
3402         // connect() will be called again after the first profile is successfully connected.
3403         let mut is_connect = false;
3404         for profile in missing_profiles {
3405             match profile {
3406                 Profile::A2dpSink => {
3407                     metrics::profile_connection_state_changed(
3408                         addr,
3409                         Profile::A2dpSink as u32,
3410                         BtStatus::Success,
3411                         BtavConnectionState::Connecting as u32,
3412                     );
3413                     match self.a2dp.as_mut() {
3414                         Some(a2dp) => {
3415                             let status: BtStatus = a2dp.connect(addr);
3416                             if BtStatus::Success != status {
3417                                 metrics::profile_connection_state_changed(
3418                                     addr,
3419                                     Profile::A2dpSink as u32,
3420                                     status,
3421                                     BtavConnectionState::Disconnected as u32,
3422                                 );
3423                             } else {
3424                                 is_connect = true;
3425                                 break;
3426                             }
3427                         }
3428                         None => {
3429                             warn!("Uninitialized A2DP to connect {}", DisplayAddress(&addr));
3430                             metrics::profile_connection_state_changed(
3431                                 addr,
3432                                 Profile::A2dpSink as u32,
3433                                 BtStatus::NotReady,
3434                                 BtavConnectionState::Disconnected as u32,
3435                             );
3436                         }
3437                     };
3438                 }
3439                 Profile::Hfp => {
3440                     metrics::profile_connection_state_changed(
3441                         addr,
3442                         Profile::Hfp as u32,
3443                         BtStatus::Success,
3444                         BtavConnectionState::Connecting as u32,
3445                     );
3446                     match self.hfp.as_mut() {
3447                         Some(hfp) => {
3448                             let status: BtStatus = hfp.connect(addr);
3449                             if BtStatus::Success != status {
3450                                 metrics::profile_connection_state_changed(
3451                                     addr,
3452                                     Profile::Hfp as u32,
3453                                     status,
3454                                     BthfConnectionState::Disconnected as u32,
3455                                 );
3456                             } else {
3457                                 is_connect = true;
3458                                 break;
3459                             }
3460                         }
3461                         None => {
3462                             warn!("Uninitialized HFP to connect {}", DisplayAddress(&addr));
3463                             metrics::profile_connection_state_changed(
3464                                 addr,
3465                                 Profile::Hfp as u32,
3466                                 BtStatus::NotReady,
3467                                 BthfConnectionState::Disconnected as u32,
3468                             );
3469                         }
3470                     };
3471                 }
3472                 Profile::AvrcpController => {
3473                     // Fluoride will resolve AVRCP as a part of A2DP connection request.
3474                     // Explicitly connect to it only when it is considered missing, and don't
3475                     // bother about it when A2DP is not connected.
3476                     if !connected_profiles.contains(&Profile::A2dpSink) {
3477                         continue;
3478                     }
3479 
3480                     metrics::profile_connection_state_changed(
3481                         addr,
3482                         Profile::AvrcpController as u32,
3483                         BtStatus::Success,
3484                         BtavConnectionState::Connecting as u32,
3485                     );
3486                     match self.avrcp.as_mut() {
3487                         Some(avrcp) => {
3488                             self.avrcp_direction = BtConnectionDirection::Outgoing;
3489                             let status: BtStatus = avrcp.connect(addr);
3490                             if BtStatus::Success != status {
3491                                 // Reset direction to unknown.
3492                                 self.avrcp_direction = BtConnectionDirection::Unknown;
3493                                 metrics::profile_connection_state_changed(
3494                                     addr,
3495                                     Profile::AvrcpController as u32,
3496                                     status,
3497                                     BtavConnectionState::Disconnected as u32,
3498                                 );
3499                             } else {
3500                                 is_connect = true;
3501                                 break;
3502                             }
3503                         }
3504 
3505                         None => {
3506                             warn!("Uninitialized AVRCP to connect {}", DisplayAddress(&addr));
3507                             metrics::profile_connection_state_changed(
3508                                 addr,
3509                                 Profile::AvrcpController as u32,
3510                                 BtStatus::NotReady,
3511                                 BtavConnectionState::Disconnected as u32,
3512                             );
3513                         }
3514                     };
3515                 }
3516                 _ => warn!("Unknown profile: {:?}", profile),
3517             }
3518         }
3519 
3520         if is_connect {
3521             let mut tasks = self.fallback_tasks.lock().unwrap();
3522             let mut states = self.device_states.lock().unwrap();
3523             if !tasks.contains_key(&addr) {
3524                 states.insert(addr, DeviceConnectionStates::Initiating);
3525 
3526                 let fallback_tasks = self.fallback_tasks.clone();
3527                 let device_states = self.device_states.clone();
3528                 let now_ts = Instant::now();
3529                 let task = topstack::get_runtime().spawn(async move {
3530                     sleep(Duration::from_secs(CONNECT_AS_INITIATOR_TIMEOUT_SEC)).await;
3531 
3532                     // If here the task is not yet aborted, probably connection is failed,
3533                     // therefore here we release the states. Even if later the connection is
3534                     // actually successful, we will just treat this as if the connection is
3535                     // initiated by the peer and will reconnect the missing profiles after
3536                     // some time, so it's safe.
3537                     {
3538                         device_states.lock().unwrap().remove(&addr);
3539                         fallback_tasks.lock().unwrap().remove(&addr);
3540                     }
3541                 });
3542                 tasks.insert(addr, Some((task, now_ts)));
3543             }
3544         }
3545     }
3546 
cleanup(&mut self) -> bool3547     fn cleanup(&mut self) -> bool {
3548         true
3549     }
3550 
3551     // This may not disconnect all media profiles at once, but once the stack
3552     // is notified of the disconnection callback, `disconnect_device` will be
3553     // invoked as necessary to ensure the device is removed.
disconnect(&mut self, addr: RawAddress)3554     fn disconnect(&mut self, addr: RawAddress) {
3555         if self.is_le_audio_only_enabled {
3556             warn!("LeAudioEnableLeAudioOnly is set");
3557             return;
3558         }
3559 
3560         let connected_profiles = match self.connected_profiles.get(&addr) {
3561             Some(profiles) => profiles,
3562             None => {
3563                 warn!(
3564                     "[{}]: Ignoring disconnection request since there is no connected profile.",
3565                     DisplayAddress(&addr)
3566                 );
3567                 return;
3568             }
3569         };
3570 
3571         for profile in connected_profiles {
3572             match profile {
3573                 Profile::A2dpSink => {
3574                     // Some headsets (b/278963515) will try reconnecting to A2DP
3575                     // when HFP is running but (requested to be) disconnected.
3576                     // TODO: Remove this workaround once proper fix lands.
3577                     if connected_profiles.contains(&Profile::Hfp) {
3578                         continue;
3579                     }
3580                     metrics::profile_connection_state_changed(
3581                         addr,
3582                         Profile::A2dpSink as u32,
3583                         BtStatus::Success,
3584                         BtavConnectionState::Disconnecting as u32,
3585                     );
3586                     match self.a2dp.as_mut() {
3587                         Some(a2dp) => {
3588                             let status: BtStatus = a2dp.disconnect(addr);
3589                             if BtStatus::Success != status {
3590                                 metrics::profile_connection_state_changed(
3591                                     addr,
3592                                     Profile::A2dpSource as u32,
3593                                     status,
3594                                     BtavConnectionState::Disconnected as u32,
3595                                 );
3596                             }
3597                         }
3598                         None => {
3599                             warn!("Uninitialized A2DP to disconnect {}", DisplayAddress(&addr));
3600                             metrics::profile_connection_state_changed(
3601                                 addr,
3602                                 Profile::A2dpSource as u32,
3603                                 BtStatus::NotReady,
3604                                 BtavConnectionState::Disconnected as u32,
3605                             );
3606                         }
3607                     };
3608                 }
3609                 Profile::Hfp => {
3610                     metrics::profile_connection_state_changed(
3611                         addr,
3612                         Profile::Hfp as u32,
3613                         BtStatus::Success,
3614                         BthfConnectionState::Disconnecting as u32,
3615                     );
3616                     match self.hfp.as_mut() {
3617                         Some(hfp) => {
3618                             let status: BtStatus = hfp.disconnect(addr);
3619                             if BtStatus::Success != status {
3620                                 metrics::profile_connection_state_changed(
3621                                     addr,
3622                                     Profile::Hfp as u32,
3623                                     status,
3624                                     BthfConnectionState::Disconnected as u32,
3625                                 );
3626                             }
3627                         }
3628                         None => {
3629                             warn!("Uninitialized HFP to disconnect {}", DisplayAddress(&addr));
3630                             metrics::profile_connection_state_changed(
3631                                 addr,
3632                                 Profile::Hfp as u32,
3633                                 BtStatus::NotReady,
3634                                 BthfConnectionState::Disconnected as u32,
3635                             );
3636                         }
3637                     };
3638                 }
3639                 Profile::AvrcpController => {
3640                     if connected_profiles.contains(&Profile::A2dpSink) {
3641                         continue;
3642                     }
3643                     metrics::profile_connection_state_changed(
3644                         addr,
3645                         Profile::AvrcpController as u32,
3646                         BtStatus::Success,
3647                         BtavConnectionState::Disconnecting as u32,
3648                     );
3649                     match self.avrcp.as_mut() {
3650                         Some(avrcp) => {
3651                             self.avrcp_direction = BtConnectionDirection::Outgoing;
3652                             let status: BtStatus = avrcp.disconnect(addr);
3653                             if BtStatus::Success != status {
3654                                 // Reset direction to unknown.
3655                                 self.avrcp_direction = BtConnectionDirection::Unknown;
3656                                 metrics::profile_connection_state_changed(
3657                                     addr,
3658                                     Profile::AvrcpController as u32,
3659                                     status,
3660                                     BtavConnectionState::Disconnected as u32,
3661                                 );
3662                             }
3663                         }
3664 
3665                         None => {
3666                             warn!("Uninitialized AVRCP to disconnect {}", DisplayAddress(&addr));
3667                             metrics::profile_connection_state_changed(
3668                                 addr,
3669                                 Profile::AvrcpController as u32,
3670                                 BtStatus::NotReady,
3671                                 BtavConnectionState::Disconnected as u32,
3672                             );
3673                         }
3674                     };
3675                 }
3676                 _ => warn!("Unknown profile: {:?}", profile),
3677             }
3678         }
3679     }
3680 
set_active_device(&mut self, addr: RawAddress)3681     fn set_active_device(&mut self, addr: RawAddress) {
3682         match self.a2dp_states.get(&addr) {
3683             Some(BtavConnectionState::Connected) => {
3684                 if let Some(a2dp) = self.a2dp.as_mut() {
3685                     a2dp.set_active_device(addr);
3686                     self.uinput.set_active_device(addr.to_string());
3687                 } else {
3688                     warn!("Uninitialized A2DP to set active device");
3689                 }
3690             }
3691             _ => warn!("[{}] Not connected or disconnected A2DP address", DisplayAddress(&addr)),
3692         };
3693     }
3694 
reset_active_device(&mut self)3695     fn reset_active_device(&mut self) {
3696         // During MPS tests, there might be some A2DP stream manipulation unexpected to CRAS.
3697         // CRAS would then attempt to reset the active device. Ignore it during test.
3698         if !self.is_complete_profiles_required() {
3699             return;
3700         }
3701 
3702         if let Some(a2dp) = self.a2dp.as_mut() {
3703             a2dp.set_active_device(RawAddress::empty());
3704         } else {
3705             warn!("Uninitialized A2DP to set active device");
3706         }
3707         self.uinput.set_active_device(RawAddress::empty().to_string());
3708     }
3709 
set_hfp_active_device(&mut self, addr: RawAddress)3710     fn set_hfp_active_device(&mut self, addr: RawAddress) {
3711         match self.hfp_states.get(&addr) {
3712             Some(BthfConnectionState::SlcConnected) => {
3713                 if let Some(hfp) = self.hfp.as_mut() {
3714                     hfp.set_active_device(addr);
3715                 } else {
3716                     warn!("Uninitialized HFP to set active device");
3717                 }
3718             }
3719             _ => warn!("[{}] Not connected or disconnected HFP address", DisplayAddress(&addr)),
3720         }
3721     }
3722 
set_audio_config( &mut self, addr: RawAddress, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool3723     fn set_audio_config(
3724         &mut self,
3725         addr: RawAddress,
3726         codec_type: A2dpCodecIndex,
3727         sample_rate: A2dpCodecSampleRate,
3728         bits_per_sample: A2dpCodecBitsPerSample,
3729         channel_mode: A2dpCodecChannelMode,
3730     ) -> bool {
3731         if self.a2dp_states.get(&addr).is_none() {
3732             warn!(
3733                 "[{}]: Ignore set config event for unconnected or disconnected A2DP device",
3734                 DisplayAddress(&addr)
3735             );
3736             return false;
3737         }
3738 
3739         match self.a2dp.as_mut() {
3740             Some(a2dp) => {
3741                 let caps = self.a2dp_caps.get(&addr).unwrap_or(&Vec::new()).to_vec();
3742 
3743                 for cap in &caps {
3744                     if A2dpCodecIndex::from(cap.codec_type) == codec_type {
3745                         if (A2dpCodecSampleRate::from_bits(cap.sample_rate).unwrap() & sample_rate)
3746                             != sample_rate
3747                         {
3748                             warn!("Unsupported sample rate {:?}", sample_rate);
3749                             return false;
3750                         }
3751                         if (A2dpCodecBitsPerSample::from_bits(cap.bits_per_sample).unwrap()
3752                             & bits_per_sample)
3753                             != bits_per_sample
3754                         {
3755                             warn!("Unsupported bit depth {:?}", bits_per_sample);
3756                             return false;
3757                         }
3758                         if (A2dpCodecChannelMode::from_bits(cap.channel_mode).unwrap()
3759                             & channel_mode)
3760                             != channel_mode
3761                         {
3762                             warn!("Unsupported channel mode {:?}", channel_mode);
3763                             return false;
3764                         }
3765 
3766                         let config = vec![A2dpCodecConfig {
3767                             codec_type: codec_type as i32,
3768                             codec_priority: A2dpCodecPriority::Highest as i32,
3769                             sample_rate: sample_rate.bits() as i32,
3770                             bits_per_sample: bits_per_sample.bits() as i32,
3771                             channel_mode: channel_mode.bits() as i32,
3772                             ..Default::default()
3773                         }];
3774 
3775                         a2dp.config_codec(addr, config);
3776                         return true;
3777                     }
3778                 }
3779 
3780                 warn!("Unsupported codec type {:?}", codec_type);
3781                 false
3782             }
3783             None => {
3784                 warn!("Uninitialized A2DP to set audio config");
3785                 false
3786             }
3787         }
3788     }
3789 
set_volume(&mut self, volume: u8)3790     fn set_volume(&mut self, volume: u8) {
3791         // Guard the range 0-127 by the try_from cast from u8 to i8.
3792         let vol = match i8::try_from(volume) {
3793             Ok(val) => val,
3794             _ => {
3795                 warn!("Ignore invalid volume {}", volume);
3796                 return;
3797             }
3798         };
3799 
3800         match self.avrcp.as_mut() {
3801             Some(avrcp) => avrcp.set_volume(vol),
3802             None => warn!("Uninitialized AVRCP to set volume"),
3803         };
3804     }
3805 
set_hfp_volume(&mut self, volume: u8, addr: RawAddress)3806     fn set_hfp_volume(&mut self, volume: u8, addr: RawAddress) {
3807         let vol = match i8::try_from(volume) {
3808             Ok(val) if val <= 15 => val,
3809             _ => {
3810                 warn!("[{}]: Ignore invalid volume {}", DisplayAddress(&addr), volume);
3811                 return;
3812             }
3813         };
3814 
3815         if self.hfp_states.get(&addr).is_none() {
3816             warn!(
3817                 "[{}]: Ignore volume event for unconnected or disconnected HFP device",
3818                 DisplayAddress(&addr)
3819             );
3820             return;
3821         }
3822 
3823         match self.hfp.as_mut() {
3824             Some(hfp) => {
3825                 hfp.set_volume(vol, addr);
3826             }
3827             None => warn!("Uninitialized HFP to set volume"),
3828         };
3829     }
3830 
start_audio_request(&mut self) -> bool3831     fn start_audio_request(&mut self) -> bool {
3832         self.start_audio_request_impl()
3833     }
3834 
stop_audio_request(&mut self)3835     fn stop_audio_request(&mut self) {
3836         debug!("Stop audio request");
3837 
3838         match self.a2dp.as_mut() {
3839             Some(a2dp) => a2dp.stop_audio_request(),
3840             None => warn!("Uninitialized A2DP to stop audio request"),
3841         };
3842     }
3843 
start_sco_call( &mut self, address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, ) -> bool3844     fn start_sco_call(
3845         &mut self,
3846         address: RawAddress,
3847         sco_offload: bool,
3848         disabled_codecs: HfpCodecBitId,
3849     ) -> bool {
3850         self.start_sco_call_impl(address, sco_offload, disabled_codecs)
3851     }
3852 
stop_sco_call(&mut self, address: RawAddress)3853     fn stop_sco_call(&mut self, address: RawAddress) {
3854         self.stop_sco_call_impl(address)
3855     }
3856 
get_a2dp_audio_started(&mut self, addr: RawAddress) -> bool3857     fn get_a2dp_audio_started(&mut self, addr: RawAddress) -> bool {
3858         match self.a2dp_audio_state.get(&addr) {
3859             Some(BtavAudioState::Started) => true,
3860             _ => false,
3861         }
3862     }
3863 
get_hfp_audio_final_codecs(&mut self, addr: RawAddress) -> u83864     fn get_hfp_audio_final_codecs(&mut self, addr: RawAddress) -> u8 {
3865         match self.hfp_audio_state.get(&addr) {
3866             Some(BthfAudioState::Connected) => match self.hfp_cap.get(&addr) {
3867                 Some(caps)
3868                     if (*caps & HfpCodecFormat::LC3_TRANSPARENT)
3869                         == HfpCodecFormat::LC3_TRANSPARENT =>
3870                 {
3871                     HfpCodecBitId::LC3
3872                 }
3873                 Some(caps) if (*caps & HfpCodecFormat::MSBC) == HfpCodecFormat::MSBC => {
3874                     HfpCodecBitId::MSBC
3875                 }
3876                 Some(caps)
3877                     if (*caps & HfpCodecFormat::MSBC_TRANSPARENT)
3878                         == HfpCodecFormat::MSBC_TRANSPARENT =>
3879                 {
3880                     HfpCodecBitId::MSBC
3881                 }
3882                 Some(caps) if (*caps & HfpCodecFormat::CVSD) == HfpCodecFormat::CVSD => {
3883                     HfpCodecBitId::CVSD
3884                 }
3885                 _ => {
3886                     warn!("hfp_cap not found, fallback to CVSD.");
3887                     HfpCodecBitId::CVSD
3888                 }
3889             },
3890             _ => HfpCodecBitId::NONE,
3891         }
3892         .try_into()
3893         .unwrap()
3894     }
3895 
get_presentation_position(&mut self) -> PresentationPosition3896     fn get_presentation_position(&mut self) -> PresentationPosition {
3897         let position = match self.a2dp.as_mut() {
3898             Some(a2dp) => a2dp.get_presentation_position(),
3899             None => {
3900                 warn!("Uninitialized A2DP to get presentation position");
3901                 Default::default()
3902             }
3903         };
3904         PresentationPosition {
3905             remote_delay_report_ns: position.remote_delay_report_ns,
3906             total_bytes_read: position.total_bytes_read,
3907             data_position_sec: position.data_position_sec,
3908             data_position_nsec: position.data_position_nsec,
3909         }
3910     }
3911 
set_player_playback_status(&mut self, status: String)3912     fn set_player_playback_status(&mut self, status: String) {
3913         debug!("AVRCP received player playback status: {}", status);
3914         match self.avrcp.as_mut() {
3915             Some(avrcp) => avrcp.set_playback_status(&status),
3916             None => warn!("Uninitialized AVRCP to set player playback status"),
3917         };
3918     }
set_player_position(&mut self, position_us: i64)3919     fn set_player_position(&mut self, position_us: i64) {
3920         debug!("AVRCP received player position: {}", position_us);
3921         match self.avrcp.as_mut() {
3922             Some(avrcp) => avrcp.set_position(position_us),
3923             None => warn!("Uninitialized AVRCP to set player position"),
3924         };
3925     }
set_player_metadata(&mut self, metadata: PlayerMetadata)3926     fn set_player_metadata(&mut self, metadata: PlayerMetadata) {
3927         debug!("AVRCP received player metadata: {:?}", metadata);
3928         match self.avrcp.as_mut() {
3929             Some(avrcp) => avrcp.set_metadata(&metadata),
3930             None => warn!("Uninitialized AVRCP to set player playback status"),
3931         };
3932     }
3933 
trigger_debug_dump(&mut self)3934     fn trigger_debug_dump(&mut self) {
3935         match self.hfp.as_mut() {
3936             Some(hfp) => hfp.debug_dump(),
3937             None => warn!("Uninitialized HFP to dump debug log"),
3938         };
3939     }
3940 
group_set_active(&mut self, group_id: i32)3941     fn group_set_active(&mut self, group_id: i32) {
3942         match self.le_audio.as_mut() {
3943             Some(le_audio) => le_audio.group_set_active(group_id),
3944             None => {
3945                 warn!("Uninitialized LEA to group set active");
3946             }
3947         }
3948     }
3949 
source_metadata_changed( &mut self, usage: BtLeAudioUsage, content_type: BtLeAudioContentType, gain: f64, ) -> bool3950     fn source_metadata_changed(
3951         &mut self,
3952         usage: BtLeAudioUsage,
3953         content_type: BtLeAudioContentType,
3954         gain: f64,
3955     ) -> bool {
3956         match self.le_audio.as_mut() {
3957             Some(le_audio) => {
3958                 let data = vec![SourceMetadata { usage, content_type, gain }];
3959                 le_audio.source_metadata_changed(data);
3960                 true
3961             }
3962             None => {
3963                 warn!("Uninitialized LEA to update source metadata");
3964                 false
3965             }
3966         }
3967     }
3968 
sink_metadata_changed(&mut self, source: BtLeAudioSource, gain: f64) -> bool3969     fn sink_metadata_changed(&mut self, source: BtLeAudioSource, gain: f64) -> bool {
3970         match self.le_audio.as_mut() {
3971             Some(le_audio) => {
3972                 let data = vec![SinkMetadata { source, gain }];
3973                 le_audio.sink_metadata_changed(data);
3974                 true
3975             }
3976             None => {
3977                 warn!("Uninitialized LEA to update sink metadata");
3978                 false
3979             }
3980         }
3981     }
3982 
host_start_audio_request(&mut self) -> bool3983     fn host_start_audio_request(&mut self) -> bool {
3984         match self.le_audio.as_mut() {
3985             Some(le_audio) => le_audio.host_start_audio_request(),
3986             None => {
3987                 warn!("Uninitialized LEA to start audio request");
3988                 false
3989             }
3990         }
3991     }
3992 
host_stop_audio_request(&mut self)3993     fn host_stop_audio_request(&mut self) {
3994         match self.le_audio.as_mut() {
3995             Some(le_audio) => le_audio.host_stop_audio_request(),
3996             None => {
3997                 warn!("Uninitialized LEA to stop audio request");
3998             }
3999         }
4000     }
4001 
peer_start_audio_request(&mut self) -> bool4002     fn peer_start_audio_request(&mut self) -> bool {
4003         match self.le_audio.as_mut() {
4004             Some(le_audio) => le_audio.peer_start_audio_request(),
4005             None => {
4006                 warn!("Uninitialized LEA for peer to start audio request");
4007                 false
4008             }
4009         }
4010     }
4011 
peer_stop_audio_request(&mut self)4012     fn peer_stop_audio_request(&mut self) {
4013         match self.le_audio.as_mut() {
4014             Some(le_audio) => le_audio.peer_stop_audio_request(),
4015             None => {
4016                 warn!("Uninitialized LEA for peer to stop audio request");
4017             }
4018         }
4019     }
4020 
get_host_pcm_config(&mut self) -> BtLePcmConfig4021     fn get_host_pcm_config(&mut self) -> BtLePcmConfig {
4022         match self.le_audio.as_mut() {
4023             Some(le_audio) => le_audio.get_host_pcm_config(),
4024             None => {
4025                 warn!("Uninitialized LEA to get active pcm config from host");
4026                 Default::default()
4027             }
4028         }
4029     }
4030 
get_peer_pcm_config(&mut self) -> BtLePcmConfig4031     fn get_peer_pcm_config(&mut self) -> BtLePcmConfig {
4032         match self.le_audio.as_mut() {
4033             Some(le_audio) => le_audio.get_peer_pcm_config(),
4034             None => {
4035                 warn!("Uninitialized LEA to get active pcm config from peer");
4036                 Default::default()
4037             }
4038         }
4039     }
4040 
get_host_stream_started(&mut self) -> BtLeStreamStartedStatus4041     fn get_host_stream_started(&mut self) -> BtLeStreamStartedStatus {
4042         match self.le_audio.as_mut() {
4043             Some(le_audio) => le_audio.get_host_stream_started(),
4044             None => {
4045                 warn!("Uninitialized LEA to get_host_stream_started");
4046                 BtLeStreamStartedStatus::Idle
4047             }
4048         }
4049     }
4050 
get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus4051     fn get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus {
4052         match self.le_audio.as_mut() {
4053             Some(le_audio) => le_audio.get_peer_stream_started(),
4054             None => {
4055                 warn!("Uninitialized LEA to get_peer_stream_started");
4056                 BtLeStreamStartedStatus::Idle
4057             }
4058         }
4059     }
4060 
get_unicast_monitor_mode_status( &mut self, direction: BtLeAudioDirection, ) -> BtLeAudioUnicastMonitorModeStatus4061     fn get_unicast_monitor_mode_status(
4062         &mut self,
4063         direction: BtLeAudioDirection,
4064     ) -> BtLeAudioUnicastMonitorModeStatus {
4065         *self
4066             .le_audio_unicast_monitor_mode_status
4067             .get(&direction.into())
4068             .unwrap_or(&BtLeAudioUnicastMonitorModeStatus::StreamingSuspended)
4069     }
4070 
get_group_stream_status(&mut self, group_id: i32) -> BtLeAudioGroupStreamStatus4071     fn get_group_stream_status(&mut self, group_id: i32) -> BtLeAudioGroupStreamStatus {
4072         if self.le_audio_groups.get(&group_id).is_none() {
4073             return BtLeAudioGroupStreamStatus::Idle;
4074         }
4075 
4076         self.le_audio_groups.get(&group_id).unwrap().stream_status
4077     }
4078 
get_group_status(&mut self, group_id: i32) -> BtLeAudioGroupStatus4079     fn get_group_status(&mut self, group_id: i32) -> BtLeAudioGroupStatus {
4080         if self.le_audio_groups.get(&group_id).is_none() {
4081             return BtLeAudioGroupStatus::Inactive;
4082         }
4083 
4084         self.le_audio_groups.get(&group_id).unwrap().status
4085     }
4086 
set_group_volume(&mut self, group_id: i32, volume: u8)4087     fn set_group_volume(&mut self, group_id: i32, volume: u8) {
4088         match self.vc.as_mut() {
4089             Some(vc) => {
4090                 vc.set_volume(group_id, volume);
4091             }
4092             None => warn!("Uninitialized VC to set volume"),
4093         };
4094     }
4095 }
4096 
4097 impl IBluetoothTelephony for BluetoothMedia {
register_telephony_callback( &mut self, callback: Box<dyn IBluetoothTelephonyCallback + Send>, ) -> bool4098     fn register_telephony_callback(
4099         &mut self,
4100         callback: Box<dyn IBluetoothTelephonyCallback + Send>,
4101     ) -> bool {
4102         let _id = self.telephony_callbacks.lock().unwrap().add_callback(callback);
4103         true
4104     }
4105 
set_network_available(&mut self, network_available: bool)4106     fn set_network_available(&mut self, network_available: bool) {
4107         if self.telephony_device_status.network_available == network_available {
4108             return;
4109         }
4110         self.telephony_device_status.network_available = network_available;
4111         self.device_status_notification();
4112     }
4113 
set_roaming(&mut self, roaming: bool)4114     fn set_roaming(&mut self, roaming: bool) {
4115         if self.telephony_device_status.roaming == roaming {
4116             return;
4117         }
4118         self.telephony_device_status.roaming = roaming;
4119         self.device_status_notification();
4120     }
4121 
set_signal_strength(&mut self, signal_strength: i32) -> bool4122     fn set_signal_strength(&mut self, signal_strength: i32) -> bool {
4123         if signal_strength < 0 || signal_strength > 5 {
4124             warn!("Invalid signal strength, got {}, want 0 to 5", signal_strength);
4125             return false;
4126         }
4127         if self.telephony_device_status.signal_strength == signal_strength {
4128             return true;
4129         }
4130 
4131         self.telephony_device_status.signal_strength = signal_strength;
4132         self.device_status_notification();
4133 
4134         true
4135     }
4136 
set_battery_level(&mut self, battery_level: i32) -> bool4137     fn set_battery_level(&mut self, battery_level: i32) -> bool {
4138         if battery_level < 0 || battery_level > 5 {
4139             warn!("Invalid battery level, got {}, want 0 to 5", battery_level);
4140             return false;
4141         }
4142         if self.telephony_device_status.battery_level == battery_level {
4143             return true;
4144         }
4145 
4146         self.telephony_device_status.battery_level = battery_level;
4147         self.device_status_notification();
4148 
4149         true
4150     }
4151 
set_phone_ops_enabled(&mut self, enable: bool)4152     fn set_phone_ops_enabled(&mut self, enable: bool) {
4153         info!("Bluetooth HID telephony mode enabled");
4154         if self.phone_ops_enabled == enable {
4155             return;
4156         }
4157 
4158         self.call_list = vec![];
4159         self.phone_state.num_active = 0;
4160         self.phone_state.num_held = 0;
4161         self.phone_state.state = CallState::Idle;
4162         self.memory_dialing_number = None;
4163         self.last_dialing_number = None;
4164         self.a2dp_has_interrupted_stream = false;
4165 
4166         self.phone_ops_enabled = enable;
4167         if self.hfp_audio_state.keys().any(|addr| self.should_insert_call_when_sco_start(*addr))
4168             && self.hfp_audio_state.values().any(|x| x == &BthfAudioState::Connected)
4169         {
4170             self.place_active_call();
4171             return;
4172         }
4173 
4174         self.phone_state_change("".into());
4175     }
4176 
set_mps_qualification_enabled(&mut self, enable: bool)4177     fn set_mps_qualification_enabled(&mut self, enable: bool) {
4178         info!("MPS qualification mode enabled");
4179         if self.mps_qualification_enabled == enable {
4180             return;
4181         }
4182 
4183         self.call_list = vec![];
4184         self.phone_state.num_active = 0;
4185         self.phone_state.num_held = 0;
4186         self.phone_state.state = CallState::Idle;
4187         self.memory_dialing_number = None;
4188         self.last_dialing_number = None;
4189         self.a2dp_has_interrupted_stream = false;
4190         self.mps_qualification_enabled = enable;
4191 
4192         if self.hfp_audio_state.keys().any(|addr| self.should_insert_call_when_sco_start(*addr))
4193             && self.hfp_audio_state.values().any(|x| x == &BthfAudioState::Connected)
4194         {
4195             self.place_active_call();
4196             return;
4197         }
4198 
4199         self.phone_state_change("".into());
4200     }
4201 
incoming_call(&mut self, number: String) -> bool4202     fn incoming_call(&mut self, number: String) -> bool {
4203         if !self.mps_qualification_enabled {
4204             warn!("Unexpected incoming_call dbus command. mps_qualification_enabled does not enabled.");
4205             return false;
4206         }
4207         return self.incoming_call_impl(number);
4208     }
4209 
dialing_call(&mut self, number: String) -> bool4210     fn dialing_call(&mut self, number: String) -> bool {
4211         if !self.mps_qualification_enabled {
4212             warn!("Unexpected incoming_call dbus command. mps_qualification_enabled does not enabled.");
4213             return false;
4214         }
4215         return self.dialing_call_impl(number, None);
4216     }
4217 
answer_call(&mut self) -> bool4218     fn answer_call(&mut self) -> bool {
4219         if !self.mps_qualification_enabled {
4220             warn!(
4221                 "Unexpected answer_call dbus command. mps_qualification_enabled does not enabled."
4222             );
4223             return false;
4224         }
4225         return self.answer_call_impl();
4226     }
4227 
hangup_call(&mut self) -> bool4228     fn hangup_call(&mut self) -> bool {
4229         if !self.mps_qualification_enabled {
4230             warn!(
4231                 "Unexpected hangup_call dbus command. mps_qualification_enabled does not enabled."
4232             );
4233             return false;
4234         }
4235         return self.hangup_call_impl();
4236     }
4237 
set_memory_call(&mut self, number: Option<String>) -> bool4238     fn set_memory_call(&mut self, number: Option<String>) -> bool {
4239         if !self.mps_qualification_enabled {
4240             warn!("Unexpected set_memory_call dbus command. mps_qualification_enabled does not enabled.");
4241             return false;
4242         }
4243         self.memory_dialing_number = number;
4244         true
4245     }
4246 
set_last_call(&mut self, number: Option<String>) -> bool4247     fn set_last_call(&mut self, number: Option<String>) -> bool {
4248         if !self.mps_qualification_enabled {
4249             warn!("Unexpected set_last_call dbus command. mps_qualification_enabled does not enabled.");
4250             return false;
4251         }
4252         self.last_dialing_number = number;
4253         true
4254     }
4255 
release_held(&mut self) -> bool4256     fn release_held(&mut self) -> bool {
4257         if !self.mps_qualification_enabled {
4258             warn!(
4259                 "Unexpected release_held dbus command. mps_qualification_enabled does not enabled."
4260             );
4261             return false;
4262         }
4263         return self.release_held_impl(None);
4264     }
4265 
release_active_accept_held(&mut self) -> bool4266     fn release_active_accept_held(&mut self) -> bool {
4267         if !self.mps_qualification_enabled {
4268             warn!("Unexpected release_active_accept_held dbus command. mps_qualification_enabled does not enabled.");
4269             return false;
4270         }
4271         return self.release_active_accept_held_impl(None);
4272     }
4273 
hold_active_accept_held(&mut self) -> bool4274     fn hold_active_accept_held(&mut self) -> bool {
4275         if !self.mps_qualification_enabled {
4276             warn!("Unexpected hold_active_accept_held dbus command. mps_qualification_enabled does not enabled.");
4277             return false;
4278         }
4279         return self.hold_active_accept_held_impl(None);
4280     }
4281 
audio_connect(&mut self, address: RawAddress) -> bool4282     fn audio_connect(&mut self, address: RawAddress) -> bool {
4283         self.start_sco_call_impl(address, false, HfpCodecBitId::NONE)
4284     }
4285 
audio_disconnect(&mut self, address: RawAddress)4286     fn audio_disconnect(&mut self, address: RawAddress) {
4287         self.stop_sco_call_impl(address)
4288     }
4289 }
4290 
4291 struct BatteryProviderCallback {}
4292 
4293 impl BatteryProviderCallback {
new() -> Self4294     fn new() -> Self {
4295         Self {}
4296     }
4297 }
4298 
4299 impl IBatteryProviderCallback for BatteryProviderCallback {
4300     // We do not support refreshing HFP battery information.
refresh_battery_info(&mut self)4301     fn refresh_battery_info(&mut self) {}
4302 }
4303 
4304 impl RPCProxy for BatteryProviderCallback {
get_object_id(&self) -> String4305     fn get_object_id(&self) -> String {
4306         "HFP BatteryProvider Callback".to_string()
4307     }
4308 }
4309