1 //! Anything related to the adapter API (IBluetooth).
2
3 use bt_topshim::btif::{
4 BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState,
5 BtBondState, BtConnectionDirection, BtConnectionState, BtDeviceType, BtDiscMode,
6 BtDiscoveryState, BtHciErrorCode, BtPinCode, BtPropertyType, BtScanMode, BtSspVariant, BtState,
7 BtStatus, BtTransport, BtVendorProductInfo, DisplayAddress, RawAddress, ToggleableProfile,
8 Uuid, Uuid128Bit,
9 };
10 use bt_topshim::{
11 metrics,
12 profiles::gatt::GattStatus,
13 profiles::hid_host::{
14 BthhConnectionState, BthhHidInfo, BthhProtocolMode, BthhReportType, BthhStatus,
15 HHCallbacks, HHCallbacksDispatcher, HidHost,
16 },
17 profiles::sdp::{BtSdpRecord, Sdp, SdpCallbacks, SdpCallbacksDispatcher},
18 profiles::ProfileConnectionState,
19 topstack,
20 };
21
22 use bt_utils::array_utils;
23 use bt_utils::cod::{is_cod_hid_combo, is_cod_hid_keyboard};
24 use btif_macros::{btif_callback, btif_callbacks_dispatcher};
25
26 use log::{debug, warn};
27 use num_traits::cast::ToPrimitive;
28 use num_traits::pow;
29 use std::collections::HashMap;
30 use std::convert::TryInto;
31 use std::fs::File;
32 use std::hash::Hash;
33 use std::io::Write;
34 use std::process;
35 use std::sync::{Arc, Condvar, Mutex};
36 use std::time::Duration;
37 use std::time::Instant;
38 use tokio::sync::mpsc::Sender;
39 use tokio::task::JoinHandle;
40 use tokio::time;
41
42 use crate::battery_service::BatteryServiceActions;
43 use crate::bluetooth_admin::{BluetoothAdmin, IBluetoothAdmin};
44 use crate::bluetooth_gatt::{BluetoothGatt, IBluetoothGatt, IScannerCallback, ScanResult};
45 use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions};
46 use crate::callbacks::Callbacks;
47 use crate::uuid::{Profile, UuidHelper, HOGP};
48 use crate::{Message, RPCProxy, SuspendMode};
49
50 const FLOSS_VER: u16 = 0x0001;
51 const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800;
52 const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5;
53
54 /// Devices that were last seen longer than this duration are considered stale
55 /// if they haven't already bonded or connected. Once this duration expires, the
56 /// clear event should be sent to clients.
57 const FOUND_DEVICE_FRESHNESS: Duration = Duration::from_secs(30);
58
59 /// This is the value returned from Bluetooth Interface calls.
60 // TODO(241930383): Add enum to topshim
61 const BTM_SUCCESS: i32 = 0;
62
63 const PID_DIR: &str = "/var/run/bluetooth";
64
65 /// Defines the adapter API.
66 pub trait IBluetooth {
67 /// Adds a callback from a client who wishes to observe adapter events.
register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>)68 fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>);
69
70 /// Adds a callback from a client who wishes to observe connection events.
register_connection_callback( &mut self, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u3271 fn register_connection_callback(
72 &mut self,
73 callback: Box<dyn IBluetoothConnectionCallback + Send>,
74 ) -> u32;
75
76 /// Removes registered callback.
unregister_connection_callback(&mut self, callback_id: u32) -> bool77 fn unregister_connection_callback(&mut self, callback_id: u32) -> bool;
78
79 /// Enables the adapter.
80 ///
81 /// Returns true if the request is accepted.
enable(&mut self) -> bool82 fn enable(&mut self) -> bool;
83
84 /// Disables the adapter.
85 ///
86 /// Returns true if the request is accepted.
disable(&mut self) -> bool87 fn disable(&mut self) -> bool;
88
89 /// Returns the Bluetooth address of the local adapter.
get_address(&self) -> String90 fn get_address(&self) -> String;
91
92 /// Gets supported UUIDs by the local adapter.
get_uuids(&self) -> Vec<Uuid128Bit>93 fn get_uuids(&self) -> Vec<Uuid128Bit>;
94
95 /// Gets the local adapter name.
get_name(&self) -> String96 fn get_name(&self) -> String;
97
98 /// Sets the local adapter name.
set_name(&self, name: String) -> bool99 fn set_name(&self, name: String) -> bool;
100
101 /// Gets the bluetooth class.
get_bluetooth_class(&self) -> u32102 fn get_bluetooth_class(&self) -> u32;
103
104 /// Sets the bluetooth class.
set_bluetooth_class(&self, cod: u32) -> bool105 fn set_bluetooth_class(&self, cod: u32) -> bool;
106
107 /// Returns whether the adapter is discoverable.
get_discoverable(&self) -> bool108 fn get_discoverable(&self) -> bool;
109
110 /// Returns the adapter discoverable timeout.
get_discoverable_timeout(&self) -> u32111 fn get_discoverable_timeout(&self) -> u32;
112
113 /// Sets discoverability. If discoverable, limits the duration with given value.
set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool114 fn set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool;
115
116 /// Returns whether multi-advertisement is supported.
117 /// A minimum number of 5 advertising instances is required for multi-advertisment support.
is_multi_advertisement_supported(&self) -> bool118 fn is_multi_advertisement_supported(&self) -> bool;
119
120 /// Returns whether LE extended advertising is supported.
is_le_extended_advertising_supported(&self) -> bool121 fn is_le_extended_advertising_supported(&self) -> bool;
122
123 /// Starts BREDR Inquiry.
start_discovery(&mut self) -> bool124 fn start_discovery(&mut self) -> bool;
125
126 /// Cancels BREDR Inquiry.
cancel_discovery(&mut self) -> bool127 fn cancel_discovery(&mut self) -> bool;
128
129 /// Checks if discovery is started.
is_discovering(&self) -> bool130 fn is_discovering(&self) -> bool;
131
132 /// Checks when discovery ends in milliseconds from now.
get_discovery_end_millis(&self) -> u64133 fn get_discovery_end_millis(&self) -> u64;
134
135 /// Initiates pairing to a remote device. Triggers connection if not already started.
create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool136 fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool;
137
138 /// Cancels any pending bond attempt on given device.
cancel_bond_process(&self, device: BluetoothDevice) -> bool139 fn cancel_bond_process(&self, device: BluetoothDevice) -> bool;
140
141 /// Removes pairing for given device.
remove_bond(&self, device: BluetoothDevice) -> bool142 fn remove_bond(&self, device: BluetoothDevice) -> bool;
143
144 /// Returns a list of known bonded devices.
get_bonded_devices(&self) -> Vec<BluetoothDevice>145 fn get_bonded_devices(&self) -> Vec<BluetoothDevice>;
146
147 /// Gets the bond state of a single device.
get_bond_state(&self, device: BluetoothDevice) -> BtBondState148 fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState;
149
150 /// Set pin on bonding device.
set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool151 fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool;
152
153 /// Set passkey on bonding device.
set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool154 fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool;
155
156 /// Confirm that a pairing should be completed on a bonding device.
set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool157 fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool;
158
159 /// Gets the name of the remote device.
get_remote_name(&self, device: BluetoothDevice) -> String160 fn get_remote_name(&self, device: BluetoothDevice) -> String;
161
162 /// Gets the type of the remote device.
get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType163 fn get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType;
164
165 /// Gets the alias of the remote device.
get_remote_alias(&self, device: BluetoothDevice) -> String166 fn get_remote_alias(&self, device: BluetoothDevice) -> String;
167
168 /// Sets the alias of the remote device.
set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String)169 fn set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String);
170
171 /// Gets the class of the remote device.
get_remote_class(&self, device: BluetoothDevice) -> u32172 fn get_remote_class(&self, device: BluetoothDevice) -> u32;
173
174 /// Gets the appearance of the remote device.
get_remote_appearance(&self, device: BluetoothDevice) -> u16175 fn get_remote_appearance(&self, device: BluetoothDevice) -> u16;
176
177 /// Gets whether the remote device is connected.
get_remote_connected(&self, device: BluetoothDevice) -> bool178 fn get_remote_connected(&self, device: BluetoothDevice) -> bool;
179
180 /// Gets whether the remote device can wake the system.
get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool181 fn get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool;
182
183 /// Returns a list of connected devices.
get_connected_devices(&self) -> Vec<BluetoothDevice>184 fn get_connected_devices(&self) -> Vec<BluetoothDevice>;
185
186 /// Gets the connection state of a single device.
get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState187 fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState;
188
189 /// Gets the connection state of a specific profile.
get_profile_connection_state(&self, profile: Uuid128Bit) -> ProfileConnectionState190 fn get_profile_connection_state(&self, profile: Uuid128Bit) -> ProfileConnectionState;
191
192 /// Returns the cached UUIDs of a remote device.
get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>193 fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>;
194
195 /// Triggers SDP to get UUIDs of a remote device.
fetch_remote_uuids(&self, device: BluetoothDevice) -> bool196 fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool;
197
198 /// Triggers SDP and searches for a specific UUID on a remote device.
sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool199 fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool;
200
201 /// Creates a new SDP record.
create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool202 fn create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool;
203
204 /// Removes the SDP record associated with the provided handle.
remove_sdp_record(&self, handle: i32) -> bool205 fn remove_sdp_record(&self, handle: i32) -> bool;
206
207 /// Connect all profiles supported by device and enabled on adapter.
connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool208 fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool;
209
210 /// Disconnect all profiles supported by device and enabled on adapter.
disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool211 fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool;
212
213 /// Returns whether WBS is supported.
is_wbs_supported(&self) -> bool214 fn is_wbs_supported(&self) -> bool;
215
216 /// Returns whether SWB is supported.
is_swb_supported(&self) -> bool217 fn is_swb_supported(&self) -> bool;
218 }
219
220 /// Adapter API for Bluetooth qualification and verification.
221 ///
222 /// This interface is provided for testing and debugging.
223 /// Clients should not use this interface for production.
224 pub trait IBluetoothQALegacy {
225 /// Returns whether the adapter is connectable.
get_connectable(&self) -> bool226 fn get_connectable(&self) -> bool;
227
228 /// Sets connectability. Returns true on success, false otherwise.
set_connectable(&mut self, mode: bool) -> bool229 fn set_connectable(&mut self, mode: bool) -> bool;
230
231 /// Returns the adapter's Bluetooth friendly name.
get_alias(&self) -> String232 fn get_alias(&self) -> String;
233
234 /// Returns the adapter's Device ID information in modalias format
235 /// used by the kernel and udev.
get_modalias(&self) -> String236 fn get_modalias(&self) -> String;
237
238 /// Gets HID report on the peer.
get_hid_report( &mut self, addr: String, report_type: BthhReportType, report_id: u8, ) -> BtStatus239 fn get_hid_report(
240 &mut self,
241 addr: String,
242 report_type: BthhReportType,
243 report_id: u8,
244 ) -> BtStatus;
245
246 /// Sets HID report to the peer.
set_hid_report( &mut self, addr: String, report_type: BthhReportType, report: String, ) -> BtStatus247 fn set_hid_report(
248 &mut self,
249 addr: String,
250 report_type: BthhReportType,
251 report: String,
252 ) -> BtStatus;
253
254 /// Snd HID data report to the peer.
send_hid_data(&mut self, addr: String, data: String) -> BtStatus255 fn send_hid_data(&mut self, addr: String, data: String) -> BtStatus;
256 }
257
258 /// Delayed actions from adapter events.
259 pub enum DelayedActions {
260 /// Check whether the current set of found devices are still fresh.
261 DeviceFreshnessCheck,
262
263 /// Connect to all supported profiles on target device.
264 ConnectAllProfiles(BluetoothDevice),
265
266 /// Scanner for BLE discovery is registered with given status and scanner id.
267 BleDiscoveryScannerRegistered(Uuid128Bit, u8, GattStatus),
268
269 /// Scanner for BLE discovery is reporting a result.
270 BleDiscoveryScannerResult(ScanResult),
271 }
272
273 /// Serializable device used in various apis.
274 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
275 pub struct BluetoothDevice {
276 pub address: String,
277 pub name: String,
278 }
279
280 impl BluetoothDevice {
new(address: String, name: String) -> BluetoothDevice281 pub(crate) fn new(address: String, name: String) -> BluetoothDevice {
282 BluetoothDevice { address, name }
283 }
284
from_properties(in_properties: &Vec<BluetoothProperty>) -> BluetoothDevice285 pub(crate) fn from_properties(in_properties: &Vec<BluetoothProperty>) -> BluetoothDevice {
286 let mut address = String::from("");
287 let mut name = String::from("");
288
289 for prop in in_properties {
290 match &prop {
291 BluetoothProperty::BdAddr(bdaddr) => {
292 address = bdaddr.to_string();
293 }
294 BluetoothProperty::BdName(bdname) => {
295 name = bdname.clone();
296 }
297 _ => {}
298 }
299 }
300
301 BluetoothDevice::new(address, name)
302 }
303 }
304
305 /// Internal data structure that keeps a map of cached properties for a remote device.
306 struct BluetoothDeviceContext {
307 /// Transport type reported by ACL connection (if completed).
308 pub acl_reported_transport: BtTransport,
309
310 pub acl_state: BtAclState,
311 pub bond_state: BtBondState,
312 pub info: BluetoothDevice,
313 pub last_seen: Instant,
314 pub properties: HashMap<BtPropertyType, BluetoothProperty>,
315
316 /// Keep track of whether services have been resolved.
317 pub services_resolved: bool,
318
319 /// If supported UUIDs weren't available in EIR, wait for services to be
320 /// resolved to connect.
321 pub wait_to_connect: bool,
322 }
323
324 impl BluetoothDeviceContext {
new( bond_state: BtBondState, acl_state: BtAclState, info: BluetoothDevice, last_seen: Instant, properties: Vec<BluetoothProperty>, ) -> BluetoothDeviceContext325 pub(crate) fn new(
326 bond_state: BtBondState,
327 acl_state: BtAclState,
328 info: BluetoothDevice,
329 last_seen: Instant,
330 properties: Vec<BluetoothProperty>,
331 ) -> BluetoothDeviceContext {
332 let mut device = BluetoothDeviceContext {
333 acl_reported_transport: BtTransport::Auto,
334 acl_state,
335 bond_state,
336 info,
337 last_seen,
338 properties: HashMap::new(),
339 services_resolved: false,
340 wait_to_connect: false,
341 };
342 device.update_properties(&properties);
343 device
344 }
345
update_properties(&mut self, in_properties: &Vec<BluetoothProperty>)346 pub(crate) fn update_properties(&mut self, in_properties: &Vec<BluetoothProperty>) {
347 for prop in in_properties {
348 // Handle merging of certain properties.
349 match &prop {
350 BluetoothProperty::BdAddr(bdaddr) => {
351 self.info.address = bdaddr.to_string();
352 self.properties.insert(prop.get_type(), prop.clone());
353 }
354 BluetoothProperty::BdName(bdname) => {
355 if !bdname.is_empty() {
356 self.info.name = bdname.clone();
357 self.properties.insert(prop.get_type(), prop.clone());
358 }
359 }
360 _ => {
361 self.properties.insert(prop.get_type(), prop.clone());
362 }
363 }
364 }
365 }
366
367 /// Mark this device as seen.
seen(&mut self)368 pub(crate) fn seen(&mut self) {
369 self.last_seen = Instant::now();
370 }
371 }
372
373 /// The interface for adapter callbacks registered through `IBluetooth::register_callback`.
374 pub trait IBluetoothCallback: RPCProxy {
375 /// When any adapter property changes.
on_adapter_property_changed(&mut self, prop: BtPropertyType)376 fn on_adapter_property_changed(&mut self, prop: BtPropertyType);
377
378 /// When any of the adapter local address is changed.
on_address_changed(&mut self, addr: String)379 fn on_address_changed(&mut self, addr: String);
380
381 /// When the adapter name is changed.
on_name_changed(&mut self, name: String)382 fn on_name_changed(&mut self, name: String);
383
384 /// When the adapter's discoverable mode is changed.
on_discoverable_changed(&mut self, discoverable: bool)385 fn on_discoverable_changed(&mut self, discoverable: bool);
386
387 /// When a device is found via discovery.
on_device_found(&mut self, remote_device: BluetoothDevice)388 fn on_device_found(&mut self, remote_device: BluetoothDevice);
389
390 /// When a device is cleared from discovered devices cache.
on_device_cleared(&mut self, remote_device: BluetoothDevice)391 fn on_device_cleared(&mut self, remote_device: BluetoothDevice);
392
393 /// When the discovery state is changed.
on_discovering_changed(&mut self, discovering: bool)394 fn on_discovering_changed(&mut self, discovering: bool);
395
396 /// When there is a pairing/bonding process and requires agent to display the event to UI.
on_ssp_request( &mut self, remote_device: BluetoothDevice, cod: u32, variant: BtSspVariant, passkey: u32, )397 fn on_ssp_request(
398 &mut self,
399 remote_device: BluetoothDevice,
400 cod: u32,
401 variant: BtSspVariant,
402 passkey: u32,
403 );
404
405 /// When there is a pin request to display the event to client.
on_pin_request(&mut self, remote_device: BluetoothDevice, cod: u32, min_16_digit: bool)406 fn on_pin_request(&mut self, remote_device: BluetoothDevice, cod: u32, min_16_digit: bool);
407
408 /// When there is a auto-gen pin to display the event to client.
on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String)409 fn on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String);
410
411 /// When a bonding attempt has completed.
on_bond_state_changed(&mut self, status: u32, device_address: String, state: u32)412 fn on_bond_state_changed(&mut self, status: u32, device_address: String, state: u32);
413
414 /// When an SDP search has completed.
on_sdp_search_complete( &mut self, remote_device: BluetoothDevice, searched_uuid: Uuid128Bit, sdp_records: Vec<BtSdpRecord>, )415 fn on_sdp_search_complete(
416 &mut self,
417 remote_device: BluetoothDevice,
418 searched_uuid: Uuid128Bit,
419 sdp_records: Vec<BtSdpRecord>,
420 );
421
422 /// When an SDP record has been successfully created.
on_sdp_record_created(&mut self, record: BtSdpRecord, handle: i32)423 fn on_sdp_record_created(&mut self, record: BtSdpRecord, handle: i32);
424 }
425
426 /// An interface for other modules to track found remote devices.
427 pub trait IBluetoothDeviceCallback {
428 /// When a device is found via discovery.
on_device_found(&mut self, remote_device: BluetoothDevice)429 fn on_device_found(&mut self, remote_device: BluetoothDevice);
430
431 /// When a device is cleared from discovered devices cache.
on_device_cleared(&mut self, remote_device: BluetoothDevice)432 fn on_device_cleared(&mut self, remote_device: BluetoothDevice);
433
434 /// When a device property is changed.
on_remote_device_properties_changed( &mut self, remote_device: BluetoothDevice, properties: Vec<BluetoothProperty>, )435 fn on_remote_device_properties_changed(
436 &mut self,
437 remote_device: BluetoothDevice,
438 properties: Vec<BluetoothProperty>,
439 );
440 }
441
442 pub trait IBluetoothConnectionCallback: RPCProxy {
443 /// Notification sent when a remote device completes HCI connection.
on_device_connected(&mut self, remote_device: BluetoothDevice)444 fn on_device_connected(&mut self, remote_device: BluetoothDevice);
445
446 /// Notification sent when a remote device completes HCI disconnection.
on_device_disconnected(&mut self, remote_device: BluetoothDevice)447 fn on_device_disconnected(&mut self, remote_device: BluetoothDevice);
448 }
449
450 /// Implementation of the adapter API.
451 pub struct Bluetooth {
452 intf: Arc<Mutex<BluetoothInterface>>,
453
454 adapter_index: i32,
455 bonded_devices: HashMap<String, BluetoothDeviceContext>,
456 ble_scanner_id: Option<u8>,
457 ble_scanner_uuid: Option<Uuid128Bit>,
458 bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
459 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
460 bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
461 callbacks: Callbacks<dyn IBluetoothCallback + Send>,
462 connection_callbacks: Callbacks<dyn IBluetoothConnectionCallback + Send>,
463 discovering_started: Instant,
464 hh: Option<HidHost>,
465 is_connectable: bool,
466 is_discovering: bool,
467 is_discovering_before_suspend: bool,
468 is_discovery_paused: bool,
469 discovery_suspend_mode: SuspendMode,
470 local_address: Option<RawAddress>,
471 pending_discovery: bool,
472 properties: HashMap<BtPropertyType, BluetoothProperty>,
473 profiles_ready: bool,
474 found_devices: HashMap<String, BluetoothDeviceContext>,
475 freshness_check: Option<JoinHandle<()>>,
476 sdp: Option<Sdp>,
477 state: BtState,
478 tx: Sender<Message>,
479 // Internal API members
480 discoverable_timeout: Option<JoinHandle<()>>,
481
482 /// Used to notify signal handler that we have turned off the stack.
483 sig_notifier: Arc<(Mutex<bool>, Condvar)>,
484 }
485
486 impl Bluetooth {
487 /// Constructs the IBluetooth implementation.
new( adapter_index: i32, tx: Sender<Message>, sig_notifier: Arc<(Mutex<bool>, Condvar)>, intf: Arc<Mutex<BluetoothInterface>>, bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, ) -> Bluetooth488 pub fn new(
489 adapter_index: i32,
490 tx: Sender<Message>,
491 sig_notifier: Arc<(Mutex<bool>, Condvar)>,
492 intf: Arc<Mutex<BluetoothInterface>>,
493 bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
494 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
495 bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
496 ) -> Bluetooth {
497 Bluetooth {
498 adapter_index,
499 bonded_devices: HashMap::new(),
500 callbacks: Callbacks::new(tx.clone(), Message::AdapterCallbackDisconnected),
501 connection_callbacks: Callbacks::new(
502 tx.clone(),
503 Message::ConnectionCallbackDisconnected,
504 ),
505 hh: None,
506 ble_scanner_id: None,
507 ble_scanner_uuid: None,
508 bluetooth_admin,
509 bluetooth_gatt,
510 bluetooth_media,
511 discovering_started: Instant::now(),
512 intf,
513 is_connectable: false,
514 is_discovering: false,
515 is_discovering_before_suspend: false,
516 is_discovery_paused: false,
517 discovery_suspend_mode: SuspendMode::Normal,
518 local_address: None,
519 pending_discovery: false,
520 properties: HashMap::new(),
521 profiles_ready: false,
522 found_devices: HashMap::new(),
523 freshness_check: None,
524 sdp: None,
525 state: BtState::Off,
526 tx,
527 // Internal API members
528 discoverable_timeout: None,
529 sig_notifier,
530 }
531 }
532
disable_profile(&mut self, profile: &Profile)533 fn disable_profile(&mut self, profile: &Profile) {
534 if !UuidHelper::is_profile_supported(profile) {
535 return;
536 }
537
538 match profile {
539 Profile::Hid => {
540 self.hh.as_mut().unwrap().activate_hidp(false);
541 }
542
543 Profile::Hogp => {
544 self.hh.as_mut().unwrap().activate_hogp(false);
545 }
546
547 Profile::A2dpSource | Profile::Hfp | Profile::AvrcpTarget => {
548 self.bluetooth_media.lock().unwrap().disable_profile(profile);
549 }
550 // Ignore profiles that we don't connect.
551 _ => (),
552 }
553 }
554
enable_profile(&mut self, profile: &Profile)555 fn enable_profile(&mut self, profile: &Profile) {
556 if !UuidHelper::is_profile_supported(profile) {
557 return;
558 }
559
560 match profile {
561 Profile::Hid => {
562 self.hh.as_mut().unwrap().activate_hidp(true);
563 }
564
565 Profile::Hogp => {
566 self.hh.as_mut().unwrap().activate_hogp(true);
567 }
568
569 Profile::A2dpSource | Profile::Hfp | Profile::AvrcpTarget => {
570 self.bluetooth_media.lock().unwrap().enable_profile(profile);
571 }
572 // Ignore profiles that we don't connect.
573 _ => (),
574 }
575 }
576
is_profile_enabled(&self, profile: &Profile) -> Option<bool>577 fn is_profile_enabled(&self, profile: &Profile) -> Option<bool> {
578 if !UuidHelper::is_profile_supported(profile) {
579 return None;
580 }
581
582 match profile {
583 Profile::Hid => Some(self.hh.as_ref().unwrap().is_hidp_activated),
584
585 Profile::Hogp => Some(self.hh.as_ref().unwrap().is_hogp_activated),
586
587 Profile::A2dpSource | Profile::Hfp | Profile::AvrcpTarget => {
588 self.bluetooth_media.lock().unwrap().is_profile_enabled(profile)
589 }
590 // Ignore profiles that we don't connect.
591 _ => None,
592 }
593 }
594
toggle_enabled_profiles(&mut self, allowed_services: &Vec<Uuid128Bit>)595 pub fn toggle_enabled_profiles(&mut self, allowed_services: &Vec<Uuid128Bit>) {
596 for profile in UuidHelper::get_supported_profiles().clone() {
597 // Only toggle initializable profiles.
598 if let Some(enabled) = self.is_profile_enabled(&profile) {
599 let allowed = allowed_services.len() == 0
600 || allowed_services.contains(&UuidHelper::get_profile_uuid(&profile).unwrap());
601
602 if allowed && !enabled {
603 debug!("Enabling profile {}", &profile);
604 self.enable_profile(&profile);
605 } else if !allowed && enabled {
606 debug!("Disabling profile {}", &profile);
607 self.disable_profile(&profile);
608 }
609 }
610 }
611
612 if self.hh.as_mut().unwrap().configure_enabled_profiles() {
613 self.hh.as_mut().unwrap().disable();
614 let txl = self.tx.clone();
615
616 tokio::spawn(async move {
617 // Wait 100 milliseconds to prevent race condition caused by quick disable then
618 // enable.
619 // TODO: (b/272191117): don't enable until we're sure disable is done.
620 tokio::time::sleep(Duration::from_millis(100)).await;
621 let _ = txl.send(Message::HidHostEnable).await;
622 });
623 }
624 }
625
enable_hidhost(&mut self)626 pub fn enable_hidhost(&mut self) {
627 self.hh.as_mut().unwrap().enable();
628 }
629
init_profiles(&mut self)630 pub fn init_profiles(&mut self) {
631 let sdptx = self.tx.clone();
632 self.sdp = Some(Sdp::new(&self.intf.lock().unwrap()));
633 self.sdp.as_mut().unwrap().initialize(SdpCallbacksDispatcher {
634 dispatch: Box::new(move |cb| {
635 let txl = sdptx.clone();
636 topstack::get_runtime().spawn(async move {
637 let _ = txl.send(Message::Sdp(cb)).await;
638 });
639 }),
640 });
641
642 let hhtx = self.tx.clone();
643 self.hh = Some(HidHost::new(&self.intf.lock().unwrap()));
644 self.hh.as_mut().unwrap().initialize(HHCallbacksDispatcher {
645 dispatch: Box::new(move |cb| {
646 let txl = hhtx.clone();
647 topstack::get_runtime().spawn(async move {
648 let _ = txl.send(Message::HidHost(cb)).await;
649 });
650 }),
651 });
652
653 let allowed_profiles = self.bluetooth_admin.lock().unwrap().get_allowed_services();
654 self.toggle_enabled_profiles(&allowed_profiles);
655 // Mark profiles as ready
656 self.profiles_ready = true;
657 }
658
update_local_address(&mut self, addr: &RawAddress)659 fn update_local_address(&mut self, addr: &RawAddress) {
660 self.local_address = Some(addr.clone());
661
662 self.callbacks.for_all_callbacks(|callback| {
663 callback.on_address_changed(addr.to_string());
664 });
665 }
666
adapter_callback_disconnected(&mut self, id: u32)667 pub(crate) fn adapter_callback_disconnected(&mut self, id: u32) {
668 self.callbacks.remove_callback(id);
669 }
670
connection_callback_disconnected(&mut self, id: u32)671 pub(crate) fn connection_callback_disconnected(&mut self, id: u32) {
672 self.connection_callbacks.remove_callback(id);
673 }
674
get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext>675 fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> {
676 self.bonded_devices.get(address).or_else(|| self.found_devices.get(address))
677 }
678
get_remote_device_if_found_mut( &mut self, address: &str, ) -> Option<&mut BluetoothDeviceContext>679 fn get_remote_device_if_found_mut(
680 &mut self,
681 address: &str,
682 ) -> Option<&mut BluetoothDeviceContext> {
683 match self.bonded_devices.get_mut(address) {
684 None => self.found_devices.get_mut(address),
685 some => some,
686 }
687 }
688
get_remote_device_info_if_found(&self, remote_address: &str) -> Option<BluetoothDevice>689 fn get_remote_device_info_if_found(&self, remote_address: &str) -> Option<BluetoothDevice> {
690 self.get_remote_device_if_found(remote_address)
691 .map(|device_context| device_context.info.clone())
692 }
693
get_remote_device_property( &self, device: &BluetoothDevice, property_type: &BtPropertyType, ) -> Option<BluetoothProperty>694 fn get_remote_device_property(
695 &self,
696 device: &BluetoothDevice,
697 property_type: &BtPropertyType,
698 ) -> Option<BluetoothProperty> {
699 self.get_remote_device_if_found(&device.address)
700 .and_then(|d| d.properties.get(property_type).and_then(|p| Some(p.clone())))
701 }
702
set_remote_device_property( &mut self, device: &BluetoothDevice, property_type: BtPropertyType, property: BluetoothProperty, ) -> Result<(), ()>703 fn set_remote_device_property(
704 &mut self,
705 device: &BluetoothDevice,
706 property_type: BtPropertyType,
707 property: BluetoothProperty,
708 ) -> Result<(), ()> {
709 let remote_device = match self.get_remote_device_if_found_mut(&device.address) {
710 Some(d) => d,
711 None => {
712 return Err(());
713 }
714 };
715
716 let mut addr = RawAddress::from_string(device.address.clone());
717 if addr.is_none() {
718 return Err(());
719 }
720 let addr = addr.as_mut().unwrap();
721
722 // TODO: Determine why a callback isn't invoked to do this.
723 remote_device.properties.insert(property_type, property.clone());
724 self.intf.lock().unwrap().set_remote_device_property(addr, property);
725 Ok(())
726 }
727
728 /// Returns whether the adapter is connectable.
get_connectable_internal(&self) -> bool729 pub(crate) fn get_connectable_internal(&self) -> bool {
730 match self.properties.get(&BtPropertyType::AdapterScanMode) {
731 Some(prop) => match prop {
732 BluetoothProperty::AdapterScanMode(mode) => match *mode {
733 BtScanMode::Connectable | BtScanMode::ConnectableDiscoverable => true,
734 _ => false,
735 },
736 _ => false,
737 },
738 _ => false,
739 }
740 }
741
742 /// Sets the adapter's connectable mode for classic connections.
set_connectable_internal(&mut self, mode: bool) -> bool743 pub(crate) fn set_connectable_internal(&mut self, mode: bool) -> bool {
744 self.is_connectable = mode;
745 if mode && self.get_discoverable() {
746 return true;
747 }
748 self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::AdapterScanMode(
749 if mode { BtScanMode::Connectable } else { BtScanMode::None_ },
750 )) == 0
751 }
752
753 /// Returns adapter's discoverable mode.
get_discoverable_mode_internal(&self) -> BtDiscMode754 pub fn get_discoverable_mode_internal(&self) -> BtDiscMode {
755 let off_mode = BtDiscMode::NonDiscoverable;
756
757 match self.properties.get(&BtPropertyType::AdapterScanMode) {
758 Some(prop) => match prop {
759 BluetoothProperty::AdapterScanMode(mode) => match *mode {
760 BtScanMode::ConnectableDiscoverable => BtDiscMode::GeneralDiscoverable,
761 BtScanMode::ConnectableLimitedDiscoverable => BtDiscMode::LimitedDiscoverable,
762 _ => off_mode,
763 },
764 _ => off_mode,
765 },
766 _ => off_mode,
767 }
768 }
769
770 /// Caches the discoverable mode into BluetoothQA.
cache_discoverable_mode_into_qa(&self)771 pub fn cache_discoverable_mode_into_qa(&self) {
772 let disc_mode = self.get_discoverable_mode_internal();
773
774 let txl = self.tx.clone();
775 tokio::spawn(async move {
776 let _ = txl.send(Message::QaOnDiscoverableModeChanged(disc_mode)).await;
777 });
778 }
779
780 /// Returns all bonded and connected devices.
get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice>781 pub(crate) fn get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice> {
782 self.bonded_devices
783 .values()
784 .filter(|v| v.acl_state == BtAclState::Connected && v.bond_state == BtBondState::Bonded)
785 .map(|v| v.info.clone())
786 .collect()
787 }
788
789 /// Gets the bond state of a single device with its address.
get_bond_state_by_addr(&self, addr: &String) -> BtBondState790 pub fn get_bond_state_by_addr(&self, addr: &String) -> BtBondState {
791 match self.bonded_devices.get(addr) {
792 Some(device) => device.bond_state.clone(),
793 None => BtBondState::NotBonded,
794 }
795 }
796
797 /// Check whether found devices are still fresh. If they're outside the
798 /// freshness window, send a notification to clear the device from clients.
trigger_freshness_check(&mut self)799 fn trigger_freshness_check(&mut self) {
800 if let Some(ref handle) = self.freshness_check {
801 // Abort and drop the previous JoinHandle.
802 handle.abort();
803 self.freshness_check = None;
804 }
805
806 // A found device is considered fresh if:
807 // * It was last seen less than |FOUND_DEVICE_FRESHNESS| ago.
808 // * It is currently connected.
809 fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool {
810 let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS;
811 now < &fresh_at || d.acl_state == BtAclState::Connected
812 }
813
814 let now = Instant::now();
815 let stale_devices: Vec<BluetoothDevice> = self
816 .found_devices
817 .iter()
818 .filter(|(_, d)| !is_fresh(d, &now))
819 .map(|(_, d)| d.info.clone())
820 .collect();
821
822 // Retain only devices that are fresh.
823 self.found_devices.retain(|_, d| is_fresh(d, &now));
824
825 for d in stale_devices {
826 self.callbacks.for_all_callbacks(|callback| {
827 callback.on_device_cleared(d.clone());
828 });
829
830 self.bluetooth_admin.lock().unwrap().on_device_cleared(&d);
831 }
832
833 // If we have any fresh devices remaining, re-queue a freshness check.
834 if self.found_devices.len() > 0 {
835 let txl = self.tx.clone();
836
837 self.freshness_check = Some(tokio::spawn(async move {
838 time::sleep(FOUND_DEVICE_FRESHNESS).await;
839 let _ = txl
840 .send(Message::DelayedAdapterActions(DelayedActions::DeviceFreshnessCheck))
841 .await;
842 }));
843 }
844 }
845
846 /// Makes an LE_RAND call to the Bluetooth interface.
le_rand(&mut self) -> bool847 pub fn le_rand(&mut self) -> bool {
848 self.intf.lock().unwrap().le_rand() == BTM_SUCCESS
849 }
850
send_metrics_remote_device_info(device: &BluetoothDeviceContext)851 fn send_metrics_remote_device_info(device: &BluetoothDeviceContext) {
852 if device.bond_state != BtBondState::Bonded && device.acl_state != BtAclState::Connected {
853 return;
854 }
855
856 let addr = RawAddress::from_string(device.info.address.clone()).unwrap();
857 let mut class_of_device = 0u32;
858 let mut device_type = BtDeviceType::Unknown;
859 let mut appearance = 0u16;
860 let mut vpi =
861 BtVendorProductInfo { vendor_id_src: 0, vendor_id: 0, product_id: 0, version: 0 };
862
863 for prop in device.properties.values() {
864 match prop {
865 BluetoothProperty::TypeOfDevice(p) => device_type = p.clone(),
866 BluetoothProperty::ClassOfDevice(p) => class_of_device = p.clone(),
867 BluetoothProperty::Appearance(p) => appearance = p.clone(),
868 BluetoothProperty::VendorProductInfo(p) => vpi = p.clone(),
869 _ => (),
870 }
871 }
872
873 metrics::device_info_report(
874 addr,
875 device_type,
876 class_of_device,
877 appearance,
878 vpi.vendor_id,
879 vpi.vendor_id_src,
880 vpi.product_id,
881 vpi.version,
882 );
883 }
884
885 /// Handle some delayed and recurring actions within the adapter.
handle_delayed_actions(&mut self, action: DelayedActions)886 pub(crate) fn handle_delayed_actions(&mut self, action: DelayedActions) {
887 match action {
888 DelayedActions::DeviceFreshnessCheck => {
889 self.trigger_freshness_check();
890 }
891
892 DelayedActions::ConnectAllProfiles(device) => {
893 self.connect_all_enabled_profiles(device);
894 }
895
896 DelayedActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status) => {
897 if let Some(app_uuid) = self.ble_scanner_uuid {
898 if app_uuid == uuid {
899 if status == GattStatus::Success {
900 self.ble_scanner_id = Some(scanner_id);
901 } else {
902 log::error!("BLE discovery scanner failed to register: {:?}", status);
903 }
904 }
905 }
906 }
907
908 DelayedActions::BleDiscoveryScannerResult(result) => {
909 let addr = RawAddress::from_string(result.address);
910
911 let properties = match addr {
912 Some(v) => {
913 let mut props = vec![];
914 props.push(BluetoothProperty::BdName(result.name.clone()));
915 props.push(BluetoothProperty::BdAddr(v.clone()));
916 if result.service_uuids.len() > 0 {
917 props.push(BluetoothProperty::Uuids(
918 result
919 .service_uuids
920 .iter()
921 .map(|&v| Uuid::from(v.clone()))
922 .collect(),
923 ));
924 }
925 props.push(BluetoothProperty::RemoteRssi(result.rssi));
926
927 props
928 }
929 None => {
930 return;
931 }
932 };
933
934 // Generate a vector of properties from ScanResult.
935 let device = BluetoothDevice::from_properties(&properties);
936 let address = device.address.clone();
937
938 if let Some(existing) = self.found_devices.get_mut(&address) {
939 existing.update_properties(&properties);
940 existing.seen();
941 } else {
942 let device_with_props = BluetoothDeviceContext::new(
943 BtBondState::NotBonded,
944 BtAclState::Disconnected,
945 device,
946 Instant::now(),
947 properties,
948 );
949 self.found_devices.insert(address.clone(), device_with_props);
950 }
951 }
952 }
953 }
954
955 /// Creates a file to notify btmanagerd the adapter is enabled.
create_pid_file(&self) -> std::io::Result<()>956 fn create_pid_file(&self) -> std::io::Result<()> {
957 let file_name = format!("{}/bluetooth{}.pid", PID_DIR, self.adapter_index);
958 let mut f = File::create(&file_name)?;
959 f.write_all(process::id().to_string().as_bytes())?;
960 Ok(())
961 }
962
963 /// Removes the file to notify btmanagerd the adapter is disabled.
remove_pid_file(&self) -> std::io::Result<()>964 fn remove_pid_file(&self) -> std::io::Result<()> {
965 let file_name = format!("{}/bluetooth{}.pid", PID_DIR, self.adapter_index);
966 std::fs::remove_file(&file_name)?;
967 Ok(())
968 }
969
970 /// Set the suspend mode.
set_discovery_suspend_mode(&mut self, suspend_mode: SuspendMode)971 pub fn set_discovery_suspend_mode(&mut self, suspend_mode: SuspendMode) {
972 if suspend_mode != self.discovery_suspend_mode {
973 self.discovery_suspend_mode = suspend_mode;
974 }
975 }
976
977 /// Gets current suspend mode.
get_discovery_suspend_mode(&self) -> SuspendMode978 pub fn get_discovery_suspend_mode(&self) -> SuspendMode {
979 self.discovery_suspend_mode.clone()
980 }
981
982 /// Enters the suspend mode for discovery.
discovery_enter_suspend(&mut self) -> BtStatus983 pub fn discovery_enter_suspend(&mut self) -> BtStatus {
984 if self.get_discovery_suspend_mode() != SuspendMode::Normal {
985 return BtStatus::Busy;
986 }
987 self.set_discovery_suspend_mode(SuspendMode::Suspending);
988
989 if self.is_discovering {
990 self.is_discovering_before_suspend = true;
991 self.cancel_discovery();
992 }
993 self.set_discovery_suspend_mode(SuspendMode::Suspended);
994
995 return BtStatus::Success;
996 }
997
998 /// Exits the suspend mode for discovery.
discovery_exit_suspend(&mut self) -> BtStatus999 pub fn discovery_exit_suspend(&mut self) -> BtStatus {
1000 if self.get_discovery_suspend_mode() != SuspendMode::Suspended {
1001 return BtStatus::Busy;
1002 }
1003 self.set_discovery_suspend_mode(SuspendMode::Resuming);
1004
1005 if self.is_discovering_before_suspend {
1006 self.is_discovering_before_suspend = false;
1007 self.start_discovery();
1008 }
1009 self.set_discovery_suspend_mode(SuspendMode::Normal);
1010
1011 return BtStatus::Success;
1012 }
1013
1014 /// Temporarily stop the discovery process and mark it as paused so that clients cannot restart
1015 /// it.
pause_discovery(&mut self)1016 fn pause_discovery(&mut self) {
1017 self.cancel_discovery();
1018 self.is_discovery_paused = true;
1019 }
1020
1021 /// Remove the paused flag to allow clients to begin discovery, and if there is already a
1022 /// pending request, start discovery.
resume_discovery(&mut self)1023 fn resume_discovery(&mut self) {
1024 if self.pending_discovery {
1025 self.pending_discovery = false;
1026 self.start_discovery();
1027 }
1028 self.is_discovery_paused = false;
1029 }
1030 }
1031
1032 #[btif_callbacks_dispatcher(dispatch_base_callbacks, BaseCallbacks)]
1033 #[allow(unused_variables)]
1034 pub(crate) trait BtifBluetoothCallbacks {
1035 #[btif_callback(AdapterState)]
adapter_state_changed(&mut self, state: BtState)1036 fn adapter_state_changed(&mut self, state: BtState) {}
1037
1038 #[btif_callback(AdapterProperties)]
adapter_properties_changed( &mut self, status: BtStatus, num_properties: i32, properties: Vec<BluetoothProperty>, )1039 fn adapter_properties_changed(
1040 &mut self,
1041 status: BtStatus,
1042 num_properties: i32,
1043 properties: Vec<BluetoothProperty>,
1044 ) {
1045 }
1046
1047 #[btif_callback(DeviceFound)]
device_found(&mut self, n: i32, properties: Vec<BluetoothProperty>)1048 fn device_found(&mut self, n: i32, properties: Vec<BluetoothProperty>) {}
1049
1050 #[btif_callback(DiscoveryState)]
discovery_state(&mut self, state: BtDiscoveryState)1051 fn discovery_state(&mut self, state: BtDiscoveryState) {}
1052
1053 #[btif_callback(SspRequest)]
ssp_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, variant: BtSspVariant, passkey: u32, )1054 fn ssp_request(
1055 &mut self,
1056 remote_addr: RawAddress,
1057 remote_name: String,
1058 cod: u32,
1059 variant: BtSspVariant,
1060 passkey: u32,
1061 ) {
1062 }
1063
1064 #[btif_callback(BondState)]
bond_state( &mut self, status: BtStatus, addr: RawAddress, bond_state: BtBondState, fail_reason: i32, )1065 fn bond_state(
1066 &mut self,
1067 status: BtStatus,
1068 addr: RawAddress,
1069 bond_state: BtBondState,
1070 fail_reason: i32,
1071 ) {
1072 }
1073
1074 #[btif_callback(RemoteDeviceProperties)]
remote_device_properties_changed( &mut self, status: BtStatus, addr: RawAddress, num_properties: i32, properties: Vec<BluetoothProperty>, )1075 fn remote_device_properties_changed(
1076 &mut self,
1077 status: BtStatus,
1078 addr: RawAddress,
1079 num_properties: i32,
1080 properties: Vec<BluetoothProperty>,
1081 ) {
1082 }
1083
1084 #[btif_callback(AclState)]
acl_state( &mut self, status: BtStatus, addr: RawAddress, state: BtAclState, link_type: BtTransport, hci_reason: BtHciErrorCode, conn_direction: BtConnectionDirection, acl_handle: u16, )1085 fn acl_state(
1086 &mut self,
1087 status: BtStatus,
1088 addr: RawAddress,
1089 state: BtAclState,
1090 link_type: BtTransport,
1091 hci_reason: BtHciErrorCode,
1092 conn_direction: BtConnectionDirection,
1093 acl_handle: u16,
1094 ) {
1095 }
1096
1097 #[btif_callback(LeRandCallback)]
le_rand_cb(&mut self, random: u64)1098 fn le_rand_cb(&mut self, random: u64) {}
1099
1100 #[btif_callback(PinRequest)]
pin_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, min_16_digit: bool, )1101 fn pin_request(
1102 &mut self,
1103 remote_addr: RawAddress,
1104 remote_name: String,
1105 cod: u32,
1106 min_16_digit: bool,
1107 ) {
1108 }
1109 }
1110
1111 #[btif_callbacks_dispatcher(dispatch_hid_host_callbacks, HHCallbacks)]
1112 pub(crate) trait BtifHHCallbacks {
1113 #[btif_callback(ConnectionState)]
connection_state(&mut self, address: RawAddress, state: BthhConnectionState)1114 fn connection_state(&mut self, address: RawAddress, state: BthhConnectionState);
1115
1116 #[btif_callback(HidInfo)]
hid_info(&mut self, address: RawAddress, info: BthhHidInfo)1117 fn hid_info(&mut self, address: RawAddress, info: BthhHidInfo);
1118
1119 #[btif_callback(ProtocolMode)]
protocol_mode(&mut self, address: RawAddress, status: BthhStatus, mode: BthhProtocolMode)1120 fn protocol_mode(&mut self, address: RawAddress, status: BthhStatus, mode: BthhProtocolMode);
1121
1122 #[btif_callback(IdleTime)]
idle_time(&mut self, address: RawAddress, status: BthhStatus, idle_rate: i32)1123 fn idle_time(&mut self, address: RawAddress, status: BthhStatus, idle_rate: i32);
1124
1125 #[btif_callback(GetReport)]
get_report(&mut self, address: RawAddress, status: BthhStatus, data: Vec<u8>, size: i32)1126 fn get_report(&mut self, address: RawAddress, status: BthhStatus, data: Vec<u8>, size: i32);
1127
1128 #[btif_callback(Handshake)]
handshake(&mut self, address: RawAddress, status: BthhStatus)1129 fn handshake(&mut self, address: RawAddress, status: BthhStatus);
1130 }
1131
1132 #[btif_callbacks_dispatcher(dispatch_sdp_callbacks, SdpCallbacks)]
1133 pub(crate) trait BtifSdpCallbacks {
1134 #[btif_callback(SdpSearch)]
sdp_search( &mut self, status: BtStatus, address: RawAddress, uuid: Uuid, count: i32, records: Vec<BtSdpRecord>, )1135 fn sdp_search(
1136 &mut self,
1137 status: BtStatus,
1138 address: RawAddress,
1139 uuid: Uuid,
1140 count: i32,
1141 records: Vec<BtSdpRecord>,
1142 );
1143 }
1144
get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher1145 pub fn get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher {
1146 BaseCallbacksDispatcher {
1147 dispatch: Box::new(move |cb| {
1148 let txl = tx.clone();
1149 topstack::get_runtime().spawn(async move {
1150 let _ = txl.send(Message::Base(cb)).await;
1151 });
1152 }),
1153 }
1154 }
1155
1156 impl BtifBluetoothCallbacks for Bluetooth {
adapter_state_changed(&mut self, state: BtState)1157 fn adapter_state_changed(&mut self, state: BtState) {
1158 let prev_state = self.state.clone();
1159 self.state = state;
1160 metrics::adapter_state_changed(self.state.clone());
1161
1162 // If it's the same state as before, no further action
1163 if self.state == prev_state {
1164 return;
1165 }
1166
1167 match self.state {
1168 BtState::Off => {
1169 self.properties.clear();
1170 match self.remove_pid_file() {
1171 Err(err) => warn!("remove_pid_file() error: {}", err),
1172 _ => (),
1173 }
1174
1175 // Let the signal notifier know we are turned off.
1176 *self.sig_notifier.0.lock().unwrap() = false;
1177 self.sig_notifier.1.notify_all();
1178 }
1179
1180 BtState::On => {
1181 // Initialize media
1182 self.bluetooth_media.lock().unwrap().initialize();
1183
1184 // Trigger properties update
1185 self.intf.lock().unwrap().get_adapter_properties();
1186
1187 // Also need to manually request some properties
1188 self.intf.lock().unwrap().get_adapter_property(BtPropertyType::ClassOfDevice);
1189
1190 // Initialize the BLE scanner for discovery.
1191 let callback_id = self.bluetooth_gatt.lock().unwrap().register_scanner_callback(
1192 Box::new(BleDiscoveryCallbacks::new(self.tx.clone())),
1193 );
1194 self.ble_scanner_uuid =
1195 Some(self.bluetooth_gatt.lock().unwrap().register_scanner(callback_id));
1196
1197 // Ensure device is connectable so that disconnected device can reconnect
1198 self.set_connectable(true);
1199
1200 // Notify the signal notifier that we are turned on.
1201 *self.sig_notifier.0.lock().unwrap() = true;
1202 self.sig_notifier.1.notify_all();
1203
1204 // Signal that the stack is up and running.
1205 match self.create_pid_file() {
1206 Err(err) => warn!("create_pid_file() error: {}", err),
1207 _ => (),
1208 }
1209
1210 // Inform the rest of the stack we're ready.
1211 let txl = self.tx.clone();
1212 tokio::spawn(async move {
1213 let _ = txl.send(Message::AdapterReady).await;
1214 });
1215 }
1216 }
1217 }
1218
1219 #[allow(unused_variables)]
adapter_properties_changed( &mut self, status: BtStatus, num_properties: i32, properties: Vec<BluetoothProperty>, )1220 fn adapter_properties_changed(
1221 &mut self,
1222 status: BtStatus,
1223 num_properties: i32,
1224 properties: Vec<BluetoothProperty>,
1225 ) {
1226 if status != BtStatus::Success {
1227 return;
1228 }
1229
1230 // Update local property cache
1231 for prop in properties {
1232 self.properties.insert(prop.get_type(), prop.clone());
1233
1234 match &prop {
1235 BluetoothProperty::BdAddr(bdaddr) => {
1236 self.update_local_address(&bdaddr);
1237 }
1238 BluetoothProperty::AdapterBondedDevices(bondlist) => {
1239 for addr in bondlist.iter() {
1240 let address = addr.to_string();
1241
1242 // Update bonded state if already in the list. Otherwise create a new
1243 // context with empty properties and name.
1244 self.bonded_devices
1245 .entry(address.clone())
1246 .and_modify(|d| d.bond_state = BtBondState::Bonded)
1247 .or_insert(BluetoothDeviceContext::new(
1248 BtBondState::Bonded,
1249 BtAclState::Disconnected,
1250 BluetoothDevice::new(address.clone(), "".to_string()),
1251 Instant::now(),
1252 vec![],
1253 ));
1254 }
1255 }
1256 BluetoothProperty::BdName(bdname) => {
1257 self.callbacks.for_all_callbacks(|callback| {
1258 callback.on_name_changed(bdname.clone());
1259 });
1260 }
1261 BluetoothProperty::AdapterScanMode(mode) => {
1262 self.cache_discoverable_mode_into_qa();
1263
1264 self.callbacks.for_all_callbacks(|callback| {
1265 callback
1266 .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable);
1267 });
1268 }
1269 _ => {}
1270 }
1271
1272 self.callbacks.for_all_callbacks(|callback| {
1273 callback.on_adapter_property_changed(prop.get_type());
1274 });
1275 }
1276 }
1277
device_found(&mut self, _n: i32, properties: Vec<BluetoothProperty>)1278 fn device_found(&mut self, _n: i32, properties: Vec<BluetoothProperty>) {
1279 let device = BluetoothDevice::from_properties(&properties);
1280 let address = device.address.clone();
1281
1282 if let Some(existing) = self.found_devices.get_mut(&address) {
1283 existing.update_properties(&properties);
1284 existing.seen();
1285 } else {
1286 let device_with_props = BluetoothDeviceContext::new(
1287 BtBondState::NotBonded,
1288 BtAclState::Disconnected,
1289 device,
1290 Instant::now(),
1291 properties,
1292 );
1293 self.found_devices.insert(address.clone(), device_with_props);
1294 }
1295
1296 let device = self.found_devices.get(&address).unwrap();
1297
1298 self.callbacks.for_all_callbacks(|callback| {
1299 callback.on_device_found(device.info.clone());
1300 });
1301
1302 self.bluetooth_admin.lock().unwrap().on_device_found(&device.info);
1303 }
1304
discovery_state(&mut self, state: BtDiscoveryState)1305 fn discovery_state(&mut self, state: BtDiscoveryState) {
1306 let is_discovering = &state == &BtDiscoveryState::Started;
1307
1308 // No-op if we're updating the state to the same value again.
1309 if &is_discovering == &self.is_discovering {
1310 return;
1311 }
1312
1313 // Cache discovering state
1314 self.is_discovering = &state == &BtDiscoveryState::Started;
1315 if self.is_discovering {
1316 self.discovering_started = Instant::now();
1317 }
1318
1319 // Prevent sending out discovering changes or freshness checks when
1320 // suspending. Clients don't need to be notified of discovery pausing
1321 // during suspend. They will probably try to restore it and fail.
1322 let discovery_suspend_mode = self.get_discovery_suspend_mode();
1323 if discovery_suspend_mode != SuspendMode::Normal
1324 && discovery_suspend_mode != SuspendMode::Resuming
1325 {
1326 return;
1327 }
1328
1329 self.callbacks.for_all_callbacks(|callback| {
1330 callback.on_discovering_changed(state == BtDiscoveryState::Started);
1331 });
1332
1333 // Stopped discovering and no freshness check is active. Immediately do
1334 // freshness check which will schedule a recurring future until all
1335 // entries are cleared.
1336 if !is_discovering && self.freshness_check.is_none() {
1337 self.trigger_freshness_check();
1338 }
1339
1340 // Start or stop BLE scanning based on discovering state
1341 if let Some(scanner_id) = self.ble_scanner_id {
1342 if is_discovering {
1343 self.bluetooth_gatt.lock().unwrap().start_active_scan(scanner_id);
1344 } else {
1345 self.bluetooth_gatt.lock().unwrap().stop_active_scan(scanner_id);
1346 }
1347 }
1348 }
1349
ssp_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, variant: BtSspVariant, passkey: u32, )1350 fn ssp_request(
1351 &mut self,
1352 remote_addr: RawAddress,
1353 remote_name: String,
1354 cod: u32,
1355 variant: BtSspVariant,
1356 passkey: u32,
1357 ) {
1358 // Currently this supports many agent because we accept many callbacks.
1359 // TODO(b/274706838): We need a way to select the default agent.
1360 self.callbacks.for_all_callbacks(|callback| {
1361 callback.on_ssp_request(
1362 BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()),
1363 cod,
1364 variant.clone(),
1365 passkey,
1366 );
1367 });
1368 }
1369
pin_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, min_16_digit: bool, )1370 fn pin_request(
1371 &mut self,
1372 remote_addr: RawAddress,
1373 remote_name: String,
1374 cod: u32,
1375 min_16_digit: bool,
1376 ) {
1377 let device = BluetoothDevice::new(remote_addr.to_string(), remote_name.clone());
1378
1379 let digits = match min_16_digit {
1380 true => 16,
1381 false => 6,
1382 };
1383
1384 if is_cod_hid_keyboard(cod) || is_cod_hid_combo(cod) {
1385 debug!("auto gen pin for device {} (cod={:#x})", device.address, cod);
1386 // generate a random pin code to display.
1387 let pin = rand::random::<u64>() % pow(10, digits);
1388 let display_pin = format!("{:06}", pin);
1389
1390 // Currently this supports many agent because we accept many callbacks.
1391 // TODO(b/274706838): We need a way to select the default agent.
1392 self.callbacks.for_all_callbacks(|callback| {
1393 callback.on_pin_display(device.clone(), display_pin.clone());
1394 });
1395
1396 let pin_vec = display_pin.chars().map(|d| d.try_into().unwrap()).collect::<Vec<u8>>();
1397
1398 self.set_pin(device, true, pin_vec);
1399 } else {
1400 debug!("sending pin request for device {} (cod={:#x}) to clients", device.address, cod);
1401 // Currently this supports many agent because we accept many callbacks.
1402 // TODO(b/274706838): We need a way to select the default agent.
1403 self.callbacks.for_all_callbacks(|callback| {
1404 callback.on_pin_request(device.clone(), cod, min_16_digit);
1405 });
1406 }
1407 }
1408
bond_state( &mut self, status: BtStatus, addr: RawAddress, bond_state: BtBondState, fail_reason: i32, )1409 fn bond_state(
1410 &mut self,
1411 status: BtStatus,
1412 addr: RawAddress,
1413 bond_state: BtBondState,
1414 fail_reason: i32,
1415 ) {
1416 let address = addr.to_string();
1417
1418 // Get the device type before the device is potentially deleted.
1419 let device_type =
1420 self.get_remote_type(BluetoothDevice::new(address.clone(), "".to_string()));
1421
1422 // Easy case of not bonded -- we remove the device from the bonded list and change the bond
1423 // state in the found list (in case it was previously bonding).
1424 if &bond_state == &BtBondState::NotBonded {
1425 self.bonded_devices.remove(&address);
1426 self.found_devices
1427 .entry(address.clone())
1428 .and_modify(|d| d.bond_state = bond_state.clone());
1429 }
1430 // We will only insert into the bonded list after bonding is complete
1431 else if &bond_state == &BtBondState::Bonded && !self.bonded_devices.contains_key(&address)
1432 {
1433 // We either need to construct a new BluetoothDeviceContext or grab it from the found
1434 // devices map. Immediately insert that into the bonded list.
1435 let mut device = match self.found_devices.remove(&address) {
1436 Some(mut v) => {
1437 v.bond_state = bond_state.clone();
1438 v
1439 }
1440 None => BluetoothDeviceContext::new(
1441 bond_state.clone(),
1442 BtAclState::Disconnected,
1443 BluetoothDevice::new(address.clone(), "".to_string()),
1444 Instant::now(),
1445 vec![],
1446 ),
1447 };
1448 let device_info = device.info.clone();
1449
1450 // Since this is a newly bonded device, we also need to trigger SDP
1451 // on it.
1452 device.services_resolved = false;
1453 self.bonded_devices.insert(address.clone(), device);
1454 self.fetch_remote_uuids(device_info);
1455 } else {
1456 // If we're bonding, we need to update the found devices list
1457 self.found_devices
1458 .entry(address.clone())
1459 .and_modify(|d| d.bond_state = bond_state.clone());
1460 }
1461
1462 // Resume discovery once the bonding process is complete. Discovery was paused before the
1463 // bond request to avoid ACL connection from interfering with active inquiry.
1464 if &bond_state == &BtBondState::NotBonded || &bond_state == &BtBondState::Bonded {
1465 self.resume_discovery();
1466 }
1467
1468 // Send bond state changed notifications
1469 self.callbacks.for_all_callbacks(|callback| {
1470 callback.on_bond_state_changed(
1471 status.to_u32().unwrap(),
1472 address.clone(),
1473 bond_state.to_u32().unwrap(),
1474 );
1475 });
1476
1477 metrics::bond_state_changed(addr, device_type, status, bond_state, fail_reason);
1478 }
1479
remote_device_properties_changed( &mut self, _status: BtStatus, addr: RawAddress, _num_properties: i32, properties: Vec<BluetoothProperty>, )1480 fn remote_device_properties_changed(
1481 &mut self,
1482 _status: BtStatus,
1483 addr: RawAddress,
1484 _num_properties: i32,
1485 properties: Vec<BluetoothProperty>,
1486 ) {
1487 let address = addr.to_string();
1488 let txl = self.tx.clone();
1489 let device = match self.get_remote_device_if_found_mut(&address) {
1490 None => {
1491 self.found_devices.insert(
1492 address.clone(),
1493 BluetoothDeviceContext::new(
1494 BtBondState::NotBonded,
1495 BtAclState::Disconnected,
1496 BluetoothDevice::new(address.clone(), String::from("")),
1497 Instant::now(),
1498 vec![],
1499 ),
1500 );
1501
1502 self.found_devices.get_mut(&address)
1503 }
1504 some => some,
1505 };
1506
1507 match device {
1508 Some(d) => {
1509 d.update_properties(&properties);
1510 d.seen();
1511
1512 Bluetooth::send_metrics_remote_device_info(d);
1513
1514 let info = d.info.clone();
1515 let has_uuids = d
1516 .properties
1517 .get(&BtPropertyType::Uuids)
1518 .and_then(|prop| match prop {
1519 BluetoothProperty::Uuids(uu) => Some(uu.len() > 0),
1520 _ => None,
1521 })
1522 .map_or(false, |v| v);
1523
1524 // Services are resolved when uuids are fetched.
1525 d.services_resolved = has_uuids;
1526
1527 if d.wait_to_connect && has_uuids {
1528 d.wait_to_connect = false;
1529
1530 let sent_info = info.clone();
1531 tokio::spawn(async move {
1532 let _ = txl
1533 .send(Message::DelayedAdapterActions(
1534 DelayedActions::ConnectAllProfiles(sent_info),
1535 ))
1536 .await;
1537 });
1538 }
1539
1540 self.bluetooth_admin
1541 .lock()
1542 .unwrap()
1543 .on_remote_device_properties_changed(&info, &properties);
1544 }
1545 None => (),
1546 }
1547 }
1548
acl_state( &mut self, status: BtStatus, addr: RawAddress, state: BtAclState, link_type: BtTransport, hci_reason: BtHciErrorCode, conn_direction: BtConnectionDirection, _acl_handle: u16, )1549 fn acl_state(
1550 &mut self,
1551 status: BtStatus,
1552 addr: RawAddress,
1553 state: BtAclState,
1554 link_type: BtTransport,
1555 hci_reason: BtHciErrorCode,
1556 conn_direction: BtConnectionDirection,
1557 _acl_handle: u16,
1558 ) {
1559 // If discovery was previously paused at connect_all_enabled_profiles to avoid an outgoing
1560 // ACL connection colliding with an ongoing inquiry, resume it.
1561 self.resume_discovery();
1562
1563 if status != BtStatus::Success {
1564 warn!(
1565 "Connection to [{}] failed. Status: {:?}, Reason: {:?}",
1566 addr.to_string(),
1567 status,
1568 hci_reason
1569 );
1570 metrics::acl_connection_state_changed(
1571 addr,
1572 link_type,
1573 status,
1574 BtAclState::Disconnected,
1575 conn_direction,
1576 hci_reason,
1577 );
1578 return;
1579 }
1580
1581 let address = addr.to_string();
1582 let device = match self.get_remote_device_if_found_mut(&address) {
1583 None => {
1584 self.found_devices.insert(
1585 address.clone(),
1586 BluetoothDeviceContext::new(
1587 BtBondState::NotBonded,
1588 BtAclState::Disconnected,
1589 BluetoothDevice::new(address.clone(), String::from("")),
1590 Instant::now(),
1591 vec![],
1592 ),
1593 );
1594
1595 self.found_devices.get_mut(&address)
1596 }
1597 some => some,
1598 };
1599
1600 match device {
1601 Some(found) => {
1602 // Only notify if there's been a change in state
1603 let prev_state = &found.acl_state;
1604 if prev_state != &state {
1605 let device = found.info.clone();
1606 found.acl_state = state.clone();
1607 found.acl_reported_transport = link_type;
1608
1609 metrics::acl_connection_state_changed(
1610 addr,
1611 link_type,
1612 BtStatus::Success,
1613 state.clone(),
1614 conn_direction,
1615 hci_reason,
1616 );
1617
1618 match state {
1619 BtAclState::Connected => {
1620 let bluetooth_device = found.info.clone();
1621 let acl_reported_transport = found.acl_reported_transport.clone();
1622 Bluetooth::send_metrics_remote_device_info(found);
1623 self.connection_callbacks.for_all_callbacks(|callback| {
1624 callback.on_device_connected(device.clone());
1625 });
1626 let tx = self.tx.clone();
1627 let transport = match self.get_remote_type(bluetooth_device.clone()) {
1628 BtDeviceType::Bredr => BtTransport::Bredr,
1629 BtDeviceType::Ble => BtTransport::Le,
1630 _ => acl_reported_transport,
1631 };
1632 tokio::spawn(async move {
1633 let _ = tx
1634 .send(Message::OnAclConnected(bluetooth_device, transport))
1635 .await;
1636 });
1637 }
1638 BtAclState::Disconnected => {
1639 self.connection_callbacks.for_all_callbacks(|callback| {
1640 callback.on_device_disconnected(device.clone());
1641 });
1642 let tx = self.tx.clone();
1643 tokio::spawn(async move {
1644 let _ = tx.send(Message::OnAclDisconnected(device.clone())).await;
1645 });
1646 }
1647 };
1648 }
1649 }
1650 None => (),
1651 };
1652 }
1653 }
1654
1655 struct BleDiscoveryCallbacks {
1656 tx: Sender<Message>,
1657 }
1658
1659 impl BleDiscoveryCallbacks {
new(tx: Sender<Message>) -> Self1660 fn new(tx: Sender<Message>) -> Self {
1661 Self { tx }
1662 }
1663 }
1664
1665 // Handle BLE scanner results.
1666 impl IScannerCallback for BleDiscoveryCallbacks {
on_scanner_registered(&mut self, uuid: Uuid128Bit, scanner_id: u8, status: GattStatus)1667 fn on_scanner_registered(&mut self, uuid: Uuid128Bit, scanner_id: u8, status: GattStatus) {
1668 let tx = self.tx.clone();
1669 tokio::spawn(async move {
1670 let _ = tx
1671 .send(Message::DelayedAdapterActions(
1672 DelayedActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status),
1673 ))
1674 .await;
1675 });
1676 }
1677
on_scan_result(&mut self, scan_result: ScanResult)1678 fn on_scan_result(&mut self, scan_result: ScanResult) {
1679 let tx = self.tx.clone();
1680 tokio::spawn(async move {
1681 let _ = tx
1682 .send(Message::DelayedAdapterActions(DelayedActions::BleDiscoveryScannerResult(
1683 scan_result,
1684 )))
1685 .await;
1686 });
1687 }
1688
on_advertisement_found(&mut self, _scanner_id: u8, _scan_result: ScanResult)1689 fn on_advertisement_found(&mut self, _scanner_id: u8, _scan_result: ScanResult) {}
on_advertisement_lost(&mut self, _scanner_id: u8, _scan_result: ScanResult)1690 fn on_advertisement_lost(&mut self, _scanner_id: u8, _scan_result: ScanResult) {}
on_suspend_mode_change(&mut self, _suspend_mode: SuspendMode)1691 fn on_suspend_mode_change(&mut self, _suspend_mode: SuspendMode) {}
1692 }
1693
1694 impl RPCProxy for BleDiscoveryCallbacks {
get_object_id(&self) -> String1695 fn get_object_id(&self) -> String {
1696 "BLE Discovery Callback".to_string()
1697 }
1698 }
1699
1700 // TODO: Add unit tests for this implementation
1701 impl IBluetooth for Bluetooth {
register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>)1702 fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) {
1703 self.callbacks.add_callback(callback);
1704 }
1705
register_connection_callback( &mut self, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u321706 fn register_connection_callback(
1707 &mut self,
1708 callback: Box<dyn IBluetoothConnectionCallback + Send>,
1709 ) -> u32 {
1710 self.connection_callbacks.add_callback(callback)
1711 }
1712
unregister_connection_callback(&mut self, callback_id: u32) -> bool1713 fn unregister_connection_callback(&mut self, callback_id: u32) -> bool {
1714 self.connection_callbacks.remove_callback(callback_id)
1715 }
1716
enable(&mut self) -> bool1717 fn enable(&mut self) -> bool {
1718 self.intf.lock().unwrap().enable() == 0
1719 }
1720
disable(&mut self) -> bool1721 fn disable(&mut self) -> bool {
1722 self.intf.lock().unwrap().disable() == 0
1723 }
1724
get_address(&self) -> String1725 fn get_address(&self) -> String {
1726 match self.local_address {
1727 None => String::from(""),
1728 Some(addr) => addr.to_string(),
1729 }
1730 }
1731
get_uuids(&self) -> Vec<Uuid128Bit>1732 fn get_uuids(&self) -> Vec<Uuid128Bit> {
1733 match self.properties.get(&BtPropertyType::Uuids) {
1734 Some(prop) => match prop {
1735 BluetoothProperty::Uuids(uuids) => {
1736 uuids.iter().map(|&x| x.uu.clone()).collect::<Vec<Uuid128Bit>>()
1737 }
1738 _ => vec![],
1739 },
1740 _ => vec![],
1741 }
1742 }
1743
get_name(&self) -> String1744 fn get_name(&self) -> String {
1745 match self.properties.get(&BtPropertyType::BdName) {
1746 Some(prop) => match prop {
1747 BluetoothProperty::BdName(name) => name.clone(),
1748 _ => String::new(),
1749 },
1750 _ => String::new(),
1751 }
1752 }
1753
set_name(&self, name: String) -> bool1754 fn set_name(&self, name: String) -> bool {
1755 self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::BdName(name)) == 0
1756 }
1757
get_bluetooth_class(&self) -> u321758 fn get_bluetooth_class(&self) -> u32 {
1759 match self.properties.get(&BtPropertyType::ClassOfDevice) {
1760 Some(prop) => match prop {
1761 BluetoothProperty::ClassOfDevice(cod) => cod.clone(),
1762 _ => 0,
1763 },
1764 _ => 0,
1765 }
1766 }
1767
set_bluetooth_class(&self, cod: u32) -> bool1768 fn set_bluetooth_class(&self, cod: u32) -> bool {
1769 self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::ClassOfDevice(cod)) == 0
1770 }
1771
get_discoverable(&self) -> bool1772 fn get_discoverable(&self) -> bool {
1773 match self.properties.get(&BtPropertyType::AdapterScanMode) {
1774 Some(prop) => match prop {
1775 BluetoothProperty::AdapterScanMode(mode) => match mode {
1776 BtScanMode::ConnectableDiscoverable => true,
1777 _ => false,
1778 },
1779 _ => false,
1780 },
1781 _ => false,
1782 }
1783 }
1784
get_discoverable_timeout(&self) -> u321785 fn get_discoverable_timeout(&self) -> u32 {
1786 match self.properties.get(&BtPropertyType::AdapterDiscoverableTimeout) {
1787 Some(prop) => match prop {
1788 BluetoothProperty::AdapterDiscoverableTimeout(timeout) => timeout.clone(),
1789 _ => 0,
1790 },
1791 _ => 0,
1792 }
1793 }
1794
set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool1795 fn set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool {
1796 let intf = self.intf.lock().unwrap();
1797
1798 // Checks if the duration is valid.
1799 if mode == BtDiscMode::LimitedDiscoverable && (duration > 60 || duration <= 0) {
1800 warn!("Invalid duration for setting the device into limited discoverable mode. The valid duration is 1~60 seconds.");
1801 return false;
1802 }
1803
1804 let off_mode =
1805 if self.is_connectable { BtScanMode::Connectable } else { BtScanMode::None_ };
1806
1807 let new_mode = match mode {
1808 BtDiscMode::LimitedDiscoverable => BtScanMode::ConnectableLimitedDiscoverable,
1809 BtDiscMode::GeneralDiscoverable => BtScanMode::ConnectableDiscoverable,
1810 BtDiscMode::NonDiscoverable => off_mode.clone(),
1811 };
1812
1813 // The old timer should be overwritten regardless of what the new mode is.
1814 if let Some(ref handle) = self.discoverable_timeout {
1815 handle.abort();
1816 self.discoverable_timeout = None;
1817 }
1818
1819 if intf.set_adapter_property(BluetoothProperty::AdapterDiscoverableTimeout(duration)) != 0
1820 || intf.set_adapter_property(BluetoothProperty::AdapterScanMode(new_mode)) != 0
1821 {
1822 return false;
1823 }
1824
1825 if (mode != BtDiscMode::NonDiscoverable) && (duration != 0) {
1826 let intf_clone = self.intf.clone();
1827 self.discoverable_timeout = Some(tokio::spawn(async move {
1828 time::sleep(Duration::from_secs(duration.into())).await;
1829 intf_clone
1830 .lock()
1831 .unwrap()
1832 .set_adapter_property(BluetoothProperty::AdapterScanMode(off_mode));
1833 }));
1834 }
1835
1836 true
1837 }
1838
is_multi_advertisement_supported(&self) -> bool1839 fn is_multi_advertisement_supported(&self) -> bool {
1840 match self.properties.get(&BtPropertyType::LocalLeFeatures) {
1841 Some(prop) => match prop {
1842 BluetoothProperty::LocalLeFeatures(llf) => {
1843 llf.max_adv_instance >= MIN_ADV_INSTANCES_FOR_MULTI_ADV
1844 }
1845 _ => false,
1846 },
1847 _ => false,
1848 }
1849 }
1850
is_le_extended_advertising_supported(&self) -> bool1851 fn is_le_extended_advertising_supported(&self) -> bool {
1852 match self.properties.get(&BtPropertyType::LocalLeFeatures) {
1853 Some(prop) => match prop {
1854 BluetoothProperty::LocalLeFeatures(llf) => llf.le_extended_advertising_supported,
1855 _ => false,
1856 },
1857 _ => false,
1858 }
1859 }
1860
start_discovery(&mut self) -> bool1861 fn start_discovery(&mut self) -> bool {
1862 // Short-circuit to avoid sending multiple start discovery calls.
1863 if self.is_discovering {
1864 return true;
1865 }
1866
1867 // Short-circuit if paused and add the discovery intent to the queue.
1868 if self.is_discovery_paused {
1869 self.pending_discovery = true;
1870 debug!("Queue the discovery request during paused state");
1871 return true;
1872 }
1873
1874 let discovery_suspend_mode = self.get_discovery_suspend_mode();
1875 if discovery_suspend_mode != SuspendMode::Normal
1876 && discovery_suspend_mode != SuspendMode::Resuming
1877 {
1878 log::warn!("start_discovery is not allowed when suspending or suspended.");
1879 return false;
1880 }
1881
1882 self.intf.lock().unwrap().start_discovery() == 0
1883 }
1884
cancel_discovery(&mut self) -> bool1885 fn cancel_discovery(&mut self) -> bool {
1886 // Client no longer want to discover, clear the request
1887 if self.is_discovery_paused {
1888 self.pending_discovery = false;
1889 debug!("Cancel the discovery request during paused state");
1890 }
1891
1892 // Reject the cancel discovery request if the underlying stack is not in a discovering
1893 // state. For example, previous start discovery was enqueued for ongoing discovery.
1894 if !self.is_discovering {
1895 debug!("Reject cancel_discovery as it's not in discovering state.");
1896 return false;
1897 }
1898
1899 let discovery_suspend_mode = self.get_discovery_suspend_mode();
1900 if discovery_suspend_mode != SuspendMode::Normal
1901 && discovery_suspend_mode != SuspendMode::Suspending
1902 {
1903 log::warn!("cancel_discovery is not allowed when resuming or suspended.");
1904 return false;
1905 }
1906
1907 self.intf.lock().unwrap().cancel_discovery() == 0
1908 }
1909
is_discovering(&self) -> bool1910 fn is_discovering(&self) -> bool {
1911 self.is_discovering
1912 }
1913
get_discovery_end_millis(&self) -> u641914 fn get_discovery_end_millis(&self) -> u64 {
1915 if !self.is_discovering {
1916 return 0;
1917 }
1918
1919 let elapsed_ms = self.discovering_started.elapsed().as_millis() as u64;
1920 if elapsed_ms >= DEFAULT_DISCOVERY_TIMEOUT_MS {
1921 0
1922 } else {
1923 DEFAULT_DISCOVERY_TIMEOUT_MS - elapsed_ms
1924 }
1925 }
1926
create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool1927 fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> bool {
1928 let addr = RawAddress::from_string(device.address.clone());
1929
1930 if addr.is_none() {
1931 metrics::bond_create_attempt(RawAddress::default(), BtDeviceType::Unknown);
1932 metrics::bond_state_changed(
1933 RawAddress::default(),
1934 BtDeviceType::Unknown,
1935 BtStatus::InvalidParam,
1936 BtBondState::NotBonded,
1937 0,
1938 );
1939 warn!("Can't create bond. Address {} is not valid", device.address);
1940 return false;
1941 }
1942
1943 let address = addr.unwrap();
1944 let device_type = match transport {
1945 BtTransport::Bredr => BtDeviceType::Bredr,
1946 BtTransport::Le => BtDeviceType::Ble,
1947 _ => self.get_remote_type(device.clone()),
1948 };
1949
1950 // We explicitly log the attempt to start the bonding separate from logging the bond state.
1951 // The start of the attempt is critical to help identify a bonding/pairing session.
1952 metrics::bond_create_attempt(address, device_type.clone());
1953
1954 // BREDR connection won't work when Inquiry is in progress.
1955 self.pause_discovery();
1956 let status = self.intf.lock().unwrap().create_bond(&address, transport);
1957
1958 if status != 0 {
1959 metrics::bond_state_changed(
1960 address,
1961 device_type,
1962 BtStatus::from(status as u32),
1963 BtBondState::NotBonded,
1964 0,
1965 );
1966 return false;
1967 }
1968
1969 // Creating bond automatically create ACL connection as well, therefore also log metrics
1970 // ACL connection attempt here.
1971 let is_connected = self
1972 .get_remote_device_if_found(&device.address)
1973 .map_or(false, |d| d.acl_state == BtAclState::Connected);
1974 if !is_connected {
1975 metrics::acl_connect_attempt(address, BtAclState::Connected);
1976 }
1977
1978 return true;
1979 }
1980
cancel_bond_process(&self, device: BluetoothDevice) -> bool1981 fn cancel_bond_process(&self, device: BluetoothDevice) -> bool {
1982 let addr = RawAddress::from_string(device.address.clone());
1983
1984 if addr.is_none() {
1985 warn!("Can't cancel bond. Address {} is not valid.", device.address);
1986 return false;
1987 }
1988
1989 let address = addr.unwrap();
1990 self.intf.lock().unwrap().cancel_bond(&address) == 0
1991 }
1992
remove_bond(&self, device: BluetoothDevice) -> bool1993 fn remove_bond(&self, device: BluetoothDevice) -> bool {
1994 // Temporary for debugging b/255849761. Should change to debug after fix.
1995 log::info!("Removing bond for {}", device.address);
1996
1997 let addr = RawAddress::from_string(device.address.clone());
1998
1999 if addr.is_none() {
2000 warn!("Can't remove bond. Address {} is not valid.", device.address);
2001 return false;
2002 }
2003
2004 let address = addr.unwrap();
2005 let status = self.intf.lock().unwrap().remove_bond(&address);
2006
2007 if status != 0 {
2008 return false;
2009 }
2010
2011 // Removing bond also disconnects the ACL if is connected. Therefore, also log ACL
2012 // disconnection attempt here.
2013 let is_connected = self
2014 .get_remote_device_if_found(&device.address)
2015 .map_or(false, |d| d.acl_state == BtAclState::Connected);
2016 if is_connected {
2017 metrics::acl_connect_attempt(address, BtAclState::Disconnected);
2018 }
2019
2020 return true;
2021 }
2022
get_bonded_devices(&self) -> Vec<BluetoothDevice>2023 fn get_bonded_devices(&self) -> Vec<BluetoothDevice> {
2024 let mut devices: Vec<BluetoothDevice> = vec![];
2025
2026 for (_, device) in self.bonded_devices.iter() {
2027 devices.push(device.info.clone());
2028 }
2029
2030 devices
2031 }
2032
get_bond_state(&self, device: BluetoothDevice) -> BtBondState2033 fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState {
2034 self.get_bond_state_by_addr(&device.address)
2035 }
2036
set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool2037 fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool {
2038 let addr = RawAddress::from_string(device.address.clone());
2039
2040 if addr.is_none() {
2041 warn!("Can't set pin. Address {} is not valid.", device.address);
2042 return false;
2043 }
2044
2045 let is_bonding = match self.found_devices.get(&device.address) {
2046 Some(d) => d.bond_state == BtBondState::Bonding,
2047 None => false,
2048 };
2049
2050 if !is_bonding {
2051 warn!("Can't set pin. Device {} isn't bonding.", device.address);
2052 return false;
2053 }
2054
2055 let mut btpin = BtPinCode { pin: array_utils::to_sized_array(&pin_code) };
2056
2057 self.intf.lock().unwrap().pin_reply(
2058 &addr.unwrap(),
2059 accept as u8,
2060 pin_code.len() as u8,
2061 &mut btpin,
2062 ) == 0
2063 }
2064
set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool2065 fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool {
2066 let addr = RawAddress::from_string(device.address.clone());
2067
2068 if addr.is_none() {
2069 warn!("Can't set passkey. Address {} is not valid.", device.address);
2070 return false;
2071 }
2072
2073 let is_bonding = match self.found_devices.get(&device.address) {
2074 Some(d) => d.bond_state == BtBondState::Bonding,
2075 None => false,
2076 };
2077
2078 if !is_bonding {
2079 warn!("Can't set passkey. Device {} isn't bonding.", device.address);
2080 return false;
2081 }
2082
2083 let mut tmp: [u8; 4] = [0; 4];
2084 tmp.copy_from_slice(passkey.as_slice());
2085 let passkey = u32::from_ne_bytes(tmp);
2086
2087 self.intf.lock().unwrap().ssp_reply(
2088 &addr.unwrap(),
2089 BtSspVariant::PasskeyEntry,
2090 accept as u8,
2091 passkey,
2092 ) == 0
2093 }
2094
set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool2095 fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
2096 let addr = RawAddress::from_string(device.address.clone());
2097
2098 if addr.is_none() {
2099 warn!("Can't set pairing confirmation. Address {} is not valid.", device.address);
2100 return false;
2101 }
2102
2103 self.intf.lock().unwrap().ssp_reply(
2104 &addr.unwrap(),
2105 BtSspVariant::PasskeyConfirmation,
2106 accept as u8,
2107 0,
2108 ) == 0
2109 }
2110
get_remote_name(&self, device: BluetoothDevice) -> String2111 fn get_remote_name(&self, device: BluetoothDevice) -> String {
2112 match self.get_remote_device_property(&device, &BtPropertyType::BdName) {
2113 Some(BluetoothProperty::BdName(name)) => return name.clone(),
2114 _ => return "".to_string(),
2115 }
2116 }
2117
get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType2118 fn get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType {
2119 match self.get_remote_device_property(&device, &BtPropertyType::TypeOfDevice) {
2120 Some(BluetoothProperty::TypeOfDevice(device_type)) => return device_type,
2121 _ => return BtDeviceType::Unknown,
2122 }
2123 }
2124
get_remote_alias(&self, device: BluetoothDevice) -> String2125 fn get_remote_alias(&self, device: BluetoothDevice) -> String {
2126 match self.get_remote_device_property(&device, &BtPropertyType::RemoteFriendlyName) {
2127 Some(BluetoothProperty::RemoteFriendlyName(name)) => return name.clone(),
2128 _ => "".to_string(),
2129 }
2130 }
2131
set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String)2132 fn set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String) {
2133 let _ = self.set_remote_device_property(
2134 &device,
2135 BtPropertyType::RemoteFriendlyName,
2136 BluetoothProperty::RemoteFriendlyName(new_alias),
2137 );
2138 }
2139
get_remote_class(&self, device: BluetoothDevice) -> u322140 fn get_remote_class(&self, device: BluetoothDevice) -> u32 {
2141 match self.get_remote_device_property(&device, &BtPropertyType::ClassOfDevice) {
2142 Some(BluetoothProperty::ClassOfDevice(class)) => return class,
2143 _ => 0,
2144 }
2145 }
2146
get_remote_appearance(&self, device: BluetoothDevice) -> u162147 fn get_remote_appearance(&self, device: BluetoothDevice) -> u16 {
2148 match self.get_remote_device_property(&device, &BtPropertyType::Appearance) {
2149 Some(BluetoothProperty::Appearance(appearance)) => appearance,
2150 _ => 0,
2151 }
2152 }
2153
get_remote_connected(&self, device: BluetoothDevice) -> bool2154 fn get_remote_connected(&self, device: BluetoothDevice) -> bool {
2155 self.get_connection_state(device) != BtConnectionState::NotConnected
2156 }
2157
get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool2158 fn get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool {
2159 // Wake is allowed if the device supports HIDP or HOGP only.
2160 match self.get_remote_device_property(&device, &BtPropertyType::Uuids) {
2161 Some(BluetoothProperty::Uuids(uuids)) => {
2162 return uuids.iter().any(|&x| {
2163 UuidHelper::is_known_profile(&x.uu).map_or(false, |profile| {
2164 profile == Profile::Hid || profile == Profile::Hogp
2165 })
2166 });
2167 }
2168 _ => false,
2169 }
2170 }
2171
get_connected_devices(&self) -> Vec<BluetoothDevice>2172 fn get_connected_devices(&self) -> Vec<BluetoothDevice> {
2173 let bonded_connected: HashMap<String, BluetoothDevice> = self
2174 .bonded_devices
2175 .iter()
2176 .filter(|(_, v)| v.acl_state == BtAclState::Connected)
2177 .map(|(k, v)| (k.clone(), v.info.clone()))
2178 .collect();
2179 let mut found_connected: Vec<BluetoothDevice> = self
2180 .found_devices
2181 .iter()
2182 .filter(|(k, v)| {
2183 v.acl_state == BtAclState::Connected
2184 && !bonded_connected.contains_key(&k.to_string())
2185 })
2186 .map(|(_, v)| v.info.clone())
2187 .collect();
2188
2189 let mut all =
2190 bonded_connected.iter().map(|(_, v)| v.clone()).collect::<Vec<BluetoothDevice>>();
2191 all.append(&mut found_connected);
2192
2193 all
2194 }
2195
get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState2196 fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState {
2197 let addr = RawAddress::from_string(device.address.clone());
2198
2199 if addr.is_none() {
2200 warn!("Can't check connection state. Address {} is not valid.", device.address);
2201 return BtConnectionState::NotConnected;
2202 }
2203
2204 // The underlying api adds whether this is ENCRYPTED_BREDR or ENCRYPTED_LE.
2205 // As long as it is non-zero, it is connected.
2206 self.intf.lock().unwrap().get_connection_state(&addr.unwrap())
2207 }
2208
get_profile_connection_state(&self, profile: Uuid128Bit) -> ProfileConnectionState2209 fn get_profile_connection_state(&self, profile: Uuid128Bit) -> ProfileConnectionState {
2210 if let Some(known) = UuidHelper::is_known_profile(&profile) {
2211 match known {
2212 Profile::A2dpSink | Profile::A2dpSource => {
2213 self.bluetooth_media.lock().unwrap().get_a2dp_connection_state()
2214 }
2215 Profile::Hfp | Profile::HfpAg => {
2216 self.bluetooth_media.lock().unwrap().get_hfp_connection_state()
2217 }
2218 // TODO: (b/223431229) Profile::Hid and Profile::Hogp
2219 _ => ProfileConnectionState::Disconnected,
2220 }
2221 } else {
2222 ProfileConnectionState::Disconnected
2223 }
2224 }
2225
get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>2226 fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
2227 match self.get_remote_device_property(&device, &BtPropertyType::Uuids) {
2228 Some(BluetoothProperty::Uuids(uuids)) => {
2229 return uuids.iter().map(|&x| x.uu.clone()).collect::<Vec<Uuid128Bit>>()
2230 }
2231 _ => return vec![],
2232 }
2233 }
2234
fetch_remote_uuids(&self, remote_device: BluetoothDevice) -> bool2235 fn fetch_remote_uuids(&self, remote_device: BluetoothDevice) -> bool {
2236 let device = match self.get_remote_device_if_found(&remote_device.address) {
2237 Some(v) => v,
2238 None => {
2239 warn!("Won't fetch UUIDs on unknown device {}", remote_device.address);
2240 return false;
2241 }
2242 };
2243
2244 let mut addr = match RawAddress::from_string(device.info.address.clone()) {
2245 Some(v) => v,
2246 None => {
2247 warn!("Can't fetch UUIDs. Address {} is not valid.", device.info.address);
2248 return false;
2249 }
2250 };
2251
2252 let transport = match self.get_remote_type(device.info.clone()) {
2253 BtDeviceType::Bredr => BtTransport::Bredr,
2254 BtDeviceType::Ble => BtTransport::Le,
2255 _ => device.acl_reported_transport,
2256 };
2257
2258 self.intf.lock().unwrap().get_remote_services(&mut addr, transport) == 0
2259 }
2260
sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool2261 fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
2262 if self.sdp.is_none() {
2263 warn!("SDP is not initialized. Can't do SDP search.");
2264 return false;
2265 }
2266
2267 let addr = RawAddress::from_string(device.address.clone());
2268 if addr.is_none() {
2269 warn!("Can't SDP search. Address {} is not valid.", device.address);
2270 return false;
2271 }
2272
2273 let uu = Uuid::from(uuid);
2274 self.sdp.as_ref().unwrap().sdp_search(&mut addr.unwrap(), &uu) == BtStatus::Success
2275 }
2276
create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool2277 fn create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool {
2278 let mut handle: i32 = -1;
2279 let mut sdp_record = sdp_record;
2280 match self.sdp.as_ref().unwrap().create_sdp_record(&mut sdp_record, &mut handle) {
2281 BtStatus::Success => {
2282 let record_clone = sdp_record.clone();
2283 self.callbacks.for_all_callbacks(|callback| {
2284 callback.on_sdp_record_created(record_clone.clone(), handle);
2285 });
2286 true
2287 }
2288 _ => false,
2289 }
2290 }
2291
remove_sdp_record(&self, handle: i32) -> bool2292 fn remove_sdp_record(&self, handle: i32) -> bool {
2293 self.sdp.as_ref().unwrap().remove_sdp_record(handle) == BtStatus::Success
2294 }
2295
connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool2296 fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool {
2297 // Profile init must be complete before this api is callable
2298 if !self.profiles_ready {
2299 return false;
2300 }
2301
2302 let mut addr = match RawAddress::from_string(device.address.clone()) {
2303 Some(v) => v,
2304 None => {
2305 warn!("Can't connect profiles on invalid address [{}]", &device.address);
2306 return false;
2307 }
2308 };
2309
2310 let is_connected = self
2311 .get_remote_device_if_found(&device.address)
2312 .map_or(false, |d| d.acl_state == BtAclState::Connected);
2313 if !is_connected {
2314 // log ACL connection attempt if it's not already connected.
2315 metrics::acl_connect_attempt(addr, BtAclState::Connected);
2316 // Pause discovery before connecting, or the ACL connection request may conflict with
2317 // the ongoing inquiry.
2318 self.pause_discovery();
2319 }
2320
2321 // Check all remote uuids to see if they match enabled profiles and connect them.
2322 let mut has_enabled_uuids = false;
2323 let mut has_media_profile = false;
2324 let mut has_supported_profile = false;
2325 let uuids = self.get_remote_uuids(device.clone());
2326 for uuid in uuids.iter() {
2327 match UuidHelper::is_known_profile(uuid) {
2328 Some(p) => {
2329 if UuidHelper::is_profile_supported(&p) {
2330 match p {
2331 Profile::Hid | Profile::Hogp => {
2332 has_supported_profile = true;
2333 let status = self.hh.as_ref().unwrap().connect(&mut addr);
2334 metrics::profile_connection_state_changed(
2335 addr,
2336 p as u32,
2337 BtStatus::Success,
2338 BthhConnectionState::Connecting as u32,
2339 );
2340
2341 if status != BtStatus::Success {
2342 metrics::profile_connection_state_changed(
2343 addr,
2344 p as u32,
2345 status,
2346 BthhConnectionState::Disconnected as u32,
2347 );
2348 }
2349 }
2350
2351 Profile::A2dpSink | Profile::A2dpSource | Profile::Hfp
2352 if !has_media_profile =>
2353 {
2354 has_supported_profile = true;
2355 has_media_profile = true;
2356 let txl = self.tx.clone();
2357 let address = device.address.clone();
2358 topstack::get_runtime().spawn(async move {
2359 let _ = txl
2360 .send(Message::Media(MediaActions::Connect(address)))
2361 .await;
2362 });
2363 }
2364
2365 Profile::Bas => {
2366 has_supported_profile = true;
2367 let tx = self.tx.clone();
2368 let transport =
2369 match self.get_remote_device_if_found(&device.address) {
2370 Some(context) => context.acl_reported_transport,
2371 None => return false,
2372 };
2373 let device_to_send = device.clone();
2374 let transport = match self.get_remote_type(device.clone()) {
2375 BtDeviceType::Bredr => BtTransport::Bredr,
2376 BtDeviceType::Ble => BtTransport::Le,
2377 _ => transport,
2378 };
2379 topstack::get_runtime().spawn(async move {
2380 let _ = tx
2381 .send(Message::BatteryService(
2382 BatteryServiceActions::Connect(
2383 device_to_send,
2384 transport,
2385 ),
2386 ))
2387 .await;
2388 });
2389 }
2390
2391 // We don't connect most profiles
2392 _ => (),
2393 }
2394 }
2395 has_enabled_uuids = true;
2396 }
2397 _ => {}
2398 }
2399 }
2400
2401 // If SDP isn't completed yet, we wait for it to complete and retry the connection again.
2402 // Otherwise, this connection request is done, no retry is required.
2403 if !has_enabled_uuids {
2404 warn!("[{}] SDP hasn't completed for device, wait to connect.", DisplayAddress(&addr));
2405 if let Some(d) = self.get_remote_device_if_found_mut(&device.address) {
2406 if uuids.len() == 0 || !d.services_resolved {
2407 d.wait_to_connect = true;
2408 }
2409 }
2410 }
2411
2412 // If the SDP has not been completed or the device does not have a profile that we are
2413 // interested in connecting to, resume discovery now. Other cases will be handled in the
2414 // ACL connection state or bond state callbacks.
2415 if !has_enabled_uuids || !has_supported_profile {
2416 self.resume_discovery();
2417 }
2418
2419 return true;
2420 }
2421
disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool2422 fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool {
2423 if !self.profiles_ready {
2424 return false;
2425 }
2426
2427 let addr = RawAddress::from_string(device.address.clone());
2428 if addr.is_none() {
2429 warn!("Can't connect profiles on invalid address [{}]", &device.address);
2430 return false;
2431 }
2432
2433 // log ACL disconnection attempt if it's not already disconnected.
2434 let is_connected = self
2435 .get_remote_device_if_found(&device.address)
2436 .map_or(false, |d| d.acl_state == BtAclState::Connected);
2437 if is_connected {
2438 metrics::acl_connect_attempt(addr.unwrap(), BtAclState::Disconnected);
2439 }
2440
2441 let uuids = self.get_remote_uuids(device.clone());
2442 let mut has_media_profile = false;
2443 for uuid in uuids.iter() {
2444 match UuidHelper::is_known_profile(uuid) {
2445 Some(p) => {
2446 if UuidHelper::is_profile_supported(&p) {
2447 match p {
2448 Profile::Hid | Profile::Hogp => {
2449 self.hh.as_ref().unwrap().disconnect(&mut addr.unwrap());
2450 }
2451
2452 Profile::A2dpSink
2453 | Profile::A2dpSource
2454 | Profile::Hfp
2455 | Profile::AvrcpController
2456 if !has_media_profile =>
2457 {
2458 has_media_profile = true;
2459 let txl = self.tx.clone();
2460 let address = device.address.clone();
2461 topstack::get_runtime().spawn(async move {
2462 let _ = txl
2463 .send(Message::Media(MediaActions::Disconnect(address)))
2464 .await;
2465 });
2466 }
2467
2468 Profile::Bas => {
2469 let tx = self.tx.clone();
2470 let device_to_send = device.clone();
2471 topstack::get_runtime().spawn(async move {
2472 let _ = tx
2473 .send(Message::BatteryService(
2474 BatteryServiceActions::Disconnect(device_to_send),
2475 ))
2476 .await;
2477 });
2478 }
2479
2480 // We don't connect most profiles
2481 _ => (),
2482 }
2483 }
2484 }
2485 _ => {}
2486 }
2487 }
2488
2489 return true;
2490 }
2491
is_wbs_supported(&self) -> bool2492 fn is_wbs_supported(&self) -> bool {
2493 self.intf.lock().unwrap().get_wbs_supported()
2494 }
2495
is_swb_supported(&self) -> bool2496 fn is_swb_supported(&self) -> bool {
2497 self.intf.lock().unwrap().get_swb_supported()
2498 }
2499 }
2500
2501 impl BtifSdpCallbacks for Bluetooth {
sdp_search( &mut self, status: BtStatus, address: RawAddress, uuid: Uuid, _count: i32, records: Vec<BtSdpRecord>, )2502 fn sdp_search(
2503 &mut self,
2504 status: BtStatus,
2505 address: RawAddress,
2506 uuid: Uuid,
2507 _count: i32,
2508 records: Vec<BtSdpRecord>,
2509 ) {
2510 let uuid_to_send = match UuidHelper::from_string(uuid.to_string()) {
2511 Some(uu) => uu,
2512 None => return,
2513 };
2514 let device_info = match self.get_remote_device_info_if_found(&address.to_string()) {
2515 Some(info) => info,
2516 None => BluetoothDevice::new(address.to_string(), "".to_string()),
2517 };
2518
2519 // The SDP records we get back do not populate the UUID so we populate it ourselves before
2520 // sending them on.
2521 let mut records = records;
2522 records.iter_mut().for_each(|record| {
2523 match record {
2524 BtSdpRecord::HeaderOverlay(header) => header.uuid = uuid.clone(),
2525 BtSdpRecord::MapMas(record) => record.hdr.uuid = uuid.clone(),
2526 BtSdpRecord::MapMns(record) => record.hdr.uuid = uuid.clone(),
2527 BtSdpRecord::PbapPse(record) => record.hdr.uuid = uuid.clone(),
2528 BtSdpRecord::PbapPce(record) => record.hdr.uuid = uuid.clone(),
2529 BtSdpRecord::OppServer(record) => record.hdr.uuid = uuid.clone(),
2530 BtSdpRecord::SapServer(record) => record.hdr.uuid = uuid.clone(),
2531 BtSdpRecord::Dip(record) => record.hdr.uuid = uuid.clone(),
2532 BtSdpRecord::Mps(record) => record.hdr.uuid = uuid.clone(),
2533 };
2534 });
2535 self.callbacks.for_all_callbacks(|callback| {
2536 callback.on_sdp_search_complete(device_info.clone(), uuid_to_send, records.clone());
2537 });
2538 debug!(
2539 "Sdp search result found: Status({:?}) Address({:?}) Uuid({:?})",
2540 status, address, uuid
2541 );
2542 }
2543 }
2544
2545 impl BtifHHCallbacks for Bluetooth {
connection_state(&mut self, mut address: RawAddress, state: BthhConnectionState)2546 fn connection_state(&mut self, mut address: RawAddress, state: BthhConnectionState) {
2547 debug!("Hid host connection state updated: Address({:?}) State({:?})", address, state);
2548
2549 // HID or HOG is not differentiated by the hid host when callback this function. Assume HOG
2550 // if the device is LE only and HID if classic only. And assume HOG if UUID said so when
2551 // device type is dual or unknown.
2552 let device = BluetoothDevice::new(address.to_string(), "".to_string());
2553 let profile = match self.get_remote_type(device.clone()) {
2554 BtDeviceType::Ble => Profile::Hogp,
2555 BtDeviceType::Bredr => Profile::Hid,
2556 _ => {
2557 if self.get_remote_uuids(device).contains(&UuidHelper::from_string(HOGP).unwrap()) {
2558 Profile::Hogp
2559 } else {
2560 Profile::Hid
2561 }
2562 }
2563 };
2564
2565 metrics::profile_connection_state_changed(
2566 address,
2567 profile as u32,
2568 BtStatus::Success,
2569 state as u32,
2570 );
2571
2572 if BtBondState::Bonded != self.get_bond_state_by_addr(&address.to_string()) {
2573 warn!(
2574 "[{}]: Rejecting a unbonded device's attempt to connect to HID/HOG profiles",
2575 DisplayAddress(&address)
2576 );
2577 self.hh.as_ref().unwrap().disconnect(&mut address);
2578 }
2579 }
2580
hid_info(&mut self, address: RawAddress, info: BthhHidInfo)2581 fn hid_info(&mut self, address: RawAddress, info: BthhHidInfo) {
2582 debug!("Hid host info updated: Address({:?}) Info({:?})", address, info);
2583 }
2584
protocol_mode(&mut self, address: RawAddress, status: BthhStatus, mode: BthhProtocolMode)2585 fn protocol_mode(&mut self, address: RawAddress, status: BthhStatus, mode: BthhProtocolMode) {
2586 debug!(
2587 "Hid host protocol mode updated: Address({:?}) Status({:?}) Mode({:?})",
2588 address, status, mode
2589 );
2590 }
2591
idle_time(&mut self, address: RawAddress, status: BthhStatus, idle_rate: i32)2592 fn idle_time(&mut self, address: RawAddress, status: BthhStatus, idle_rate: i32) {
2593 debug!(
2594 "Hid host idle time updated: Address({:?}) Status({:?}) Idle Rate({:?})",
2595 address, status, idle_rate
2596 );
2597 }
2598
get_report( &mut self, mut address: RawAddress, status: BthhStatus, mut data: Vec<u8>, size: i32, )2599 fn get_report(
2600 &mut self,
2601 mut address: RawAddress,
2602 status: BthhStatus,
2603 mut data: Vec<u8>,
2604 size: i32,
2605 ) {
2606 debug!(
2607 "Hid host got report: Address({:?}) Status({:?}) Report Size({:?})",
2608 address, status, size
2609 );
2610 self.hh.as_ref().unwrap().get_report_reply(&mut address, status, &mut data, size as u16);
2611 }
2612
handshake(&mut self, address: RawAddress, status: BthhStatus)2613 fn handshake(&mut self, address: RawAddress, status: BthhStatus) {
2614 debug!("Hid host handshake: Address({:?}) Status({:?})", address, status);
2615 }
2616 }
2617
2618 impl IBluetoothQALegacy for Bluetooth {
get_connectable(&self) -> bool2619 fn get_connectable(&self) -> bool {
2620 self.get_connectable_internal()
2621 }
2622
set_connectable(&mut self, mode: bool) -> bool2623 fn set_connectable(&mut self, mode: bool) -> bool {
2624 self.set_connectable_internal(mode)
2625 }
2626
get_alias(&self) -> String2627 fn get_alias(&self) -> String {
2628 let name = self.get_name();
2629 if !name.is_empty() {
2630 return name;
2631 }
2632
2633 // If the adapter name is empty, generate one based on local BDADDR
2634 // so that test programs can have a friendly name for the adapter.
2635 match self.local_address {
2636 None => "floss_0000".to_string(),
2637 Some(addr) => format!("floss_{:02X}{:02X}", addr.address[4], addr.address[5]),
2638 }
2639 }
2640
get_modalias(&self) -> String2641 fn get_modalias(&self) -> String {
2642 format!("bluetooth:v00E0pC405d{:04x}", FLOSS_VER)
2643 }
2644
get_hid_report( &mut self, addr: String, report_type: BthhReportType, report_id: u8, ) -> BtStatus2645 fn get_hid_report(
2646 &mut self,
2647 addr: String,
2648 report_type: BthhReportType,
2649 report_id: u8,
2650 ) -> BtStatus {
2651 if let Some(mut addr) = RawAddress::from_string(addr) {
2652 self.hh.as_mut().unwrap().get_report(&mut addr, report_type, report_id, 128)
2653 } else {
2654 BtStatus::InvalidParam
2655 }
2656 }
2657
set_hid_report( &mut self, addr: String, report_type: BthhReportType, report: String, ) -> BtStatus2658 fn set_hid_report(
2659 &mut self,
2660 addr: String,
2661 report_type: BthhReportType,
2662 report: String,
2663 ) -> BtStatus {
2664 if let Some(mut addr) = RawAddress::from_string(addr) {
2665 let mut rb = report.clone().into_bytes();
2666 self.hh.as_mut().unwrap().set_report(&mut addr, report_type, rb.as_mut_slice())
2667 } else {
2668 BtStatus::InvalidParam
2669 }
2670 }
2671
send_hid_data(&mut self, addr: String, data: String) -> BtStatus2672 fn send_hid_data(&mut self, addr: String, data: String) -> BtStatus {
2673 if let Some(mut addr) = RawAddress::from_string(addr) {
2674 let mut rb = data.clone().into_bytes();
2675 self.hh.as_mut().unwrap().send_data(&mut addr, rb.as_mut_slice())
2676 } else {
2677 BtStatus::InvalidParam
2678 }
2679 }
2680 }
2681