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