• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Anything related to audio and media API.
2 
3 use bt_topshim::btif::{
4     BluetoothInterface, BtBondState, BtConnectionDirection, BtStatus, DisplayAddress, RawAddress,
5     ToggleableProfile,
6 };
7 use bt_topshim::profiles::a2dp::{
8     A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
9     A2dpCodecConfig, A2dpCodecSampleRate, BtavAudioState, BtavConnectionState,
10     PresentationPosition,
11 };
12 use bt_topshim::profiles::avrcp::{
13     Avrcp, AvrcpCallbacks, AvrcpCallbacksDispatcher, PlayerMetadata,
14 };
15 use bt_topshim::profiles::hfp::{
16     BthfAudioState, BthfConnectionState, CallHoldCommand, CallInfo, CallState, Hfp, HfpCallbacks,
17     HfpCallbacksDispatcher, HfpCodecCapability, PhoneState, TelephonyDeviceStatus,
18 };
19 use bt_topshim::profiles::ProfileConnectionState;
20 use bt_topshim::{metrics, topstack};
21 use bt_utils::uinput::UInput;
22 
23 use itertools::Itertools;
24 use log::{debug, info, warn};
25 use std::collections::{HashMap, HashSet};
26 use std::convert::TryFrom;
27 use std::sync::Arc;
28 use std::sync::Mutex;
29 
30 use tokio::sync::mpsc::Sender;
31 use tokio::task::JoinHandle;
32 use tokio::time::{sleep, Duration, Instant};
33 
34 use crate::battery_manager::{Battery, BatterySet};
35 use crate::battery_provider_manager::{
36     BatteryProviderManager, IBatteryProviderCallback, IBatteryProviderManager,
37 };
38 use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth};
39 use crate::callbacks::Callbacks;
40 use crate::uuid;
41 use crate::uuid::Profile;
42 use crate::{Message, RPCProxy};
43 
44 // The timeout we have to wait for all supported profiles to connect after we
45 // receive the first profile connected event. The host shall disconnect the
46 // device after this many seconds of timeout.
47 const PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 10;
48 // The timeout we have to wait for the initiator peer device to complete the
49 // initial profile connection. After this many seconds, we will begin to
50 // connect the missing profiles.
51 // 6s is set to align with Android's default. See "btservice/PhonePolicy".
52 const CONNECT_MISSING_PROFILES_TIMEOUT_SEC: u64 = 6;
53 // The duration we assume the role of the initiator, i.e. the side that starts
54 // the profile connection. If the profile is connected before this many seconds,
55 // we assume we are the initiator and can keep connecting the remaining
56 // profiles, otherwise we wait for the peer initiator.
57 // Set to 5s to align with default page timeout (BT spec vol 4 part E sec 6.6)
58 const CONNECT_AS_INITIATOR_TIMEOUT_SEC: u64 = 5;
59 
60 /// The list of profiles we consider as audio profiles for media.
61 const MEDIA_AUDIO_PROFILES: &[uuid::Profile] =
62     &[uuid::Profile::A2dpSink, uuid::Profile::Hfp, uuid::Profile::AvrcpController];
63 
64 pub trait IBluetoothMedia {
65     ///
register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool66     fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool;
67 
68     /// initializes media (both A2dp and AVRCP) stack
initialize(&mut self) -> bool69     fn initialize(&mut self) -> bool;
70 
71     /// clean up media stack
cleanup(&mut self) -> bool72     fn cleanup(&mut self) -> bool;
73 
74     /// connect to available but missing media profiles
connect(&mut self, address: String)75     fn connect(&mut self, address: String);
disconnect(&mut self, address: String)76     fn disconnect(&mut self, address: String);
77 
78     // Set the device as the active A2DP device
set_active_device(&mut self, address: String)79     fn set_active_device(&mut self, address: String);
80 
81     // Reset the active A2DP device
reset_active_device(&mut self)82     fn reset_active_device(&mut self);
83 
84     // Set the device as the active HFP device
set_hfp_active_device(&mut self, address: String)85     fn set_hfp_active_device(&mut self, address: String);
86 
set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, ) -> bool87     fn set_audio_config(
88         &mut self,
89         sample_rate: i32,
90         bits_per_sample: i32,
91         channel_mode: i32,
92     ) -> bool;
93 
94     // Set the A2DP/AVRCP volume. Valid volume specified by the spec should be
95     // in the range of 0-127.
set_volume(&mut self, volume: u8)96     fn set_volume(&mut self, volume: u8);
97 
98     // Set the HFP speaker volume. Valid volume specified by the HFP spec should
99     // be in the range of 0-15.
set_hfp_volume(&mut self, volume: u8, address: String)100     fn set_hfp_volume(&mut self, volume: u8, address: String);
start_audio_request(&mut self) -> bool101     fn start_audio_request(&mut self) -> bool;
stop_audio_request(&mut self)102     fn stop_audio_request(&mut self);
103 
104     /// Returns true iff A2DP audio has started.
get_a2dp_audio_started(&mut self, address: String) -> bool105     fn get_a2dp_audio_started(&mut self, address: String) -> bool;
106 
107     /// Returns the negotiated codec (CVSD=1, mSBC=2, LC3=4) to use if HFP audio has started.
108     /// Returns 0 if HFP audio hasn't started.
get_hfp_audio_final_codecs(&mut self, address: String) -> u8109     fn get_hfp_audio_final_codecs(&mut self, address: String) -> u8;
110 
get_presentation_position(&mut self) -> PresentationPosition111     fn get_presentation_position(&mut self) -> PresentationPosition;
112 
113     /// Start the SCO setup to connect audio
start_sco_call(&mut self, address: String, sco_offload: bool, force_cvsd: bool) -> bool114     fn start_sco_call(&mut self, address: String, sco_offload: bool, force_cvsd: bool) -> bool;
stop_sco_call(&mut self, address: String)115     fn stop_sco_call(&mut self, address: String);
116 
117     /// Set the current playback status: e.g., playing, paused, stopped, etc. The method is a copy
118     /// of the existing CRAS API, hence not following Floss API conventions.
set_player_playback_status(&mut self, status: String)119     fn set_player_playback_status(&mut self, status: String);
120     /// Set the position of the current media in microseconds. The method is a copy of the existing
121     /// CRAS API, hence not following Floss API conventions.
set_player_position(&mut self, position: i64)122     fn set_player_position(&mut self, position: i64);
123     /// Set the media metadata, including title, artist, album, and length. The method is a
124     /// copy of the existing CRAS API, hence not following Floss API conventions. PlayerMetadata is
125     /// a custom data type that requires special handlng.
set_player_metadata(&mut self, metadata: PlayerMetadata)126     fn set_player_metadata(&mut self, metadata: PlayerMetadata);
127 }
128 
129 pub trait IBluetoothMediaCallback: RPCProxy {
130     /// Triggered when a Bluetooth audio device is ready to be used. This should
131     /// only be triggered once for a device and send an event to clients. If the
132     /// device supports both HFP and A2DP, both should be ready when this is
133     /// triggered.
on_bluetooth_audio_device_added(&mut self, device: BluetoothAudioDevice)134     fn on_bluetooth_audio_device_added(&mut self, device: BluetoothAudioDevice);
135 
136     ///
on_bluetooth_audio_device_removed(&mut self, addr: String)137     fn on_bluetooth_audio_device_removed(&mut self, addr: String);
138 
139     ///
on_absolute_volume_supported_changed(&mut self, supported: bool)140     fn on_absolute_volume_supported_changed(&mut self, supported: bool);
141 
142     /// Triggered when a Bluetooth device triggers an AVRCP/A2DP volume change
143     /// event. We need to notify audio client to reflect the change on the audio
144     /// stack. The volume should be in the range of 0 to 127.
on_absolute_volume_changed(&mut self, volume: u8)145     fn on_absolute_volume_changed(&mut self, volume: u8);
146 
147     /// Triggered when a Bluetooth device triggers a HFP AT command (AT+VGS) to
148     /// notify AG about its speaker volume change. We need to notify audio
149     /// client to reflect the change on the audio stack. The volume should be
150     /// in the range of 0 to 15.
on_hfp_volume_changed(&mut self, volume: u8, addr: String)151     fn on_hfp_volume_changed(&mut self, volume: u8, addr: String);
152 
153     /// Triggered when HFP audio is disconnected, in which case it could be
154     /// waiting for the audio client to issue a reconnection request. We need
155     /// to notify audio client of this event for it to do appropriate handling.
on_hfp_audio_disconnected(&mut self, addr: String)156     fn on_hfp_audio_disconnected(&mut self, addr: String);
157 }
158 
159 pub trait IBluetoothTelephony {
160     /// Sets whether the device is connected to the cellular network.
set_network_available(&mut self, network_available: bool)161     fn set_network_available(&mut self, network_available: bool);
162     /// Sets whether the device is roaming.
set_roaming(&mut self, roaming: bool)163     fn set_roaming(&mut self, roaming: bool);
164     /// Sets the device signal strength, 0 to 5.
set_signal_strength(&mut self, signal_strength: i32) -> bool165     fn set_signal_strength(&mut self, signal_strength: i32) -> bool;
166     /// Sets the device battery level, 0 to 5.
set_battery_level(&mut self, battery_level: i32) -> bool167     fn set_battery_level(&mut self, battery_level: i32) -> bool;
168     /// Enables/disables phone operations.
169     /// The call state is fully reset whenever this is called.
set_phone_ops_enabled(&mut self, enable: bool)170     fn set_phone_ops_enabled(&mut self, enable: bool);
171     /// Acts like the AG received an incoming call.
incoming_call(&mut self, number: String) -> bool172     fn incoming_call(&mut self, number: String) -> bool;
173     /// Acts like dialing a call from the AG.
dialing_call(&mut self, number: String) -> bool174     fn dialing_call(&mut self, number: String) -> bool;
175     /// Acts like answering an incoming/dialing call from the AG.
answer_call(&mut self) -> bool176     fn answer_call(&mut self) -> bool;
177     /// Acts like hanging up an active/incoming/dialing call from the AG.
hangup_call(&mut self) -> bool178     fn hangup_call(&mut self) -> bool;
179     /// Sets/unsets the memory slot. Note that we store at most one memory
180     /// number and return it regardless of which slot is specified by HF.
set_memory_call(&mut self, number: Option<String>) -> bool181     fn set_memory_call(&mut self, number: Option<String>) -> bool;
182     /// Sets/unsets the last call.
set_last_call(&mut self, number: Option<String>) -> bool183     fn set_last_call(&mut self, number: Option<String>) -> bool;
184     /// Releases all of the held calls.
release_held(&mut self) -> bool185     fn release_held(&mut self) -> bool;
186     /// Releases the active call and accepts a held call.
release_active_accept_held(&mut self) -> bool187     fn release_active_accept_held(&mut self) -> bool;
188     /// Holds the active call and accepts a held call.
hold_active_accept_held(&mut self) -> bool189     fn hold_active_accept_held(&mut self) -> bool;
190     /// Establishes an audio connection to <address>.
audio_connect(&mut self, address: String) -> bool191     fn audio_connect(&mut self, address: String) -> bool;
192     /// Stops the audio connection to <address>.
audio_disconnect(&mut self, address: String)193     fn audio_disconnect(&mut self, address: String);
194 }
195 
196 /// Serializable device used in.
197 #[derive(Debug, Default, Clone)]
198 pub struct BluetoothAudioDevice {
199     pub address: String,
200     pub name: String,
201     pub a2dp_caps: Vec<A2dpCodecConfig>,
202     pub hfp_cap: HfpCodecCapability,
203     pub absolute_volume: bool,
204 }
205 
206 impl BluetoothAudioDevice {
new( address: String, name: String, a2dp_caps: Vec<A2dpCodecConfig>, hfp_cap: HfpCodecCapability, absolute_volume: bool, ) -> BluetoothAudioDevice207     pub(crate) fn new(
208         address: String,
209         name: String,
210         a2dp_caps: Vec<A2dpCodecConfig>,
211         hfp_cap: HfpCodecCapability,
212         absolute_volume: bool,
213     ) -> BluetoothAudioDevice {
214         BluetoothAudioDevice { address, name, a2dp_caps, hfp_cap, absolute_volume }
215     }
216 }
217 /// Actions that `BluetoothMedia` can take on behalf of the stack.
218 pub enum MediaActions {
219     Connect(String),
220     Disconnect(String),
221     ForceEnterConnected(String), // Only used for qualification.
222 }
223 
224 #[derive(Debug, Clone, PartialEq)]
225 enum DeviceConnectionStates {
226     Initiating,            // Some profile is connected, initiated from host side
227     ConnectingBeforeRetry, // Some profile is connected, probably initiated from peer side
228     ConnectingAfterRetry,  // Host initiated requests to missing profiles after timeout
229     FullyConnected,        // All profiles (excluding AVRCP) are connected
230     Disconnecting,         // Working towards disconnection of each connected profile
231 }
232 
233 pub struct BluetoothMedia {
234     intf: Arc<Mutex<BluetoothInterface>>,
235     battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
236     battery_provider_id: u32,
237     initialized: bool,
238     callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>,
239     tx: Sender<Message>,
240     adapter: Option<Arc<Mutex<Box<Bluetooth>>>>,
241     a2dp: Option<A2dp>,
242     avrcp: Option<Avrcp>,
243     avrcp_direction: BtConnectionDirection,
244     a2dp_states: HashMap<RawAddress, BtavConnectionState>,
245     a2dp_audio_state: HashMap<RawAddress, BtavAudioState>,
246     a2dp_has_interrupted_stream: bool, // Only used for qualification.
247     hfp: Option<Hfp>,
248     hfp_states: HashMap<RawAddress, BthfConnectionState>,
249     hfp_audio_state: HashMap<RawAddress, BthfAudioState>,
250     a2dp_caps: HashMap<RawAddress, Vec<A2dpCodecConfig>>,
251     hfp_cap: HashMap<RawAddress, HfpCodecCapability>,
252     fallback_tasks: Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
253     absolute_volume: bool,
254     uinput: UInput,
255     delay_enable_profiles: HashSet<uuid::Profile>,
256     connected_profiles: HashMap<RawAddress, HashSet<uuid::Profile>>,
257     device_states: Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
258     delay_volume_update: HashMap<uuid::Profile, u8>,
259     telephony_device_status: TelephonyDeviceStatus,
260     phone_state: PhoneState,
261     call_list: Vec<CallInfo>,
262     phone_ops_enabled: bool,
263     memory_dialing_number: Option<String>,
264     last_dialing_number: Option<String>,
265 }
266 
267 impl BluetoothMedia {
new( tx: Sender<Message>, intf: Arc<Mutex<BluetoothInterface>>, battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>, ) -> BluetoothMedia268     pub fn new(
269         tx: Sender<Message>,
270         intf: Arc<Mutex<BluetoothInterface>>,
271         battery_provider_manager: Arc<Mutex<Box<BatteryProviderManager>>>,
272     ) -> BluetoothMedia {
273         let battery_provider_id = battery_provider_manager
274             .lock()
275             .unwrap()
276             .register_battery_provider(Box::new(BatteryProviderCallback::new()));
277         BluetoothMedia {
278             intf,
279             battery_provider_manager,
280             battery_provider_id,
281             initialized: false,
282             callbacks: Arc::new(Mutex::new(Callbacks::new(
283                 tx.clone(),
284                 Message::MediaCallbackDisconnected,
285             ))),
286             tx,
287             adapter: None,
288             a2dp: None,
289             avrcp: None,
290             avrcp_direction: BtConnectionDirection::Unknown,
291             a2dp_states: HashMap::new(),
292             a2dp_audio_state: HashMap::new(),
293             a2dp_has_interrupted_stream: false,
294             hfp: None,
295             hfp_states: HashMap::new(),
296             hfp_audio_state: HashMap::new(),
297             a2dp_caps: HashMap::new(),
298             hfp_cap: HashMap::new(),
299             fallback_tasks: Arc::new(Mutex::new(HashMap::new())),
300             absolute_volume: false,
301             uinput: UInput::new(),
302             delay_enable_profiles: HashSet::new(),
303             connected_profiles: HashMap::new(),
304             device_states: Arc::new(Mutex::new(HashMap::new())),
305             delay_volume_update: HashMap::new(),
306             telephony_device_status: TelephonyDeviceStatus::new(),
307             phone_state: PhoneState { num_active: 0, num_held: 0, state: CallState::Idle },
308             call_list: vec![],
309             phone_ops_enabled: false,
310             memory_dialing_number: None,
311             last_dialing_number: None,
312         }
313     }
314 
is_profile_connected(&self, addr: &RawAddress, profile: &uuid::Profile) -> bool315     fn is_profile_connected(&self, addr: &RawAddress, profile: &uuid::Profile) -> bool {
316         self.is_any_profile_connected(addr, &[profile.clone()])
317     }
318 
is_any_profile_connected(&self, addr: &RawAddress, profiles: &[uuid::Profile]) -> bool319     fn is_any_profile_connected(&self, addr: &RawAddress, profiles: &[uuid::Profile]) -> bool {
320         if let Some(connected_profiles) = self.connected_profiles.get(addr) {
321             return profiles.iter().any(|p| connected_profiles.contains(&p));
322         }
323 
324         return false;
325     }
326 
add_connected_profile(&mut self, addr: RawAddress, profile: uuid::Profile)327     fn add_connected_profile(&mut self, addr: RawAddress, profile: uuid::Profile) {
328         if self.is_profile_connected(&addr, &profile) {
329             warn!("[{}]: profile is already connected", DisplayAddress(&addr));
330             return;
331         }
332 
333         self.connected_profiles.entry(addr).or_insert_with(HashSet::new).insert(profile);
334 
335         self.notify_media_capability_updated(addr);
336     }
337 
rm_connected_profile( &mut self, addr: RawAddress, profile: uuid::Profile, is_profile_critical: bool, )338     fn rm_connected_profile(
339         &mut self,
340         addr: RawAddress,
341         profile: uuid::Profile,
342         is_profile_critical: bool,
343     ) {
344         if !self.is_profile_connected(&addr, &profile) {
345             warn!("[{}]: profile is already disconnected", DisplayAddress(&addr));
346             return;
347         }
348 
349         self.connected_profiles.entry(addr).or_insert_with(HashSet::new).remove(&profile);
350         self.delay_volume_update.remove(&profile);
351 
352         if is_profile_critical && self.is_complete_profiles_required() {
353             self.notify_critical_profile_disconnected(addr);
354         }
355 
356         self.notify_media_capability_updated(addr);
357     }
358 
set_adapter(&mut self, adapter: Arc<Mutex<Box<Bluetooth>>>)359     pub fn set_adapter(&mut self, adapter: Arc<Mutex<Box<Bluetooth>>>) {
360         self.adapter = Some(adapter);
361     }
362 
enable_profile(&mut self, profile: &Profile)363     pub fn enable_profile(&mut self, profile: &Profile) {
364         match profile {
365             &Profile::A2dpSource => {
366                 if let Some(a2dp) = &mut self.a2dp {
367                     a2dp.enable();
368                 }
369             }
370             &Profile::AvrcpTarget => {
371                 if let Some(avrcp) = &mut self.avrcp {
372                     avrcp.enable();
373                 }
374             }
375             &Profile::Hfp => {
376                 if let Some(hfp) = &mut self.hfp {
377                     hfp.enable();
378                 }
379             }
380             _ => {
381                 warn!("Tried to enable {} in bluetooth_media", profile);
382                 return;
383             }
384         }
385 
386         if self.is_profile_enabled(profile).unwrap() {
387             self.delay_enable_profiles.remove(profile);
388         } else {
389             self.delay_enable_profiles.insert(profile.clone());
390         }
391     }
392 
disable_profile(&mut self, profile: &Profile)393     pub fn disable_profile(&mut self, profile: &Profile) {
394         match profile {
395             &Profile::A2dpSource => {
396                 if let Some(a2dp) = &mut self.a2dp {
397                     a2dp.disable();
398                 }
399             }
400             &Profile::AvrcpTarget => {
401                 if let Some(avrcp) = &mut self.avrcp {
402                     avrcp.disable();
403                 }
404             }
405             &Profile::Hfp => {
406                 if let Some(hfp) = &mut self.hfp {
407                     hfp.disable();
408                 }
409             }
410             _ => {
411                 warn!("Tried to disable {} in bluetooth_media", profile);
412                 return;
413             }
414         }
415 
416         self.delay_enable_profiles.remove(profile);
417     }
418 
is_profile_enabled(&self, profile: &Profile) -> Option<bool>419     pub fn is_profile_enabled(&self, profile: &Profile) -> Option<bool> {
420         match profile {
421             &Profile::A2dpSource => {
422                 Some(self.a2dp.as_ref().map_or(false, |a2dp| a2dp.is_enabled()))
423             }
424             &Profile::AvrcpTarget => {
425                 Some(self.avrcp.as_ref().map_or(false, |avrcp| avrcp.is_enabled()))
426             }
427             &Profile::Hfp => Some(self.hfp.as_ref().map_or(false, |hfp| hfp.is_enabled())),
428             _ => {
429                 warn!("Tried to query enablement status of {} in bluetooth_media", profile);
430                 None
431             }
432         }
433     }
434 
dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks)435     pub fn dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks) {
436         match cb {
437             A2dpCallbacks::ConnectionState(addr, state, error) => {
438                 if !self.a2dp_states.get(&addr).is_none()
439                     && state == *self.a2dp_states.get(&addr).unwrap()
440                 {
441                     return;
442                 }
443                 metrics::profile_connection_state_changed(
444                     addr,
445                     Profile::A2dpSink as u32,
446                     error.status,
447                     state.clone() as u32,
448                 );
449                 match state {
450                     BtavConnectionState::Connected => {
451                         info!("[{}]: a2dp connected.", DisplayAddress(&addr));
452                         self.a2dp_states.insert(addr, state);
453                         self.add_connected_profile(addr, uuid::Profile::A2dpSink);
454                     }
455                     BtavConnectionState::Disconnected => {
456                         info!("[{}]: a2dp disconnected.", DisplayAddress(&addr));
457                         self.a2dp_states.remove(&addr);
458                         self.a2dp_caps.remove(&addr);
459                         self.a2dp_audio_state.remove(&addr);
460                         self.rm_connected_profile(addr, uuid::Profile::A2dpSink, true);
461                         if self.is_complete_profiles_required() {
462                             self.disconnect(addr.to_string());
463                         }
464                     }
465                     _ => {
466                         self.a2dp_states.insert(addr, state);
467                     }
468                 }
469             }
470             A2dpCallbacks::AudioState(addr, state) => {
471                 self.a2dp_audio_state.insert(addr, state);
472             }
473             A2dpCallbacks::AudioConfig(addr, _config, _local_caps, a2dp_caps) => {
474                 debug!("[{}]: a2dp updated audio config: {:?}", DisplayAddress(&addr), a2dp_caps);
475                 self.a2dp_caps.insert(addr, a2dp_caps);
476             }
477             A2dpCallbacks::MandatoryCodecPreferred(_addr) => {}
478         }
479     }
480 
dispatch_avrcp_callbacks(&mut self, cb: AvrcpCallbacks)481     pub fn dispatch_avrcp_callbacks(&mut self, cb: AvrcpCallbacks) {
482         match cb {
483             AvrcpCallbacks::AvrcpDeviceConnected(addr, supported) => {
484                 info!(
485                     "[{}]: avrcp connected. Absolute volume support: {}.",
486                     DisplayAddress(&addr),
487                     supported
488                 );
489 
490                 match self.uinput.create(self.adapter_get_remote_name(addr), addr.to_string()) {
491                     Ok(()) => info!("uinput device created for: {}", DisplayAddress(&addr)),
492                     Err(e) => warn!("{}", e),
493                 }
494 
495                 // Notify change via callback if device is added.
496                 if self.absolute_volume != supported {
497                     let guard = self.fallback_tasks.lock().unwrap();
498                     if let Some(task) = guard.get(&addr) {
499                         if task.is_none() {
500                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
501                                 callback.on_absolute_volume_supported_changed(supported);
502                             });
503                         }
504                     }
505                 }
506 
507                 self.absolute_volume = supported;
508 
509                 // If is device initiated the AVRCP connection, emit a fake connecting state as
510                 // stack don't receive one.
511                 if self.avrcp_direction != BtConnectionDirection::Outgoing {
512                     metrics::profile_connection_state_changed(
513                         addr,
514                         Profile::AvrcpController as u32,
515                         BtStatus::Success,
516                         BtavConnectionState::Connecting as u32,
517                     );
518                 }
519                 metrics::profile_connection_state_changed(
520                     addr,
521                     Profile::AvrcpController as u32,
522                     BtStatus::Success,
523                     BtavConnectionState::Connected as u32,
524                 );
525                 // Reset direction to unknown.
526                 self.avrcp_direction = BtConnectionDirection::Unknown;
527 
528                 self.add_connected_profile(addr, uuid::Profile::AvrcpController);
529             }
530             AvrcpCallbacks::AvrcpDeviceDisconnected(addr) => {
531                 info!("[{}]: avrcp disconnected.", DisplayAddress(&addr));
532 
533                 self.uinput.close(addr.to_string());
534 
535                 // TODO: better support for multi-device
536                 self.absolute_volume = false;
537 
538                 // This may be considered a critical profile in the extreme case
539                 // where only AVRCP was connected.
540                 let is_profile_critical = match self.connected_profiles.get(&addr) {
541                     Some(profiles) => *profiles == HashSet::from([uuid::Profile::AvrcpController]),
542                     None => false,
543                 };
544 
545                 // If the peer device initiated the AVRCP disconnection, emit a fake connecting
546                 // state as stack don't receive one.
547                 if self.avrcp_direction != BtConnectionDirection::Outgoing {
548                     metrics::profile_connection_state_changed(
549                         addr,
550                         Profile::AvrcpController as u32,
551                         BtStatus::Success,
552                         BtavConnectionState::Disconnecting as u32,
553                     );
554                 }
555                 metrics::profile_connection_state_changed(
556                     addr,
557                     Profile::AvrcpController as u32,
558                     BtStatus::Success,
559                     BtavConnectionState::Disconnected as u32,
560                 );
561                 // Reset direction to unknown.
562                 self.avrcp_direction = BtConnectionDirection::Unknown;
563 
564                 self.rm_connected_profile(
565                     addr,
566                     uuid::Profile::AvrcpController,
567                     is_profile_critical,
568                 );
569             }
570             AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => {
571                 for (addr, state) in self.device_states.lock().unwrap().iter() {
572                     info!("[{}]: state {:?}", DisplayAddress(&addr), state);
573                     match state {
574                         DeviceConnectionStates::ConnectingBeforeRetry
575                         | DeviceConnectionStates::ConnectingAfterRetry => {
576                             self.delay_volume_update.insert(Profile::AvrcpController, volume);
577                         }
578                         DeviceConnectionStates::FullyConnected => {
579                             self.delay_volume_update.remove(&Profile::AvrcpController);
580                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
581                                 callback.on_absolute_volume_changed(volume);
582                             });
583                             return;
584                         }
585                         _ => {}
586                     }
587                 }
588             }
589             AvrcpCallbacks::AvrcpSendKeyEvent(key, value) => {
590                 match self.uinput.send_key(key, value) {
591                     Ok(()) => (),
592                     Err(e) => warn!("{}", e),
593                 }
594 
595                 const AVRCP_ID_PAUSE: u8 = 0x46;
596                 const AVRCP_STATE_PRESS: u8 = 0;
597 
598                 // Per MPS v1.0, on receiving a pause key through AVRCP,
599                 // central should pause the A2DP stream with an AVDTP suspend command.
600                 if self.phone_ops_enabled && key == AVRCP_ID_PAUSE && value == AVRCP_STATE_PRESS {
601                     self.suspend_audio_request_impl();
602                 }
603             }
604             AvrcpCallbacks::AvrcpSetActiveDevice(addr) => {
605                 self.uinput.set_active_device(addr.to_string());
606             }
607         }
608     }
609 
dispatch_media_actions(&mut self, action: MediaActions)610     pub fn dispatch_media_actions(&mut self, action: MediaActions) {
611         match action {
612             MediaActions::Connect(address) => self.connect(address),
613             MediaActions::Disconnect(address) => self.disconnect(address),
614             MediaActions::ForceEnterConnected(address) => self.force_enter_connected(address),
615         }
616     }
617 
dispatch_hfp_callbacks(&mut self, cb: HfpCallbacks)618     pub fn dispatch_hfp_callbacks(&mut self, cb: HfpCallbacks) {
619         match cb {
620             HfpCallbacks::ConnectionState(state, addr) => {
621                 if !self.hfp_states.get(&addr).is_none()
622                     && state == *self.hfp_states.get(&addr).unwrap()
623                 {
624                     return;
625                 }
626                 metrics::profile_connection_state_changed(
627                     addr,
628                     Profile::Hfp as u32,
629                     BtStatus::Success,
630                     state.clone() as u32,
631                 );
632                 match state {
633                     BthfConnectionState::Connected => {
634                         info!("[{}]: hfp connected.", DisplayAddress(&addr));
635                     }
636                     BthfConnectionState::SlcConnected => {
637                         info!("[{}]: hfp slc connected.", DisplayAddress(&addr));
638                         // The device may not support codec-negotiation,
639                         // in which case we shall assume it supports CVSD at this point.
640                         if !self.hfp_cap.contains_key(&addr) {
641                             self.hfp_cap.insert(addr, HfpCodecCapability::CVSD);
642                         }
643                         self.add_connected_profile(addr, uuid::Profile::Hfp);
644 
645                         // Connect SCO if phone operations are enabled and an active call exists.
646                         // This is only used for Bluetooth HFP qualification.
647                         if self.phone_ops_enabled && self.phone_state.num_active > 0 {
648                             debug!("[{}]: Connect SCO due to active call.", DisplayAddress(&addr));
649                             self.start_sco_call_impl(addr.to_string(), false, false);
650                         }
651                     }
652                     BthfConnectionState::Disconnected => {
653                         info!("[{}]: hfp disconnected.", DisplayAddress(&addr));
654                         self.hfp_states.remove(&addr);
655                         self.hfp_cap.remove(&addr);
656                         self.hfp_audio_state.remove(&addr);
657                         self.rm_connected_profile(addr, uuid::Profile::Hfp, true);
658                         if self.is_complete_profiles_required() {
659                             self.disconnect(addr.to_string());
660                         }
661                     }
662                     BthfConnectionState::Connecting => {
663                         info!("[{}]: hfp connecting.", DisplayAddress(&addr));
664                     }
665                     BthfConnectionState::Disconnecting => {
666                         info!("[{}]: hfp disconnecting.", DisplayAddress(&addr));
667                     }
668                 }
669 
670                 self.hfp_states.insert(addr, state);
671             }
672             HfpCallbacks::AudioState(state, addr) => {
673                 if self.hfp_states.get(&addr).is_none()
674                     || BthfConnectionState::SlcConnected != *self.hfp_states.get(&addr).unwrap()
675                 {
676                     warn!("[{}]: Unknown address hfp or slc not ready", DisplayAddress(&addr));
677                     return;
678                 }
679 
680                 match state {
681                     BthfAudioState::Connected => {
682                         info!("[{}]: hfp audio connected.", DisplayAddress(&addr));
683 
684                         self.hfp_audio_state.insert(addr, state);
685 
686                         // Change the phone state only when it's currently managed by media stack
687                         // (I.e., phone operations are not enabled).
688                         if !self.phone_ops_enabled && self.phone_state.num_active != 1 {
689                             // This triggers a +CIEV command to set the call status for HFP devices.
690                             // It is required for some devices to provide sound.
691                             self.phone_state.num_active = 1;
692                             self.call_list = vec![CallInfo {
693                                 index: 1,
694                                 dir_incoming: false,
695                                 state: CallState::Active,
696                                 number: "".into(),
697                             }];
698                             self.phone_state_change("".into());
699                         }
700                     }
701                     BthfAudioState::Disconnected => {
702                         info!("[{}]: hfp audio disconnected.", DisplayAddress(&addr));
703 
704                         // Ignore disconnected -> disconnected
705                         if let Some(BthfAudioState::Connected) =
706                             self.hfp_audio_state.insert(addr, state)
707                         {
708                             self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
709                                 callback.on_hfp_audio_disconnected(addr.to_string());
710                             });
711                         }
712 
713                         // Change the phone state only when it's currently managed by media stack
714                         // (I.e., phone operations are not enabled).
715                         if !self.phone_ops_enabled && self.phone_state.num_active != 0 {
716                             self.phone_state.num_active = 0;
717                             self.call_list = vec![];
718                             self.phone_state_change("".into());
719                         }
720 
721                         // Resume the A2DP stream when a phone call ended (per MPS v1.0).
722                         self.try_a2dp_resume();
723                     }
724                     BthfAudioState::Connecting => {
725                         info!("[{}]: hfp audio connecting.", DisplayAddress(&addr));
726                     }
727                     BthfAudioState::Disconnecting => {
728                         info!("[{}]: hfp audio disconnecting.", DisplayAddress(&addr));
729                     }
730                 }
731             }
732             HfpCallbacks::VolumeUpdate(volume, addr) => {
733                 if self.hfp_states.get(&addr).is_none()
734                     || BthfConnectionState::SlcConnected != *self.hfp_states.get(&addr).unwrap()
735                 {
736                     warn!("[{}]: Unknown address hfp or slc not ready", addr.to_string());
737                     return;
738                 }
739 
740                 let states = self.device_states.lock().unwrap();
741                 info!(
742                     "[{}]: VolumeUpdate state: {:?}",
743                     DisplayAddress(&addr),
744                     states.get(&addr).unwrap()
745                 );
746                 match states.get(&addr).unwrap() {
747                     DeviceConnectionStates::ConnectingBeforeRetry
748                     | DeviceConnectionStates::ConnectingAfterRetry => {
749                         self.delay_volume_update.insert(Profile::Hfp, volume);
750                     }
751                     DeviceConnectionStates::FullyConnected => {
752                         self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
753                             callback.on_hfp_volume_changed(volume, addr.to_string());
754                         });
755                     }
756                     _ => {}
757                 }
758             }
759             HfpCallbacks::BatteryLevelUpdate(battery_level, addr) => {
760                 let battery_set = BatterySet::new(
761                     addr.to_string(),
762                     uuid::HFP.to_string(),
763                     "HFP".to_string(),
764                     vec![Battery { percentage: battery_level as u32, variant: "".to_string() }],
765                 );
766                 self.battery_provider_manager
767                     .lock()
768                     .unwrap()
769                     .set_battery_info(self.battery_provider_id, battery_set);
770             }
771             HfpCallbacks::WbsCapsUpdate(wbs_supported, addr) => {
772                 if let Some(cur_hfp_cap) = self.hfp_cap.get_mut(&addr) {
773                     if wbs_supported {
774                         *cur_hfp_cap |= HfpCodecCapability::MSBC;
775                     } else if (*cur_hfp_cap & HfpCodecCapability::MSBC) == HfpCodecCapability::MSBC
776                     {
777                         *cur_hfp_cap ^= HfpCodecCapability::MSBC;
778                     }
779                 } else {
780                     let new_hfp_cap = match wbs_supported {
781                         true => HfpCodecCapability::CVSD | HfpCodecCapability::MSBC,
782                         false => HfpCodecCapability::CVSD,
783                     };
784                     self.hfp_cap.insert(addr, new_hfp_cap);
785                 }
786             }
787             HfpCallbacks::SwbCapsUpdate(swb_supported, addr) => {
788                 if let Some(cur_hfp_cap) = self.hfp_cap.get_mut(&addr) {
789                     if swb_supported {
790                         *cur_hfp_cap |= HfpCodecCapability::LC3;
791                     } else if (*cur_hfp_cap & HfpCodecCapability::LC3) == HfpCodecCapability::LC3 {
792                         *cur_hfp_cap ^= HfpCodecCapability::LC3;
793                     }
794                 } else {
795                     let new_hfp_cap = match swb_supported {
796                         true => HfpCodecCapability::CVSD | HfpCodecCapability::LC3,
797                         false => HfpCodecCapability::CVSD,
798                     };
799                     self.hfp_cap.insert(addr, new_hfp_cap);
800                 }
801             }
802             HfpCallbacks::IndicatorQuery(addr) => {
803                 match self.hfp.as_mut() {
804                     Some(hfp) => {
805                         debug!(
806                             "[{}]: Responding CIND query with device={:?} phone={:?}",
807                             DisplayAddress(&addr),
808                             self.telephony_device_status,
809                             self.phone_state,
810                         );
811                         let status = hfp.indicator_query_response(
812                             self.telephony_device_status,
813                             self.phone_state,
814                             addr,
815                         );
816                         if status != BtStatus::Success {
817                             warn!(
818                                 "[{}]: CIND response failed, status={:?}",
819                                 DisplayAddress(&addr),
820                                 status
821                             );
822                         }
823                     }
824                     None => warn!("Uninitialized HFP to notify telephony status"),
825                 };
826             }
827             HfpCallbacks::CurrentCallsQuery(addr) => {
828                 match self.hfp.as_mut() {
829                     Some(hfp) => {
830                         debug!(
831                             "[{}]: Responding CLCC query with call_list={:?}",
832                             DisplayAddress(&addr),
833                             self.call_list,
834                         );
835                         let status = hfp.current_calls_query_response(&self.call_list, addr);
836                         if status != BtStatus::Success {
837                             warn!(
838                                 "[{}]: CLCC response failed, status={:?}",
839                                 DisplayAddress(&addr),
840                                 status
841                             );
842                         }
843                     }
844                     None => warn!("Uninitialized HFP to notify telephony status"),
845                 };
846             }
847             HfpCallbacks::AnswerCall(addr) => {
848                 if !self.answer_call_impl() {
849                     warn!("[{}]: answer_call triggered by ATA failed", DisplayAddress(&addr));
850                     return;
851                 }
852                 self.phone_state_change("".into());
853 
854                 debug!("[{}]: Start SCO call due to ATA", DisplayAddress(&addr));
855                 self.start_sco_call_impl(addr.to_string(), false, false);
856             }
857             HfpCallbacks::HangupCall(addr) => {
858                 if !self.hangup_call_impl() {
859                     warn!("[{}]: hangup_call triggered by AT+CHUP failed", DisplayAddress(&addr));
860                     return;
861                 }
862                 self.phone_state_change("".into());
863 
864                 // Try resume the A2DP stream (per MPS v1.0) on rejecting an incoming call or an
865                 // outgoing call is rejected.
866                 // It may fail if a SCO connection is still active (terminate call case), in that
867                 // case we will retry on SCO disconnected.
868                 self.try_a2dp_resume();
869             }
870             HfpCallbacks::DialCall(number, addr) => {
871                 let number = if number == "" {
872                     self.last_dialing_number.clone()
873                 } else if number.starts_with(">") {
874                     self.memory_dialing_number.clone()
875                 } else {
876                     Some(number)
877                 };
878 
879                 let success = number.map_or(false, |num| self.dialing_call_impl(num));
880 
881                 // Respond OK/ERROR to the HF which sent the command.
882                 // This should be called before calling phone_state_change.
883                 self.simple_at_response(success, addr.clone());
884                 if !success {
885                     warn!("[{}]: Unexpected dialing command from HF", DisplayAddress(&addr));
886                     return;
887                 }
888                 // Inform libbluetooth that the state has changed to dialing.
889                 self.phone_state_change("".into());
890                 self.try_a2dp_suspend();
891                 // Change to alerting state and inform libbluetooth.
892                 self.dialing_to_alerting();
893                 self.phone_state_change("".into());
894             }
895             HfpCallbacks::CallHold(command, addr) => {
896                 let success = match command {
897                     CallHoldCommand::ReleaseHeld => self.release_held_impl(),
898                     CallHoldCommand::ReleaseActiveAcceptHeld => {
899                         self.release_active_accept_held_impl()
900                     }
901                     CallHoldCommand::HoldActiveAcceptHeld => self.hold_active_accept_held_impl(),
902                     _ => false, // We only support the 3 operations above.
903                 };
904                 // Respond OK/ERROR to the HF which sent the command.
905                 // This should be called before calling phone_state_change.
906                 self.simple_at_response(success, addr.clone());
907                 if success {
908                     // Success means the call state has changed. Inform libbluetooth.
909                     self.phone_state_change("".into());
910                 } else {
911                     warn!(
912                         "[{}]: Unexpected or unsupported CHLD command {:?} from HF",
913                         DisplayAddress(&addr),
914                         command
915                     );
916                 }
917             }
918         }
919     }
920 
remove_callback(&mut self, id: u32) -> bool921     pub fn remove_callback(&mut self, id: u32) -> bool {
922         self.callbacks.lock().unwrap().remove_callback(id)
923     }
924 
notify_critical_profile_disconnected(&mut self, addr: RawAddress)925     fn notify_critical_profile_disconnected(&mut self, addr: RawAddress) {
926         info!(
927             "[{}]: Device connection state: {:?}.",
928             DisplayAddress(&addr),
929             DeviceConnectionStates::Disconnecting
930         );
931 
932         let mut states = self.device_states.lock().unwrap();
933         let prev_state = states.insert(addr, DeviceConnectionStates::Disconnecting).unwrap();
934         if prev_state != DeviceConnectionStates::Disconnecting {
935             let mut guard = self.fallback_tasks.lock().unwrap();
936             if let Some(task) = guard.get(&addr) {
937                 match task {
938                     // Abort pending task if there is any.
939                     Some((handler, _ts)) => {
940                         warn!(
941                             "[{}]: Device disconnected a critical profile before it was added.",
942                             DisplayAddress(&addr)
943                         );
944                         handler.abort();
945                         guard.insert(addr, None);
946                     }
947                     // Notify device removal if it has been added.
948                     None => {
949                         info!(
950                             "[{}]: Device disconnected a critical profile, removing the device.",
951                             DisplayAddress(&addr)
952                         );
953                         self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
954                             callback.on_bluetooth_audio_device_removed(addr.to_string());
955                         });
956                     }
957                 };
958             }
959             self.delay_volume_update.clear();
960         }
961     }
962 
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, )963     async fn wait_retry(
964         _fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
965         device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
966         txl: &Sender<Message>,
967         addr: &RawAddress,
968         first_conn_ts: Instant,
969     ) {
970         let now_ts = Instant::now();
971         let total_duration = Duration::from_secs(CONNECT_MISSING_PROFILES_TIMEOUT_SEC);
972         let sleep_duration = (first_conn_ts + total_duration).saturating_duration_since(now_ts);
973         sleep(sleep_duration).await;
974 
975         device_states.lock().unwrap().insert(*addr, DeviceConnectionStates::ConnectingAfterRetry);
976 
977         info!(
978             "[{}]: Device connection state: {:?}.",
979             DisplayAddress(addr),
980             DeviceConnectionStates::ConnectingAfterRetry
981         );
982 
983         let _ = txl.send(Message::Media(MediaActions::Connect(addr.to_string()))).await;
984     }
985 
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, )986     async fn wait_disconnect(
987         fallback_tasks: &Arc<Mutex<HashMap<RawAddress, Option<(JoinHandle<()>, Instant)>>>>,
988         device_states: &Arc<Mutex<HashMap<RawAddress, DeviceConnectionStates>>>,
989         txl: &Sender<Message>,
990         addr: &RawAddress,
991         first_conn_ts: Instant,
992     ) {
993         let now_ts = Instant::now();
994         let total_duration = Duration::from_secs(PROFILE_DISCOVERY_TIMEOUT_SEC);
995         let sleep_duration = (first_conn_ts + total_duration).saturating_duration_since(now_ts);
996         sleep(sleep_duration).await;
997 
998         device_states.lock().unwrap().insert(*addr, DeviceConnectionStates::Disconnecting);
999         fallback_tasks.lock().unwrap().insert(*addr, None);
1000 
1001         info!(
1002             "[{}]: Device connection state: {:?}.",
1003             DisplayAddress(addr),
1004             DeviceConnectionStates::Disconnecting
1005         );
1006 
1007         let _ = txl.send(Message::Media(MediaActions::Disconnect(addr.to_string()))).await;
1008     }
1009 
wait_force_enter_connected( txl: &Sender<Message>, addr: &RawAddress, first_conn_ts: Instant, )1010     async fn wait_force_enter_connected(
1011         txl: &Sender<Message>,
1012         addr: &RawAddress,
1013         first_conn_ts: Instant,
1014     ) {
1015         let now_ts = Instant::now();
1016         let total_duration = Duration::from_secs(CONNECT_MISSING_PROFILES_TIMEOUT_SEC);
1017         let sleep_duration = (first_conn_ts + total_duration).saturating_duration_since(now_ts);
1018         sleep(sleep_duration).await;
1019         let _ = txl.send(Message::Media(MediaActions::ForceEnterConnected(addr.to_string()))).await;
1020     }
1021 
notify_media_capability_updated(&mut self, addr: RawAddress)1022     fn notify_media_capability_updated(&mut self, addr: RawAddress) {
1023         let mut guard = self.fallback_tasks.lock().unwrap();
1024         let mut states = self.device_states.lock().unwrap();
1025         let mut first_conn_ts = Instant::now();
1026 
1027         let is_profile_cleared = self.connected_profiles.get(&addr).unwrap().is_empty();
1028 
1029         if let Some(task) = guard.get(&addr) {
1030             if let Some((handler, ts)) = task {
1031                 // Abort the pending task. It may be updated or
1032                 // removed depending on whether all profiles are cleared.
1033                 handler.abort();
1034                 first_conn_ts = *ts;
1035                 guard.insert(addr, None);
1036             } else {
1037                 // The device is already added or is disconnecting.
1038                 // Ignore unless all profiles are cleared.
1039                 if !is_profile_cleared {
1040                     return;
1041                 }
1042             }
1043         }
1044 
1045         // Cleanup if transitioning to empty set.
1046         if is_profile_cleared {
1047             info!("[{}]: Device connection state: Disconnected.", DisplayAddress(&addr));
1048             self.connected_profiles.remove(&addr);
1049             states.remove(&addr);
1050             guard.remove(&addr);
1051             return;
1052         }
1053 
1054         let available_profiles = self.adapter_get_audio_profiles(addr);
1055         let connected_profiles = self.connected_profiles.get(&addr).unwrap();
1056         let missing_profiles =
1057             available_profiles.difference(&connected_profiles).cloned().collect::<HashSet<_>>();
1058 
1059         // Update device states
1060         if states.get(&addr).is_none() {
1061             states.insert(addr, DeviceConnectionStates::ConnectingBeforeRetry);
1062         }
1063         if missing_profiles.is_empty()
1064             || missing_profiles == HashSet::from([Profile::AvrcpController])
1065         {
1066             info!(
1067                 "[{}]: Fully connected, available profiles: {:?}, connected profiles: {:?}.",
1068                 DisplayAddress(&addr),
1069                 available_profiles,
1070                 connected_profiles
1071             );
1072 
1073             states.insert(addr, DeviceConnectionStates::FullyConnected);
1074         }
1075 
1076         info!(
1077             "[{}]: Device connection state: {:?}.",
1078             DisplayAddress(&addr),
1079             states.get(&addr).unwrap()
1080         );
1081 
1082         // React on updated device states
1083         let tasks = self.fallback_tasks.clone();
1084         let device_states = self.device_states.clone();
1085         let txl = self.tx.clone();
1086         let ts = first_conn_ts;
1087         let is_complete_profiles_required = self.is_complete_profiles_required();
1088         match states.get(&addr).unwrap() {
1089             DeviceConnectionStates::Initiating => {
1090                 let task = topstack::get_runtime().spawn(async move {
1091                     // As initiator we can just immediately start connecting
1092                     let _ = txl.send(Message::Media(MediaActions::Connect(addr.to_string()))).await;
1093                     if !is_complete_profiles_required {
1094                         BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
1095                         return;
1096                     }
1097                     BluetoothMedia::wait_retry(&tasks, &device_states, &txl, &addr, ts).await;
1098                     BluetoothMedia::wait_disconnect(&tasks, &device_states, &txl, &addr, ts).await;
1099                 });
1100                 guard.insert(addr, Some((task, ts)));
1101             }
1102             DeviceConnectionStates::ConnectingBeforeRetry => {
1103                 let task = topstack::get_runtime().spawn(async move {
1104                     if !is_complete_profiles_required {
1105                         BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
1106                         return;
1107                     }
1108                     BluetoothMedia::wait_retry(&tasks, &device_states, &txl, &addr, ts).await;
1109                     BluetoothMedia::wait_disconnect(&tasks, &device_states, &txl, &addr, ts).await;
1110                 });
1111                 guard.insert(addr, Some((task, ts)));
1112             }
1113             DeviceConnectionStates::ConnectingAfterRetry => {
1114                 let task = topstack::get_runtime().spawn(async move {
1115                     if !is_complete_profiles_required {
1116                         BluetoothMedia::wait_force_enter_connected(&txl, &addr, ts).await;
1117                         return;
1118                     }
1119                     BluetoothMedia::wait_disconnect(&tasks, &device_states, &txl, &addr, ts).await;
1120                 });
1121                 guard.insert(addr, Some((task, ts)));
1122             }
1123             DeviceConnectionStates::FullyConnected => {
1124                 // Rejecting the unbonded connection after we finished our profile
1125                 // reconnectinglogic to avoid a collision.
1126                 if let Some(adapter) = &self.adapter {
1127                     if BtBondState::Bonded
1128                         != adapter.lock().unwrap().get_bond_state_by_addr(&addr.to_string())
1129                     {
1130                         warn!(
1131                             "[{}]: Rejecting a unbonded device's attempt to connect to media profiles",
1132                             DisplayAddress(&addr));
1133                         let fallback_tasks = self.fallback_tasks.clone();
1134                         let device_states = self.device_states.clone();
1135                         let txl = self.tx.clone();
1136                         let task = topstack::get_runtime().spawn(async move {
1137                             {
1138                                 device_states
1139                                     .lock()
1140                                     .unwrap()
1141                                     .insert(addr, DeviceConnectionStates::Disconnecting);
1142                                 fallback_tasks.lock().unwrap().insert(addr, None);
1143                             }
1144 
1145                             debug!(
1146                                 "[{}]: Device connection state: {:?}.",
1147                                 DisplayAddress(&addr),
1148                                 DeviceConnectionStates::Disconnecting
1149                             );
1150 
1151                             let _ = txl
1152                                 .send(Message::Media(MediaActions::Disconnect(addr.to_string())))
1153                                 .await;
1154                         });
1155                         guard.insert(addr, Some((task, first_conn_ts)));
1156                         return;
1157                     }
1158                 }
1159 
1160                 let cur_a2dp_caps = self.a2dp_caps.get(&addr);
1161                 let cur_hfp_cap = self.hfp_cap.get(&addr);
1162                 let name = self.adapter_get_remote_name(addr);
1163                 let absolute_volume = self.absolute_volume;
1164                 let device = BluetoothAudioDevice::new(
1165                     addr.to_string(),
1166                     name.clone(),
1167                     cur_a2dp_caps.unwrap_or(&Vec::new()).to_vec(),
1168                     *cur_hfp_cap.unwrap_or(&HfpCodecCapability::UNSUPPORTED),
1169                     absolute_volume,
1170                 );
1171 
1172                 let hfp_volume = self.delay_volume_update.remove(&Profile::Hfp);
1173                 let avrcp_volume = self.delay_volume_update.remove(&Profile::AvrcpController);
1174 
1175                 self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
1176                     callback.on_bluetooth_audio_device_added(device.clone());
1177                     if let Some(volume) = hfp_volume {
1178                         info!("Trigger HFP volume update to {}", DisplayAddress(&addr));
1179                         callback.on_hfp_volume_changed(volume, addr.to_string());
1180                     }
1181 
1182                     if let Some(volume) = avrcp_volume {
1183                         info!("Trigger avrcp volume update");
1184                         callback.on_absolute_volume_changed(volume);
1185                     }
1186                 });
1187 
1188                 guard.insert(addr, None);
1189             }
1190             DeviceConnectionStates::Disconnecting => {}
1191         }
1192     }
1193 
adapter_get_remote_name(&self, addr: RawAddress) -> String1194     fn adapter_get_remote_name(&self, addr: RawAddress) -> String {
1195         let device = BluetoothDevice::new(
1196             addr.to_string(),
1197             // get_remote_name needs a BluetoothDevice just for its address, the
1198             // name field is unused so construct one with a fake name.
1199             "Classic Device".to_string(),
1200         );
1201         if let Some(adapter) = &self.adapter {
1202             match adapter.lock().unwrap().get_remote_name(device).as_str() {
1203                 "" => addr.to_string(),
1204                 name => name.into(),
1205             }
1206         } else {
1207             addr.to_string()
1208         }
1209     }
1210 
adapter_get_audio_profiles(&self, addr: RawAddress) -> HashSet<uuid::Profile>1211     fn adapter_get_audio_profiles(&self, addr: RawAddress) -> HashSet<uuid::Profile> {
1212         let device = BluetoothDevice::new(addr.to_string(), "".to_string());
1213         if let Some(adapter) = &self.adapter {
1214             adapter
1215                 .lock()
1216                 .unwrap()
1217                 .get_remote_uuids(device)
1218                 .into_iter()
1219                 .map(|u| uuid::UuidHelper::is_known_profile(&u))
1220                 .filter(|u| u.is_some())
1221                 .map(|u| u.unwrap())
1222                 .filter(|u| MEDIA_AUDIO_PROFILES.contains(&u))
1223                 .collect()
1224         } else {
1225             HashSet::new()
1226         }
1227     }
1228 
get_hfp_connection_state(&self) -> ProfileConnectionState1229     pub fn get_hfp_connection_state(&self) -> ProfileConnectionState {
1230         if self.hfp_audio_state.values().any(|state| *state == BthfAudioState::Connected) {
1231             ProfileConnectionState::Active
1232         } else {
1233             let mut winning_state = ProfileConnectionState::Disconnected;
1234             for state in self.hfp_states.values() {
1235                 // Grab any state higher than the current state.
1236                 match state {
1237                     // Any SLC completed state means the profile is connected.
1238                     BthfConnectionState::SlcConnected => {
1239                         winning_state = ProfileConnectionState::Connected;
1240                     }
1241 
1242                     // Connecting or Connected are both counted as connecting for profile state
1243                     // since it's not a complete connection.
1244                     BthfConnectionState::Connecting | BthfConnectionState::Connected
1245                         if winning_state != ProfileConnectionState::Connected =>
1246                     {
1247                         winning_state = ProfileConnectionState::Connecting;
1248                     }
1249 
1250                     BthfConnectionState::Disconnecting
1251                         if winning_state == ProfileConnectionState::Disconnected =>
1252                     {
1253                         winning_state = ProfileConnectionState::Disconnecting;
1254                     }
1255 
1256                     _ => (),
1257                 }
1258             }
1259 
1260             winning_state
1261         }
1262     }
1263 
get_a2dp_connection_state(&self) -> ProfileConnectionState1264     pub fn get_a2dp_connection_state(&self) -> ProfileConnectionState {
1265         if self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
1266             ProfileConnectionState::Active
1267         } else {
1268             let mut winning_state = ProfileConnectionState::Disconnected;
1269             for state in self.a2dp_states.values() {
1270                 // Grab any state higher than the current state.
1271                 match state {
1272                     BtavConnectionState::Connected => {
1273                         winning_state = ProfileConnectionState::Connected;
1274                     }
1275 
1276                     BtavConnectionState::Connecting
1277                         if winning_state != ProfileConnectionState::Connected =>
1278                     {
1279                         winning_state = ProfileConnectionState::Connecting;
1280                     }
1281 
1282                     BtavConnectionState::Disconnecting
1283                         if winning_state == ProfileConnectionState::Disconnected =>
1284                     {
1285                         winning_state = ProfileConnectionState::Disconnecting;
1286                     }
1287 
1288                     _ => (),
1289                 }
1290             }
1291 
1292             winning_state
1293         }
1294     }
1295 
filter_to_connected_audio_devices_from( &self, devices: &Vec<BluetoothDevice>, ) -> Vec<BluetoothDevice>1296     pub fn filter_to_connected_audio_devices_from(
1297         &self,
1298         devices: &Vec<BluetoothDevice>,
1299     ) -> Vec<BluetoothDevice> {
1300         devices
1301             .iter()
1302             .filter(|d| {
1303                 let addr = match RawAddress::from_string(&d.address) {
1304                     None => return false,
1305                     Some(a) => a,
1306                 };
1307 
1308                 self.is_any_profile_connected(&addr, &MEDIA_AUDIO_PROFILES)
1309             })
1310             .cloned()
1311             .collect()
1312     }
1313 
start_audio_request_impl(&mut self) -> bool1314     fn start_audio_request_impl(&mut self) -> bool {
1315         debug!("Start audio request");
1316 
1317         match self.a2dp.as_mut() {
1318             Some(a2dp) => a2dp.start_audio_request(),
1319             None => {
1320                 warn!("Uninitialized A2DP to start audio request");
1321                 false
1322             }
1323         }
1324     }
1325 
suspend_audio_request_impl(&mut self)1326     fn suspend_audio_request_impl(&mut self) {
1327         match self.a2dp.as_mut() {
1328             Some(a2dp) => a2dp.suspend_audio_request(),
1329             None => warn!("Uninitialized A2DP to suspend audio request"),
1330         };
1331     }
1332 
try_a2dp_resume(&mut self)1333     fn try_a2dp_resume(&mut self) {
1334         if !self.phone_ops_enabled {
1335             return;
1336         }
1337         // Make sure there is no any SCO connection and then resume the A2DP stream.
1338         if self.a2dp_has_interrupted_stream
1339             && !self.hfp_audio_state.values().any(|state| *state == BthfAudioState::Connected)
1340         {
1341             self.a2dp_has_interrupted_stream = false;
1342             self.start_audio_request_impl();
1343         }
1344     }
1345 
try_a2dp_suspend(&mut self)1346     fn try_a2dp_suspend(&mut self) {
1347         if !self.phone_ops_enabled {
1348             return;
1349         }
1350         // Suspend the A2DP stream if there is any.
1351         if self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
1352             self.a2dp_has_interrupted_stream = true;
1353             self.suspend_audio_request_impl();
1354         }
1355     }
1356 
start_sco_call_impl( &mut self, address: String, sco_offload: bool, force_cvsd: bool, ) -> bool1357     fn start_sco_call_impl(
1358         &mut self,
1359         address: String,
1360         sco_offload: bool,
1361         force_cvsd: bool,
1362     ) -> bool {
1363         match (|| -> Result<(), &str> {
1364             let addr = RawAddress::from_string(address.clone())
1365                 .ok_or("Can't start sco call with bad address")?;
1366             info!("Start sco call for {}", DisplayAddress(&addr));
1367 
1368             let hfp = self.hfp.as_mut().ok_or("Uninitialized HFP to start the sco call")?;
1369             if hfp.connect_audio(addr, sco_offload, force_cvsd) != 0 {
1370                 return Err("SCO connect_audio status failed");
1371             }
1372             info!("SCO connect_audio status success");
1373             Ok(())
1374         })() {
1375             Ok(_) => true,
1376             Err(msg) => {
1377                 warn!("{}", msg);
1378                 false
1379             }
1380         }
1381     }
1382 
stop_sco_call_impl(&mut self, address: String)1383     fn stop_sco_call_impl(&mut self, address: String) {
1384         match (|| -> Result<(), &str> {
1385             let addr = RawAddress::from_string(address.clone())
1386                 .ok_or("Can't stop sco call with bad address")?;
1387             info!("Stop sco call for {}", DisplayAddress(&addr));
1388             let hfp = self.hfp.as_mut().ok_or("Uninitialized HFP to stop the sco call")?;
1389             hfp.disconnect_audio(addr);
1390             Ok(())
1391         })() {
1392             Ok(_) => {}
1393             Err(msg) => warn!("{}", msg),
1394         }
1395     }
1396 
device_status_notification(&mut self)1397     fn device_status_notification(&mut self) {
1398         match self.hfp.as_mut() {
1399             Some(hfp) => {
1400                 for (addr, state) in self.hfp_states.iter() {
1401                     if *state != BthfConnectionState::SlcConnected {
1402                         continue;
1403                     }
1404                     debug!(
1405                         "[{}]: Device status notification {:?}",
1406                         DisplayAddress(addr),
1407                         self.telephony_device_status
1408                     );
1409                     let status =
1410                         hfp.device_status_notification(self.telephony_device_status, addr.clone());
1411                     if status != BtStatus::Success {
1412                         warn!(
1413                             "[{}]: Device status notification failed, status={:?}",
1414                             DisplayAddress(addr),
1415                             status
1416                         );
1417                     }
1418                 }
1419             }
1420             None => warn!("Uninitialized HFP to notify telephony status"),
1421         }
1422     }
1423 
phone_state_change(&mut self, number: String)1424     fn phone_state_change(&mut self, number: String) {
1425         match self.hfp.as_mut() {
1426             Some(hfp) => {
1427                 for (addr, state) in self.hfp_states.iter() {
1428                     if *state != BthfConnectionState::SlcConnected {
1429                         continue;
1430                     }
1431                     debug!(
1432                         "[{}]: Phone state change state={:?} number={}",
1433                         DisplayAddress(addr),
1434                         self.phone_state,
1435                         number
1436                     );
1437                     let status = hfp.phone_state_change(self.phone_state, &number, addr.clone());
1438                     if status != BtStatus::Success {
1439                         warn!(
1440                             "[{}]: Device status notification failed, status={:?}",
1441                             DisplayAddress(addr),
1442                             status
1443                         );
1444                     }
1445                 }
1446             }
1447             None => warn!("Uninitialized HFP to notify telephony status"),
1448         }
1449     }
1450 
1451     // Returns the minimum unoccupied index starting from 1.
new_call_index(&self) -> i321452     fn new_call_index(&self) -> i32 {
1453         (1..)
1454             .find(|&index| self.call_list.iter().all(|x| x.index != index))
1455             .expect("There must be an unoccupied index")
1456     }
1457 
simple_at_response(&mut self, ok: bool, addr: RawAddress)1458     fn simple_at_response(&mut self, ok: bool, addr: RawAddress) {
1459         match self.hfp.as_mut() {
1460             Some(hfp) => {
1461                 let status = hfp.simple_at_response(ok, addr.clone());
1462                 if status != BtStatus::Success {
1463                     warn!("[{}]: AT response failed, status={:?}", DisplayAddress(&addr), status);
1464                 }
1465             }
1466             None => warn!("Uninitialized HFP to send AT response"),
1467         }
1468     }
1469 
answer_call_impl(&mut self) -> bool1470     fn answer_call_impl(&mut self) -> bool {
1471         if !self.phone_ops_enabled || self.phone_state.state == CallState::Idle {
1472             return false;
1473         }
1474         // There must be exactly one incoming/dialing call in the list.
1475         for c in self.call_list.iter_mut() {
1476             match c.state {
1477                 CallState::Incoming | CallState::Dialing | CallState::Alerting => {
1478                     c.state = CallState::Active;
1479                     break;
1480                 }
1481                 _ => {}
1482             }
1483         }
1484         self.phone_state.state = CallState::Idle;
1485         self.phone_state.num_active += 1;
1486         true
1487     }
1488 
hangup_call_impl(&mut self) -> bool1489     fn hangup_call_impl(&mut self) -> bool {
1490         if !self.phone_ops_enabled {
1491             return false;
1492         }
1493         match self.phone_state.state {
1494             CallState::Idle if self.phone_state.num_active > 0 => {
1495                 self.phone_state.num_active -= 1;
1496             }
1497             CallState::Incoming | CallState::Dialing | CallState::Alerting => {
1498                 self.phone_state.state = CallState::Idle;
1499             }
1500             _ => {
1501                 return false;
1502             }
1503         }
1504         // At this point, there must be exactly one incoming/dialing/alerting/active call to be
1505         // removed.
1506         self.call_list.retain(|x| match x.state {
1507             CallState::Active | CallState::Incoming | CallState::Dialing | CallState::Alerting => {
1508                 false
1509             }
1510             _ => true,
1511         });
1512         true
1513     }
1514 
dialing_call_impl(&mut self, number: String) -> bool1515     fn dialing_call_impl(&mut self, number: String) -> bool {
1516         if !self.phone_ops_enabled
1517             || self.phone_state.state != CallState::Idle
1518             || self.phone_state.num_active > 0
1519         {
1520             return false;
1521         }
1522         self.call_list.push(CallInfo {
1523             index: self.new_call_index(),
1524             dir_incoming: false,
1525             state: CallState::Dialing,
1526             number: number.clone(),
1527         });
1528         self.phone_state.state = CallState::Dialing;
1529         true
1530     }
1531 
dialing_to_alerting(&mut self) -> bool1532     fn dialing_to_alerting(&mut self) -> bool {
1533         if !self.phone_ops_enabled || self.phone_state.state != CallState::Dialing {
1534             return false;
1535         }
1536         for c in self.call_list.iter_mut() {
1537             if c.state == CallState::Dialing {
1538                 c.state = CallState::Alerting;
1539                 break;
1540             }
1541         }
1542         self.phone_state.state = CallState::Alerting;
1543         true
1544     }
1545 
release_held_impl(&mut self) -> bool1546     fn release_held_impl(&mut self) -> bool {
1547         if !self.phone_ops_enabled || self.phone_state.state != CallState::Idle {
1548             return false;
1549         }
1550         self.call_list.retain(|x| x.state != CallState::Held);
1551         self.phone_state.num_held = 0;
1552         true
1553     }
1554 
release_active_accept_held_impl(&mut self) -> bool1555     fn release_active_accept_held_impl(&mut self) -> bool {
1556         if !self.phone_ops_enabled || self.phone_state.state != CallState::Idle {
1557             return false;
1558         }
1559         self.call_list.retain(|x| x.state != CallState::Active);
1560         self.phone_state.num_active = 0;
1561         // Activate the first held call
1562         for c in self.call_list.iter_mut() {
1563             if c.state == CallState::Held {
1564                 c.state = CallState::Active;
1565                 self.phone_state.num_held -= 1;
1566                 self.phone_state.num_active += 1;
1567                 break;
1568             }
1569         }
1570         true
1571     }
1572 
hold_active_accept_held_impl(&mut self) -> bool1573     fn hold_active_accept_held_impl(&mut self) -> bool {
1574         if !self.phone_ops_enabled || self.phone_state.state != CallState::Idle {
1575             return false;
1576         }
1577 
1578         self.phone_state.num_held += self.phone_state.num_active;
1579         self.phone_state.num_active = 0;
1580 
1581         for c in self.call_list.iter_mut() {
1582             match c.state {
1583                 // Activate at most one held call
1584                 CallState::Held if self.phone_state.num_active == 0 => {
1585                     c.state = CallState::Active;
1586                     self.phone_state.num_held -= 1;
1587                     self.phone_state.num_active = 1;
1588                 }
1589                 CallState::Active => {
1590                     c.state = CallState::Held;
1591                 }
1592                 _ => {}
1593             }
1594         }
1595         true
1596     }
1597 
1598     // Per MPS v1.0 (Multi-Profile Specification), disconnecting or failing to connect
1599     // a profile should not affect the others.
1600     // Allow partial profiles connection during qualification (phone operations are enabled).
is_complete_profiles_required(&self) -> bool1601     fn is_complete_profiles_required(&self) -> bool {
1602         !self.phone_ops_enabled
1603     }
1604 
1605     // Force the media enters the FullyConnected state and then triggers a retry.
1606     // This function is only used for qualification as a replacement of normal retry.
1607     // Usually PTS initiates the connection of the necessary profiles, and Floss should notify
1608     // CRAS of the new audio device regardless of the unconnected profiles.
1609     // Still retry in the end because some test cases require that.
force_enter_connected(&mut self, address: String)1610     fn force_enter_connected(&mut self, address: String) {
1611         let addr = match RawAddress::from_string(address.clone()) {
1612             None => {
1613                 warn!("Invalid device address for force_enter_connected");
1614                 return;
1615             }
1616             Some(addr) => addr,
1617         };
1618         self.device_states
1619             .lock()
1620             .unwrap()
1621             .insert(addr.clone(), DeviceConnectionStates::FullyConnected);
1622         self.notify_media_capability_updated(addr);
1623         self.connect(address);
1624     }
add_player(&mut self, name: String, browsing_supported: bool)1625     pub fn add_player(&mut self, name: String, browsing_supported: bool) {
1626         self.avrcp.as_mut().unwrap().add_player(&name, browsing_supported);
1627     }
1628 }
1629 
get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher1630 fn get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher {
1631     A2dpCallbacksDispatcher {
1632         dispatch: Box::new(move |cb| {
1633             let txl = tx.clone();
1634             topstack::get_runtime().spawn(async move {
1635                 let _ = txl.send(Message::A2dp(cb)).await;
1636             });
1637         }),
1638     }
1639 }
1640 
get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher1641 fn get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher {
1642     AvrcpCallbacksDispatcher {
1643         dispatch: Box::new(move |cb| {
1644             let txl = tx.clone();
1645             topstack::get_runtime().spawn(async move {
1646                 let _ = txl.send(Message::Avrcp(cb)).await;
1647             });
1648         }),
1649     }
1650 }
1651 
get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher1652 fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher {
1653     HfpCallbacksDispatcher {
1654         dispatch: Box::new(move |cb| {
1655             let txl = tx.clone();
1656             topstack::get_runtime().spawn(async move {
1657                 let _ = txl.send(Message::Hfp(cb)).await;
1658             });
1659         }),
1660     }
1661 }
1662 
1663 impl IBluetoothMedia for BluetoothMedia {
register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool1664     fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool {
1665         let _id = self.callbacks.lock().unwrap().add_callback(callback);
1666         true
1667     }
1668 
initialize(&mut self) -> bool1669     fn initialize(&mut self) -> bool {
1670         if self.initialized {
1671             return false;
1672         }
1673         self.initialized = true;
1674 
1675         // A2DP
1676         let a2dp_dispatcher = get_a2dp_dispatcher(self.tx.clone());
1677         self.a2dp = Some(A2dp::new(&self.intf.lock().unwrap()));
1678         self.a2dp.as_mut().unwrap().initialize(a2dp_dispatcher);
1679 
1680         // AVRCP
1681         let avrcp_dispatcher = get_avrcp_dispatcher(self.tx.clone());
1682         self.avrcp = Some(Avrcp::new(&self.intf.lock().unwrap()));
1683         self.avrcp.as_mut().unwrap().initialize(avrcp_dispatcher);
1684 
1685         // HFP
1686         let hfp_dispatcher = get_hfp_dispatcher(self.tx.clone());
1687         self.hfp = Some(Hfp::new(&self.intf.lock().unwrap()));
1688         self.hfp.as_mut().unwrap().initialize(hfp_dispatcher);
1689 
1690         for profile in self.delay_enable_profiles.clone() {
1691             self.enable_profile(&profile);
1692         }
1693         true
1694     }
1695 
connect(&mut self, address: String)1696     fn connect(&mut self, address: String) {
1697         let addr = match RawAddress::from_string(address.clone()) {
1698             None => {
1699                 warn!("Invalid device address for connecting");
1700                 return;
1701             }
1702             Some(addr) => addr,
1703         };
1704 
1705         let available_profiles = self.adapter_get_audio_profiles(addr);
1706 
1707         info!(
1708             "[{}]: Connecting to device, available profiles: {:?}.",
1709             DisplayAddress(&addr),
1710             available_profiles
1711         );
1712 
1713         let connected_profiles = self.connected_profiles.entry(addr).or_insert_with(HashSet::new);
1714 
1715         // Sort here so the order of connection is always consistent
1716         let missing_profiles =
1717             available_profiles.difference(&connected_profiles).sorted().collect::<Vec<_>>();
1718 
1719         // Connect the profiles one-by-one so it won't stuck at the lower layer.
1720         // Therefore, just connect to one profile for now.
1721         // connect() will be called again after the first profile is successfully connected.
1722         let mut is_connect = false;
1723         for profile in missing_profiles {
1724             match profile {
1725                 uuid::Profile::A2dpSink => {
1726                     metrics::profile_connection_state_changed(
1727                         addr,
1728                         Profile::A2dpSink as u32,
1729                         BtStatus::Success,
1730                         BtavConnectionState::Connecting as u32,
1731                     );
1732                     match self.a2dp.as_mut() {
1733                         Some(a2dp) => {
1734                             let status: BtStatus = a2dp.connect(addr);
1735                             if BtStatus::Success != status {
1736                                 metrics::profile_connection_state_changed(
1737                                     addr,
1738                                     Profile::A2dpSink as u32,
1739                                     status,
1740                                     BtavConnectionState::Disconnected as u32,
1741                                 );
1742                             } else {
1743                                 is_connect = true;
1744                                 break;
1745                             }
1746                         }
1747                         None => {
1748                             warn!("Uninitialized A2DP to connect {}", DisplayAddress(&addr));
1749                             metrics::profile_connection_state_changed(
1750                                 addr,
1751                                 Profile::A2dpSink as u32,
1752                                 BtStatus::NotReady,
1753                                 BtavConnectionState::Disconnected as u32,
1754                             );
1755                         }
1756                     };
1757                 }
1758                 uuid::Profile::Hfp => {
1759                     metrics::profile_connection_state_changed(
1760                         addr,
1761                         Profile::Hfp as u32,
1762                         BtStatus::Success,
1763                         BtavConnectionState::Connecting as u32,
1764                     );
1765                     match self.hfp.as_mut() {
1766                         Some(hfp) => {
1767                             let status: BtStatus = hfp.connect(addr);
1768                             if BtStatus::Success != status {
1769                                 metrics::profile_connection_state_changed(
1770                                     addr,
1771                                     Profile::Hfp as u32,
1772                                     status,
1773                                     BthfConnectionState::Disconnected as u32,
1774                                 );
1775                             } else {
1776                                 is_connect = true;
1777                                 break;
1778                             }
1779                         }
1780                         None => {
1781                             warn!("Uninitialized HFP to connect {}", DisplayAddress(&addr));
1782                             metrics::profile_connection_state_changed(
1783                                 addr,
1784                                 Profile::Hfp as u32,
1785                                 BtStatus::NotReady,
1786                                 BthfConnectionState::Disconnected as u32,
1787                             );
1788                         }
1789                     };
1790                 }
1791                 uuid::Profile::AvrcpController => {
1792                     // Fluoride will resolve AVRCP as a part of A2DP connection request.
1793                     // Explicitly connect to it only when it is considered missing, and don't
1794                     // bother about it when A2DP is not connected.
1795                     if !connected_profiles.contains(&Profile::A2dpSink) {
1796                         continue;
1797                     }
1798 
1799                     metrics::profile_connection_state_changed(
1800                         addr,
1801                         Profile::AvrcpController as u32,
1802                         BtStatus::Success,
1803                         BtavConnectionState::Connecting as u32,
1804                     );
1805                     match self.avrcp.as_mut() {
1806                         Some(avrcp) => {
1807                             self.avrcp_direction = BtConnectionDirection::Outgoing;
1808                             let status: BtStatus = avrcp.connect(addr);
1809                             if BtStatus::Success != status {
1810                                 // Reset direction to unknown.
1811                                 self.avrcp_direction = BtConnectionDirection::Unknown;
1812                                 metrics::profile_connection_state_changed(
1813                                     addr,
1814                                     Profile::AvrcpController as u32,
1815                                     status,
1816                                     BtavConnectionState::Disconnected as u32,
1817                                 );
1818                             } else {
1819                                 is_connect = true;
1820                                 break;
1821                             }
1822                         }
1823 
1824                         None => {
1825                             warn!("Uninitialized AVRCP to connect {}", DisplayAddress(&addr));
1826                             metrics::profile_connection_state_changed(
1827                                 addr,
1828                                 Profile::AvrcpController as u32,
1829                                 BtStatus::NotReady,
1830                                 BtavConnectionState::Disconnected as u32,
1831                             );
1832                         }
1833                     };
1834                 }
1835                 _ => warn!("Unknown profile: {:?}", profile),
1836             }
1837         }
1838 
1839         if is_connect {
1840             let mut tasks = self.fallback_tasks.lock().unwrap();
1841             let mut states = self.device_states.lock().unwrap();
1842             if !tasks.contains_key(&addr) {
1843                 states.insert(addr, DeviceConnectionStates::Initiating);
1844 
1845                 let fallback_tasks = self.fallback_tasks.clone();
1846                 let device_states = self.device_states.clone();
1847                 let now_ts = Instant::now();
1848                 let task = topstack::get_runtime().spawn(async move {
1849                     sleep(Duration::from_secs(CONNECT_AS_INITIATOR_TIMEOUT_SEC)).await;
1850 
1851                     // If here the task is not yet aborted, probably connection is failed,
1852                     // therefore here we release the states. Even if later the connection is
1853                     // actually successful, we will just treat this as if the connection is
1854                     // initiated by the peer and will reconnect the missing profiles after
1855                     // some time, so it's safe.
1856                     {
1857                         device_states.lock().unwrap().remove(&addr);
1858                         fallback_tasks.lock().unwrap().remove(&addr);
1859                     }
1860                 });
1861                 tasks.insert(addr, Some((task, now_ts)));
1862             }
1863         }
1864     }
1865 
cleanup(&mut self) -> bool1866     fn cleanup(&mut self) -> bool {
1867         true
1868     }
1869 
1870     // TODO(b/278963515): Currently this is designed to be called from both the
1871     // UI and via disconnection callbacks. Remove this workaround once the
1872     // proper fix has landed.
disconnect(&mut self, address: String)1873     fn disconnect(&mut self, address: String) {
1874         let addr = match RawAddress::from_string(address.clone()) {
1875             None => {
1876                 warn!("Invalid device address for disconnecting");
1877                 return;
1878             }
1879             Some(addr) => addr,
1880         };
1881 
1882         let connected_profiles = match self.connected_profiles.get(&addr) {
1883             Some(profiles) => profiles,
1884             None => {
1885                 warn!(
1886                     "[{}]: Ignoring disconnection request since there is no connected profile.",
1887                     DisplayAddress(&addr)
1888                 );
1889                 return;
1890             }
1891         };
1892 
1893         for profile in connected_profiles {
1894             match profile {
1895                 uuid::Profile::A2dpSink => {
1896                     // Some headsets (b/278963515) will try reconnecting to A2DP
1897                     // when HFP is running but (requested to be) disconnected.
1898                     if connected_profiles.contains(&Profile::Hfp) {
1899                         continue;
1900                     }
1901                     metrics::profile_connection_state_changed(
1902                         addr,
1903                         Profile::A2dpSink as u32,
1904                         BtStatus::Success,
1905                         BtavConnectionState::Disconnecting as u32,
1906                     );
1907                     match self.a2dp.as_mut() {
1908                         Some(a2dp) => {
1909                             let status: BtStatus = a2dp.disconnect(addr);
1910                             if BtStatus::Success != status {
1911                                 metrics::profile_connection_state_changed(
1912                                     addr,
1913                                     Profile::A2dpSource as u32,
1914                                     status,
1915                                     BtavConnectionState::Disconnected as u32,
1916                                 );
1917                             }
1918                         }
1919                         None => {
1920                             warn!("Uninitialized A2DP to disconnect {}", DisplayAddress(&addr));
1921                             metrics::profile_connection_state_changed(
1922                                 addr,
1923                                 Profile::A2dpSource as u32,
1924                                 BtStatus::NotReady,
1925                                 BtavConnectionState::Disconnected as u32,
1926                             );
1927                         }
1928                     };
1929                 }
1930                 uuid::Profile::Hfp => {
1931                     metrics::profile_connection_state_changed(
1932                         addr,
1933                         Profile::Hfp as u32,
1934                         BtStatus::Success,
1935                         BthfConnectionState::Disconnecting as u32,
1936                     );
1937                     match self.hfp.as_mut() {
1938                         Some(hfp) => {
1939                             let status: BtStatus = hfp.disconnect(addr);
1940                             if BtStatus::Success != status {
1941                                 metrics::profile_connection_state_changed(
1942                                     addr,
1943                                     Profile::Hfp as u32,
1944                                     status,
1945                                     BthfConnectionState::Disconnected as u32,
1946                                 );
1947                             }
1948                         }
1949                         None => {
1950                             warn!("Uninitialized HFP to disconnect {}", DisplayAddress(&addr));
1951                             metrics::profile_connection_state_changed(
1952                                 addr,
1953                                 Profile::Hfp as u32,
1954                                 BtStatus::NotReady,
1955                                 BthfConnectionState::Disconnected as u32,
1956                             );
1957                         }
1958                     };
1959                 }
1960                 uuid::Profile::AvrcpController => {
1961                     if connected_profiles.contains(&Profile::A2dpSink) {
1962                         continue;
1963                     }
1964                     metrics::profile_connection_state_changed(
1965                         addr,
1966                         Profile::AvrcpController as u32,
1967                         BtStatus::Success,
1968                         BtavConnectionState::Disconnecting as u32,
1969                     );
1970                     match self.avrcp.as_mut() {
1971                         Some(avrcp) => {
1972                             self.avrcp_direction = BtConnectionDirection::Outgoing;
1973                             let status: BtStatus = avrcp.disconnect(addr);
1974                             if BtStatus::Success != status {
1975                                 // Reset direction to unknown.
1976                                 self.avrcp_direction = BtConnectionDirection::Unknown;
1977                                 metrics::profile_connection_state_changed(
1978                                     addr,
1979                                     Profile::AvrcpController as u32,
1980                                     status,
1981                                     BtavConnectionState::Disconnected as u32,
1982                                 );
1983                             }
1984                         }
1985 
1986                         None => {
1987                             warn!("Uninitialized AVRCP to disconnect {}", DisplayAddress(&addr));
1988                             metrics::profile_connection_state_changed(
1989                                 addr,
1990                                 Profile::AvrcpController as u32,
1991                                 BtStatus::NotReady,
1992                                 BtavConnectionState::Disconnected as u32,
1993                             );
1994                         }
1995                     };
1996                 }
1997                 _ => warn!("Unknown profile: {:?}", profile),
1998             }
1999         }
2000     }
2001 
set_active_device(&mut self, address: String)2002     fn set_active_device(&mut self, address: String) {
2003         let addr = match RawAddress::from_string(address.clone()) {
2004             None => {
2005                 warn!("Invalid device address for set_active_device");
2006                 return;
2007             }
2008             Some(addr) => addr,
2009         };
2010 
2011         match self.a2dp_states.get(&addr) {
2012             Some(BtavConnectionState::Connected) => {
2013                 if let Some(a2dp) = self.a2dp.as_mut() {
2014                     a2dp.set_active_device(addr);
2015                     self.uinput.set_active_device(addr.to_string());
2016                 } else {
2017                     warn!("Uninitialized A2DP to set active device");
2018                 }
2019             }
2020             _ => warn!("[{}] Not connected or disconnected A2DP address", address),
2021         };
2022     }
2023 
reset_active_device(&mut self)2024     fn reset_active_device(&mut self) {
2025         // During MPS tests, there might be some A2DP stream manipulation unexpected to CRAS.
2026         // CRAS would then attempt to reset the active device. Ignore it during test.
2027         if !self.is_complete_profiles_required() {
2028             return;
2029         }
2030 
2031         if let Some(a2dp) = self.a2dp.as_mut() {
2032             a2dp.set_active_device(RawAddress::empty());
2033         } else {
2034             warn!("Uninitialized A2DP to set active device");
2035         }
2036         self.uinput.set_active_device(RawAddress::empty().to_string());
2037     }
2038 
set_hfp_active_device(&mut self, address: String)2039     fn set_hfp_active_device(&mut self, address: String) {
2040         let addr = match RawAddress::from_string(address.clone()) {
2041             None => {
2042                 warn!("Invalid device address for set_hfp_active_device");
2043                 return;
2044             }
2045             Some(addr) => addr,
2046         };
2047 
2048         match self.hfp_states.get(&addr) {
2049             Some(BthfConnectionState::SlcConnected) => {
2050                 if let Some(hfp) = self.hfp.as_mut() {
2051                     hfp.set_active_device(addr);
2052                 } else {
2053                     warn!("Uninitialized HFP to set active device");
2054                 }
2055             }
2056             _ => warn!("[{}] Not connected or disconnected HFP address", address),
2057         }
2058     }
2059 
set_audio_config( &mut self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32, ) -> bool2060     fn set_audio_config(
2061         &mut self,
2062         sample_rate: i32,
2063         bits_per_sample: i32,
2064         channel_mode: i32,
2065     ) -> bool {
2066         if !A2dpCodecSampleRate::validate_bits(sample_rate)
2067             || !A2dpCodecBitsPerSample::validate_bits(bits_per_sample)
2068             || !A2dpCodecChannelMode::validate_bits(channel_mode)
2069         {
2070             return false;
2071         }
2072 
2073         match self.a2dp.as_mut() {
2074             Some(a2dp) => {
2075                 a2dp.set_audio_config(sample_rate, bits_per_sample, channel_mode);
2076                 true
2077             }
2078             None => {
2079                 warn!("Uninitialized A2DP to set audio config");
2080                 false
2081             }
2082         }
2083     }
2084 
set_volume(&mut self, volume: u8)2085     fn set_volume(&mut self, volume: u8) {
2086         // Guard the range 0-127 by the try_from cast from u8 to i8.
2087         let vol = match i8::try_from(volume) {
2088             Ok(val) => val,
2089             _ => {
2090                 warn!("Ignore invalid volume {}", volume);
2091                 return;
2092             }
2093         };
2094 
2095         match self.avrcp.as_mut() {
2096             Some(avrcp) => avrcp.set_volume(vol),
2097             None => warn!("Uninitialized AVRCP to set volume"),
2098         };
2099     }
2100 
set_hfp_volume(&mut self, volume: u8, address: String)2101     fn set_hfp_volume(&mut self, volume: u8, address: String) {
2102         let addr = match RawAddress::from_string(address.clone()) {
2103             None => {
2104                 warn!("Invalid device address for set_hfp_volume");
2105                 return;
2106             }
2107             Some(addr) => addr,
2108         };
2109 
2110         let vol = match i8::try_from(volume) {
2111             Ok(val) if val <= 15 => val,
2112             _ => {
2113                 warn!("[{}]: Ignore invalid volume {}", DisplayAddress(&addr), volume);
2114                 return;
2115             }
2116         };
2117 
2118         if self.hfp_states.get(&addr).is_none() {
2119             warn!(
2120                 "[{}]: Ignore volume event for unconnected or disconnected HFP device",
2121                 DisplayAddress(&addr)
2122             );
2123             return;
2124         }
2125 
2126         match self.hfp.as_mut() {
2127             Some(hfp) => {
2128                 hfp.set_volume(vol, addr);
2129             }
2130             None => warn!("Uninitialized HFP to set volume"),
2131         };
2132     }
2133 
start_audio_request(&mut self) -> bool2134     fn start_audio_request(&mut self) -> bool {
2135         self.start_audio_request_impl()
2136     }
2137 
stop_audio_request(&mut self)2138     fn stop_audio_request(&mut self) {
2139         if !self.a2dp_audio_state.values().any(|state| *state == BtavAudioState::Started) {
2140             info!("No active stream on A2DP device, ignoring request to stop audio.");
2141             return;
2142         }
2143 
2144         debug!("Stop audio request");
2145 
2146         match self.a2dp.as_mut() {
2147             Some(a2dp) => a2dp.stop_audio_request(),
2148             None => warn!("Uninitialized A2DP to stop audio request"),
2149         };
2150     }
2151 
start_sco_call(&mut self, address: String, sco_offload: bool, force_cvsd: bool) -> bool2152     fn start_sco_call(&mut self, address: String, sco_offload: bool, force_cvsd: bool) -> bool {
2153         self.start_sco_call_impl(address, sco_offload, force_cvsd)
2154     }
2155 
stop_sco_call(&mut self, address: String)2156     fn stop_sco_call(&mut self, address: String) {
2157         self.stop_sco_call_impl(address)
2158     }
2159 
get_a2dp_audio_started(&mut self, address: String) -> bool2160     fn get_a2dp_audio_started(&mut self, address: String) -> bool {
2161         let addr = match RawAddress::from_string(address.clone()) {
2162             None => {
2163                 warn!("Invalid device address for get_a2dp_audio_started");
2164                 return false;
2165             }
2166             Some(addr) => addr,
2167         };
2168 
2169         match self.a2dp_audio_state.get(&addr) {
2170             Some(BtavAudioState::Started) => true,
2171             _ => false,
2172         }
2173     }
2174 
get_hfp_audio_final_codecs(&mut self, address: String) -> u82175     fn get_hfp_audio_final_codecs(&mut self, address: String) -> u8 {
2176         let addr = match RawAddress::from_string(address.clone()) {
2177             None => {
2178                 warn!("Invalid device address for get_hfp_audio_final_codecs");
2179                 return 0;
2180             }
2181             Some(addr) => addr,
2182         };
2183 
2184         match self.hfp_audio_state.get(&addr) {
2185             Some(BthfAudioState::Connected) => match self.hfp_cap.get(&addr) {
2186                 Some(caps) if (*caps & HfpCodecCapability::LC3) == HfpCodecCapability::LC3 => 4,
2187                 Some(caps) if (*caps & HfpCodecCapability::MSBC) == HfpCodecCapability::MSBC => 2,
2188                 Some(caps) if (*caps & HfpCodecCapability::CVSD) == HfpCodecCapability::CVSD => 1,
2189                 _ => {
2190                     warn!("hfp_cap not found, fallback to CVSD.");
2191                     1
2192                 }
2193             },
2194             _ => 0,
2195         }
2196     }
2197 
get_presentation_position(&mut self) -> PresentationPosition2198     fn get_presentation_position(&mut self) -> PresentationPosition {
2199         let position = match self.a2dp.as_mut() {
2200             Some(a2dp) => a2dp.get_presentation_position(),
2201             None => {
2202                 warn!("Uninitialized A2DP to get presentation position");
2203                 Default::default()
2204             }
2205         };
2206         PresentationPosition {
2207             remote_delay_report_ns: position.remote_delay_report_ns,
2208             total_bytes_read: position.total_bytes_read,
2209             data_position_sec: position.data_position_sec,
2210             data_position_nsec: position.data_position_nsec,
2211         }
2212     }
2213 
set_player_playback_status(&mut self, status: String)2214     fn set_player_playback_status(&mut self, status: String) {
2215         debug!("AVRCP received player playback status: {}", status);
2216         match self.avrcp.as_mut() {
2217             Some(avrcp) => avrcp.set_playback_status(&status),
2218             None => warn!("Uninitialized AVRCP to set player playback status"),
2219         };
2220     }
set_player_position(&mut self, position_us: i64)2221     fn set_player_position(&mut self, position_us: i64) {
2222         debug!("AVRCP received player position: {}", position_us);
2223         match self.avrcp.as_mut() {
2224             Some(avrcp) => avrcp.set_position(position_us),
2225             None => warn!("Uninitialized AVRCP to set player position"),
2226         };
2227     }
set_player_metadata(&mut self, metadata: PlayerMetadata)2228     fn set_player_metadata(&mut self, metadata: PlayerMetadata) {
2229         debug!("AVRCP received player metadata: {:?}", metadata);
2230         match self.avrcp.as_mut() {
2231             Some(avrcp) => avrcp.set_metadata(&metadata),
2232             None => warn!("Uninitialized AVRCP to set player playback status"),
2233         };
2234     }
2235 }
2236 
2237 impl IBluetoothTelephony for BluetoothMedia {
set_network_available(&mut self, network_available: bool)2238     fn set_network_available(&mut self, network_available: bool) {
2239         if self.telephony_device_status.network_available == network_available {
2240             return;
2241         }
2242         self.telephony_device_status.network_available = network_available;
2243         self.device_status_notification();
2244     }
2245 
set_roaming(&mut self, roaming: bool)2246     fn set_roaming(&mut self, roaming: bool) {
2247         if self.telephony_device_status.roaming == roaming {
2248             return;
2249         }
2250         self.telephony_device_status.roaming = roaming;
2251         self.device_status_notification();
2252     }
2253 
set_signal_strength(&mut self, signal_strength: i32) -> bool2254     fn set_signal_strength(&mut self, signal_strength: i32) -> bool {
2255         if signal_strength < 0 || signal_strength > 5 {
2256             warn!("Invalid signal strength, got {}, want 0 to 5", signal_strength);
2257             return false;
2258         }
2259         if self.telephony_device_status.signal_strength == signal_strength {
2260             return true;
2261         }
2262 
2263         self.telephony_device_status.signal_strength = signal_strength;
2264         self.device_status_notification();
2265 
2266         true
2267     }
2268 
set_battery_level(&mut self, battery_level: i32) -> bool2269     fn set_battery_level(&mut self, battery_level: i32) -> bool {
2270         if battery_level < 0 || battery_level > 5 {
2271             warn!("Invalid battery level, got {}, want 0 to 5", battery_level);
2272             return false;
2273         }
2274         if self.telephony_device_status.battery_level == battery_level {
2275             return true;
2276         }
2277 
2278         self.telephony_device_status.battery_level = battery_level;
2279         self.device_status_notification();
2280 
2281         true
2282     }
2283 
set_phone_ops_enabled(&mut self, enable: bool)2284     fn set_phone_ops_enabled(&mut self, enable: bool) {
2285         if self.phone_ops_enabled == enable {
2286             return;
2287         }
2288 
2289         self.call_list = vec![];
2290         self.phone_state.num_active = 0;
2291         self.phone_state.num_held = 0;
2292         self.phone_state.state = CallState::Idle;
2293         self.memory_dialing_number = None;
2294         self.last_dialing_number = None;
2295         self.a2dp_has_interrupted_stream = false;
2296 
2297         if !enable {
2298             if self.hfp_states.values().any(|x| x == &BthfConnectionState::SlcConnected) {
2299                 self.call_list.push(CallInfo {
2300                     index: 1,
2301                     dir_incoming: false,
2302                     state: CallState::Active,
2303                     number: "".into(),
2304                 });
2305                 self.phone_state.num_active = 1;
2306             }
2307         }
2308 
2309         self.phone_ops_enabled = enable;
2310         self.phone_state_change("".into());
2311     }
2312 
incoming_call(&mut self, number: String) -> bool2313     fn incoming_call(&mut self, number: String) -> bool {
2314         if !self.phone_ops_enabled
2315             || self.phone_state.state != CallState::Idle
2316             || self.phone_state.num_active > 0
2317         {
2318             return false;
2319         }
2320         self.call_list.push(CallInfo {
2321             index: self.new_call_index(),
2322             dir_incoming: true,
2323             state: CallState::Incoming,
2324             number: number.clone(),
2325         });
2326         self.phone_state.state = CallState::Incoming;
2327         self.phone_state_change(number);
2328         self.try_a2dp_suspend();
2329         true
2330     }
2331 
dialing_call(&mut self, number: String) -> bool2332     fn dialing_call(&mut self, number: String) -> bool {
2333         if !self.dialing_call_impl(number) {
2334             return false;
2335         }
2336         self.phone_state_change("".into());
2337         self.try_a2dp_suspend();
2338         // Change to alerting state and inform libbluetooth.
2339         self.dialing_to_alerting();
2340         self.phone_state_change("".into());
2341         true
2342     }
2343 
answer_call(&mut self) -> bool2344     fn answer_call(&mut self) -> bool {
2345         if !self.answer_call_impl() {
2346             return false;
2347         }
2348         self.phone_state_change("".into());
2349 
2350         // Find a connected HFP and try to establish an SCO.
2351         if let Some(addr) = self.hfp_states.iter().find_map(|(addr, state)| {
2352             if *state == BthfConnectionState::SlcConnected {
2353                 Some(addr.clone())
2354             } else {
2355                 None
2356             }
2357         }) {
2358             info!("Start SCO call due to call answered");
2359             self.start_sco_call_impl(addr.to_string(), false, false);
2360         }
2361 
2362         true
2363     }
2364 
hangup_call(&mut self) -> bool2365     fn hangup_call(&mut self) -> bool {
2366         if !self.hangup_call_impl() {
2367             return false;
2368         }
2369         self.phone_state_change("".into());
2370         // Try resume the A2DP stream (per MPS v1.0) on rejecting an incoming call or an
2371         // outgoing call is rejected.
2372         // It may fail if a SCO connection is still active (terminate call case), in that
2373         // case we will retry on SCO disconnected.
2374         self.try_a2dp_resume();
2375         true
2376     }
2377 
set_memory_call(&mut self, number: Option<String>) -> bool2378     fn set_memory_call(&mut self, number: Option<String>) -> bool {
2379         if !self.phone_ops_enabled {
2380             return false;
2381         }
2382         self.memory_dialing_number = number;
2383         true
2384     }
2385 
set_last_call(&mut self, number: Option<String>) -> bool2386     fn set_last_call(&mut self, number: Option<String>) -> bool {
2387         if !self.phone_ops_enabled {
2388             return false;
2389         }
2390         self.last_dialing_number = number;
2391         true
2392     }
2393 
release_held(&mut self) -> bool2394     fn release_held(&mut self) -> bool {
2395         if !self.release_held_impl() {
2396             return false;
2397         }
2398         self.phone_state_change("".into());
2399         true
2400     }
2401 
release_active_accept_held(&mut self) -> bool2402     fn release_active_accept_held(&mut self) -> bool {
2403         if !self.release_active_accept_held_impl() {
2404             return false;
2405         }
2406         self.phone_state_change("".into());
2407         true
2408     }
2409 
hold_active_accept_held(&mut self) -> bool2410     fn hold_active_accept_held(&mut self) -> bool {
2411         if !self.hold_active_accept_held_impl() {
2412             return false;
2413         }
2414         self.phone_state_change("".into());
2415         true
2416     }
2417 
audio_connect(&mut self, address: String) -> bool2418     fn audio_connect(&mut self, address: String) -> bool {
2419         self.start_sco_call_impl(address, false, false)
2420     }
2421 
audio_disconnect(&mut self, address: String)2422     fn audio_disconnect(&mut self, address: String) {
2423         self.stop_sco_call_impl(address)
2424     }
2425 }
2426 
2427 struct BatteryProviderCallback {}
2428 
2429 impl BatteryProviderCallback {
new() -> Self2430     fn new() -> Self {
2431         Self {}
2432     }
2433 }
2434 
2435 impl IBatteryProviderCallback for BatteryProviderCallback {
2436     // We do not support refreshing HFP battery information.
refresh_battery_info(&mut self)2437     fn refresh_battery_info(&mut self) {}
2438 }
2439 
2440 impl RPCProxy for BatteryProviderCallback {
get_object_id(&self) -> String2441     fn get_object_id(&self) -> String {
2442         "HFP BatteryProvider Callback".to_string()
2443     }
2444 }
2445