• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_disable_hf_profile, 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: i64, src_audio_location: i64, avail_cont: u16, )295     fn on_lea_audio_conf(
296         &mut self,
297         direction: u8,
298         group_id: i32,
299         snk_audio_location: i64,
300         src_audio_location: i64,
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: i64,
424     pub src_audio_location: i64,
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 name = self.adapter_get_remote_name(addr);
2557         let device = BluetoothDevice::new(addr, "".to_string());
2558         let mut profiles: HashSet<_> = self
2559             .adapter
2560             .lock()
2561             .unwrap()
2562             .get_remote_uuids(device)
2563             .into_iter()
2564             .filter_map(|u| UuidHelper::is_known_profile(&u))
2565             .filter(|u| MEDIA_CLASSIC_AUDIO_PROFILES.contains(u))
2566             .collect();
2567 
2568         if interop_disable_hf_profile(name) {
2569             profiles.remove(&Profile::Hfp);
2570         }
2571 
2572         profiles
2573     }
2574 
get_hfp_connection_state(&self) -> ProfileConnectionState2575     pub fn get_hfp_connection_state(&self) -> ProfileConnectionState {
2576         if self.hfp_audio_state.values().any(|state| *state == BthfAudioState::Connected) {
2577             ProfileConnectionState::Active
2578         } else {
2579             let mut winning_state = ProfileConnectionState::Disconnected;
2580             for state in self.hfp_states.values() {
2581                 // Grab any state higher than the current state.
2582                 match state {
2583                     // Any SLC completed state means the profile is connected.
2584                     BthfConnectionState::SlcConnected => {
2585                         winning_state = ProfileConnectionState::Connected;
2586                     }
2587 
2588                     // Connecting or Connected are both counted as connecting for profile state
2589                     // since it's not a complete connection.
2590                     BthfConnectionState::Connecting | BthfConnectionState::Connected
2591                         if winning_state != ProfileConnectionState::Connected =>
2592                     {
2593                         winning_state = ProfileConnectionState::Connecting;
2594                     }
2595 
2596                     BthfConnectionState::Disconnecting
2597                         if winning_state == ProfileConnectionState::Disconnected =>
2598                     {
2599                         winning_state = ProfileConnectionState::Disconnecting;
2600                     }
2601 
2602                     _ => (),
2603                 }
2604             }
2605 
2606             winning_state
2607         }
2608     }
2609 
get_a2dp_connection_state(&self) -> ProfileConnectionState2610     pub fn get_a2dp_connection_state(&self) -> ProfileConnectionState {
2611         if self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
2612             ProfileConnectionState::Active
2613         } else {
2614             let mut winning_state = ProfileConnectionState::Disconnected;
2615             for state in self.a2dp_states.values() {
2616                 // Grab any state higher than the current state.
2617                 match state {
2618                     BtavConnectionState::Connected => {
2619                         winning_state = ProfileConnectionState::Connected;
2620                     }
2621 
2622                     BtavConnectionState::Connecting
2623                         if winning_state != ProfileConnectionState::Connected =>
2624                     {
2625                         winning_state = ProfileConnectionState::Connecting;
2626                     }
2627 
2628                     BtavConnectionState::Disconnecting
2629                         if winning_state == ProfileConnectionState::Disconnected =>
2630                     {
2631                         winning_state = ProfileConnectionState::Disconnecting;
2632                     }
2633 
2634                     _ => (),
2635                 }
2636             }
2637 
2638             winning_state
2639         }
2640     }
2641 
filter_to_connected_audio_devices_from( &self, devices: &Vec<BluetoothDevice>, ) -> Vec<BluetoothDevice>2642     pub fn filter_to_connected_audio_devices_from(
2643         &self,
2644         devices: &Vec<BluetoothDevice>,
2645     ) -> Vec<BluetoothDevice> {
2646         devices
2647             .iter()
2648             .filter(|d| {
2649                 self.is_any_profile_connected(&d.address, MEDIA_CLASSIC_AUDIO_PROFILES)
2650                     || self.is_any_profile_connected(&d.address, MEDIA_LE_AUDIO_PROFILES)
2651             })
2652             .cloned()
2653             .collect()
2654     }
2655 
start_audio_request_impl(&mut self) -> bool2656     fn start_audio_request_impl(&mut self) -> bool {
2657         debug!("Start audio request");
2658         self.a2dp.start_audio_request()
2659     }
2660 
suspend_audio_request_impl(&mut self)2661     fn suspend_audio_request_impl(&mut self) {
2662         self.a2dp.suspend_audio_request();
2663     }
2664 
try_a2dp_resume(&mut self)2665     fn try_a2dp_resume(&mut self) {
2666         // Try resume the A2DP stream (per MPS v1.0) on rejecting an incoming call or an
2667         // outgoing call is rejected.
2668         // It may fail if a SCO connection is still active (terminate call case), in that
2669         // case we will retry on SCO disconnected.
2670         if !self.mps_qualification_enabled {
2671             return;
2672         }
2673         // Make sure there is no any SCO connection and then resume the A2DP stream.
2674         if self.a2dp_has_interrupted_stream
2675             && !self.hfp_audio_state.values().any(|state| *state == BthfAudioState::Connected)
2676         {
2677             self.a2dp_has_interrupted_stream = false;
2678             self.start_audio_request_impl();
2679         }
2680     }
2681 
try_a2dp_suspend(&mut self)2682     fn try_a2dp_suspend(&mut self) {
2683         // Try suspend the A2DP stream (per MPS v1.0) when receiving an incoming call
2684         if !self.mps_qualification_enabled {
2685             return;
2686         }
2687         // Suspend the A2DP stream if there is any.
2688         if self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
2689             self.a2dp_has_interrupted_stream = true;
2690             self.suspend_audio_request_impl();
2691         }
2692     }
2693 
start_sco_call_impl( &mut self, addr: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, ) -> bool2694     fn start_sco_call_impl(
2695         &mut self,
2696         addr: RawAddress,
2697         sco_offload: bool,
2698         disabled_codecs: HfpCodecBitId,
2699     ) -> bool {
2700         info!("Start sco call for {}", DisplayAddress(&addr));
2701 
2702         let Ok(disabled_codecs) = disabled_codecs.try_into() else {
2703             warn!("Can't parse disabled_codecs");
2704             return false;
2705         };
2706         if self.hfp.connect_audio(addr, sco_offload, disabled_codecs) != 0 {
2707             warn!("SCO connect_audio status failed");
2708             return false;
2709         }
2710         info!("SCO connect_audio status success");
2711         true
2712     }
2713 
stop_sco_call_impl(&mut self, addr: RawAddress)2714     fn stop_sco_call_impl(&mut self, addr: RawAddress) {
2715         info!("Stop sco call for {}", DisplayAddress(&addr));
2716         self.hfp.disconnect_audio(addr);
2717     }
2718 
device_status_notification(&mut self)2719     fn device_status_notification(&mut self) {
2720         for (addr, state) in self.hfp_states.iter() {
2721             if *state != BthfConnectionState::SlcConnected {
2722                 continue;
2723             }
2724             debug!(
2725                 "[{}]: Device status notification {:?}",
2726                 DisplayAddress(addr),
2727                 self.telephony_device_status
2728             );
2729             let status = self.hfp.device_status_notification(self.telephony_device_status, *addr);
2730             if status != BtStatus::Success {
2731                 warn!(
2732                     "[{}]: Device status notification failed, status={:?}",
2733                     DisplayAddress(addr),
2734                     status
2735                 );
2736             }
2737         }
2738     }
2739 
phone_state_change(&mut self, number: String)2740     fn phone_state_change(&mut self, number: String) {
2741         for (addr, state) in self.hfp_states.iter() {
2742             if *state != BthfConnectionState::SlcConnected {
2743                 continue;
2744             }
2745             debug!(
2746                 "[{}]: Phone state change state={:?} number={}",
2747                 DisplayAddress(addr),
2748                 self.phone_state,
2749                 number
2750             );
2751             let status = self.hfp.phone_state_change(self.phone_state, &number, *addr);
2752             if status != BtStatus::Success {
2753                 warn!(
2754                     "[{}]: Device status notification failed, status={:?}",
2755                     DisplayAddress(addr),
2756                     status
2757                 );
2758             }
2759         }
2760     }
2761 
2762     // Returns the minimum unoccupied index starting from 1.
new_call_index(&self) -> i322763     fn new_call_index(&self) -> i32 {
2764         (1..)
2765             .find(|&index| self.call_list.iter().all(|x| x.index != index))
2766             .expect("There must be an unoccupied index")
2767     }
2768 
simple_at_response(&mut self, ok: bool, addr: RawAddress)2769     fn simple_at_response(&mut self, ok: bool, addr: RawAddress) {
2770         let status = self.hfp.simple_at_response(ok, addr);
2771         if status != BtStatus::Success {
2772             warn!("[{}]: AT response failed, status={:?}", DisplayAddress(&addr), status);
2773         }
2774     }
2775 
incoming_call_impl(&mut self, number: String) -> bool2776     fn incoming_call_impl(&mut self, number: String) -> bool {
2777         if self.phone_state.state != CallState::Idle {
2778             return false;
2779         }
2780 
2781         if self.phone_state.num_active > 0 {
2782             return false;
2783         }
2784 
2785         self.call_list.push(CallInfo {
2786             index: self.new_call_index(),
2787             dir_incoming: true,
2788             state: CallState::Incoming,
2789             number: number.clone(),
2790         });
2791         self.phone_state.state = CallState::Incoming;
2792         self.phone_state_change(number);
2793         self.try_a2dp_suspend();
2794         true
2795     }
2796 
answer_call_impl(&mut self) -> bool2797     fn answer_call_impl(&mut self) -> bool {
2798         if self.phone_state.state == CallState::Idle {
2799             return false;
2800         }
2801         // There must be exactly one incoming/dialing call in the list.
2802         for c in self.call_list.iter_mut() {
2803             match c.state {
2804                 CallState::Incoming | CallState::Dialing | CallState::Alerting => {
2805                     c.state = CallState::Active;
2806                     break;
2807                 }
2808                 _ => {}
2809             }
2810         }
2811         self.phone_state.state = CallState::Idle;
2812         self.phone_state.num_active += 1;
2813 
2814         self.phone_state_change("".into());
2815 
2816         if self.mps_qualification_enabled {
2817             // Find a connected HFP and try to establish an SCO.
2818             if let Some(addr) = self.hfp_states.iter().find_map(|(addr, state)| {
2819                 if *state == BthfConnectionState::SlcConnected {
2820                     Some(addr)
2821                 } else {
2822                     None
2823                 }
2824             }) {
2825                 info!("Start SCO call due to call answered");
2826                 self.start_sco_call_impl(*addr, false, HfpCodecBitId::NONE);
2827             }
2828         }
2829 
2830         true
2831     }
2832 
hangup_call_impl(&mut self) -> bool2833     fn hangup_call_impl(&mut self) -> bool {
2834         if !self.phone_ops_enabled && !self.mps_qualification_enabled {
2835             return false;
2836         }
2837 
2838         match self.phone_state.state {
2839             CallState::Idle if self.phone_state.num_active > 0 => {
2840                 self.phone_state.num_active -= 1;
2841             }
2842             CallState::Incoming | CallState::Dialing | CallState::Alerting => {
2843                 self.phone_state.state = CallState::Idle;
2844             }
2845             _ => return false,
2846         }
2847         // At this point, there must be exactly one incoming/dialing/alerting/active call to be
2848         // removed.
2849         self.call_list.retain(|x| match x.state {
2850             CallState::Active | CallState::Incoming | CallState::Dialing | CallState::Alerting => {
2851                 false
2852             }
2853             _ => true,
2854         });
2855 
2856         self.phone_state_change("".into());
2857         self.try_a2dp_resume();
2858 
2859         true
2860     }
2861 
dialing_call_impl(&mut self, number: String, addr: Option<RawAddress>) -> bool2862     fn dialing_call_impl(&mut self, number: String, addr: Option<RawAddress>) -> bool {
2863         if self.phone_state.num_active > 0 || self.phone_state.state != CallState::Idle {
2864             if let Some(addr) = addr {
2865                 self.simple_at_response(false, addr);
2866                 warn!("[{}]: Unexpected dialing command from HF", DisplayAddress(&addr));
2867             }
2868             return false;
2869         }
2870 
2871         self.call_list.push(CallInfo {
2872             index: self.new_call_index(),
2873             dir_incoming: false,
2874             state: CallState::Dialing,
2875             number: number.clone(),
2876         });
2877         self.phone_state.state = CallState::Dialing;
2878 
2879         if let Some(addr) = addr {
2880             self.simple_at_response(true, addr);
2881             warn!("[{}]: Unexpected dialing command from HF", DisplayAddress(&addr));
2882         }
2883 
2884         // Inform libbluetooth that the state has changed to dialing.
2885         self.phone_state_change("".into());
2886         self.try_a2dp_suspend();
2887         // Change to alerting state and inform libbluetooth.
2888         self.dialing_to_alerting();
2889         true
2890     }
2891 
dialing_to_alerting(&mut self) -> bool2892     fn dialing_to_alerting(&mut self) -> bool {
2893         if !(self.phone_ops_enabled || self.mps_qualification_enabled)
2894             || self.phone_state.state != CallState::Dialing
2895         {
2896             return false;
2897         }
2898         for c in self.call_list.iter_mut() {
2899             if c.state == CallState::Dialing {
2900                 c.state = CallState::Alerting;
2901                 break;
2902             }
2903         }
2904         self.phone_state.state = CallState::Alerting;
2905         self.phone_state_change("".into());
2906         true
2907     }
2908 
release_held_impl(&mut self, addr: Option<RawAddress>) -> bool2909     fn release_held_impl(&mut self, addr: Option<RawAddress>) -> bool {
2910         if self.phone_state.state != CallState::Idle {
2911             if let Some(addr) = addr {
2912                 // Respond ERROR to the HF which sent the command.
2913                 self.simple_at_response(false, addr);
2914             }
2915             return false;
2916         }
2917         self.call_list.retain(|x| x.state != CallState::Held);
2918         self.phone_state.num_held = 0;
2919 
2920         if let Some(addr) = addr {
2921             // This should be called before calling phone_state_change.
2922             self.simple_at_response(true, addr);
2923         }
2924         // Success means the call state has changed. Inform libbluetooth.
2925         self.phone_state_change("".into());
2926         true
2927     }
2928 
release_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool2929     fn release_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool {
2930         self.call_list.retain(|x| x.state != CallState::Active);
2931         self.phone_state.num_active = 0;
2932         // Activate the first held call
2933         if self.phone_state.state != CallState::Idle {
2934             if let Some(addr) = addr {
2935                 // Respond ERROR to the HF which sent the command.
2936                 self.simple_at_response(false, addr);
2937             }
2938             return false;
2939         }
2940         for c in self.call_list.iter_mut() {
2941             if c.state == CallState::Held {
2942                 c.state = CallState::Active;
2943                 self.phone_state.num_held -= 1;
2944                 self.phone_state.num_active += 1;
2945                 break;
2946             }
2947         }
2948         if let Some(addr) = addr {
2949             // This should be called before calling phone_state_change.
2950             self.simple_at_response(true, addr);
2951         }
2952         // Success means the call state has changed. Inform libbluetooth.
2953         self.phone_state_change("".into());
2954         true
2955     }
2956 
hold_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool2957     fn hold_active_accept_held_impl(&mut self, addr: Option<RawAddress>) -> bool {
2958         if self.phone_state.state != CallState::Idle {
2959             if let Some(addr) = addr {
2960                 // Respond ERROR to the HF which sent the command.
2961                 self.simple_at_response(false, addr);
2962             }
2963             return false;
2964         }
2965         self.phone_state.num_held += self.phone_state.num_active;
2966         self.phone_state.num_active = 0;
2967 
2968         for c in self.call_list.iter_mut() {
2969             match c.state {
2970                 // Activate at most one held call
2971                 CallState::Held if self.phone_state.num_active == 0 => {
2972                     c.state = CallState::Active;
2973                     self.phone_state.num_held -= 1;
2974                     self.phone_state.num_active = 1;
2975                 }
2976                 CallState::Active => {
2977                     c.state = CallState::Held;
2978                 }
2979                 _ => {}
2980             }
2981         }
2982         if let Some(addr) = addr {
2983             // This should be called before calling phone_state_change.
2984             self.simple_at_response(true, addr);
2985         }
2986         // Success means the call state has changed. Inform libbluetooth.
2987         self.phone_state_change("".into());
2988         true
2989     }
2990 
2991     // Per MPS v1.0 (Multi-Profile Specification), disconnecting or failing to connect
2992     // a profile should not affect the others.
2993     // Allow partial profiles connection during qualification (MPS qualification mode is enabled).
is_complete_profiles_required(&self) -> bool2994     fn is_complete_profiles_required(&self) -> bool {
2995         !self.mps_qualification_enabled
2996     }
2997 
2998     // Force the media enters the FullyConnected state and then triggers a retry.
2999     // When this function is used for qualification as a replacement of normal retry,
3000     // PTS could initiate the connection of the necessary profiles, and Floss should
3001     // notify CRAS of the new audio device regardless of the unconnected profiles.
3002     // Still retry in the end because some test cases require that.
force_enter_connected(&mut self, addr: RawAddress)3003     fn force_enter_connected(&mut self, addr: RawAddress) {
3004         self.device_states.lock().unwrap().insert(addr, DeviceConnectionStates::FullyConnected);
3005         self.notify_media_capability_updated(addr);
3006         self.connect(addr);
3007     }
add_player(&mut self, name: String, browsing_supported: bool)3008     pub fn add_player(&mut self, name: String, browsing_supported: bool) {
3009         self.avrcp.add_player(&name, browsing_supported);
3010     }
3011 
3012     // This function determines if it's safe to send a +CIEV command to an HFP device when SCO starts.
3013 
3014     // The +CIEV command should NOT be sent if:
3015     //  - MPS qualification mode is enabled, as it may cause qualification failures.
3016     //  - Uhid device is open, as it may conflict with ongoing telephony operations.
3017 
3018     // The +CIEV command is safe to send if:
3019     //  - Both MPS qualification and Bluetooth telephony are disabled.
3020     //  - Uhid device is closed, preventing any telephony conflicts.
3021     //  - The headset is listed in interop_database.conf, indicating it requires +CIEV for audio.
should_insert_call_when_sco_start(&self, address: RawAddress) -> bool3022     fn should_insert_call_when_sco_start(&self, address: RawAddress) -> bool {
3023         if self.mps_qualification_enabled {
3024             return false;
3025         }
3026         if !self.phone_ops_enabled {
3027             return true;
3028         }
3029 
3030         match self.uhid.get(&address) {
3031             Some(uhid) => {
3032                 if !uhid.is_open {
3033                     return true;
3034                 }
3035             }
3036             None => {
3037                 return true;
3038             }
3039         };
3040 
3041         interop_insert_call_when_sco_start(address)
3042     }
3043     // Places an active call into the call list and triggers a headset update (+CIEV).
3044     // Preconditions:
3045     //   - No active calls in progress (phone_state.num_active == 0)
3046     //   - Phone state is idle (phone_state.state == CallState::Idle)
place_active_call(&mut self)3047     fn place_active_call(&mut self) {
3048         if self.phone_state.num_active != 0 {
3049             warn!("Unexpected usage. phone_state.num_active can only be 0 when calling place_active_call");
3050             return;
3051         }
3052 
3053         if self.phone_state.state != CallState::Idle {
3054             warn!("Unexpected usage. phone_state.state can only be idle when calling place_active_call");
3055             return;
3056         }
3057 
3058         self.dialing_call_impl("".into(), None);
3059         self.answer_call_impl();
3060     }
3061 
get_group_devices(&self, group_id: i32) -> HashSet<RawAddress>3062     pub fn get_group_devices(&self, group_id: i32) -> HashSet<RawAddress> {
3063         match self.le_audio_groups.get(&group_id) {
3064             Some(g) => g.devices.clone(),
3065             _ => HashSet::new(),
3066         }
3067     }
3068 
get_group_id(&self, addr: RawAddress) -> i323069     pub fn get_group_id(&self, addr: RawAddress) -> i32 {
3070         *self.le_audio_node_to_group.get(&addr).unwrap_or(&LEA_UNKNOWN_GROUP_ID)
3071     }
3072 }
3073 
get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher3074 fn get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher {
3075     A2dpCallbacksDispatcher { dispatch: make_message_dispatcher(tx, Message::A2dp) }
3076 }
3077 
get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher3078 fn get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher {
3079     AvrcpCallbacksDispatcher { dispatch: make_message_dispatcher(tx, Message::Avrcp) }
3080 }
3081 
get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher3082 fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher {
3083     HfpCallbacksDispatcher { dispatch: make_message_dispatcher(tx, Message::Hfp) }
3084 }
3085 
get_le_audio_dispatcher(tx: Sender<Message>) -> LeAudioClientCallbacksDispatcher3086 fn get_le_audio_dispatcher(tx: Sender<Message>) -> LeAudioClientCallbacksDispatcher {
3087     LeAudioClientCallbacksDispatcher {
3088         dispatch: make_message_dispatcher(tx, Message::LeAudioClient),
3089     }
3090 }
3091 
get_vc_dispatcher(tx: Sender<Message>) -> VolumeControlCallbacksDispatcher3092 fn get_vc_dispatcher(tx: Sender<Message>) -> VolumeControlCallbacksDispatcher {
3093     VolumeControlCallbacksDispatcher {
3094         dispatch: make_message_dispatcher(tx, Message::VolumeControl),
3095     }
3096 }
3097 
get_csis_dispatcher(tx: Sender<Message>) -> CsisClientCallbacksDispatcher3098 fn get_csis_dispatcher(tx: Sender<Message>) -> CsisClientCallbacksDispatcher {
3099     CsisClientCallbacksDispatcher { dispatch: make_message_dispatcher(tx, Message::CsisClient) }
3100 }
3101 
3102 impl IBluetoothMedia for BluetoothMedia {
register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool3103     fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool {
3104         let _id = self.callbacks.lock().unwrap().add_callback(callback);
3105         true
3106     }
3107 
initialize(&mut self) -> bool3108     fn initialize(&mut self) -> bool {
3109         if self.initialized {
3110             return false;
3111         }
3112         self.initialized = true;
3113 
3114         self.is_le_audio_only_enabled =
3115             features::is_feature_enabled("CrOSLateBootBluetoothAudioLEAudioOnly").unwrap_or(false);
3116 
3117         // A2DP
3118         let a2dp_dispatcher = get_a2dp_dispatcher(self.tx.clone());
3119         self.a2dp.initialize(a2dp_dispatcher);
3120 
3121         // AVRCP
3122         let avrcp_dispatcher = get_avrcp_dispatcher(self.tx.clone());
3123         self.avrcp.initialize(avrcp_dispatcher);
3124 
3125         // HFP
3126         let hfp_dispatcher = get_hfp_dispatcher(self.tx.clone());
3127         self.hfp.initialize(hfp_dispatcher);
3128 
3129         // LEA
3130         let le_audio_dispatcher = get_le_audio_dispatcher(self.tx.clone());
3131         self.le_audio.initialize(le_audio_dispatcher);
3132 
3133         // VC
3134         let vc_dispatcher = get_vc_dispatcher(self.tx.clone());
3135         self.vc.initialize(vc_dispatcher);
3136 
3137         // CSIS
3138         let csis_dispatcher = get_csis_dispatcher(self.tx.clone());
3139         self.csis.initialize(csis_dispatcher);
3140 
3141         // TODO(b/284811956) A2DP needs to be enabled before AVRCP otherwise AVRCP gets memset'd.
3142         // Iterate the delay_enable_profiles hashmap directly when this is fixed.
3143         for profile in MEDIA_PROFILE_ENABLE_ORDER {
3144             if self.delay_enable_profiles.contains(&profile) {
3145                 self.enable_profile(&profile);
3146             }
3147         }
3148         let api_tx = self.api_tx.clone();
3149         tokio::spawn(async move {
3150             // TODO(b:300202052) make sure media interface is exposed after initialized
3151             let _ = api_tx.send(APIMessage::IsReady(BluetoothAPI::Media)).await;
3152         });
3153         true
3154     }
3155 
connect_lea_group_by_member_address(&mut self, addr: RawAddress)3156     fn connect_lea_group_by_member_address(&mut self, addr: RawAddress) {
3157         // Note that at this point the scanning of profiles may be incomplete,
3158         // TODO(b/335780769): connect to available profiles and ensure
3159         // this function is invoked whenever there is an incremental
3160         // discovery of LE audio profiles.
3161         for profile in MEDIA_LE_AUDIO_PROFILES {
3162             match profile {
3163                 Profile::LeAudio => {
3164                     self.connect_lea(addr);
3165                 }
3166                 Profile::VolumeControl => {
3167                     self.connect_vc(addr);
3168                 }
3169                 Profile::CoordinatedSet => {
3170                     self.connect_csis(addr);
3171                 }
3172                 _ => {}
3173             }
3174         }
3175     }
3176 
disconnect_lea_group_by_member_address(&mut self, addr: RawAddress)3177     fn disconnect_lea_group_by_member_address(&mut self, addr: RawAddress) {
3178         let group_id = self.get_group_id(addr);
3179         if group_id == LEA_UNKNOWN_GROUP_ID {
3180             warn!(
3181                 "disconnect_lea_group_by_member_address: [{}]: address belongs to no group",
3182                 DisplayAddress(&addr)
3183             );
3184             return;
3185         }
3186 
3187         let group = self.le_audio_groups.entry(group_id).or_default().clone();
3188 
3189         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3190 
3191         info!(
3192             "disconnect_lea_group_by_member_address: [{}]: available profiles: {:?}.",
3193             DisplayAddress(&addr),
3194             available_profiles
3195         );
3196 
3197         for &member_addr in group.devices.iter() {
3198             for profile in self.adapter_get_le_audio_profiles(addr) {
3199                 match profile {
3200                     Profile::LeAudio => {
3201                         self.disconnect_lea(member_addr);
3202                     }
3203                     Profile::VolumeControl => {
3204                         self.disconnect_vc(member_addr);
3205                     }
3206                     Profile::CoordinatedSet => {
3207                         self.disconnect_csis(member_addr);
3208                     }
3209                     _ => {}
3210                 }
3211             }
3212         }
3213     }
3214 
connect_lea(&mut self, addr: RawAddress)3215     fn connect_lea(&mut self, addr: RawAddress) {
3216         if !self.is_le_audio_only_enabled {
3217             warn!("connect_lea: LeAudioEnableLeAudioOnly is not set");
3218             return;
3219         }
3220 
3221         if *self.le_audio_states.get(&addr).unwrap_or(&BtLeAudioConnectionState::Disconnected)
3222             == BtLeAudioConnectionState::Connected
3223         {
3224             info!("connect_lea: already connected.");
3225             return;
3226         }
3227 
3228         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3229 
3230         info!(
3231             "connect_lea: [{}]: connecting, available profiles: {:?}.",
3232             DisplayAddress(&addr),
3233             available_profiles
3234         );
3235 
3236         self.le_audio.set_enable_state(addr, true);
3237         self.le_audio.connect(addr);
3238     }
3239 
disconnect_lea(&mut self, addr: RawAddress)3240     fn disconnect_lea(&mut self, addr: RawAddress) {
3241         if *self.le_audio_states.get(&addr).unwrap_or(&BtLeAudioConnectionState::Disconnected)
3242             == BtLeAudioConnectionState::Disconnected
3243         {
3244             info!("disconnect_lea: [{}]: already disconnected", DisplayAddress(&addr));
3245             return;
3246         }
3247 
3248         info!("disconnect_lea: [{}]: disconnecting", DisplayAddress(&addr));
3249 
3250         self.le_audio.set_enable_state(addr, false);
3251         self.le_audio.disconnect(addr);
3252     }
3253 
connect_vc(&mut self, addr: RawAddress)3254     fn connect_vc(&mut self, addr: RawAddress) {
3255         if !self.is_le_audio_only_enabled {
3256             warn!("connect_vc: LeAudioEnableLeAudioOnly is not set");
3257             return;
3258         }
3259 
3260         if *self.vc_states.get(&addr).unwrap_or(&BtVcConnectionState::Disconnected)
3261             == BtVcConnectionState::Connected
3262         {
3263             info!("connect_vc: already connected");
3264             return;
3265         }
3266 
3267         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3268 
3269         info!(
3270             "connect_vc: [{}]: connecting, available profiles: {:?}.",
3271             DisplayAddress(&addr),
3272             available_profiles
3273         );
3274 
3275         self.vc.connect(addr);
3276     }
3277 
disconnect_vc(&mut self, addr: RawAddress)3278     fn disconnect_vc(&mut self, addr: RawAddress) {
3279         if *self.vc_states.get(&addr).unwrap_or(&BtVcConnectionState::Disconnected)
3280             == BtVcConnectionState::Disconnected
3281         {
3282             info!("disconnect_vc: already disconnected");
3283             return;
3284         }
3285 
3286         info!("disconnect_vc: [{}]: disconnecting", DisplayAddress(&addr));
3287 
3288         self.vc.disconnect(addr);
3289     }
3290 
connect_csis(&mut self, addr: RawAddress)3291     fn connect_csis(&mut self, addr: RawAddress) {
3292         if !self.is_le_audio_only_enabled {
3293             warn!("connect_csis: LeAudioEnableLeAudioOnly is not set");
3294             return;
3295         }
3296 
3297         if *self.csis_states.get(&addr).unwrap_or(&BtCsisConnectionState::Disconnected)
3298             == BtCsisConnectionState::Connected
3299         {
3300             info!("connect_csis: already connected");
3301             return;
3302         }
3303 
3304         let available_profiles = self.adapter_get_le_audio_profiles(addr);
3305 
3306         info!(
3307             "connect_csis: [{}]: connecting, available profiles: {:?}.",
3308             DisplayAddress(&addr),
3309             available_profiles
3310         );
3311 
3312         self.csis.connect(addr);
3313     }
3314 
disconnect_csis(&mut self, addr: RawAddress)3315     fn disconnect_csis(&mut self, addr: RawAddress) {
3316         if *self.csis_states.get(&addr).unwrap_or(&BtCsisConnectionState::Disconnected)
3317             == BtCsisConnectionState::Disconnected
3318         {
3319             info!("disconnect_csis: already disconnected");
3320             return;
3321         }
3322 
3323         info!("disconnect_csis: [{}]: disconnecting", DisplayAddress(&addr));
3324 
3325         self.csis.disconnect(addr);
3326     }
3327 
connect(&mut self, addr: RawAddress)3328     fn connect(&mut self, addr: RawAddress) {
3329         if self.is_le_audio_only_enabled {
3330             warn!("connect: LeAudioEnableLeAudioOnly is set");
3331             return;
3332         }
3333 
3334         let available_profiles = self.adapter_get_classic_audio_profiles(addr);
3335 
3336         info!(
3337             "[{}]: Connecting to device, available profiles: {:?}.",
3338             DisplayAddress(&addr),
3339             available_profiles
3340         );
3341 
3342         let connected_profiles = self.connected_profiles.get(&addr).cloned().unwrap_or_default();
3343 
3344         // Sort here so the order of connection is always consistent
3345         let missing_profiles =
3346             available_profiles.difference(&connected_profiles).sorted().collect::<Vec<_>>();
3347 
3348         // Connect the profiles one-by-one so it won't stuck at the lower layer.
3349         // Therefore, just connect to one profile for now.
3350         // connect() will be called again after the first profile is successfully connected.
3351         let mut is_connect = false;
3352         for profile in missing_profiles {
3353             match profile {
3354                 Profile::A2dpSink => {
3355                     metrics::profile_connection_state_changed(
3356                         addr,
3357                         Profile::A2dpSink as u32,
3358                         BtStatus::Success,
3359                         BtavConnectionState::Connecting as u32,
3360                     );
3361                     let status = self.a2dp.connect(addr);
3362                     if BtStatus::Success != status {
3363                         metrics::profile_connection_state_changed(
3364                             addr,
3365                             Profile::A2dpSink as u32,
3366                             status,
3367                             BtavConnectionState::Disconnected as u32,
3368                         );
3369                     } else {
3370                         is_connect = true;
3371                         break;
3372                     }
3373                 }
3374                 Profile::Hfp => {
3375                     metrics::profile_connection_state_changed(
3376                         addr,
3377                         Profile::Hfp as u32,
3378                         BtStatus::Success,
3379                         BtavConnectionState::Connecting as u32,
3380                     );
3381                     let status = self.hfp.connect(addr);
3382                     if BtStatus::Success != status {
3383                         metrics::profile_connection_state_changed(
3384                             addr,
3385                             Profile::Hfp as u32,
3386                             status,
3387                             BthfConnectionState::Disconnected as u32,
3388                         );
3389                     } else {
3390                         is_connect = true;
3391                         break;
3392                     }
3393                 }
3394                 Profile::AvrcpController => {
3395                     // Fluoride will resolve AVRCP as a part of A2DP connection request.
3396                     // Explicitly connect to it only when it is considered missing, and don't
3397                     // bother about it when A2DP is not connected.
3398                     if !connected_profiles.contains(&Profile::A2dpSink) {
3399                         continue;
3400                     }
3401 
3402                     metrics::profile_connection_state_changed(
3403                         addr,
3404                         Profile::AvrcpController as u32,
3405                         BtStatus::Success,
3406                         BtavConnectionState::Connecting as u32,
3407                     );
3408                     self.avrcp_states.insert(addr, BtavConnectionState::Connecting);
3409                     let status = self.avrcp.connect(addr);
3410                     if BtStatus::Success != status {
3411                         // Reset direction to unknown.
3412                         self.avrcp_states.remove(&addr);
3413                         metrics::profile_connection_state_changed(
3414                             addr,
3415                             Profile::AvrcpController as u32,
3416                             status,
3417                             BtavConnectionState::Disconnected as u32,
3418                         );
3419                     } else {
3420                         is_connect = true;
3421                         break;
3422                     }
3423                 }
3424                 _ => warn!("Unknown profile: {:?}", profile),
3425             }
3426         }
3427 
3428         if is_connect {
3429             let mut tasks = self.fallback_tasks.lock().unwrap();
3430             let mut states = self.device_states.lock().unwrap();
3431             if let std::collections::hash_map::Entry::Vacant(e) = tasks.entry(addr) {
3432                 states.insert(addr, DeviceConnectionStates::Initiating);
3433 
3434                 let fallback_tasks = self.fallback_tasks.clone();
3435                 let device_states = self.device_states.clone();
3436                 let now_ts = Instant::now();
3437                 let task = topstack::get_runtime().spawn(async move {
3438                     sleep(Duration::from_secs(CONNECT_AS_INITIATOR_TIMEOUT_SEC)).await;
3439 
3440                     // If here the task is not yet aborted, probably connection is failed,
3441                     // therefore here we release the states. Even if later the connection is
3442                     // actually successful, we will just treat this as if the connection is
3443                     // initiated by the peer and will reconnect the missing profiles after
3444                     // some time, so it's safe.
3445                     {
3446                         device_states.lock().unwrap().remove(&addr);
3447                         fallback_tasks.lock().unwrap().remove(&addr);
3448                     }
3449                 });
3450                 e.insert(Some((task, now_ts)));
3451             }
3452         }
3453     }
3454 
is_initialized(&self) -> bool3455     fn is_initialized(&self) -> bool {
3456         self.initialized
3457     }
3458 
cleanup(&mut self) -> bool3459     fn cleanup(&mut self) -> bool {
3460         self.cleanup()
3461     }
3462 
3463     // This may not disconnect all media profiles at once, but once the stack
3464     // is notified of the disconnection callback, `disconnect_device` will be
3465     // invoked as necessary to ensure the device is removed.
disconnect(&mut self, addr: RawAddress)3466     fn disconnect(&mut self, addr: RawAddress) {
3467         if self.is_le_audio_only_enabled {
3468             warn!("LeAudioEnableLeAudioOnly is set");
3469             return;
3470         }
3471 
3472         let connected_profiles = match self.connected_profiles.get(&addr) {
3473             Some(profiles) => profiles,
3474             None => {
3475                 warn!(
3476                     "[{}]: Ignoring disconnection request since there is no connected profile.",
3477                     DisplayAddress(&addr)
3478                 );
3479                 return;
3480             }
3481         };
3482 
3483         for profile in connected_profiles {
3484             match profile {
3485                 Profile::A2dpSink => {
3486                     // Some headsets (b/278963515) will try reconnecting to A2DP
3487                     // when HFP is running but (requested to be) disconnected.
3488                     // TODO: Remove this workaround once proper fix lands.
3489                     if connected_profiles.contains(&Profile::Hfp) {
3490                         continue;
3491                     }
3492                     metrics::profile_connection_state_changed(
3493                         addr,
3494                         Profile::A2dpSink as u32,
3495                         BtStatus::Success,
3496                         BtavConnectionState::Disconnecting as u32,
3497                     );
3498                     let status = self.a2dp.disconnect(addr);
3499                     if BtStatus::Success != status {
3500                         metrics::profile_connection_state_changed(
3501                             addr,
3502                             Profile::A2dpSource as u32,
3503                             status,
3504                             BtavConnectionState::Disconnected as u32,
3505                         );
3506                     }
3507                 }
3508                 Profile::Hfp => {
3509                     metrics::profile_connection_state_changed(
3510                         addr,
3511                         Profile::Hfp as u32,
3512                         BtStatus::Success,
3513                         BthfConnectionState::Disconnecting as u32,
3514                     );
3515                     let status = self.hfp.disconnect(addr);
3516                     if BtStatus::Success != status {
3517                         metrics::profile_connection_state_changed(
3518                             addr,
3519                             Profile::Hfp as u32,
3520                             status,
3521                             BthfConnectionState::Disconnected as u32,
3522                         );
3523                     }
3524                 }
3525                 Profile::AvrcpController => {
3526                     if connected_profiles.contains(&Profile::A2dpSink) {
3527                         continue;
3528                     }
3529                     metrics::profile_connection_state_changed(
3530                         addr,
3531                         Profile::AvrcpController as u32,
3532                         BtStatus::Success,
3533                         BtavConnectionState::Disconnecting as u32,
3534                     );
3535                     self.avrcp_states.insert(addr, BtavConnectionState::Disconnecting);
3536                     let status = self.avrcp.disconnect(addr);
3537                     if BtStatus::Success != status {
3538                         // Reset direction to unknown.
3539                         self.avrcp_states.remove(&addr);
3540                         metrics::profile_connection_state_changed(
3541                             addr,
3542                             Profile::AvrcpController as u32,
3543                             status,
3544                             BtavConnectionState::Disconnected as u32,
3545                         );
3546                     }
3547                 }
3548                 _ => warn!("Unknown profile: {:?}", profile),
3549             }
3550         }
3551     }
3552 
set_active_device(&mut self, addr: RawAddress)3553     fn set_active_device(&mut self, addr: RawAddress) {
3554         match self.a2dp_states.get(&addr) {
3555             Some(BtavConnectionState::Connected) => {
3556                 self.a2dp.set_active_device(addr);
3557                 self.uinput.set_active_device(addr.to_string());
3558             }
3559             _ => warn!("[{}] Not connected or disconnected A2DP address", DisplayAddress(&addr)),
3560         };
3561     }
3562 
reset_active_device(&mut self)3563     fn reset_active_device(&mut self) {
3564         // During MPS tests, there might be some A2DP stream manipulation unexpected to CRAS.
3565         // CRAS would then attempt to reset the active device. Ignore it during test.
3566         if !self.is_complete_profiles_required() {
3567             return;
3568         }
3569 
3570         self.a2dp.set_active_device(RawAddress::empty());
3571         self.uinput.set_active_device(RawAddress::empty().to_string());
3572     }
3573 
set_hfp_active_device(&mut self, addr: RawAddress)3574     fn set_hfp_active_device(&mut self, addr: RawAddress) {
3575         if self.hfp_states.get(&addr) == Some(&BthfConnectionState::SlcConnected) {
3576             self.hfp.set_active_device(addr);
3577         } else {
3578             warn!("[{}] Not connected or disconnected HFP address", DisplayAddress(&addr));
3579         }
3580     }
3581 
set_audio_config( &mut self, addr: RawAddress, codec_type: A2dpCodecIndex, sample_rate: A2dpCodecSampleRate, bits_per_sample: A2dpCodecBitsPerSample, channel_mode: A2dpCodecChannelMode, ) -> bool3582     fn set_audio_config(
3583         &mut self,
3584         addr: RawAddress,
3585         codec_type: A2dpCodecIndex,
3586         sample_rate: A2dpCodecSampleRate,
3587         bits_per_sample: A2dpCodecBitsPerSample,
3588         channel_mode: A2dpCodecChannelMode,
3589     ) -> bool {
3590         if self.a2dp_states.get(&addr).is_none() {
3591             warn!(
3592                 "[{}]: Ignore set config event for unconnected or disconnected A2DP device",
3593                 DisplayAddress(&addr)
3594             );
3595             return false;
3596         }
3597 
3598         let caps = self.a2dp_caps.get(&addr).unwrap_or(&Vec::new()).to_vec();
3599 
3600         for cap in &caps {
3601             if A2dpCodecIndex::from(cap.codec_type) == codec_type {
3602                 if (A2dpCodecSampleRate::from_bits(cap.sample_rate).unwrap() & sample_rate)
3603                     != sample_rate
3604                 {
3605                     warn!("Unsupported sample rate {:?}", sample_rate);
3606                     return false;
3607                 }
3608                 if (A2dpCodecBitsPerSample::from_bits(cap.bits_per_sample).unwrap()
3609                     & bits_per_sample)
3610                     != bits_per_sample
3611                 {
3612                     warn!("Unsupported bit depth {:?}", bits_per_sample);
3613                     return false;
3614                 }
3615                 if (A2dpCodecChannelMode::from_bits(cap.channel_mode).unwrap() & channel_mode)
3616                     != channel_mode
3617                 {
3618                     warn!("Unsupported channel mode {:?}", channel_mode);
3619                     return false;
3620                 }
3621 
3622                 let config = vec![A2dpCodecConfig {
3623                     codec_type: codec_type as i32,
3624                     codec_priority: A2dpCodecPriority::Highest as i32,
3625                     sample_rate: sample_rate.bits(),
3626                     bits_per_sample: bits_per_sample.bits(),
3627                     channel_mode: channel_mode.bits(),
3628                     ..Default::default()
3629                 }];
3630 
3631                 self.a2dp.config_codec(addr, config);
3632                 return true;
3633             }
3634         }
3635 
3636         warn!("Unsupported codec type {:?}", codec_type);
3637         false
3638     }
3639 
set_volume(&mut self, volume: u8)3640     fn set_volume(&mut self, volume: u8) {
3641         // Guard the range 0-127 by the try_from cast from u8 to i8.
3642         let vol = match i8::try_from(volume) {
3643             Ok(val) => val,
3644             _ => {
3645                 warn!("Ignore invalid volume {}", volume);
3646                 return;
3647             }
3648         };
3649 
3650         // There is always no more than one active media connection, which
3651         // implies only one address is connected with AVRCP.
3652         for (addr, profiles) in &self.connected_profiles {
3653             if profiles.contains(&Profile::AvrcpController) {
3654                 self.avrcp.set_volume(*addr, vol);
3655             }
3656         }
3657     }
3658 
set_hfp_volume(&mut self, volume: u8, addr: RawAddress)3659     fn set_hfp_volume(&mut self, volume: u8, addr: RawAddress) {
3660         let vol = match i8::try_from(volume) {
3661             Ok(val) if val <= 15 => val,
3662             _ => {
3663                 warn!("[{}]: Ignore invalid volume {}", DisplayAddress(&addr), volume);
3664                 return;
3665             }
3666         };
3667 
3668         if self.hfp_states.get(&addr).is_none() {
3669             warn!(
3670                 "[{}]: Ignore volume event for unconnected or disconnected HFP device",
3671                 DisplayAddress(&addr)
3672             );
3673             return;
3674         }
3675 
3676         self.hfp.set_volume(vol, addr);
3677     }
3678 
start_audio_request(&mut self, connection_listener: File) -> bool3679     fn start_audio_request(&mut self, connection_listener: File) -> bool {
3680         if self.a2dp_audio_connection_listener.is_some() {
3681             warn!("start_audio_request: replacing an unresolved listener");
3682         }
3683 
3684         self.a2dp_audio_connection_listener = Some(connection_listener);
3685         self.start_audio_request_impl()
3686     }
3687 
stop_audio_request(&mut self, connection_listener: File)3688     fn stop_audio_request(&mut self, connection_listener: File) {
3689         debug!("Stop audio request");
3690 
3691         if self.a2dp_audio_connection_listener.is_some() {
3692             warn!("stop_audio_request: replacing an unresolved listener");
3693         }
3694 
3695         self.a2dp_audio_connection_listener = Some(connection_listener);
3696 
3697         self.a2dp.stop_audio_request();
3698     }
3699 
start_sco_call( &mut self, address: RawAddress, sco_offload: bool, disabled_codecs: HfpCodecBitId, connection_listener: File, ) -> bool3700     fn start_sco_call(
3701         &mut self,
3702         address: RawAddress,
3703         sco_offload: bool,
3704         disabled_codecs: HfpCodecBitId,
3705         connection_listener: File,
3706     ) -> bool {
3707         if self.hfp_audio_connection_listener.is_some() {
3708             warn!("start_sco_call: replacing an unresolved listener");
3709         }
3710 
3711         self.hfp_audio_connection_listener = Some(connection_listener);
3712         self.start_sco_call_impl(address, sco_offload, disabled_codecs)
3713     }
3714 
stop_sco_call(&mut self, address: RawAddress, listener: File)3715     fn stop_sco_call(&mut self, address: RawAddress, listener: File) {
3716         if self.hfp_audio_connection_listener.is_some() {
3717             warn!("stop_sco_call: replacing an unresolved listener");
3718         }
3719 
3720         self.hfp_audio_connection_listener = Some(listener);
3721         self.stop_sco_call_impl(address)
3722     }
3723 
get_a2dp_audio_started(&mut self, addr: RawAddress) -> bool3724     fn get_a2dp_audio_started(&mut self, addr: RawAddress) -> bool {
3725         match self.a2dp_audio_state.get(&addr) {
3726             Some(BtavAudioState::Started) => true,
3727             _ => false,
3728         }
3729     }
3730 
get_hfp_audio_final_codecs(&mut self, addr: RawAddress) -> u83731     fn get_hfp_audio_final_codecs(&mut self, addr: RawAddress) -> u8 {
3732         match self.hfp_audio_state.get(&addr) {
3733             Some(BthfAudioState::Connected) => match self.hfp_cap.get(&addr) {
3734                 Some(caps)
3735                     if (*caps & HfpCodecFormat::LC3_TRANSPARENT)
3736                         == HfpCodecFormat::LC3_TRANSPARENT =>
3737                 {
3738                     HfpCodecBitId::LC3
3739                 }
3740                 Some(caps) if (*caps & HfpCodecFormat::MSBC) == HfpCodecFormat::MSBC => {
3741                     HfpCodecBitId::MSBC
3742                 }
3743                 Some(caps)
3744                     if (*caps & HfpCodecFormat::MSBC_TRANSPARENT)
3745                         == HfpCodecFormat::MSBC_TRANSPARENT =>
3746                 {
3747                     HfpCodecBitId::MSBC
3748                 }
3749                 Some(caps) if (*caps & HfpCodecFormat::CVSD) == HfpCodecFormat::CVSD => {
3750                     HfpCodecBitId::CVSD
3751                 }
3752                 _ => {
3753                     warn!("hfp_cap not found, fallback to CVSD.");
3754                     HfpCodecBitId::CVSD
3755                 }
3756             },
3757             _ => HfpCodecBitId::NONE,
3758         }
3759         .try_into()
3760         .unwrap()
3761     }
3762 
get_presentation_position(&mut self) -> PresentationPosition3763     fn get_presentation_position(&mut self) -> PresentationPosition {
3764         let position = self.a2dp.get_presentation_position();
3765         PresentationPosition {
3766             remote_delay_report_ns: position.remote_delay_report_ns,
3767             total_bytes_read: position.total_bytes_read,
3768             data_position_sec: position.data_position_sec,
3769             data_position_nsec: position.data_position_nsec,
3770         }
3771     }
3772 
set_player_playback_status(&mut self, status: String)3773     fn set_player_playback_status(&mut self, status: String) {
3774         debug!("AVRCP received player playback status: {}", status);
3775         self.avrcp.set_playback_status(&status);
3776     }
set_player_position(&mut self, position_us: i64)3777     fn set_player_position(&mut self, position_us: i64) {
3778         debug!("AVRCP received player position: {}", position_us);
3779         self.avrcp.set_position(position_us);
3780     }
set_player_metadata(&mut self, metadata: PlayerMetadata)3781     fn set_player_metadata(&mut self, metadata: PlayerMetadata) {
3782         debug!("AVRCP received player metadata: {:?}", metadata);
3783         self.avrcp.set_metadata(&metadata);
3784     }
3785 
trigger_debug_dump(&mut self)3786     fn trigger_debug_dump(&mut self) {
3787         self.hfp.debug_dump();
3788     }
3789 
group_set_active(&mut self, group_id: i32)3790     fn group_set_active(&mut self, group_id: i32) {
3791         self.le_audio.group_set_active(group_id);
3792     }
3793 
source_metadata_changed( &mut self, usage: BtLeAudioUsage, content_type: BtLeAudioContentType, gain: f64, ) -> bool3794     fn source_metadata_changed(
3795         &mut self,
3796         usage: BtLeAudioUsage,
3797         content_type: BtLeAudioContentType,
3798         gain: f64,
3799     ) -> bool {
3800         let data = vec![SourceMetadata { usage, content_type, gain }];
3801         self.le_audio.source_metadata_changed(data);
3802         true
3803     }
3804 
sink_metadata_changed(&mut self, source: BtLeAudioSource, gain: f64) -> bool3805     fn sink_metadata_changed(&mut self, source: BtLeAudioSource, gain: f64) -> bool {
3806         let data = vec![SinkMetadata { source, gain }];
3807         self.le_audio.sink_metadata_changed(data);
3808         true
3809     }
3810 
host_start_audio_request(&mut self) -> bool3811     fn host_start_audio_request(&mut self) -> bool {
3812         self.le_audio.host_start_audio_request()
3813     }
3814 
host_stop_audio_request(&mut self)3815     fn host_stop_audio_request(&mut self) {
3816         self.le_audio.host_stop_audio_request();
3817     }
3818 
peer_start_audio_request(&mut self) -> bool3819     fn peer_start_audio_request(&mut self) -> bool {
3820         self.le_audio.peer_start_audio_request()
3821     }
3822 
peer_stop_audio_request(&mut self)3823     fn peer_stop_audio_request(&mut self) {
3824         self.le_audio.peer_stop_audio_request();
3825     }
3826 
get_host_pcm_config(&mut self) -> BtLePcmConfig3827     fn get_host_pcm_config(&mut self) -> BtLePcmConfig {
3828         self.le_audio.get_host_pcm_config()
3829     }
3830 
get_peer_pcm_config(&mut self) -> BtLePcmConfig3831     fn get_peer_pcm_config(&mut self) -> BtLePcmConfig {
3832         self.le_audio.get_peer_pcm_config()
3833     }
3834 
get_host_stream_started(&mut self) -> BtLeStreamStartedStatus3835     fn get_host_stream_started(&mut self) -> BtLeStreamStartedStatus {
3836         self.le_audio.get_host_stream_started()
3837     }
3838 
get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus3839     fn get_peer_stream_started(&mut self) -> BtLeStreamStartedStatus {
3840         self.le_audio.get_peer_stream_started()
3841     }
3842 
get_unicast_monitor_mode_status( &mut self, direction: BtLeAudioDirection, ) -> BtLeAudioUnicastMonitorModeStatus3843     fn get_unicast_monitor_mode_status(
3844         &mut self,
3845         direction: BtLeAudioDirection,
3846     ) -> BtLeAudioUnicastMonitorModeStatus {
3847         *self
3848             .le_audio_unicast_monitor_mode_status
3849             .get(&direction.into())
3850             .unwrap_or(&BtLeAudioUnicastMonitorModeStatus::StreamingSuspended)
3851     }
3852 
get_group_stream_status(&mut self, group_id: i32) -> BtLeAudioGroupStreamStatus3853     fn get_group_stream_status(&mut self, group_id: i32) -> BtLeAudioGroupStreamStatus {
3854         if self.le_audio_groups.get(&group_id).is_none() {
3855             return BtLeAudioGroupStreamStatus::Idle;
3856         }
3857 
3858         self.le_audio_groups.get(&group_id).unwrap().stream_status
3859     }
3860 
get_group_status(&mut self, group_id: i32) -> BtLeAudioGroupStatus3861     fn get_group_status(&mut self, group_id: i32) -> BtLeAudioGroupStatus {
3862         if self.le_audio_groups.get(&group_id).is_none() {
3863             return BtLeAudioGroupStatus::Inactive;
3864         }
3865 
3866         self.le_audio_groups.get(&group_id).unwrap().status
3867     }
3868 
set_group_volume(&mut self, group_id: i32, volume: u8)3869     fn set_group_volume(&mut self, group_id: i32, volume: u8) {
3870         self.vc.set_volume(group_id, volume);
3871     }
3872 }
3873 
3874 impl IBluetoothTelephony for BluetoothMedia {
register_telephony_callback( &mut self, callback: Box<dyn IBluetoothTelephonyCallback + Send>, ) -> bool3875     fn register_telephony_callback(
3876         &mut self,
3877         callback: Box<dyn IBluetoothTelephonyCallback + Send>,
3878     ) -> bool {
3879         let _id = self.telephony_callbacks.lock().unwrap().add_callback(callback);
3880         true
3881     }
3882 
set_network_available(&mut self, network_available: bool)3883     fn set_network_available(&mut self, network_available: bool) {
3884         if self.telephony_device_status.network_available == network_available {
3885             return;
3886         }
3887         self.telephony_device_status.network_available = network_available;
3888         self.device_status_notification();
3889     }
3890 
set_roaming(&mut self, roaming: bool)3891     fn set_roaming(&mut self, roaming: bool) {
3892         if self.telephony_device_status.roaming == roaming {
3893             return;
3894         }
3895         self.telephony_device_status.roaming = roaming;
3896         self.device_status_notification();
3897     }
3898 
set_signal_strength(&mut self, signal_strength: i32) -> bool3899     fn set_signal_strength(&mut self, signal_strength: i32) -> bool {
3900         if !(0..=5).contains(&signal_strength) {
3901             warn!("Invalid signal strength, got {}, want 0 to 5", signal_strength);
3902             return false;
3903         }
3904         if self.telephony_device_status.signal_strength == signal_strength {
3905             return true;
3906         }
3907 
3908         self.telephony_device_status.signal_strength = signal_strength;
3909         self.device_status_notification();
3910 
3911         true
3912     }
3913 
set_battery_level(&mut self, battery_level: i32) -> bool3914     fn set_battery_level(&mut self, battery_level: i32) -> bool {
3915         if !(0..=5).contains(&battery_level) {
3916             warn!("Invalid battery level, got {}, want 0 to 5", battery_level);
3917             return false;
3918         }
3919         if self.telephony_device_status.battery_level == battery_level {
3920             return true;
3921         }
3922 
3923         self.telephony_device_status.battery_level = battery_level;
3924         self.device_status_notification();
3925 
3926         true
3927     }
3928 
set_phone_ops_enabled(&mut self, enable: bool)3929     fn set_phone_ops_enabled(&mut self, enable: bool) {
3930         info!("Bluetooth HID telephony mode enabled");
3931         if self.phone_ops_enabled == enable {
3932             return;
3933         }
3934 
3935         self.call_list = vec![];
3936         self.phone_state.num_active = 0;
3937         self.phone_state.num_held = 0;
3938         self.phone_state.state = CallState::Idle;
3939         self.memory_dialing_number = None;
3940         self.last_dialing_number = None;
3941         self.a2dp_has_interrupted_stream = false;
3942 
3943         self.phone_ops_enabled = enable;
3944         if self.hfp_audio_state.keys().any(|addr| self.should_insert_call_when_sco_start(*addr))
3945             && self.hfp_audio_state.values().any(|x| x == &BthfAudioState::Connected)
3946         {
3947             self.place_active_call();
3948             return;
3949         }
3950 
3951         self.phone_state_change("".into());
3952     }
3953 
set_mps_qualification_enabled(&mut self, enable: bool)3954     fn set_mps_qualification_enabled(&mut self, enable: bool) {
3955         info!("MPS qualification mode enabled");
3956         if self.mps_qualification_enabled == enable {
3957             return;
3958         }
3959 
3960         self.call_list = vec![];
3961         self.phone_state.num_active = 0;
3962         self.phone_state.num_held = 0;
3963         self.phone_state.state = CallState::Idle;
3964         self.memory_dialing_number = None;
3965         self.last_dialing_number = None;
3966         self.a2dp_has_interrupted_stream = false;
3967         self.mps_qualification_enabled = enable;
3968 
3969         if self.hfp_audio_state.keys().any(|addr| self.should_insert_call_when_sco_start(*addr))
3970             && self.hfp_audio_state.values().any(|x| x == &BthfAudioState::Connected)
3971         {
3972             self.place_active_call();
3973             return;
3974         }
3975 
3976         self.phone_state_change("".into());
3977     }
3978 
incoming_call(&mut self, number: String) -> bool3979     fn incoming_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.incoming_call_impl(number)
3985     }
3986 
dialing_call(&mut self, number: String) -> bool3987     fn dialing_call(&mut self, number: String) -> bool {
3988         if !self.mps_qualification_enabled {
3989             warn!("Unexpected incoming_call dbus command. mps_qualification_enabled does not enabled.");
3990             return false;
3991         }
3992         self.dialing_call_impl(number, None)
3993     }
3994 
answer_call(&mut self) -> bool3995     fn answer_call(&mut self) -> bool {
3996         if !self.mps_qualification_enabled {
3997             warn!(
3998                 "Unexpected answer_call dbus command. mps_qualification_enabled does not enabled."
3999             );
4000             return false;
4001         }
4002         self.answer_call_impl()
4003     }
4004 
hangup_call(&mut self) -> bool4005     fn hangup_call(&mut self) -> bool {
4006         if !self.mps_qualification_enabled {
4007             warn!(
4008                 "Unexpected hangup_call dbus command. mps_qualification_enabled does not enabled."
4009             );
4010             return false;
4011         }
4012         self.hangup_call_impl()
4013     }
4014 
set_memory_call(&mut self, number: Option<String>) -> bool4015     fn set_memory_call(&mut self, number: Option<String>) -> bool {
4016         if !self.mps_qualification_enabled {
4017             warn!("Unexpected set_memory_call dbus command. mps_qualification_enabled does not enabled.");
4018             return false;
4019         }
4020         self.memory_dialing_number = number;
4021         true
4022     }
4023 
set_last_call(&mut self, number: Option<String>) -> bool4024     fn set_last_call(&mut self, number: Option<String>) -> bool {
4025         if !self.mps_qualification_enabled {
4026             warn!("Unexpected set_last_call dbus command. mps_qualification_enabled does not enabled.");
4027             return false;
4028         }
4029         self.last_dialing_number = number;
4030         true
4031     }
4032 
release_held(&mut self) -> bool4033     fn release_held(&mut self) -> bool {
4034         if !self.mps_qualification_enabled {
4035             warn!(
4036                 "Unexpected release_held dbus command. mps_qualification_enabled does not enabled."
4037             );
4038             return false;
4039         }
4040         self.release_held_impl(None)
4041     }
4042 
release_active_accept_held(&mut self) -> bool4043     fn release_active_accept_held(&mut self) -> bool {
4044         if !self.mps_qualification_enabled {
4045             warn!("Unexpected release_active_accept_held dbus command. mps_qualification_enabled does not enabled.");
4046             return false;
4047         }
4048         self.release_active_accept_held_impl(None)
4049     }
4050 
hold_active_accept_held(&mut self) -> bool4051     fn hold_active_accept_held(&mut self) -> bool {
4052         if !self.mps_qualification_enabled {
4053             warn!("Unexpected hold_active_accept_held dbus command. mps_qualification_enabled does not enabled.");
4054             return false;
4055         }
4056         self.hold_active_accept_held_impl(None)
4057     }
4058 
audio_connect(&mut self, address: RawAddress) -> bool4059     fn audio_connect(&mut self, address: RawAddress) -> bool {
4060         self.start_sco_call_impl(address, false, HfpCodecBitId::NONE)
4061     }
4062 
audio_disconnect(&mut self, address: RawAddress)4063     fn audio_disconnect(&mut self, address: RawAddress) {
4064         self.stop_sco_call_impl(address)
4065     }
4066 }
4067 
4068 struct BatteryProviderCallback {}
4069 
4070 impl BatteryProviderCallback {
new() -> Self4071     fn new() -> Self {
4072         Self {}
4073     }
4074 }
4075 
4076 impl IBatteryProviderCallback for BatteryProviderCallback {
4077     // We do not support refreshing HFP battery information.
refresh_battery_info(&mut self)4078     fn refresh_battery_info(&mut self) {}
4079 }
4080 
4081 impl RPCProxy for BatteryProviderCallback {
get_object_id(&self) -> String4082     fn get_object_id(&self) -> String {
4083         "HFP BatteryProvider Callback".to_string()
4084     }
4085 }
4086