• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Anything related to the adapter API (IBluetooth).
2 
3 use bt_topshim::btif::{
4     BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState,
5     BtBondState, BtDeviceType, BtDiscoveryState, BtHciErrorCode, BtPinCode, BtPropertyType,
6     BtScanMode, BtSspVariant, BtState, BtStatus, BtTransport, RawAddress, Uuid, Uuid128Bit,
7 };
8 use bt_topshim::{
9     profiles::hid_host::{HHCallbacksDispatcher, HidHost},
10     profiles::sdp::{BtSdpRecord, Sdp, SdpCallbacks, SdpCallbacksDispatcher},
11     topstack,
12 };
13 
14 use btif_macros::{btif_callback, btif_callbacks_dispatcher};
15 
16 use log::{debug, warn};
17 use num_traits::cast::ToPrimitive;
18 use std::collections::HashMap;
19 use std::sync::Arc;
20 use std::sync::Mutex;
21 use std::time::Duration;
22 use std::time::Instant;
23 use tokio::sync::mpsc::Sender;
24 use tokio::task::JoinHandle;
25 use tokio::time;
26 
27 use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions};
28 use crate::uuid::{Profile, UuidHelper};
29 use crate::{BluetoothCallbackType, Message, RPCProxy};
30 
31 const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800;
32 const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5;
33 
34 /// Devices that were last seen longer than this duration are considered stale
35 /// if they haven't already bonded or connected. Once this duration expires, the
36 /// clear event should be sent to clients.
37 const FOUND_DEVICE_FRESHNESS: Duration = Duration::from_secs(30);
38 
39 /// Defines the adapter API.
40 pub trait IBluetooth {
41     /// Adds a callback from a client who wishes to observe adapter events.
register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>)42     fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>);
43 
44     /// Adds a callback from a client who wishes to observe connection events.
register_connection_callback( &mut self, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u3245     fn register_connection_callback(
46         &mut self,
47         callback: Box<dyn IBluetoothConnectionCallback + Send>,
48     ) -> u32;
49 
50     /// Removes registered callback.
unregister_connection_callback(&mut self, callback_id: u32) -> bool51     fn unregister_connection_callback(&mut self, callback_id: u32) -> bool;
52 
53     /// Enables the adapter.
54     ///
55     /// Returns true if the request is accepted.
enable(&mut self) -> bool56     fn enable(&mut self) -> bool;
57 
58     /// Disables the adapter.
59     ///
60     /// Returns true if the request is accepted.
disable(&mut self) -> bool61     fn disable(&mut self) -> bool;
62 
63     /// Returns the Bluetooth address of the local adapter.
get_address(&self) -> String64     fn get_address(&self) -> String;
65 
66     /// Gets supported UUIDs by the local adapter.
get_uuids(&self) -> Vec<Uuid128Bit>67     fn get_uuids(&self) -> Vec<Uuid128Bit>;
68 
69     /// Gets the local adapter name.
get_name(&self) -> String70     fn get_name(&self) -> String;
71 
72     /// Sets the local adapter name.
set_name(&self, name: String) -> bool73     fn set_name(&self, name: String) -> bool;
74 
75     /// Gets the bluetooth class.
get_bluetooth_class(&self) -> u3276     fn get_bluetooth_class(&self) -> u32;
77 
78     /// Sets the bluetooth class.
set_bluetooth_class(&self, cod: u32) -> bool79     fn set_bluetooth_class(&self, cod: u32) -> bool;
80 
81     /// Returns whether the adapter is discoverable.
get_discoverable(&self) -> bool82     fn get_discoverable(&self) -> bool;
83 
84     /// Returns the adapter discoverable timeout.
get_discoverable_timeout(&self) -> u3285     fn get_discoverable_timeout(&self) -> u32;
86 
87     /// Sets discoverability. If discoverable, limits the duration with given value.
set_discoverable(&self, mode: bool, duration: u32) -> bool88     fn set_discoverable(&self, mode: bool, duration: u32) -> bool;
89 
90     /// Returns whether multi-advertisement is supported.
91     /// A minimum number of 5 advertising instances is required for multi-advertisment support.
is_multi_advertisement_supported(&self) -> bool92     fn is_multi_advertisement_supported(&self) -> bool;
93 
94     /// Returns whether LE extended advertising is supported.
is_le_extended_advertising_supported(&self) -> bool95     fn is_le_extended_advertising_supported(&self) -> bool;
96 
97     /// Starts BREDR Inquiry.
start_discovery(&self) -> bool98     fn start_discovery(&self) -> bool;
99 
100     /// Cancels BREDR Inquiry.
cancel_discovery(&self) -> bool101     fn cancel_discovery(&self) -> bool;
102 
103     /// Checks if discovery is started.
is_discovering(&self) -> bool104     fn is_discovering(&self) -> bool;
105 
106     /// Checks when discovery ends in milliseconds from now.
get_discovery_end_millis(&self) -> u64107     fn get_discovery_end_millis(&self) -> u64;
108 
109     /// Initiates pairing to a remote device. Triggers connection if not already started.
create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool110     fn create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool;
111 
112     /// Cancels any pending bond attempt on given device.
cancel_bond_process(&self, device: BluetoothDevice) -> bool113     fn cancel_bond_process(&self, device: BluetoothDevice) -> bool;
114 
115     /// Removes pairing for given device.
remove_bond(&self, device: BluetoothDevice) -> bool116     fn remove_bond(&self, device: BluetoothDevice) -> bool;
117 
118     /// Returns a list of known bonded devices.
get_bonded_devices(&self) -> Vec<BluetoothDevice>119     fn get_bonded_devices(&self) -> Vec<BluetoothDevice>;
120 
121     /// Gets the bond state of a single device.
get_bond_state(&self, device: BluetoothDevice) -> u32122     fn get_bond_state(&self, device: BluetoothDevice) -> u32;
123 
124     /// Set pin on bonding device.
set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool125     fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool;
126 
127     /// Set passkey on bonding device.
set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool128     fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool;
129 
130     /// Confirm that a pairing should be completed on a bonding device.
set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool131     fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool;
132 
133     /// Gets the name of the remote device.
get_remote_name(&self, device: BluetoothDevice) -> String134     fn get_remote_name(&self, device: BluetoothDevice) -> String;
135 
136     /// Gets the type of the remote device.
get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType137     fn get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType;
138 
139     /// Gets the alias of the remote device.
get_remote_alias(&self, device: BluetoothDevice) -> String140     fn get_remote_alias(&self, device: BluetoothDevice) -> String;
141 
142     /// Sets the alias of the remote device.
set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String)143     fn set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String);
144 
145     /// Gets the class of the remote device.
get_remote_class(&self, device: BluetoothDevice) -> u32146     fn get_remote_class(&self, device: BluetoothDevice) -> u32;
147 
148     /// Gets the connection state of a single device.
get_connection_state(&self, device: BluetoothDevice) -> u32149     fn get_connection_state(&self, device: BluetoothDevice) -> u32;
150 
151     /// Gets the connection state of a specific profile.
get_profile_connection_state(&self, profile: Profile) -> u32152     fn get_profile_connection_state(&self, profile: Profile) -> u32;
153 
154     /// Returns the cached UUIDs of a remote device.
get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>155     fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>;
156 
157     /// Triggers SDP to get UUIDs of a remote device.
fetch_remote_uuids(&self, device: BluetoothDevice) -> bool158     fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool;
159 
160     /// Triggers SDP and searches for a specific UUID on a remote device.
sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool161     fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool;
162 
163     /// Connect all profiles supported by device and enabled on adapter.
connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool164     fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool;
165 
166     /// Disconnect all profiles supported by device and enabled on adapter.
disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool167     fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool;
168 }
169 
170 /// Serializable device used in various apis.
171 #[derive(Clone, Debug, Default)]
172 pub struct BluetoothDevice {
173     pub address: String,
174     pub name: String,
175 }
176 
177 impl BluetoothDevice {
new(address: String, name: String) -> BluetoothDevice178     pub(crate) fn new(address: String, name: String) -> BluetoothDevice {
179         BluetoothDevice { address, name }
180     }
181 
from_properties(in_properties: &Vec<BluetoothProperty>) -> BluetoothDevice182     pub(crate) fn from_properties(in_properties: &Vec<BluetoothProperty>) -> BluetoothDevice {
183         let mut address = String::from("");
184         let mut name = String::from("");
185 
186         for prop in in_properties {
187             match &prop {
188                 BluetoothProperty::BdAddr(bdaddr) => {
189                     address = bdaddr.to_string();
190                 }
191                 BluetoothProperty::BdName(bdname) => {
192                     name = bdname.clone();
193                 }
194                 _ => {}
195             }
196         }
197 
198         BluetoothDevice::new(address, name)
199     }
200 }
201 
202 /// Internal data structure that keeps a map of cached properties for a remote device.
203 struct BluetoothDeviceContext {
204     pub bond_state: BtBondState,
205     pub acl_state: BtAclState,
206     pub info: BluetoothDevice,
207     pub last_seen: Instant,
208     pub properties: HashMap<BtPropertyType, BluetoothProperty>,
209 }
210 
211 impl BluetoothDeviceContext {
new( bond_state: BtBondState, acl_state: BtAclState, info: BluetoothDevice, last_seen: Instant, properties: Vec<BluetoothProperty>, ) -> BluetoothDeviceContext212     pub(crate) fn new(
213         bond_state: BtBondState,
214         acl_state: BtAclState,
215         info: BluetoothDevice,
216         last_seen: Instant,
217         properties: Vec<BluetoothProperty>,
218     ) -> BluetoothDeviceContext {
219         let mut device = BluetoothDeviceContext {
220             bond_state,
221             acl_state,
222             info,
223             last_seen,
224             properties: HashMap::new(),
225         };
226         device.update_properties(properties);
227         device
228     }
229 
update_properties(&mut self, in_properties: Vec<BluetoothProperty>)230     pub(crate) fn update_properties(&mut self, in_properties: Vec<BluetoothProperty>) {
231         for prop in in_properties {
232             match &prop {
233                 BluetoothProperty::BdAddr(bdaddr) => {
234                     self.info.address = bdaddr.to_string();
235                 }
236                 BluetoothProperty::BdName(bdname) => {
237                     self.info.name = bdname.clone();
238                 }
239                 _ => {}
240             }
241 
242             self.properties.insert(prop.get_type(), prop);
243         }
244     }
245 
246     /// Mark this device as seen.
seen(&mut self)247     pub(crate) fn seen(&mut self) {
248         self.last_seen = Instant::now();
249     }
250 }
251 
252 /// The interface for adapter callbacks registered through `IBluetooth::register_callback`.
253 pub trait IBluetoothCallback: RPCProxy {
254     /// When any of the adapter local address is changed.
on_address_changed(&self, addr: String)255     fn on_address_changed(&self, addr: String);
256 
257     /// When the adapter name is changed.
on_name_changed(&self, name: String)258     fn on_name_changed(&self, name: String);
259 
260     /// When the adapter's discoverable mode is changed.
on_discoverable_changed(&self, discoverable: bool)261     fn on_discoverable_changed(&self, discoverable: bool);
262 
263     /// When a device is found via discovery.
on_device_found(&self, remote_device: BluetoothDevice)264     fn on_device_found(&self, remote_device: BluetoothDevice);
265 
266     /// When a device is cleared from discovered devices cache.
on_device_cleared(&self, remote_device: BluetoothDevice)267     fn on_device_cleared(&self, remote_device: BluetoothDevice);
268 
269     /// When the discovery state is changed.
on_discovering_changed(&self, discovering: bool)270     fn on_discovering_changed(&self, discovering: bool);
271 
272     /// When there is a pairing/bonding process and requires agent to display the event to UI.
on_ssp_request( &self, remote_device: BluetoothDevice, cod: u32, variant: BtSspVariant, passkey: u32, )273     fn on_ssp_request(
274         &self,
275         remote_device: BluetoothDevice,
276         cod: u32,
277         variant: BtSspVariant,
278         passkey: u32,
279     );
280 
281     /// When a bonding attempt has completed.
on_bond_state_changed(&self, status: u32, device_address: String, state: u32)282     fn on_bond_state_changed(&self, status: u32, device_address: String, state: u32);
283 }
284 
285 pub trait IBluetoothConnectionCallback: RPCProxy {
286     /// Notification sent when a remote device completes HCI connection.
on_device_connected(&self, remote_device: BluetoothDevice)287     fn on_device_connected(&self, remote_device: BluetoothDevice);
288 
289     /// Notification sent when a remote device completes HCI disconnection.
on_device_disconnected(&self, remote_device: BluetoothDevice)290     fn on_device_disconnected(&self, remote_device: BluetoothDevice);
291 }
292 
293 /// Implementation of the adapter API.
294 pub struct Bluetooth {
295     intf: Arc<Mutex<BluetoothInterface>>,
296 
297     bonded_devices: HashMap<String, BluetoothDeviceContext>,
298     bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
299     callbacks: HashMap<u32, Box<dyn IBluetoothCallback + Send>>,
300     connection_callbacks: HashMap<u32, Box<dyn IBluetoothConnectionCallback + Send>>,
301     discovering_started: Instant,
302     hh: Option<HidHost>,
303     is_connectable: bool,
304     is_discovering: bool,
305     local_address: Option<RawAddress>,
306     properties: HashMap<BtPropertyType, BluetoothProperty>,
307     profiles_ready: bool,
308     found_devices: HashMap<String, BluetoothDeviceContext>,
309     freshness_check: Option<JoinHandle<()>>,
310     sdp: Option<Sdp>,
311     state: BtState,
312     tx: Sender<Message>,
313     uuid_helper: UuidHelper,
314     /// Used to delay connection until we have SDP results.
315     wait_to_connect: bool,
316 }
317 
318 impl Bluetooth {
319     /// Constructs the IBluetooth implementation.
new( tx: Sender<Message>, intf: Arc<Mutex<BluetoothInterface>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, ) -> Bluetooth320     pub fn new(
321         tx: Sender<Message>,
322         intf: Arc<Mutex<BluetoothInterface>>,
323         bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
324     ) -> Bluetooth {
325         Bluetooth {
326             bonded_devices: HashMap::new(),
327             callbacks: HashMap::new(),
328             connection_callbacks: HashMap::new(),
329             hh: None,
330             bluetooth_media,
331             discovering_started: Instant::now(),
332             intf,
333             is_connectable: false,
334             is_discovering: false,
335             local_address: None,
336             properties: HashMap::new(),
337             profiles_ready: false,
338             found_devices: HashMap::new(),
339             freshness_check: None,
340             sdp: None,
341             state: BtState::Off,
342             tx,
343             uuid_helper: UuidHelper::new(),
344             wait_to_connect: false,
345         }
346     }
347 
init_profiles(&mut self)348     pub fn init_profiles(&mut self) {
349         let hhtx = self.tx.clone();
350         self.hh = Some(HidHost::new(&self.intf.lock().unwrap()));
351         self.hh.as_mut().unwrap().initialize(HHCallbacksDispatcher {
352             dispatch: Box::new(move |cb| {
353                 let txl = hhtx.clone();
354                 topstack::get_runtime().spawn(async move {
355                     let _ = txl.send(Message::HidHost(cb)).await;
356                 });
357             }),
358         });
359 
360         let sdptx = self.tx.clone();
361         self.sdp = Some(Sdp::new(&self.intf.lock().unwrap()));
362         self.sdp.as_mut().unwrap().initialize(SdpCallbacksDispatcher {
363             dispatch: Box::new(move |cb| {
364                 let txl = sdptx.clone();
365                 topstack::get_runtime().spawn(async move {
366                     let _ = txl.send(Message::Sdp(cb)).await;
367                 });
368             }),
369         });
370 
371         // Mark profiles as ready
372         self.profiles_ready = true;
373     }
374 
update_local_address(&mut self, addr: &RawAddress)375     fn update_local_address(&mut self, addr: &RawAddress) {
376         self.local_address = Some(*addr);
377 
378         self.for_all_callbacks(|callback| {
379             callback.on_address_changed(self.local_address.unwrap().to_string());
380         });
381     }
382 
for_all_callbacks<F: Fn(&Box<dyn IBluetoothCallback + Send>)>(&self, f: F)383     fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothCallback + Send>)>(&self, f: F) {
384         for (_, callback) in self.callbacks.iter() {
385             f(&callback);
386         }
387     }
388 
for_all_connection_callbacks<F: Fn(&Box<dyn IBluetoothConnectionCallback + Send>)>( &self, f: F, )389     fn for_all_connection_callbacks<F: Fn(&Box<dyn IBluetoothConnectionCallback + Send>)>(
390         &self,
391         f: F,
392     ) {
393         for (_, callback) in self.connection_callbacks.iter() {
394             f(&callback);
395         }
396     }
397 
get_connectable(&self) -> bool398     pub fn get_connectable(&self) -> bool {
399         match self.properties.get(&BtPropertyType::AdapterScanMode) {
400             Some(prop) => match prop {
401                 BluetoothProperty::AdapterScanMode(mode) => match *mode {
402                     BtScanMode::Connectable | BtScanMode::ConnectableDiscoverable => true,
403                     _ => false,
404                 },
405                 _ => false,
406             },
407             _ => false,
408         }
409     }
410 
set_connectable(&mut self, mode: bool) -> bool411     pub fn set_connectable(&mut self, mode: bool) -> bool {
412         self.is_connectable = mode;
413         if mode && self.get_discoverable() {
414             return true;
415         }
416         self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::AdapterScanMode(
417             if mode { BtScanMode::Connectable } else { BtScanMode::None_ },
418         )) == 0
419     }
420 
callback_disconnected(&mut self, id: u32, cb_type: BluetoothCallbackType)421     pub(crate) fn callback_disconnected(&mut self, id: u32, cb_type: BluetoothCallbackType) {
422         match cb_type {
423             BluetoothCallbackType::Adapter => {
424                 self.callbacks.remove(&id);
425             }
426             BluetoothCallbackType::Connection => {
427                 self.connection_callbacks.remove(&id);
428             }
429         };
430     }
431 
get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext>432     fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> {
433         self.bonded_devices.get(address).or_else(|| self.found_devices.get(address))
434     }
435 
get_remote_device_if_found_mut( &mut self, address: &str, ) -> Option<&mut BluetoothDeviceContext>436     fn get_remote_device_if_found_mut(
437         &mut self,
438         address: &str,
439     ) -> Option<&mut BluetoothDeviceContext> {
440         match self.bonded_devices.get_mut(address) {
441             None => self.found_devices.get_mut(address),
442             some => some,
443         }
444     }
445 
get_remote_device_property( &self, device: &BluetoothDevice, property_type: &BtPropertyType, ) -> Option<BluetoothProperty>446     fn get_remote_device_property(
447         &self,
448         device: &BluetoothDevice,
449         property_type: &BtPropertyType,
450     ) -> Option<BluetoothProperty> {
451         self.get_remote_device_if_found(&device.address)
452             .and_then(|d| d.properties.get(property_type).and_then(|p| Some(p.clone())))
453     }
454 
set_remote_device_property( &mut self, device: &BluetoothDevice, property_type: BtPropertyType, property: BluetoothProperty, ) -> Result<(), ()>455     fn set_remote_device_property(
456         &mut self,
457         device: &BluetoothDevice,
458         property_type: BtPropertyType,
459         property: BluetoothProperty,
460     ) -> Result<(), ()> {
461         let remote_device = match self.get_remote_device_if_found_mut(&device.address) {
462             Some(d) => d,
463             None => {
464                 return Err(());
465             }
466         };
467 
468         let mut addr = RawAddress::from_string(device.address.clone());
469         if addr.is_none() {
470             return Err(());
471         }
472         let addr = addr.as_mut().unwrap();
473 
474         // TODO: Determine why a callback isn't invoked to do this.
475         remote_device.properties.insert(property_type, property.clone());
476         self.intf.lock().unwrap().set_remote_device_property(addr, property);
477         Ok(())
478     }
479 
480     /// Check whether found devices are still fresh. If they're outside the
481     /// freshness window, send a notification to clear the device from clients.
trigger_freshness_check(&mut self)482     pub(crate) fn trigger_freshness_check(&mut self) {
483         // Drop previous joinhandle
484         self.freshness_check = None;
485 
486         // A found device is considered fresh if:
487         // * It was last seen less than |FOUND_DEVICE_FRESHNESS| ago.
488         // * It is currently connected.
489         fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool {
490             let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS;
491             now < &fresh_at || d.acl_state == BtAclState::Connected
492         }
493 
494         let now = Instant::now();
495         let stale_devices: Vec<BluetoothDevice> = self
496             .found_devices
497             .iter()
498             .filter(|(_, d)| !is_fresh(d, &now))
499             .map(|(_, d)| d.info.clone())
500             .collect();
501 
502         // Retain only devices that are fresh.
503         self.found_devices.retain(|_, d| is_fresh(d, &now));
504 
505         for d in stale_devices {
506             self.for_all_callbacks(|callback| {
507                 callback.on_device_cleared(d.clone());
508             });
509         }
510 
511         // If we have any fresh devices remaining, re-queue a freshness check.
512         if self.found_devices.len() > 0 {
513             let txl = self.tx.clone();
514 
515             self.freshness_check = Some(tokio::spawn(async move {
516                 time::sleep(FOUND_DEVICE_FRESHNESS).await;
517                 let _ = txl.send(Message::DeviceFreshnessCheck).await;
518             }));
519         }
520     }
521 }
522 
523 #[btif_callbacks_dispatcher(Bluetooth, dispatch_base_callbacks, BaseCallbacks)]
524 pub(crate) trait BtifBluetoothCallbacks {
525     #[btif_callback(AdapterState)]
adapter_state_changed(&mut self, state: BtState)526     fn adapter_state_changed(&mut self, state: BtState);
527 
528     #[btif_callback(AdapterProperties)]
adapter_properties_changed( &mut self, status: BtStatus, num_properties: i32, properties: Vec<BluetoothProperty>, )529     fn adapter_properties_changed(
530         &mut self,
531         status: BtStatus,
532         num_properties: i32,
533         properties: Vec<BluetoothProperty>,
534     );
535 
536     #[btif_callback(DeviceFound)]
device_found(&mut self, n: i32, properties: Vec<BluetoothProperty>)537     fn device_found(&mut self, n: i32, properties: Vec<BluetoothProperty>);
538 
539     #[btif_callback(DiscoveryState)]
discovery_state(&mut self, state: BtDiscoveryState)540     fn discovery_state(&mut self, state: BtDiscoveryState);
541 
542     #[btif_callback(SspRequest)]
ssp_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, variant: BtSspVariant, passkey: u32, )543     fn ssp_request(
544         &mut self,
545         remote_addr: RawAddress,
546         remote_name: String,
547         cod: u32,
548         variant: BtSspVariant,
549         passkey: u32,
550     );
551 
552     #[btif_callback(BondState)]
bond_state( &mut self, status: BtStatus, addr: RawAddress, bond_state: BtBondState, fail_reason: i32, )553     fn bond_state(
554         &mut self,
555         status: BtStatus,
556         addr: RawAddress,
557         bond_state: BtBondState,
558         fail_reason: i32,
559     );
560 
561     #[btif_callback(RemoteDeviceProperties)]
remote_device_properties_changed( &mut self, status: BtStatus, addr: RawAddress, num_properties: i32, properties: Vec<BluetoothProperty>, )562     fn remote_device_properties_changed(
563         &mut self,
564         status: BtStatus,
565         addr: RawAddress,
566         num_properties: i32,
567         properties: Vec<BluetoothProperty>,
568     );
569 
570     #[btif_callback(AclState)]
acl_state( &mut self, status: BtStatus, addr: RawAddress, state: BtAclState, link_type: BtTransport, hci_reason: BtHciErrorCode, )571     fn acl_state(
572         &mut self,
573         status: BtStatus,
574         addr: RawAddress,
575         state: BtAclState,
576         link_type: BtTransport,
577         hci_reason: BtHciErrorCode,
578     );
579 }
580 
581 #[btif_callbacks_dispatcher(Bluetooth, dispatch_sdp_callbacks, SdpCallbacks)]
582 pub(crate) trait BtifSdpCallbacks {
583     #[btif_callback(SdpSearch)]
sdp_search( &mut self, status: BtStatus, address: RawAddress, uuid: Uuid, count: i32, records: Vec<BtSdpRecord>, )584     fn sdp_search(
585         &mut self,
586         status: BtStatus,
587         address: RawAddress,
588         uuid: Uuid,
589         count: i32,
590         records: Vec<BtSdpRecord>,
591     );
592 }
593 
get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher594 pub fn get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher {
595     BaseCallbacksDispatcher {
596         dispatch: Box::new(move |cb| {
597             let txl = tx.clone();
598             topstack::get_runtime().spawn(async move {
599                 let _ = txl.send(Message::Base(cb)).await;
600             });
601         }),
602     }
603 }
604 
605 impl BtifBluetoothCallbacks for Bluetooth {
adapter_state_changed(&mut self, state: BtState)606     fn adapter_state_changed(&mut self, state: BtState) {
607         let prev_state = self.state.clone();
608         self.state = state;
609 
610         // If it's the same state as before, no further action
611         if self.state == prev_state {
612             return;
613         }
614 
615         if self.state == BtState::On {
616             self.bluetooth_media.lock().unwrap().initialize();
617         }
618 
619         if self.state == BtState::Off {
620             self.properties.clear();
621         } else {
622             // Trigger properties update
623             self.intf.lock().unwrap().get_adapter_properties();
624 
625             // Also need to manually request some properties
626             self.intf.lock().unwrap().get_adapter_property(BtPropertyType::ClassOfDevice);
627 
628             // Ensure device is connectable so that disconnected device can reconnect
629             self.set_connectable(true);
630         }
631     }
632 
633     #[allow(unused_variables)]
adapter_properties_changed( &mut self, status: BtStatus, num_properties: i32, properties: Vec<BluetoothProperty>, )634     fn adapter_properties_changed(
635         &mut self,
636         status: BtStatus,
637         num_properties: i32,
638         properties: Vec<BluetoothProperty>,
639     ) {
640         if status != BtStatus::Success {
641             return;
642         }
643 
644         // Update local property cache
645         for prop in properties {
646             match &prop {
647                 BluetoothProperty::BdAddr(bdaddr) => {
648                     self.update_local_address(&bdaddr);
649                 }
650                 BluetoothProperty::AdapterBondedDevices(bondlist) => {
651                     for addr in bondlist.iter() {
652                         let address = addr.to_string();
653 
654                         // Update bonded state if already in the list. Otherwise create a new
655                         // context with empty properties and name.
656                         self.bonded_devices
657                             .entry(address.clone())
658                             .and_modify(|d| d.bond_state = BtBondState::Bonded)
659                             .or_insert(BluetoothDeviceContext::new(
660                                 BtBondState::Bonded,
661                                 BtAclState::Disconnected,
662                                 BluetoothDevice::new(address.clone(), "".to_string()),
663                                 Instant::now(),
664                                 vec![],
665                             ));
666                     }
667                 }
668                 BluetoothProperty::BdName(bdname) => {
669                     self.for_all_callbacks(|callback| {
670                         callback.on_name_changed(bdname.clone());
671                     });
672                 }
673                 BluetoothProperty::AdapterScanMode(mode) => {
674                     self.for_all_callbacks(|callback| {
675                         callback
676                             .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable);
677                     });
678                 }
679                 _ => {}
680             }
681 
682             self.properties.insert(prop.get_type(), prop);
683         }
684     }
685 
device_found(&mut self, _n: i32, properties: Vec<BluetoothProperty>)686     fn device_found(&mut self, _n: i32, properties: Vec<BluetoothProperty>) {
687         let device = BluetoothDevice::from_properties(&properties);
688         let address = device.address.clone();
689 
690         if let Some(existing) = self.found_devices.get_mut(&address) {
691             existing.update_properties(properties);
692             existing.seen();
693         } else {
694             let device_with_props = BluetoothDeviceContext::new(
695                 BtBondState::NotBonded,
696                 BtAclState::Disconnected,
697                 device,
698                 Instant::now(),
699                 properties,
700             );
701             self.found_devices.insert(address.clone(), device_with_props);
702         }
703 
704         let device = self.found_devices.get(&address).unwrap();
705 
706         self.for_all_callbacks(|callback| {
707             callback.on_device_found(device.info.clone());
708         });
709     }
710 
discovery_state(&mut self, state: BtDiscoveryState)711     fn discovery_state(&mut self, state: BtDiscoveryState) {
712         let is_discovering = &state == &BtDiscoveryState::Started;
713 
714         // No-op if we're updating the state to the same value again.
715         if &is_discovering == &self.is_discovering {
716             return;
717         }
718 
719         // Cache discovering state
720         self.is_discovering = &state == &BtDiscoveryState::Started;
721         if self.is_discovering {
722             self.discovering_started = Instant::now();
723         }
724 
725         self.for_all_callbacks(|callback| {
726             callback.on_discovering_changed(state == BtDiscoveryState::Started);
727         });
728 
729         // Stopped discovering and no freshness check is active. Immediately do
730         // freshness check which will schedule a recurring future until all
731         // entries are cleared.
732         if !is_discovering && self.freshness_check.is_none() {
733             self.trigger_freshness_check();
734         }
735     }
736 
ssp_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, variant: BtSspVariant, passkey: u32, )737     fn ssp_request(
738         &mut self,
739         remote_addr: RawAddress,
740         remote_name: String,
741         cod: u32,
742         variant: BtSspVariant,
743         passkey: u32,
744     ) {
745         // Currently this supports many agent because we accept many callbacks.
746         // TODO: We need a way to select the default agent.
747         self.for_all_callbacks(|callback| {
748             callback.on_ssp_request(
749                 BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()),
750                 cod,
751                 variant.clone(),
752                 passkey,
753             );
754         });
755     }
756 
bond_state( &mut self, status: BtStatus, addr: RawAddress, bond_state: BtBondState, _fail_reason: i32, )757     fn bond_state(
758         &mut self,
759         status: BtStatus,
760         addr: RawAddress,
761         bond_state: BtBondState,
762         _fail_reason: i32,
763     ) {
764         let address = addr.to_string();
765 
766         // Easy case of not bonded -- we remove the device from the bonded list and change the bond
767         // state in the found list (in case it was previously bonding).
768         if &bond_state == &BtBondState::NotBonded {
769             self.bonded_devices.remove(&address);
770             self.found_devices
771                 .entry(address.clone())
772                 .and_modify(|d| d.bond_state = bond_state.clone());
773         }
774         // We will only insert into the bonded list after bonding is complete
775         else if &bond_state == &BtBondState::Bonded && !self.bonded_devices.contains_key(&address)
776         {
777             // We either need to construct a new BluetoothDeviceContext or grab it from the found
778             // devices map
779             let device = match self.found_devices.remove(&address) {
780                 Some(mut v) => {
781                     v.bond_state = bond_state.clone();
782                     v
783                 }
784                 None => BluetoothDeviceContext::new(
785                     bond_state.clone(),
786                     BtAclState::Disconnected,
787                     BluetoothDevice::new(address.clone(), "".to_string()),
788                     Instant::now(),
789                     vec![],
790                 ),
791             };
792 
793             self.bonded_devices.insert(address.clone(), device);
794         } else {
795             // If we're bonding, we need to update the found devices list
796             self.found_devices
797                 .entry(address.clone())
798                 .and_modify(|d| d.bond_state = bond_state.clone());
799         }
800 
801         // Send bond state changed notifications
802         self.for_all_callbacks(|callback| {
803             callback.on_bond_state_changed(
804                 status.to_u32().unwrap(),
805                 address.clone(),
806                 bond_state.to_u32().unwrap(),
807             );
808         });
809     }
810 
remote_device_properties_changed( &mut self, _status: BtStatus, addr: RawAddress, _num_properties: i32, properties: Vec<BluetoothProperty>, )811     fn remote_device_properties_changed(
812         &mut self,
813         _status: BtStatus,
814         addr: RawAddress,
815         _num_properties: i32,
816         properties: Vec<BluetoothProperty>,
817     ) {
818         let address = addr.to_string();
819         let device = match self.get_remote_device_if_found_mut(&address) {
820             None => {
821                 self.found_devices.insert(
822                     address.clone(),
823                     BluetoothDeviceContext::new(
824                         BtBondState::NotBonded,
825                         BtAclState::Disconnected,
826                         BluetoothDevice::new(address.clone(), String::from("")),
827                         Instant::now(),
828                         vec![],
829                     ),
830                 );
831 
832                 self.found_devices.get_mut(&address)
833             }
834             some => some,
835         };
836 
837         match device {
838             Some(d) => {
839                 d.update_properties(properties);
840                 d.seen();
841 
842                 let info = d.info.clone();
843                 let uuids = self.get_remote_uuids(info.clone());
844                 if self.wait_to_connect && uuids.len() > 0 {
845                     self.connect_all_enabled_profiles(info);
846                 }
847             }
848             None => (),
849         };
850     }
851 
acl_state( &mut self, status: BtStatus, addr: RawAddress, state: BtAclState, _link_type: BtTransport, _hci_reason: BtHciErrorCode, )852     fn acl_state(
853         &mut self,
854         status: BtStatus,
855         addr: RawAddress,
856         state: BtAclState,
857         _link_type: BtTransport,
858         _hci_reason: BtHciErrorCode,
859     ) {
860         if status != BtStatus::Success {
861             warn!("Connection to [{}] failed. Status: {:?}", addr.to_string(), status);
862             return;
863         }
864 
865         let address = addr.to_string();
866         let device = match self.get_remote_device_if_found_mut(&address) {
867             None => {
868                 self.found_devices.insert(
869                     address.clone(),
870                     BluetoothDeviceContext::new(
871                         BtBondState::NotBonded,
872                         BtAclState::Disconnected,
873                         BluetoothDevice::new(address.clone(), String::from("")),
874                         Instant::now(),
875                         vec![],
876                     ),
877                 );
878 
879                 self.found_devices.get_mut(&address)
880             }
881             some => some,
882         };
883 
884         match device {
885             Some(found) => {
886                 // Only notify if there's been a change in state
887                 let prev_state = &found.acl_state;
888                 if prev_state != &state {
889                     let device = found.info.clone();
890                     found.acl_state = state.clone();
891 
892                     match state {
893                         BtAclState::Connected => {
894                             self.for_all_connection_callbacks(|callback| {
895                                 callback.on_device_connected(device.clone());
896                             });
897                         }
898                         BtAclState::Disconnected => {
899                             self.for_all_connection_callbacks(|callback| {
900                                 callback.on_device_disconnected(device.clone());
901                             });
902                         }
903                     };
904                 }
905             }
906             None => (),
907         };
908     }
909 }
910 
911 // TODO: Add unit tests for this implementation
912 impl IBluetooth for Bluetooth {
register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>)913     fn register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>) {
914         let tx = self.tx.clone();
915 
916         let id = callback.register_disconnect(Box::new(move |cb_id| {
917             let tx = tx.clone();
918             tokio::spawn(async move {
919                 let _result = tx
920                     .send(Message::BluetoothCallbackDisconnected(
921                         cb_id,
922                         BluetoothCallbackType::Adapter,
923                     ))
924                     .await;
925             });
926         }));
927 
928         self.callbacks.insert(id, callback);
929     }
930 
register_connection_callback( &mut self, mut callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u32931     fn register_connection_callback(
932         &mut self,
933         mut callback: Box<dyn IBluetoothConnectionCallback + Send>,
934     ) -> u32 {
935         let tx = self.tx.clone();
936 
937         let id = callback.register_disconnect(Box::new(move |cb_id| {
938             let tx = tx.clone();
939             tokio::spawn(async move {
940                 let _ = tx
941                     .send(Message::BluetoothCallbackDisconnected(
942                         cb_id,
943                         BluetoothCallbackType::Connection,
944                     ))
945                     .await;
946             });
947         }));
948 
949         self.connection_callbacks.insert(id, callback);
950 
951         id
952     }
953 
unregister_connection_callback(&mut self, callback_id: u32) -> bool954     fn unregister_connection_callback(&mut self, callback_id: u32) -> bool {
955         match self.connection_callbacks.get_mut(&callback_id) {
956             Some(cb) => cb.unregister(callback_id),
957             None => false,
958         }
959     }
960 
enable(&mut self) -> bool961     fn enable(&mut self) -> bool {
962         self.intf.lock().unwrap().enable() == 0
963     }
964 
disable(&mut self) -> bool965     fn disable(&mut self) -> bool {
966         self.intf.lock().unwrap().disable() == 0
967     }
968 
get_address(&self) -> String969     fn get_address(&self) -> String {
970         match self.local_address {
971             None => String::from(""),
972             Some(addr) => addr.to_string(),
973         }
974     }
975 
get_uuids(&self) -> Vec<Uuid128Bit>976     fn get_uuids(&self) -> Vec<Uuid128Bit> {
977         match self.properties.get(&BtPropertyType::Uuids) {
978             Some(prop) => match prop {
979                 BluetoothProperty::Uuids(uuids) => {
980                     uuids.iter().map(|&x| x.uu.clone()).collect::<Vec<Uuid128Bit>>()
981                 }
982                 _ => vec![],
983             },
984             _ => vec![],
985         }
986     }
987 
get_name(&self) -> String988     fn get_name(&self) -> String {
989         match self.properties.get(&BtPropertyType::BdName) {
990             Some(prop) => match prop {
991                 BluetoothProperty::BdName(name) => name.clone(),
992                 _ => String::new(),
993             },
994             _ => String::new(),
995         }
996     }
997 
set_name(&self, name: String) -> bool998     fn set_name(&self, name: String) -> bool {
999         self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::BdName(name)) == 0
1000     }
1001 
get_bluetooth_class(&self) -> u321002     fn get_bluetooth_class(&self) -> u32 {
1003         match self.properties.get(&BtPropertyType::ClassOfDevice) {
1004             Some(prop) => match prop {
1005                 BluetoothProperty::ClassOfDevice(cod) => cod.clone(),
1006                 _ => 0,
1007             },
1008             _ => 0,
1009         }
1010     }
1011 
set_bluetooth_class(&self, cod: u32) -> bool1012     fn set_bluetooth_class(&self, cod: u32) -> bool {
1013         self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::ClassOfDevice(cod)) == 0
1014     }
1015 
get_discoverable(&self) -> bool1016     fn get_discoverable(&self) -> bool {
1017         match self.properties.get(&BtPropertyType::AdapterScanMode) {
1018             Some(prop) => match prop {
1019                 BluetoothProperty::AdapterScanMode(mode) => match mode {
1020                     BtScanMode::ConnectableDiscoverable => true,
1021                     _ => false,
1022                 },
1023                 _ => false,
1024             },
1025             _ => false,
1026         }
1027     }
1028 
get_discoverable_timeout(&self) -> u321029     fn get_discoverable_timeout(&self) -> u32 {
1030         match self.properties.get(&BtPropertyType::AdapterDiscoverableTimeout) {
1031             Some(prop) => match prop {
1032                 BluetoothProperty::AdapterDiscoverableTimeout(timeout) => timeout.clone(),
1033                 _ => 0,
1034             },
1035             _ => 0,
1036         }
1037     }
1038 
set_discoverable(&self, mode: bool, duration: u32) -> bool1039     fn set_discoverable(&self, mode: bool, duration: u32) -> bool {
1040         self.intf
1041             .lock()
1042             .unwrap()
1043             .set_adapter_property(BluetoothProperty::AdapterDiscoverableTimeout(duration));
1044         self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::AdapterScanMode(
1045             if mode {
1046                 BtScanMode::ConnectableDiscoverable
1047             } else {
1048                 if self.is_connectable {
1049                     BtScanMode::Connectable
1050                 } else {
1051                     BtScanMode::None_
1052                 }
1053             },
1054         )) == 0
1055     }
1056 
is_multi_advertisement_supported(&self) -> bool1057     fn is_multi_advertisement_supported(&self) -> bool {
1058         match self.properties.get(&BtPropertyType::LocalLeFeatures) {
1059             Some(prop) => match prop {
1060                 BluetoothProperty::LocalLeFeatures(llf) => {
1061                     llf.max_adv_instance >= MIN_ADV_INSTANCES_FOR_MULTI_ADV
1062                 }
1063                 _ => false,
1064             },
1065             _ => false,
1066         }
1067     }
1068 
is_le_extended_advertising_supported(&self) -> bool1069     fn is_le_extended_advertising_supported(&self) -> bool {
1070         match self.properties.get(&BtPropertyType::LocalLeFeatures) {
1071             Some(prop) => match prop {
1072                 BluetoothProperty::LocalLeFeatures(llf) => llf.le_extended_advertising_supported,
1073                 _ => false,
1074             },
1075             _ => false,
1076         }
1077     }
1078 
start_discovery(&self) -> bool1079     fn start_discovery(&self) -> bool {
1080         self.intf.lock().unwrap().start_discovery() == 0
1081     }
1082 
cancel_discovery(&self) -> bool1083     fn cancel_discovery(&self) -> bool {
1084         self.intf.lock().unwrap().cancel_discovery() == 0
1085     }
1086 
is_discovering(&self) -> bool1087     fn is_discovering(&self) -> bool {
1088         self.is_discovering
1089     }
1090 
get_discovery_end_millis(&self) -> u641091     fn get_discovery_end_millis(&self) -> u64 {
1092         if !self.is_discovering {
1093             return 0;
1094         }
1095 
1096         let elapsed_ms = self.discovering_started.elapsed().as_millis() as u64;
1097         if elapsed_ms >= DEFAULT_DISCOVERY_TIMEOUT_MS {
1098             0
1099         } else {
1100             DEFAULT_DISCOVERY_TIMEOUT_MS - elapsed_ms
1101         }
1102     }
1103 
create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool1104     fn create_bond(&self, device: BluetoothDevice, transport: BtTransport) -> bool {
1105         let addr = RawAddress::from_string(device.address.clone());
1106 
1107         if addr.is_none() {
1108             warn!("Can't create bond. Address {} is not valid", device.address);
1109             return false;
1110         }
1111 
1112         let address = addr.unwrap();
1113 
1114         // BREDR connection won't work when Inquiry is in progress.
1115         self.cancel_discovery();
1116 
1117         self.intf.lock().unwrap().create_bond(&address, transport) == 0
1118     }
1119 
cancel_bond_process(&self, device: BluetoothDevice) -> bool1120     fn cancel_bond_process(&self, device: BluetoothDevice) -> bool {
1121         let addr = RawAddress::from_string(device.address.clone());
1122 
1123         if addr.is_none() {
1124             warn!("Can't cancel bond. Address {} is not valid.", device.address);
1125             return false;
1126         }
1127 
1128         let address = addr.unwrap();
1129         self.intf.lock().unwrap().cancel_bond(&address) == 0
1130     }
1131 
remove_bond(&self, device: BluetoothDevice) -> bool1132     fn remove_bond(&self, device: BluetoothDevice) -> bool {
1133         let addr = RawAddress::from_string(device.address.clone());
1134 
1135         if addr.is_none() {
1136             warn!("Can't remove bond. Address {} is not valid.", device.address);
1137             return false;
1138         }
1139 
1140         let address = addr.unwrap();
1141         self.intf.lock().unwrap().remove_bond(&address) == 0
1142     }
1143 
get_bonded_devices(&self) -> Vec<BluetoothDevice>1144     fn get_bonded_devices(&self) -> Vec<BluetoothDevice> {
1145         let mut devices: Vec<BluetoothDevice> = vec![];
1146 
1147         for (_, device) in self.bonded_devices.iter() {
1148             devices.push(device.info.clone());
1149         }
1150 
1151         devices
1152     }
1153 
get_bond_state(&self, device: BluetoothDevice) -> u321154     fn get_bond_state(&self, device: BluetoothDevice) -> u32 {
1155         match self.bonded_devices.get(&device.address) {
1156             Some(device) => device.bond_state.to_u32().unwrap(),
1157             None => BtBondState::NotBonded.to_u32().unwrap(),
1158         }
1159     }
1160 
set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool1161     fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool {
1162         let addr = RawAddress::from_string(device.address.clone());
1163 
1164         if addr.is_none() {
1165             warn!("Can't set pin. Address {} is not valid.", device.address);
1166             return false;
1167         }
1168 
1169         let is_bonding = match self.found_devices.get(&device.address) {
1170             Some(d) => d.bond_state == BtBondState::Bonding,
1171             None => false,
1172         };
1173 
1174         if !is_bonding {
1175             warn!("Can't set pin. Device {} isn't bonding.", device.address);
1176             return false;
1177         }
1178 
1179         let mut btpin: BtPinCode = BtPinCode { pin: [0; 16] };
1180         btpin.pin.copy_from_slice(pin_code.as_slice());
1181 
1182         self.intf.lock().unwrap().pin_reply(
1183             &addr.unwrap(),
1184             accept as u8,
1185             pin_code.len() as u8,
1186             &mut btpin,
1187         ) == 0
1188     }
1189 
set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool1190     fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool {
1191         let addr = RawAddress::from_string(device.address.clone());
1192 
1193         if addr.is_none() {
1194             warn!("Can't set passkey. Address {} is not valid.", device.address);
1195             return false;
1196         }
1197 
1198         let is_bonding = match self.found_devices.get(&device.address) {
1199             Some(d) => d.bond_state == BtBondState::Bonding,
1200             None => false,
1201         };
1202 
1203         if !is_bonding {
1204             warn!("Can't set passkey. Device {} isn't bonding.", device.address);
1205             return false;
1206         }
1207 
1208         let mut tmp: [u8; 4] = [0; 4];
1209         tmp.copy_from_slice(passkey.as_slice());
1210         let passkey = u32::from_ne_bytes(tmp);
1211 
1212         self.intf.lock().unwrap().ssp_reply(
1213             &addr.unwrap(),
1214             BtSspVariant::PasskeyEntry,
1215             accept as u8,
1216             passkey,
1217         ) == 0
1218     }
1219 
set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool1220     fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
1221         let addr = RawAddress::from_string(device.address.clone());
1222 
1223         if addr.is_none() {
1224             warn!("Can't set pairing confirmation. Address {} is not valid.", device.address);
1225             return false;
1226         }
1227 
1228         let is_bonding = match self.found_devices.get(&device.address) {
1229             Some(d) => d.bond_state == BtBondState::Bonding,
1230             None => false,
1231         };
1232 
1233         if !is_bonding {
1234             warn!("Can't set pairing confirmation. Device {} isn't bonding.", device.address);
1235             return false;
1236         }
1237 
1238         self.intf.lock().unwrap().ssp_reply(
1239             &addr.unwrap(),
1240             BtSspVariant::PasskeyConfirmation,
1241             accept as u8,
1242             0,
1243         ) == 0
1244     }
1245 
get_remote_name(&self, device: BluetoothDevice) -> String1246     fn get_remote_name(&self, device: BluetoothDevice) -> String {
1247         match self.get_remote_device_property(&device, &BtPropertyType::BdName) {
1248             Some(BluetoothProperty::BdName(name)) => return name.clone(),
1249             _ => return "".to_string(),
1250         }
1251     }
1252 
get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType1253     fn get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType {
1254         match self.get_remote_device_property(&device, &BtPropertyType::TypeOfDevice) {
1255             Some(BluetoothProperty::TypeOfDevice(device_type)) => return device_type,
1256             _ => return BtDeviceType::Unknown,
1257         }
1258     }
1259 
get_remote_alias(&self, device: BluetoothDevice) -> String1260     fn get_remote_alias(&self, device: BluetoothDevice) -> String {
1261         match self.get_remote_device_property(&device, &BtPropertyType::RemoteFriendlyName) {
1262             Some(BluetoothProperty::RemoteFriendlyName(name)) => return name.clone(),
1263             _ => "".to_string(),
1264         }
1265     }
1266 
set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String)1267     fn set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String) {
1268         let _ = self.set_remote_device_property(
1269             &device,
1270             BtPropertyType::RemoteFriendlyName,
1271             BluetoothProperty::RemoteFriendlyName(new_alias),
1272         );
1273     }
1274 
get_remote_class(&self, device: BluetoothDevice) -> u321275     fn get_remote_class(&self, device: BluetoothDevice) -> u32 {
1276         match self.get_remote_device_property(&device, &BtPropertyType::ClassOfDevice) {
1277             Some(BluetoothProperty::ClassOfDevice(class)) => return class,
1278             _ => 0,
1279         }
1280     }
1281 
get_connection_state(&self, device: BluetoothDevice) -> u321282     fn get_connection_state(&self, device: BluetoothDevice) -> u32 {
1283         let addr = RawAddress::from_string(device.address.clone());
1284 
1285         if addr.is_none() {
1286             warn!("Can't check connection state. Address {} is not valid.", device.address);
1287             return 0;
1288         }
1289 
1290         self.intf.lock().unwrap().get_connection_state(&addr.unwrap())
1291     }
1292 
get_profile_connection_state(&self, profile: Profile) -> u321293     fn get_profile_connection_state(&self, profile: Profile) -> u32 {
1294         match profile {
1295             Profile::A2dpSink | Profile::A2dpSource => {
1296                 self.bluetooth_media.lock().unwrap().get_a2dp_connection_state()
1297             }
1298             Profile::Hfp | Profile::HfpAg => {
1299                 self.bluetooth_media.lock().unwrap().get_hfp_connection_state()
1300             }
1301             // TODO: (b/223431229) Profile::Hid and Profile::Hogp
1302             _ => 0,
1303         }
1304     }
1305 
get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>1306     fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
1307         match self.get_remote_device_property(&device, &BtPropertyType::Uuids) {
1308             Some(BluetoothProperty::Uuids(uuids)) => {
1309                 return uuids.iter().map(|&x| x.uu.clone()).collect::<Vec<Uuid128Bit>>()
1310             }
1311             _ => return vec![],
1312         }
1313     }
1314 
fetch_remote_uuids(&self, device: BluetoothDevice) -> bool1315     fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool {
1316         if self.get_remote_device_if_found(&device.address).is_none() {
1317             warn!("Won't fetch UUIDs on unknown device {}", device.address);
1318             return false;
1319         }
1320 
1321         let addr = RawAddress::from_string(device.address.clone());
1322         if addr.is_none() {
1323             warn!("Can't fetch UUIDs. Address {} is not valid.", device.address);
1324             return false;
1325         }
1326         self.intf.lock().unwrap().get_remote_services(&mut addr.unwrap(), BtTransport::Auto) == 0
1327     }
1328 
sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool1329     fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
1330         if self.sdp.is_none() {
1331             warn!("SDP is not initialized. Can't do SDP search.");
1332             return false;
1333         }
1334 
1335         let addr = RawAddress::from_string(device.address.clone());
1336         if addr.is_none() {
1337             warn!("Can't SDP search. Address {} is not valid.", device.address);
1338             return false;
1339         }
1340 
1341         let uu = Uuid { uu: uuid };
1342         self.sdp.as_ref().unwrap().sdp_search(&mut addr.unwrap(), &uu) == BtStatus::Success
1343     }
1344 
connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool1345     fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool {
1346         // Profile init must be complete before this api is callable
1347         if !self.profiles_ready {
1348             return false;
1349         }
1350 
1351         let addr = RawAddress::from_string(device.address.clone());
1352         if addr.is_none() {
1353             warn!("Can't connect profiles on invalid address [{}]", &device.address);
1354             return false;
1355         }
1356 
1357         // Check all remote uuids to see if they match enabled profiles and connect them.
1358         let mut has_enabled_uuids = false;
1359         let uuids = self.get_remote_uuids(device.clone());
1360         for uuid in uuids.iter() {
1361             match self.uuid_helper.is_known_profile(uuid) {
1362                 Some(p) => {
1363                     if self.uuid_helper.is_profile_enabled(&p) {
1364                         match p {
1365                             Profile::Hid | Profile::Hogp => {
1366                                 self.hh.as_ref().unwrap().connect(&mut addr.unwrap());
1367                             }
1368 
1369                             Profile::A2dpSink | Profile::A2dpSource => {
1370                                 let txl = self.tx.clone();
1371                                 let address = device.address.clone();
1372                                 topstack::get_runtime().spawn(async move {
1373                                     let _ = txl
1374                                         .send(Message::Media(MediaActions::Connect(address)))
1375                                         .await;
1376                                 });
1377                             }
1378                             // We don't connect most profiles
1379                             _ => (),
1380                         }
1381                     }
1382                     has_enabled_uuids = true;
1383                 }
1384                 _ => {}
1385             }
1386         }
1387 
1388         // If SDP isn't completed yet, we wait for it to complete and retry the connection again.
1389         // Otherwise, this connection request is done, no retry is required.
1390         self.wait_to_connect = !has_enabled_uuids;
1391         return true;
1392     }
1393 
disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool1394     fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool {
1395         // No need to retry connection as we are going to disconnect all enabled profiles.
1396         self.wait_to_connect = false;
1397 
1398         if !self.profiles_ready {
1399             return false;
1400         }
1401 
1402         let addr = RawAddress::from_string(device.address.clone());
1403         if addr.is_none() {
1404             warn!("Can't connect profiles on invalid address [{}]", &device.address);
1405             return false;
1406         }
1407 
1408         let uuids = self.get_remote_uuids(device.clone());
1409         for uuid in uuids.iter() {
1410             match self.uuid_helper.is_known_profile(uuid) {
1411                 Some(p) => {
1412                     if self.uuid_helper.is_profile_enabled(&p) {
1413                         match p {
1414                             Profile::Hid | Profile::Hogp => {
1415                                 self.hh.as_ref().unwrap().disconnect(&mut addr.unwrap());
1416                             }
1417 
1418                             Profile::A2dpSink | Profile::A2dpSource => {
1419                                 let txl = self.tx.clone();
1420                                 let address = device.address.clone();
1421                                 topstack::get_runtime().spawn(async move {
1422                                     let _ = txl
1423                                         .send(Message::Media(MediaActions::Disconnect(address)))
1424                                         .await;
1425                                 });
1426                             }
1427 
1428                             // We don't connect most profiles
1429                             _ => (),
1430                         }
1431                     }
1432                 }
1433                 _ => {}
1434             }
1435         }
1436 
1437         return true;
1438     }
1439 }
1440 
1441 impl BtifSdpCallbacks for Bluetooth {
sdp_search( &mut self, status: BtStatus, address: RawAddress, uuid: Uuid, _count: i32, _records: Vec<BtSdpRecord>, )1442     fn sdp_search(
1443         &mut self,
1444         status: BtStatus,
1445         address: RawAddress,
1446         uuid: Uuid,
1447         _count: i32,
1448         _records: Vec<BtSdpRecord>,
1449     ) {
1450         debug!(
1451             "Sdp search result found: Status({:?}) Address({:?}) Uuid({:?})",
1452             status, address, uuid
1453         );
1454     }
1455 }
1456