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