1 //! Anything related to the adapter API (IBluetooth).
2
3 use bt_topshim::btif::{
4 BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BluetoothProperty, BtAclState,
5 BtAddrType, BtBondState, BtConnectionDirection, BtConnectionState, BtDeviceType, BtDiscMode,
6 BtDiscoveryState, BtHciErrorCode, BtPinCode, BtPropertyType, BtScanMode, BtSspVariant, BtState,
7 BtStatus, BtThreadEvent, BtTransport, BtVendorProductInfo, DisplayAddress, DisplayUuid,
8 RawAddress, ToggleableProfile, Uuid, INVALID_RSSI,
9 };
10 use bt_topshim::profiles::gatt::GattStatus;
11 use bt_topshim::profiles::hfp::EscoCodingFormat;
12 use bt_topshim::profiles::hid_host::{
13 BthhConnectionState, BthhHidInfo, BthhProtocolMode, BthhReportType, BthhStatus, HHCallbacks,
14 HHCallbacksDispatcher, HidHost,
15 };
16 use bt_topshim::profiles::sdp::{BtSdpRecord, Sdp, SdpCallbacks, SdpCallbacksDispatcher};
17 use bt_topshim::profiles::ProfileConnectionState;
18 use bt_topshim::{controller, metrics, sysprop, topstack};
19
20 use bt_utils::array_utils;
21 use bt_utils::cod::{is_cod_hid_combo, is_cod_hid_keyboard};
22 use bt_utils::uhid::UHid;
23 use btif_macros::{btif_callback, btif_callbacks_dispatcher, log_cb_args};
24
25 use log::{debug, error, warn};
26 use num_derive::{FromPrimitive, ToPrimitive};
27 use num_traits::cast::ToPrimitive;
28 use num_traits::pow;
29 use std::collections::{HashMap, HashSet};
30 use std::convert::TryInto;
31 use std::fs::{File, OpenOptions};
32 use std::hash::Hash;
33 use std::io::Write;
34 use std::os::fd::AsRawFd;
35 use std::process;
36 use std::sync::{Arc, Condvar, Mutex};
37 use std::time::{Duration, Instant};
38 use tokio::sync::mpsc::Sender;
39 use tokio::task::JoinHandle;
40 use tokio::time;
41
42 use crate::bluetooth_admin::BluetoothAdminPolicyHelper;
43 use crate::bluetooth_gatt::{
44 BluetoothGatt, GattActions, IBluetoothGatt, IScannerCallback, ScanResult,
45 };
46 use crate::bluetooth_media::{BluetoothMedia, MediaActions, LEA_UNKNOWN_GROUP_ID};
47 use crate::callbacks::Callbacks;
48 use crate::socket_manager::SocketActions;
49 use crate::uuid::{Profile, UuidHelper};
50 use crate::{make_message_dispatcher, APIMessage, BluetoothAPI, Message, RPCProxy, SuspendMode};
51
52 pub(crate) const FLOSS_VER: u16 = 0x0001;
53 const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800;
54 const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5;
55
56 /// Devices that were last seen longer than this duration are considered stale
57 /// if they haven't already bonded or connected. Once this duration expires, the
58 /// clear event should be sent to clients.
59 const FOUND_DEVICE_FRESHNESS: Duration = Duration::from_secs(30);
60
61 /// This is the value returned from Bluetooth Interface calls.
62 // TODO(241930383): Add enum to topshim
63 const BTM_SUCCESS: i32 = 0;
64
65 const PID_DIR: &str = "/var/run/bluetooth";
66
67 const DUMPSYS_LOG: &str = "/tmp/dumpsys.log";
68
69 /// Represents various roles the adapter supports.
70 #[derive(Debug, FromPrimitive, ToPrimitive)]
71 #[repr(u32)]
72 pub enum BtAdapterRole {
73 Central = 0,
74 Peripheral,
75 CentralPeripheral,
76 }
77 /// Defines the adapter API.
78 pub trait IBluetooth {
79 /// Adds a callback from a client who wishes to observe adapter events.
register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) -> u3280 fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) -> u32;
81
82 /// Removes registered callback.
unregister_callback(&mut self, callback_id: u32) -> bool83 fn unregister_callback(&mut self, callback_id: u32) -> bool;
84
85 /// Adds a callback from a client who wishes to observe connection events.
register_connection_callback( &mut self, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u3286 fn register_connection_callback(
87 &mut self,
88 callback: Box<dyn IBluetoothConnectionCallback + Send>,
89 ) -> u32;
90
91 /// Removes registered callback.
unregister_connection_callback(&mut self, callback_id: u32) -> bool92 fn unregister_connection_callback(&mut self, callback_id: u32) -> bool;
93
94 /// Inits the bluetooth interface. Should always be called before enable.
init(&mut self, hci_index: i32) -> bool95 fn init(&mut self, hci_index: i32) -> bool;
96
97 /// Enables the adapter.
98 ///
99 /// Returns true if the request is accepted.
enable(&mut self) -> bool100 fn enable(&mut self) -> bool;
101
102 /// Disables the adapter.
103 ///
104 /// Returns true if the request is accepted.
disable(&mut self) -> bool105 fn disable(&mut self) -> bool;
106
107 /// Cleans up the bluetooth interface. Should always be called after disable.
cleanup(&mut self)108 fn cleanup(&mut self);
109
110 /// Returns the Bluetooth address of the local adapter.
get_address(&self) -> RawAddress111 fn get_address(&self) -> RawAddress;
112
113 /// Gets supported UUIDs by the local adapter.
get_uuids(&self) -> Vec<Uuid>114 fn get_uuids(&self) -> Vec<Uuid>;
115
116 /// Gets the local adapter name.
get_name(&self) -> String117 fn get_name(&self) -> String;
118
119 /// Sets the local adapter name.
set_name(&self, name: String) -> bool120 fn set_name(&self, name: String) -> bool;
121
122 /// Gets the bluetooth class.
get_bluetooth_class(&self) -> u32123 fn get_bluetooth_class(&self) -> u32;
124
125 /// Sets the bluetooth class.
set_bluetooth_class(&self, cod: u32) -> bool126 fn set_bluetooth_class(&self, cod: u32) -> bool;
127
128 /// Returns whether the adapter is discoverable.
get_discoverable(&self) -> bool129 fn get_discoverable(&self) -> bool;
130
131 /// Returns the adapter discoverable timeout.
get_discoverable_timeout(&self) -> u32132 fn get_discoverable_timeout(&self) -> u32;
133
134 /// Sets discoverability. If discoverable, limits the duration with given value.
set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool135 fn set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool;
136
137 /// Returns whether multi-advertisement is supported.
138 /// A minimum number of 5 advertising instances is required for multi-advertisment support.
is_multi_advertisement_supported(&self) -> bool139 fn is_multi_advertisement_supported(&self) -> bool;
140
141 /// Returns whether LE extended advertising is supported.
is_le_extended_advertising_supported(&self) -> bool142 fn is_le_extended_advertising_supported(&self) -> bool;
143
144 /// Starts BREDR Inquiry.
start_discovery(&mut self) -> bool145 fn start_discovery(&mut self) -> bool;
146
147 /// Cancels BREDR Inquiry.
cancel_discovery(&mut self) -> bool148 fn cancel_discovery(&mut self) -> bool;
149
150 /// Checks if discovery is started.
is_discovering(&self) -> bool151 fn is_discovering(&self) -> bool;
152
153 /// Checks when discovery ends in milliseconds from now.
get_discovery_end_millis(&self) -> u64154 fn get_discovery_end_millis(&self) -> u64;
155
156 /// Initiates pairing to a remote device. Triggers connection if not already started.
create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus157 fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus;
158
159 /// Cancels any pending bond attempt on given device.
cancel_bond_process(&mut self, device: BluetoothDevice) -> bool160 fn cancel_bond_process(&mut self, device: BluetoothDevice) -> bool;
161
162 /// Removes pairing for given device.
remove_bond(&mut self, device: BluetoothDevice) -> bool163 fn remove_bond(&mut self, device: BluetoothDevice) -> bool;
164
165 /// Returns a list of known bonded devices.
get_bonded_devices(&self) -> Vec<BluetoothDevice>166 fn get_bonded_devices(&self) -> Vec<BluetoothDevice>;
167
168 /// Gets the bond state of a single device.
get_bond_state(&self, device: BluetoothDevice) -> BtBondState169 fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState;
170
171 /// Set pin on bonding device.
set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool172 fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool;
173
174 /// Set passkey on bonding device.
set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool175 fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool;
176
177 /// Confirm that a pairing should be completed on a bonding device.
set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool178 fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool;
179
180 /// Gets the name of the remote device.
get_remote_name(&self, device: BluetoothDevice) -> String181 fn get_remote_name(&self, device: BluetoothDevice) -> String;
182
183 /// Gets the type of the remote device.
get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType184 fn get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType;
185
186 /// Gets the alias of the remote device.
get_remote_alias(&self, device: BluetoothDevice) -> String187 fn get_remote_alias(&self, device: BluetoothDevice) -> String;
188
189 /// Sets the alias of the remote device.
set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String)190 fn set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String);
191
192 /// Gets the class of the remote device.
get_remote_class(&self, device: BluetoothDevice) -> u32193 fn get_remote_class(&self, device: BluetoothDevice) -> u32;
194
195 /// Gets the appearance of the remote device.
get_remote_appearance(&self, device: BluetoothDevice) -> u16196 fn get_remote_appearance(&self, device: BluetoothDevice) -> u16;
197
198 /// Gets whether the remote device is connected.
get_remote_connected(&self, device: BluetoothDevice) -> bool199 fn get_remote_connected(&self, device: BluetoothDevice) -> bool;
200
201 /// Gets whether the remote device can wake the system.
get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool202 fn get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool;
203
204 /// Gets the vendor and product information of the remote device.
get_remote_vendor_product_info(&self, device: BluetoothDevice) -> BtVendorProductInfo205 fn get_remote_vendor_product_info(&self, device: BluetoothDevice) -> BtVendorProductInfo;
206
207 /// Get the address type of the remote device.
get_remote_address_type(&self, device: BluetoothDevice) -> BtAddrType208 fn get_remote_address_type(&self, device: BluetoothDevice) -> BtAddrType;
209
210 /// Get the RSSI of the remote device.
get_remote_rssi(&self, device: BluetoothDevice) -> i8211 fn get_remote_rssi(&self, device: BluetoothDevice) -> i8;
212
213 /// Returns a list of connected devices.
get_connected_devices(&self) -> Vec<BluetoothDevice>214 fn get_connected_devices(&self) -> Vec<BluetoothDevice>;
215
216 /// Gets the connection state of a single device.
get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState217 fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState;
218
219 /// Gets the connection state of a specific profile.
get_profile_connection_state(&self, profile: Uuid) -> ProfileConnectionState220 fn get_profile_connection_state(&self, profile: Uuid) -> ProfileConnectionState;
221
222 /// Returns the cached UUIDs of a remote device.
get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid>223 fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid>;
224
225 /// Triggers SDP to get UUIDs of a remote device.
fetch_remote_uuids(&self, device: BluetoothDevice) -> bool226 fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool;
227
228 /// Triggers SDP and searches for a specific UUID on a remote device.
sdp_search(&self, device: BluetoothDevice, uuid: Uuid) -> bool229 fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid) -> bool;
230
231 /// Creates a new SDP record.
create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool232 fn create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool;
233
234 /// Removes the SDP record associated with the provided handle.
remove_sdp_record(&self, handle: i32) -> bool235 fn remove_sdp_record(&self, handle: i32) -> bool;
236
237 /// Connect all profiles supported by device and enabled on adapter.
connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus238 fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus;
239
240 /// Disconnect all profiles supported by device and enabled on adapter.
241 /// Note that it includes all custom profiles enabled by the users e.g. through SocketManager or
242 /// BluetoothGatt interfaces; The device shall be disconnected on baseband eventually.
disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool243 fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool;
244
245 /// Returns whether WBS is supported.
is_wbs_supported(&self) -> bool246 fn is_wbs_supported(&self) -> bool;
247
248 /// Returns whether SWB is supported.
is_swb_supported(&self) -> bool249 fn is_swb_supported(&self) -> bool;
250
251 /// Returns a list of all the roles that are supported.
get_supported_roles(&self) -> Vec<BtAdapterRole>252 fn get_supported_roles(&self) -> Vec<BtAdapterRole>;
253
254 /// Returns whether the coding format is supported.
is_coding_format_supported(&self, coding_format: EscoCodingFormat) -> bool255 fn is_coding_format_supported(&self, coding_format: EscoCodingFormat) -> bool;
256
257 /// Returns whether LE Audio is supported.
is_le_audio_supported(&self) -> bool258 fn is_le_audio_supported(&self) -> bool;
259
260 /// Returns whether the remote device is a dual mode audio sink device (supports both classic and
261 /// LE Audio sink roles).
is_dual_mode_audio_sink_device(&self, device: BluetoothDevice) -> bool262 fn is_dual_mode_audio_sink_device(&self, device: BluetoothDevice) -> bool;
263
264 /// Gets diagnostic output.
get_dumpsys(&self) -> String265 fn get_dumpsys(&self) -> String;
266 }
267
268 /// Adapter API for Bluetooth qualification and verification.
269 ///
270 /// This interface is provided for testing and debugging.
271 /// Clients should not use this interface for production.
272 pub trait IBluetoothQALegacy {
273 /// Returns whether the adapter is connectable.
get_connectable(&self) -> bool274 fn get_connectable(&self) -> bool;
275
276 /// Sets connectability. Returns true on success, false otherwise.
set_connectable(&mut self, mode: bool) -> bool277 fn set_connectable(&mut self, mode: bool) -> bool;
278
279 /// Returns the adapter's Bluetooth friendly name.
get_alias(&self) -> String280 fn get_alias(&self) -> String;
281
282 /// Returns the adapter's Device ID information in modalias format
283 /// used by the kernel and udev.
get_modalias(&self) -> String284 fn get_modalias(&self) -> String;
285
286 /// Gets HID report on the peer.
get_hid_report( &mut self, addr: RawAddress, report_type: BthhReportType, report_id: u8, ) -> BtStatus287 fn get_hid_report(
288 &mut self,
289 addr: RawAddress,
290 report_type: BthhReportType,
291 report_id: u8,
292 ) -> BtStatus;
293
294 /// Sets HID report to the peer.
set_hid_report( &mut self, addr: RawAddress, report_type: BthhReportType, report: String, ) -> BtStatus295 fn set_hid_report(
296 &mut self,
297 addr: RawAddress,
298 report_type: BthhReportType,
299 report: String,
300 ) -> BtStatus;
301
302 /// Snd HID data report to the peer.
send_hid_data(&mut self, addr: RawAddress, data: String) -> BtStatus303 fn send_hid_data(&mut self, addr: RawAddress, data: String) -> BtStatus;
304 }
305
306 /// Action events from lib.rs
307 pub enum AdapterActions {
308 /// Check whether the current set of found devices are still fresh.
309 DeviceFreshnessCheck,
310
311 /// Connect to all supported profiles on target device.
312 ConnectAllProfiles(BluetoothDevice),
313
314 /// Connect to the specified profiles on target device.
315 ConnectProfiles(Vec<Uuid>, BluetoothDevice),
316
317 /// Scanner for BLE discovery is registered with given status and scanner id.
318 BleDiscoveryScannerRegistered(Uuid, u8, GattStatus),
319
320 /// Scanner for BLE discovery is reporting a result.
321 BleDiscoveryScannerResult(ScanResult),
322
323 /// Reset the discoverable mode to BtDiscMode::NonDiscoverable.
324 ResetDiscoverable,
325
326 /// Create bond to the device stored in |pending_create_bond|.
327 CreateBond,
328 }
329
330 /// Serializable device used in various apis.
331 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
332 pub struct BluetoothDevice {
333 pub address: RawAddress,
334 pub name: String,
335 }
336
337 impl BluetoothDevice {
new(address: RawAddress, name: String) -> Self338 pub(crate) fn new(address: RawAddress, name: String) -> Self {
339 Self { address, name }
340 }
341
from_properties(in_properties: &Vec<BluetoothProperty>) -> Self342 pub(crate) fn from_properties(in_properties: &Vec<BluetoothProperty>) -> Self {
343 let mut address = RawAddress::default();
344 let mut name = String::from("");
345
346 for prop in in_properties {
347 match &prop {
348 BluetoothProperty::BdAddr(bdaddr) => {
349 address = *bdaddr;
350 }
351 BluetoothProperty::BdName(bdname) => {
352 name = bdname.clone();
353 }
354 _ => {}
355 }
356 }
357
358 Self { address, name }
359 }
360 }
361
362 /// Internal data structure that keeps a map of cached properties for a remote device.
363 struct BluetoothDeviceContext {
364 /// Transport type reported by ACL connection (if completed).
365 pub acl_reported_transport: BtTransport,
366
367 pub bredr_acl_state: BtAclState,
368 pub ble_acl_state: BtAclState,
369 pub bond_state: BtBondState,
370 pub info: BluetoothDevice,
371 pub last_seen: Instant,
372 pub properties: HashMap<BtPropertyType, BluetoothProperty>,
373 pub is_initiated_hh_connection: bool,
374
375 /// If user wants to connect to all profiles, when new profiles are discovered we will also try
376 /// to connect them.
377 pub connect_to_new_profiles: bool,
378 }
379
380 impl BluetoothDeviceContext {
new( bond_state: BtBondState, bredr_acl_state: BtAclState, ble_acl_state: BtAclState, info: BluetoothDevice, last_seen: Instant, properties: Vec<BluetoothProperty>, ) -> BluetoothDeviceContext381 pub(crate) fn new(
382 bond_state: BtBondState,
383 bredr_acl_state: BtAclState,
384 ble_acl_state: BtAclState,
385 info: BluetoothDevice,
386 last_seen: Instant,
387 properties: Vec<BluetoothProperty>,
388 ) -> BluetoothDeviceContext {
389 let mut device = BluetoothDeviceContext {
390 acl_reported_transport: BtTransport::Auto,
391 bredr_acl_state,
392 ble_acl_state,
393 bond_state,
394 info,
395 last_seen,
396 properties: HashMap::new(),
397 is_initiated_hh_connection: false,
398 connect_to_new_profiles: false,
399 };
400 device.update_properties(&properties);
401 device
402 }
403
update_properties(&mut self, in_properties: &Vec<BluetoothProperty>)404 pub(crate) fn update_properties(&mut self, in_properties: &Vec<BluetoothProperty>) {
405 for prop in in_properties {
406 // Handle merging of certain properties.
407 match &prop {
408 BluetoothProperty::BdAddr(bdaddr) => {
409 self.info.address = *bdaddr;
410 self.properties.insert(BtPropertyType::BdAddr, prop.clone());
411 }
412 BluetoothProperty::BdName(bdname) => {
413 if !bdname.is_empty() {
414 self.info.name = bdname.clone();
415 self.properties.insert(BtPropertyType::BdName, prop.clone());
416 }
417 }
418 BluetoothProperty::Uuids(new_uuids) => {
419 // Merge the new and the old (if exist) UUIDs.
420 self.properties
421 .entry(BtPropertyType::Uuids)
422 .and_modify(|old_prop| {
423 if let BluetoothProperty::Uuids(old_uuids) = old_prop {
424 for uuid in new_uuids {
425 if !old_uuids.contains(uuid) {
426 old_uuids.push(*uuid);
427 }
428 }
429 }
430 })
431 .or_insert(prop.clone());
432 }
433 _ => {
434 self.properties.insert(prop.get_type(), prop.clone());
435 }
436 }
437 }
438 }
439
440 /// Mark this device as seen.
seen(&mut self)441 pub(crate) fn seen(&mut self) {
442 self.last_seen = Instant::now();
443 }
444
get_default_transport(&self) -> BtTransport445 fn get_default_transport(&self) -> BtTransport {
446 self.properties.get(&BtPropertyType::TypeOfDevice).map_or(BtTransport::Auto, |prop| {
447 match prop {
448 BluetoothProperty::TypeOfDevice(t) => match *t {
449 BtDeviceType::Bredr => BtTransport::Bredr,
450 BtDeviceType::Ble => BtTransport::Le,
451 _ => BtTransport::Auto,
452 },
453 _ => BtTransport::Auto,
454 }
455 })
456 }
457
458 /// Check if it is connected in at least one transport.
is_connected(&self) -> bool459 fn is_connected(&self) -> bool {
460 self.bredr_acl_state == BtAclState::Connected || self.ble_acl_state == BtAclState::Connected
461 }
462
463 /// Set ACL state given transport. Return true if state changed.
set_transport_state(&mut self, transport: &BtTransport, state: &BtAclState) -> bool464 fn set_transport_state(&mut self, transport: &BtTransport, state: &BtAclState) -> bool {
465 match (transport, self.get_default_transport()) {
466 (t, d)
467 if *t == BtTransport::Bredr
468 || (*t == BtTransport::Auto && d == BtTransport::Bredr) =>
469 {
470 if self.bredr_acl_state == *state {
471 return false;
472 }
473 self.bredr_acl_state = state.clone();
474 }
475 (t, d)
476 if *t == BtTransport::Le || (*t == BtTransport::Auto && d == BtTransport::Le) =>
477 {
478 if self.ble_acl_state == *state {
479 return false;
480 }
481 self.ble_acl_state = state.clone();
482 }
483 // both link transport and the default transport are Auto.
484 _ => {
485 warn!("Unable to decide the transport! Set current connection states bredr({:?}), ble({:?}) to {:?}", self.bredr_acl_state, self.ble_acl_state, *state);
486 if self.bredr_acl_state == *state && self.ble_acl_state == *state {
487 return false;
488 }
489 // There is no way for us to know which transport the link is referring to in this case.
490 self.ble_acl_state = state.clone();
491 self.bredr_acl_state = state.clone();
492 return true;
493 }
494 };
495 true
496 }
497 }
498
499 /// Structure to track all the signals for SIGTERM.
500 pub struct SigData {
501 pub enabled: Mutex<bool>,
502 pub enabled_notify: Condvar,
503
504 pub thread_attached: Mutex<bool>,
505 pub thread_notify: Condvar,
506
507 pub api_enabled: Mutex<bool>,
508 pub api_notify: Condvar,
509 }
510
511 /// The interface for adapter callbacks registered through `IBluetooth::register_callback`.
512 pub trait IBluetoothCallback: RPCProxy {
513 /// When any adapter property changes.
on_adapter_property_changed(&mut self, prop: BtPropertyType)514 fn on_adapter_property_changed(&mut self, prop: BtPropertyType);
515
516 /// When any device properties change.
on_device_properties_changed( &mut self, remote_device: BluetoothDevice, props: Vec<BtPropertyType>, )517 fn on_device_properties_changed(
518 &mut self,
519 remote_device: BluetoothDevice,
520 props: Vec<BtPropertyType>,
521 );
522
523 /// When any of the adapter local address is changed.
on_address_changed(&mut self, addr: RawAddress)524 fn on_address_changed(&mut self, addr: RawAddress);
525
526 /// When the adapter name is changed.
on_name_changed(&mut self, name: String)527 fn on_name_changed(&mut self, name: String);
528
529 /// When the adapter's discoverable mode is changed.
on_discoverable_changed(&mut self, discoverable: bool)530 fn on_discoverable_changed(&mut self, discoverable: bool);
531
532 /// When a device is found via discovery.
on_device_found(&mut self, remote_device: BluetoothDevice)533 fn on_device_found(&mut self, remote_device: BluetoothDevice);
534
535 /// When a device is cleared from discovered devices cache.
on_device_cleared(&mut self, remote_device: BluetoothDevice)536 fn on_device_cleared(&mut self, remote_device: BluetoothDevice);
537
538 /// When a device is missing keys.
on_device_key_missing(&mut self, remote_device: BluetoothDevice)539 fn on_device_key_missing(&mut self, remote_device: BluetoothDevice);
540
541 /// When the discovery state is changed.
on_discovering_changed(&mut self, discovering: bool)542 fn on_discovering_changed(&mut self, discovering: bool);
543
544 /// 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, )545 fn on_ssp_request(
546 &mut self,
547 remote_device: BluetoothDevice,
548 cod: u32,
549 variant: BtSspVariant,
550 passkey: u32,
551 );
552
553 /// 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)554 fn on_pin_request(&mut self, remote_device: BluetoothDevice, cod: u32, min_16_digit: bool);
555
556 /// When there is a auto-gen pin to display the event to client.
on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String)557 fn on_pin_display(&mut self, remote_device: BluetoothDevice, pincode: String);
558
559 /// When a bonding attempt has completed.
on_bond_state_changed(&mut self, status: u32, device_address: RawAddress, state: u32)560 fn on_bond_state_changed(&mut self, status: u32, device_address: RawAddress, state: u32);
561
562 /// When an SDP search has completed.
on_sdp_search_complete( &mut self, remote_device: BluetoothDevice, searched_uuid: Uuid, sdp_records: Vec<BtSdpRecord>, )563 fn on_sdp_search_complete(
564 &mut self,
565 remote_device: BluetoothDevice,
566 searched_uuid: Uuid,
567 sdp_records: Vec<BtSdpRecord>,
568 );
569
570 /// When an SDP record has been successfully created.
on_sdp_record_created(&mut self, record: BtSdpRecord, handle: i32)571 fn on_sdp_record_created(&mut self, record: BtSdpRecord, handle: i32);
572 }
573
574 pub trait IBluetoothConnectionCallback: RPCProxy {
575 /// Notification sent when a remote device completes HCI connection.
on_device_connected(&mut self, remote_device: BluetoothDevice)576 fn on_device_connected(&mut self, remote_device: BluetoothDevice);
577
578 /// Notification sent when a remote device completes HCI disconnection.
on_device_disconnected(&mut self, remote_device: BluetoothDevice)579 fn on_device_disconnected(&mut self, remote_device: BluetoothDevice);
580
581 /// Notification sent when a remote device fails to complete HCI connection.
on_device_connection_failed(&mut self, remote_device: BluetoothDevice, status: BtStatus)582 fn on_device_connection_failed(&mut self, remote_device: BluetoothDevice, status: BtStatus);
583 }
584
585 /// Implementation of the adapter API.
586 pub struct Bluetooth {
587 intf: Arc<Mutex<BluetoothInterface>>,
588
589 virt_index: i32,
590 hci_index: i32,
591 remote_devices: HashMap<RawAddress, BluetoothDeviceContext>,
592 ble_scanner_id: Option<u8>,
593 ble_scanner_uuid: Option<Uuid>,
594 bluetooth_gatt: Option<Arc<Mutex<Box<BluetoothGatt>>>>,
595 bluetooth_media: Option<Arc<Mutex<Box<BluetoothMedia>>>>,
596 callbacks: Callbacks<dyn IBluetoothCallback + Send>,
597 connection_callbacks: Callbacks<dyn IBluetoothConnectionCallback + Send>,
598 discovering_started: Instant,
599 hh: Option<HidHost>,
600 is_connectable: bool,
601 is_socket_listening: bool,
602 discoverable_mode: BtDiscMode,
603 discoverable_duration: u32,
604 // This refers to the suspend mode of the functionality related to Classic scan mode,
605 // i.e., page scan and inquiry scan; Also known as connectable and discoverable.
606 scan_suspend_mode: SuspendMode,
607 is_discovering: bool,
608 is_discovering_before_suspend: bool,
609 is_discovery_paused: bool,
610 discovery_suspend_mode: SuspendMode,
611 local_address: Option<RawAddress>,
612 pending_discovery: bool,
613 properties: HashMap<BtPropertyType, BluetoothProperty>,
614 profiles_ready: bool,
615 freshness_check: Option<JoinHandle<()>>,
616 sdp: Option<Sdp>,
617 state: BtState,
618 disabling: bool,
619 tx: Sender<Message>,
620 api_tx: Sender<APIMessage>,
621 // Internal API members
622 discoverable_timeout: Option<JoinHandle<()>>,
623 cancelling_devices: HashSet<RawAddress>,
624 pending_create_bond: Option<(BluetoothDevice, BtTransport)>,
625 active_pairing_address: Option<RawAddress>,
626 le_supported_states: u64,
627 le_local_supported_features: u64,
628
629 /// Used to notify signal handler that we have turned off the stack.
630 sig_notifier: Arc<SigData>,
631
632 /// Virtual uhid device created to keep bluetooth as a wakeup source.
633 uhid_wakeup_source: UHid,
634 }
635
636 impl Bluetooth {
637 /// Constructs the IBluetooth implementation.
new( virt_index: i32, hci_index: i32, tx: Sender<Message>, api_tx: Sender<APIMessage>, sig_notifier: Arc<SigData>, intf: Arc<Mutex<BluetoothInterface>>, ) -> Bluetooth638 pub fn new(
639 virt_index: i32,
640 hci_index: i32,
641 tx: Sender<Message>,
642 api_tx: Sender<APIMessage>,
643 sig_notifier: Arc<SigData>,
644 intf: Arc<Mutex<BluetoothInterface>>,
645 ) -> Bluetooth {
646 Bluetooth {
647 virt_index,
648 hci_index,
649 remote_devices: HashMap::new(),
650 callbacks: Callbacks::new(tx.clone(), Message::AdapterCallbackDisconnected),
651 connection_callbacks: Callbacks::new(
652 tx.clone(),
653 Message::ConnectionCallbackDisconnected,
654 ),
655 hh: None,
656 ble_scanner_id: None,
657 ble_scanner_uuid: None,
658 bluetooth_gatt: None,
659 bluetooth_media: None,
660 discovering_started: Instant::now(),
661 intf,
662 is_connectable: false,
663 is_socket_listening: false,
664 discoverable_mode: BtDiscMode::NonDiscoverable,
665 discoverable_duration: 0,
666 scan_suspend_mode: SuspendMode::Normal,
667 is_discovering: false,
668 is_discovering_before_suspend: false,
669 is_discovery_paused: false,
670 discovery_suspend_mode: SuspendMode::Normal,
671 local_address: None,
672 pending_discovery: false,
673 properties: HashMap::new(),
674 profiles_ready: false,
675 freshness_check: None,
676 sdp: None,
677 state: BtState::Off,
678 disabling: false,
679 tx,
680 api_tx,
681 // Internal API members
682 discoverable_timeout: None,
683 cancelling_devices: HashSet::new(),
684 pending_create_bond: None,
685 active_pairing_address: None,
686 le_supported_states: 0u64,
687 le_local_supported_features: 0u64,
688 sig_notifier,
689 uhid_wakeup_source: UHid::new(),
690 }
691 }
692
set_media(&mut self, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>)693 pub(crate) fn set_media(&mut self, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>) {
694 self.bluetooth_media = Some(bluetooth_media);
695 }
696
set_gatt_and_init_scanner( &mut self, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, )697 pub(crate) fn set_gatt_and_init_scanner(
698 &mut self,
699 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
700 ) {
701 self.bluetooth_gatt = Some(bluetooth_gatt.clone());
702
703 // Initialize the BLE scanner for discovery.
704 let callback_id = bluetooth_gatt
705 .lock()
706 .unwrap()
707 .register_scanner_callback(Box::new(BleDiscoveryCallbacks::new(self.tx.clone())));
708 self.ble_scanner_uuid = Some(bluetooth_gatt.lock().unwrap().register_scanner(callback_id));
709 }
710
update_connectable_mode(&mut self)711 fn update_connectable_mode(&mut self) {
712 // Don't bother if we are disabling. See b/361510982
713 if self.disabling {
714 return;
715 }
716 if self.get_scan_suspend_mode() != SuspendMode::Normal {
717 return;
718 }
719 // Set connectable if
720 // - there is bredr socket listening, or
721 // - there is a classic device bonded and not connected
722 self.set_connectable_internal(
723 self.is_socket_listening
724 || self.remote_devices.values().any(|ctx| {
725 ctx.bond_state == BtBondState::Bonded
726 && ctx.bredr_acl_state == BtAclState::Disconnected
727 && ctx
728 .properties
729 .get(&BtPropertyType::TypeOfDevice)
730 .and_then(|prop| match prop {
731 BluetoothProperty::TypeOfDevice(transport) => {
732 Some(*transport != BtDeviceType::Ble)
733 }
734 _ => None,
735 })
736 .unwrap_or(false)
737 }),
738 );
739 }
740
set_socket_listening(&mut self, is_listening: bool)741 pub(crate) fn set_socket_listening(&mut self, is_listening: bool) {
742 if self.is_socket_listening == is_listening {
743 return;
744 }
745 self.is_socket_listening = is_listening;
746 self.update_connectable_mode();
747 }
748
get_hci_index(&self) -> u16749 pub(crate) fn get_hci_index(&self) -> u16 {
750 self.hci_index as u16
751 }
752
handle_admin_policy_changed( &mut self, admin_policy_helper: BluetoothAdminPolicyHelper, )753 pub(crate) fn handle_admin_policy_changed(
754 &mut self,
755 admin_policy_helper: BluetoothAdminPolicyHelper,
756 ) {
757 match (
758 admin_policy_helper.is_profile_allowed(&Profile::Hid),
759 self.hh.as_ref().unwrap().is_hidp_activated,
760 ) {
761 (true, false) => self.hh.as_mut().unwrap().activate_hidp(true),
762 (false, true) => self.hh.as_mut().unwrap().activate_hidp(false),
763 _ => {}
764 }
765
766 match (
767 admin_policy_helper.is_profile_allowed(&Profile::Hogp),
768 self.hh.as_ref().unwrap().is_hogp_activated,
769 ) {
770 (true, false) => self.hh.as_mut().unwrap().activate_hogp(true),
771 (false, true) => self.hh.as_mut().unwrap().activate_hogp(false),
772 _ => {}
773 }
774
775 if self.hh.as_mut().unwrap().configure_enabled_profiles() {
776 self.hh.as_mut().unwrap().disable();
777 let tx = self.tx.clone();
778
779 tokio::spawn(async move {
780 // Wait 100 milliseconds to prevent race condition caused by quick disable then
781 // enable.
782 // TODO: (b/272191117): don't enable until we're sure disable is done.
783 tokio::time::sleep(Duration::from_millis(100)).await;
784 let _ = tx.send(Message::HidHostEnable).await;
785 });
786 }
787 }
788
enable_hidhost(&mut self)789 pub fn enable_hidhost(&mut self) {
790 self.hh.as_mut().unwrap().enable();
791 }
792
init_profiles(&mut self)793 pub fn init_profiles(&mut self) {
794 self.sdp = Some(Sdp::new(&self.intf.lock().unwrap()));
795 self.sdp.as_mut().unwrap().initialize(SdpCallbacksDispatcher {
796 dispatch: make_message_dispatcher(self.tx.clone(), Message::Sdp),
797 });
798
799 self.hh = Some(HidHost::new(&self.intf.lock().unwrap()));
800 self.hh.as_mut().unwrap().initialize(HHCallbacksDispatcher {
801 dispatch: make_message_dispatcher(self.tx.clone(), Message::HidHost),
802 });
803
804 // Mark profiles as ready
805 self.profiles_ready = true;
806 }
807
update_local_address(&mut self, addr: RawAddress)808 fn update_local_address(&mut self, addr: RawAddress) {
809 self.local_address = Some(addr);
810
811 self.callbacks.for_all_callbacks(|callback| {
812 callback.on_address_changed(addr);
813 });
814 }
815
adapter_callback_disconnected(&mut self, id: u32)816 pub(crate) fn adapter_callback_disconnected(&mut self, id: u32) {
817 self.callbacks.remove_callback(id);
818 }
819
connection_callback_disconnected(&mut self, id: u32)820 pub(crate) fn connection_callback_disconnected(&mut self, id: u32) {
821 self.connection_callbacks.remove_callback(id);
822 }
823
shutdown_adapter(&mut self, abort: bool) -> bool824 pub fn shutdown_adapter(&mut self, abort: bool) -> bool {
825 self.disabling = true;
826
827 if !abort {
828 if !self.set_discoverable(BtDiscMode::NonDiscoverable, 0) {
829 warn!("set_discoverable failed on disabling");
830 }
831 if !self.set_connectable_internal(false) {
832 warn!("set_connectable_internal failed on disabling");
833 }
834 }
835
836 self.intf.lock().unwrap().disable() == 0
837 }
838
get_remote_device_property( &self, device: &BluetoothDevice, property_type: &BtPropertyType, ) -> Option<BluetoothProperty>839 fn get_remote_device_property(
840 &self,
841 device: &BluetoothDevice,
842 property_type: &BtPropertyType,
843 ) -> Option<BluetoothProperty> {
844 self.remote_devices
845 .get(&device.address)
846 .and_then(|d| d.properties.get(property_type))
847 .cloned()
848 }
849
set_remote_device_property( &mut self, device: &BluetoothDevice, property_type: BtPropertyType, property: BluetoothProperty, ) -> Result<(), ()>850 fn set_remote_device_property(
851 &mut self,
852 device: &BluetoothDevice,
853 property_type: BtPropertyType,
854 property: BluetoothProperty,
855 ) -> Result<(), ()> {
856 let Some(remote_device) = self.remote_devices.get_mut(&device.address) else {
857 return Err(());
858 };
859
860 // TODO: Determine why a callback isn't invoked to do this.
861 remote_device.properties.insert(property_type, property.clone());
862 self.intf.lock().unwrap().set_remote_device_property(&mut device.address.clone(), property);
863 Ok(())
864 }
865
866 /// Returns whether the adapter is connectable.
get_connectable_internal(&self) -> bool867 pub(crate) fn get_connectable_internal(&self) -> bool {
868 self.discoverable_mode != BtDiscMode::NonDiscoverable || self.is_connectable
869 }
870
871 /// Sets the adapter's connectable mode for classic connections.
set_connectable_internal(&mut self, mode: bool) -> bool872 pub(crate) fn set_connectable_internal(&mut self, mode: bool) -> bool {
873 if self.get_scan_suspend_mode() != SuspendMode::Normal {
874 // We will always trigger an update on resume so no need so store the mode change.
875 return false;
876 }
877 if self.is_connectable == mode {
878 return true;
879 }
880 if self.discoverable_mode != BtDiscMode::NonDiscoverable {
881 // Discoverable always implies connectable. Don't affect the discoverable mode for now
882 // and the connectable mode would be restored when discoverable becomes off.
883 self.is_connectable = mode;
884 return true;
885 }
886 self.intf.lock().unwrap().set_scan_mode(if mode {
887 BtScanMode::Connectable
888 } else {
889 BtScanMode::None_
890 });
891 self.is_connectable = mode;
892 true
893 }
894
895 /// Returns adapter's discoverable mode.
get_discoverable_mode_internal(&self) -> BtDiscMode896 pub(crate) fn get_discoverable_mode_internal(&self) -> BtDiscMode {
897 self.discoverable_mode.clone()
898 }
899
900 /// Set the suspend mode for scan mode (connectable/discoverable mode).
set_scan_suspend_mode(&mut self, suspend_mode: SuspendMode)901 pub(crate) fn set_scan_suspend_mode(&mut self, suspend_mode: SuspendMode) {
902 if suspend_mode != self.scan_suspend_mode {
903 self.scan_suspend_mode = suspend_mode;
904 }
905 }
906
907 /// Gets current suspend mode for scan mode (connectable/discoverable mode).
get_scan_suspend_mode(&self) -> SuspendMode908 pub(crate) fn get_scan_suspend_mode(&self) -> SuspendMode {
909 self.scan_suspend_mode.clone()
910 }
911
912 /// Enters the suspend mode for scan mode (connectable/discoverable mode).
scan_mode_enter_suspend(&mut self) -> BtStatus913 pub(crate) fn scan_mode_enter_suspend(&mut self) -> BtStatus {
914 if self.get_scan_suspend_mode() != SuspendMode::Normal {
915 return BtStatus::Busy;
916 }
917 self.set_scan_suspend_mode(SuspendMode::Suspending);
918
919 self.intf.lock().unwrap().set_scan_mode(BtScanMode::None_);
920
921 self.set_scan_suspend_mode(SuspendMode::Suspended);
922
923 BtStatus::Success
924 }
925
926 /// Exits the suspend mode for scan mode (connectable/discoverable mode).
scan_mode_exit_suspend(&mut self) -> BtStatus927 pub(crate) fn scan_mode_exit_suspend(&mut self) -> BtStatus {
928 if self.get_scan_suspend_mode() != SuspendMode::Suspended {
929 return BtStatus::Busy;
930 }
931 self.set_scan_suspend_mode(SuspendMode::Resuming);
932
933 let mode = match self.discoverable_mode {
934 BtDiscMode::LimitedDiscoverable => BtScanMode::ConnectableLimitedDiscoverable,
935 BtDiscMode::GeneralDiscoverable => BtScanMode::ConnectableDiscoverable,
936 BtDiscMode::NonDiscoverable => match self.is_connectable {
937 true => BtScanMode::Connectable,
938 false => BtScanMode::None_,
939 },
940 };
941 self.intf.lock().unwrap().set_scan_mode(mode);
942
943 self.set_scan_suspend_mode(SuspendMode::Normal);
944
945 // Update is only available after SuspendMode::Normal
946 self.update_connectable_mode();
947
948 BtStatus::Success
949 }
950
951 /// Returns adapter's alias.
get_alias_internal(&self) -> String952 pub(crate) fn get_alias_internal(&self) -> String {
953 let name = self.get_name();
954 if !name.is_empty() {
955 return name;
956 }
957
958 // If the adapter name is empty, generate one based on local BDADDR
959 // so that test programs can have a friendly name for the adapter.
960 match self.local_address {
961 None => "floss_0000".to_string(),
962 Some(addr) => format!("floss_{:02X}{:02X}", addr.address[4], addr.address[5]),
963 }
964 }
965
966 // TODO(b/328675014): Add BtAddrType and BtTransport parameters
get_hid_report_internal( &mut self, mut addr: RawAddress, report_type: BthhReportType, report_id: u8, ) -> BtStatus967 pub(crate) fn get_hid_report_internal(
968 &mut self,
969 mut addr: RawAddress,
970 report_type: BthhReportType,
971 report_id: u8,
972 ) -> BtStatus {
973 self.hh.as_mut().unwrap().get_report(
974 &mut addr,
975 BtAddrType::Public,
976 BtTransport::Auto,
977 report_type,
978 report_id,
979 128,
980 )
981 }
982
983 // TODO(b/328675014): Add BtAddrType and BtTransport parameters
set_hid_report_internal( &mut self, mut addr: RawAddress, report_type: BthhReportType, report: String, ) -> BtStatus984 pub(crate) fn set_hid_report_internal(
985 &mut self,
986 mut addr: RawAddress,
987 report_type: BthhReportType,
988 report: String,
989 ) -> BtStatus {
990 let mut rb = report.clone().into_bytes();
991 self.hh.as_mut().unwrap().set_report(
992 &mut addr,
993 BtAddrType::Public,
994 BtTransport::Auto,
995 report_type,
996 rb.as_mut_slice(),
997 )
998 }
999
1000 // TODO(b/328675014): Add BtAddrType and BtTransport parameters
send_hid_data_internal( &mut self, mut addr: RawAddress, data: String, ) -> BtStatus1001 pub(crate) fn send_hid_data_internal(
1002 &mut self,
1003 mut addr: RawAddress,
1004 data: String,
1005 ) -> BtStatus {
1006 let mut rb = data.clone().into_bytes();
1007 self.hh.as_mut().unwrap().send_data(
1008 &mut addr,
1009 BtAddrType::Public,
1010 BtTransport::Auto,
1011 rb.as_mut_slice(),
1012 )
1013 }
1014
1015 // TODO(b/328675014): Add BtAddrType and BtTransport parameters
send_hid_virtual_unplug_internal(&mut self, mut addr: RawAddress) -> BtStatus1016 pub(crate) fn send_hid_virtual_unplug_internal(&mut self, mut addr: RawAddress) -> BtStatus {
1017 self.hh.as_mut().unwrap().virtual_unplug(&mut addr, BtAddrType::Public, BtTransport::Auto)
1018 }
1019
1020 /// Returns all bonded and connected devices.
get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice>1021 pub(crate) fn get_bonded_and_connected_devices(&mut self) -> Vec<BluetoothDevice> {
1022 self.remote_devices
1023 .values()
1024 .filter(|v| v.is_connected() && v.bond_state == BtBondState::Bonded)
1025 .map(|v| v.info.clone())
1026 .collect()
1027 }
1028
1029 /// Returns all devices with UUIDs, while None means there's not yet an UUID property change.
get_all_devices_and_uuids(&self) -> Vec<(BluetoothDevice, Option<Vec<Uuid>>)>1030 pub(crate) fn get_all_devices_and_uuids(&self) -> Vec<(BluetoothDevice, Option<Vec<Uuid>>)> {
1031 self.remote_devices
1032 .values()
1033 .map(|d| {
1034 let uuids = d.properties.get(&BtPropertyType::Uuids).and_then(|prop| match prop {
1035 BluetoothProperty::Uuids(uuids) => Some(uuids.clone()),
1036 _ => None,
1037 });
1038 (d.info.clone(), uuids)
1039 })
1040 .collect()
1041 }
1042
1043 /// Gets the bond state of a single device with its address.
get_bond_state_by_addr(&self, addr: &RawAddress) -> BtBondState1044 pub fn get_bond_state_by_addr(&self, addr: &RawAddress) -> BtBondState {
1045 self.remote_devices.get(addr).map_or(BtBondState::NotBonded, |d| d.bond_state.clone())
1046 }
1047
1048 /// Gets whether a single device is connected with its address.
get_acl_state_by_addr(&self, addr: &RawAddress) -> bool1049 fn get_acl_state_by_addr(&self, addr: &RawAddress) -> bool {
1050 self.remote_devices.get(addr).map_or(false, |d| d.is_connected())
1051 }
1052
1053 /// Check whether remote devices are still fresh. If they're outside the
1054 /// freshness window, send a notification to clear the device from clients.
trigger_freshness_check(&mut self)1055 fn trigger_freshness_check(&mut self) {
1056 // A remote device is considered fresh if:
1057 // * It was last seen less than |FOUND_DEVICE_FRESHNESS| ago.
1058 // * It is bonded / bonding (i.e., not NotBonded)
1059 // * It is currently connected.
1060 fn is_fresh(d: &BluetoothDeviceContext, now: &Instant) -> bool {
1061 let fresh_at = d.last_seen + FOUND_DEVICE_FRESHNESS;
1062 now < &fresh_at || d.is_connected() || d.bond_state != BtBondState::NotBonded
1063 }
1064
1065 let now = Instant::now();
1066 let stale_devices: Vec<BluetoothDevice> = self
1067 .remote_devices
1068 .values()
1069 .filter(|d| !is_fresh(d, &now))
1070 .map(|d| d.info.clone())
1071 .collect();
1072
1073 // Retain only devices that are fresh.
1074 self.remote_devices.retain(|_, d| is_fresh(d, &now));
1075
1076 for d in stale_devices {
1077 self.callbacks.for_all_callbacks(|callback| {
1078 callback.on_device_cleared(d.clone());
1079 });
1080 }
1081 }
1082
send_metrics_remote_device_info(device: &BluetoothDeviceContext)1083 fn send_metrics_remote_device_info(device: &BluetoothDeviceContext) {
1084 if device.bond_state != BtBondState::Bonded && !device.is_connected() {
1085 return;
1086 }
1087
1088 let mut class_of_device = 0u32;
1089 let mut device_type = BtDeviceType::Unknown;
1090 let mut appearance = 0u16;
1091 let mut vpi =
1092 BtVendorProductInfo { vendor_id_src: 0, vendor_id: 0, product_id: 0, version: 0 };
1093
1094 for prop in device.properties.values() {
1095 match prop {
1096 BluetoothProperty::TypeOfDevice(p) => device_type = p.clone(),
1097 BluetoothProperty::ClassOfDevice(p) => class_of_device = *p,
1098 BluetoothProperty::Appearance(p) => appearance = *p,
1099 BluetoothProperty::VendorProductInfo(p) => vpi = *p,
1100 _ => (),
1101 }
1102 }
1103
1104 metrics::device_info_report(
1105 device.info.address,
1106 device_type,
1107 class_of_device,
1108 appearance,
1109 vpi.vendor_id,
1110 vpi.vendor_id_src,
1111 vpi.product_id,
1112 vpi.version,
1113 );
1114 }
1115
1116 /// Handle adapter actions.
handle_actions(&mut self, action: AdapterActions)1117 pub(crate) fn handle_actions(&mut self, action: AdapterActions) {
1118 match action {
1119 AdapterActions::DeviceFreshnessCheck => {
1120 self.trigger_freshness_check();
1121 }
1122
1123 AdapterActions::ConnectAllProfiles(device) => {
1124 self.connect_all_enabled_profiles(device);
1125 }
1126
1127 AdapterActions::ConnectProfiles(uuids, device) => {
1128 self.connect_profiles_internal(&uuids, device);
1129 }
1130
1131 AdapterActions::BleDiscoveryScannerRegistered(uuid, scanner_id, status) => {
1132 if let Some(app_uuid) = self.ble_scanner_uuid {
1133 if app_uuid == uuid {
1134 if status == GattStatus::Success {
1135 self.ble_scanner_id = Some(scanner_id);
1136 } else {
1137 log::error!("BLE discovery scanner failed to register: {:?}", status);
1138 }
1139 }
1140 }
1141 }
1142
1143 AdapterActions::BleDiscoveryScannerResult(result) => {
1144 // Generate a vector of properties from ScanResult.
1145 let properties = {
1146 let mut props = vec![];
1147 props.push(BluetoothProperty::BdName(result.name.clone()));
1148 props.push(BluetoothProperty::BdAddr(result.address));
1149 if !result.service_uuids.is_empty() {
1150 props.push(BluetoothProperty::Uuids(result.service_uuids.clone()));
1151 }
1152 if !result.service_data.is_empty() {
1153 props.push(BluetoothProperty::Uuids(
1154 result
1155 .service_data
1156 .keys()
1157 .map(|v| Uuid::from_string(v).unwrap())
1158 .collect(),
1159 ));
1160 }
1161 props.push(BluetoothProperty::RemoteRssi(result.rssi));
1162 props.push(BluetoothProperty::RemoteAddrType((result.addr_type as u32).into()));
1163 props
1164 };
1165
1166 let device_info = BluetoothDevice::from_properties(&properties);
1167 self.check_new_property_and_potentially_connect_profiles(
1168 result.address,
1169 &properties,
1170 );
1171
1172 self.remote_devices
1173 .entry(device_info.address)
1174 .and_modify(|d| {
1175 d.update_properties(&properties);
1176 d.seen();
1177 })
1178 .or_insert(BluetoothDeviceContext::new(
1179 BtBondState::NotBonded,
1180 BtAclState::Disconnected,
1181 BtAclState::Disconnected,
1182 device_info,
1183 Instant::now(),
1184 properties,
1185 ));
1186 }
1187
1188 AdapterActions::ResetDiscoverable => {
1189 self.set_discoverable(BtDiscMode::NonDiscoverable, 0);
1190 }
1191
1192 AdapterActions::CreateBond => {
1193 if let Some((device, transport)) = self.pending_create_bond.take() {
1194 let status = self.create_bond(device, transport);
1195 if status != BtStatus::Success {
1196 error!("Failed CreateBond status={:?}", status);
1197 }
1198 }
1199 }
1200 }
1201 }
1202
1203 /// Creates a file to notify btmanagerd the adapter is enabled.
create_pid_file(&self) -> std::io::Result<()>1204 fn create_pid_file(&self) -> std::io::Result<()> {
1205 let file_name = format!("{}/bluetooth{}.pid", PID_DIR, self.virt_index);
1206 let mut f = File::create(file_name)?;
1207 f.write_all(process::id().to_string().as_bytes())?;
1208 Ok(())
1209 }
1210
1211 /// Removes the file to notify btmanagerd the adapter is disabled.
remove_pid_file(&self) -> std::io::Result<()>1212 fn remove_pid_file(&self) -> std::io::Result<()> {
1213 let file_name = format!("{}/bluetooth{}.pid", PID_DIR, self.virt_index);
1214 std::fs::remove_file(file_name)?;
1215 Ok(())
1216 }
1217
1218 /// Set the suspend mode.
set_discovery_suspend_mode(&mut self, suspend_mode: SuspendMode)1219 pub fn set_discovery_suspend_mode(&mut self, suspend_mode: SuspendMode) {
1220 if suspend_mode != self.discovery_suspend_mode {
1221 self.discovery_suspend_mode = suspend_mode;
1222 }
1223 }
1224
1225 /// Gets current suspend mode.
get_discovery_suspend_mode(&self) -> SuspendMode1226 pub fn get_discovery_suspend_mode(&self) -> SuspendMode {
1227 self.discovery_suspend_mode.clone()
1228 }
1229
1230 /// Enters the suspend mode for discovery.
discovery_enter_suspend(&mut self) -> BtStatus1231 pub fn discovery_enter_suspend(&mut self) -> BtStatus {
1232 if self.get_discovery_suspend_mode() != SuspendMode::Normal {
1233 return BtStatus::Busy;
1234 }
1235 self.set_discovery_suspend_mode(SuspendMode::Suspending);
1236
1237 if self.is_discovering {
1238 self.is_discovering_before_suspend = true;
1239 self.cancel_discovery();
1240 }
1241 self.set_discovery_suspend_mode(SuspendMode::Suspended);
1242
1243 BtStatus::Success
1244 }
1245
1246 /// Exits the suspend mode for discovery.
discovery_exit_suspend(&mut self) -> BtStatus1247 pub fn discovery_exit_suspend(&mut self) -> BtStatus {
1248 if self.get_discovery_suspend_mode() != SuspendMode::Suspended {
1249 return BtStatus::Busy;
1250 }
1251 self.set_discovery_suspend_mode(SuspendMode::Resuming);
1252
1253 if self.is_discovering_before_suspend {
1254 self.is_discovering_before_suspend = false;
1255 self.start_discovery();
1256 }
1257 self.set_discovery_suspend_mode(SuspendMode::Normal);
1258
1259 BtStatus::Success
1260 }
1261
1262 /// Temporarily stop the discovery process and mark it as paused so that clients cannot restart
1263 /// it.
pause_discovery(&mut self)1264 fn pause_discovery(&mut self) {
1265 self.cancel_discovery();
1266 self.is_discovery_paused = true;
1267 }
1268
1269 /// Remove the paused flag to allow clients to begin discovery, and if there is already a
1270 /// pending request, start discovery.
resume_discovery(&mut self)1271 fn resume_discovery(&mut self) {
1272 self.is_discovery_paused = false;
1273 if self.pending_discovery {
1274 self.pending_discovery = false;
1275 self.start_discovery();
1276 }
1277 }
1278
1279 /// Return if there are wake-allowed device in bonded status.
get_wake_allowed_device_bonded(&self) -> bool1280 fn get_wake_allowed_device_bonded(&self) -> bool {
1281 self.get_bonded_devices().into_iter().any(|d| self.get_remote_wake_allowed(d))
1282 }
1283
1284 /// Powerd recognizes bluetooth activities as valid wakeup sources if powerd keeps bluetooth in
1285 /// the monitored path. This only happens if there is at least one valid wake-allowed BT device
1286 /// connected during the suspending process. If there is no BT devices connected at any time
1287 /// during the suspending process, the wakeup count will be lost, and system goes to dark
1288 /// resume instead of full resume.
1289 /// Bluetooth stack disconnects all physical bluetooth HID devices for suspend, so a virtual
1290 /// uhid device is necessary to keep bluetooth as a valid wakeup source.
create_uhid_for_suspend_wakesource(&mut self)1291 fn create_uhid_for_suspend_wakesource(&mut self) {
1292 if !self.uhid_wakeup_source.is_empty() {
1293 return;
1294 }
1295 match self.uhid_wakeup_source.create(
1296 "VIRTUAL_SUSPEND_UHID".to_string(),
1297 self.get_address(),
1298 RawAddress::empty(),
1299 ) {
1300 Err(e) => error!("Fail to create uhid {}", e),
1301 Ok(_) => (),
1302 }
1303 }
1304
1305 /// Clear the UHID device.
clear_uhid(&mut self)1306 fn clear_uhid(&mut self) {
1307 self.uhid_wakeup_source.clear();
1308 }
1309
1310 /// Checks whether pairing is busy.
is_pairing_busy(&self) -> bool1311 pub fn is_pairing_busy(&self) -> bool {
1312 self.intf.lock().unwrap().pairing_is_busy()
1313 || self.active_pairing_address.is_some()
1314 || self.pending_create_bond.is_some()
1315 }
1316
1317 /// Checks whether a Hid/Hog connection is being established or active.
is_initiated_hh_connection(&self, device_address: &RawAddress) -> bool1318 pub fn is_initiated_hh_connection(&self, device_address: &RawAddress) -> bool {
1319 self.remote_devices
1320 .get(&device_address)
1321 .map_or(false, |context| context.is_initiated_hh_connection)
1322 }
1323
1324 /// Checks whether the list of device properties contains some UUID we should connect now
1325 /// This function also connects those UUIDs.
check_new_property_and_potentially_connect_profiles( &self, addr: RawAddress, properties: &Vec<BluetoothProperty>, )1326 fn check_new_property_and_potentially_connect_profiles(
1327 &self,
1328 addr: RawAddress,
1329 properties: &Vec<BluetoothProperty>,
1330 ) {
1331 // Return early if no need to connect new profiles
1332 if !self.remote_devices.get(&addr).map_or(false, |d| d.connect_to_new_profiles) {
1333 return;
1334 }
1335
1336 // Get the reported UUIDs, if any. Otherwise return early.
1337 let mut new_uuids: Vec<Uuid> = vec![];
1338 for prop in properties.iter() {
1339 if let BluetoothProperty::Uuids(value) = prop {
1340 new_uuids.extend(value);
1341 }
1342 }
1343 if new_uuids.is_empty() {
1344 return;
1345 }
1346
1347 // Only connect if the UUID is not seen before and it's supported
1348 let device = BluetoothDevice::new(addr, "".to_string());
1349 let current_uuids = self.get_remote_uuids(device.clone());
1350 new_uuids.retain(|uuid| !current_uuids.contains(uuid));
1351
1352 let profile_known_and_supported = new_uuids.iter().any(|uuid| {
1353 if let Some(profile) = UuidHelper::is_known_profile(uuid) {
1354 return UuidHelper::is_profile_supported(&profile);
1355 }
1356 return false;
1357 });
1358 if !profile_known_and_supported {
1359 return;
1360 }
1361
1362 log::info!("[{}]: Connecting to newly discovered profiles", DisplayAddress(&addr));
1363 let tx = self.tx.clone();
1364 tokio::spawn(async move {
1365 let _ = tx
1366 .send(Message::AdapterActions(AdapterActions::ConnectProfiles(new_uuids, device)))
1367 .await;
1368 });
1369 }
1370
1371 /// Connect these profiles of a peripheral device
connect_profiles_internal(&mut self, uuids: &Vec<Uuid>, device: BluetoothDevice)1372 fn connect_profiles_internal(&mut self, uuids: &Vec<Uuid>, device: BluetoothDevice) {
1373 let addr = device.address;
1374 if !self.get_acl_state_by_addr(&addr) {
1375 // log ACL connection attempt if it's not already connected.
1376 metrics::acl_connect_attempt(addr, BtAclState::Connected);
1377 // Pause discovery before connecting, or the ACL connection request may conflict with
1378 // the ongoing inquiry.
1379 self.pause_discovery();
1380 }
1381
1382 let mut has_supported_profile = false;
1383 let mut has_le_media_profile = false;
1384 let mut has_classic_media_profile = false;
1385
1386 for uuid in uuids.iter() {
1387 match UuidHelper::is_known_profile(uuid) {
1388 Some(p) => {
1389 if UuidHelper::is_profile_supported(&p) {
1390 match p {
1391 Profile::Hid | Profile::Hogp => {
1392 has_supported_profile = true;
1393 // TODO(b/328675014): Use BtAddrType
1394 // and BtTransport from
1395 // BluetoothDevice instead of default
1396 let status = self.hh.as_ref().unwrap().connect(
1397 &mut addr.clone(),
1398 BtAddrType::Public,
1399 BtTransport::Auto,
1400 );
1401 metrics::profile_connection_state_changed(
1402 addr,
1403 p as u32,
1404 BtStatus::Success,
1405 BthhConnectionState::Connecting as u32,
1406 );
1407
1408 if status != BtStatus::Success {
1409 metrics::profile_connection_state_changed(
1410 addr,
1411 p as u32,
1412 status,
1413 BthhConnectionState::Disconnected as u32,
1414 );
1415 }
1416 }
1417
1418 // TODO(b/317682584): implement policy to connect to LEA, VC, and CSIS
1419 Profile::LeAudio | Profile::VolumeControl | Profile::CoordinatedSet
1420 if !has_le_media_profile =>
1421 {
1422 has_le_media_profile = true;
1423 let txl = self.tx.clone();
1424 topstack::get_runtime().spawn(async move {
1425 let _ = txl
1426 .send(Message::Media(
1427 MediaActions::ConnectLeaGroupByMemberAddress(addr),
1428 ))
1429 .await;
1430 });
1431 }
1432
1433 Profile::A2dpSink | Profile::A2dpSource | Profile::Hfp
1434 if !has_classic_media_profile =>
1435 {
1436 has_supported_profile = true;
1437 has_classic_media_profile = true;
1438 let txl = self.tx.clone();
1439 topstack::get_runtime().spawn(async move {
1440 let _ =
1441 txl.send(Message::Media(MediaActions::Connect(addr))).await;
1442 });
1443 }
1444
1445 // We don't connect most profiles
1446 _ => (),
1447 }
1448 }
1449 }
1450 _ => {}
1451 }
1452 }
1453
1454 // If the device does not have a profile that we are interested in connecting to, resume
1455 // discovery now. Other cases will be handled in the ACL connection state or bond state
1456 // callbacks.
1457 if !has_supported_profile {
1458 self.resume_discovery();
1459 }
1460 }
1461
fire_device_connection_or_bonded_state_changed(&self, addr: RawAddress)1462 fn fire_device_connection_or_bonded_state_changed(&self, addr: RawAddress) {
1463 if let Some(device) = self.remote_devices.get(&addr) {
1464 let tx = self.tx.clone();
1465 let bredr_acl_state = device.bredr_acl_state.clone();
1466 let ble_acl_state = device.ble_acl_state.clone();
1467 let bond_state = device.bond_state.clone();
1468 let transport = match self.get_remote_type(device.info.clone()) {
1469 BtDeviceType::Bredr => BtTransport::Bredr,
1470 BtDeviceType::Ble => BtTransport::Le,
1471 _ => device.acl_reported_transport.clone(),
1472 };
1473 tokio::spawn(async move {
1474 let _ = tx
1475 .send(Message::OnDeviceConnectionOrBondStateChanged(
1476 addr,
1477 bredr_acl_state,
1478 ble_acl_state,
1479 bond_state,
1480 transport,
1481 ))
1482 .await;
1483 });
1484 }
1485 }
1486 }
1487
1488 #[btif_callbacks_dispatcher(dispatch_base_callbacks, BaseCallbacks)]
1489 #[allow(unused_variables)]
1490 pub(crate) trait BtifBluetoothCallbacks {
1491 #[btif_callback(AdapterState)]
adapter_state_changed(&mut self, state: BtState)1492 fn adapter_state_changed(&mut self, state: BtState) {}
1493
1494 #[btif_callback(AdapterProperties)]
adapter_properties_changed( &mut self, status: BtStatus, num_properties: i32, properties: Vec<BluetoothProperty>, )1495 fn adapter_properties_changed(
1496 &mut self,
1497 status: BtStatus,
1498 num_properties: i32,
1499 properties: Vec<BluetoothProperty>,
1500 ) {
1501 }
1502
1503 #[btif_callback(DeviceFound)]
device_found(&mut self, n: i32, properties: Vec<BluetoothProperty>)1504 fn device_found(&mut self, n: i32, properties: Vec<BluetoothProperty>) {}
1505
1506 #[btif_callback(DiscoveryState)]
discovery_state(&mut self, state: BtDiscoveryState)1507 fn discovery_state(&mut self, state: BtDiscoveryState) {}
1508
1509 #[btif_callback(SspRequest)]
ssp_request(&mut self, remote_addr: RawAddress, variant: BtSspVariant, passkey: u32)1510 fn ssp_request(&mut self, remote_addr: RawAddress, variant: BtSspVariant, passkey: u32) {}
1511
1512 #[btif_callback(BondState)]
bond_state( &mut self, status: BtStatus, addr: RawAddress, bond_state: BtBondState, fail_reason: i32, )1513 fn bond_state(
1514 &mut self,
1515 status: BtStatus,
1516 addr: RawAddress,
1517 bond_state: BtBondState,
1518 fail_reason: i32,
1519 ) {
1520 }
1521
1522 #[btif_callback(RemoteDeviceProperties)]
remote_device_properties_changed( &mut self, status: BtStatus, addr: RawAddress, num_properties: i32, properties: Vec<BluetoothProperty>, )1523 fn remote_device_properties_changed(
1524 &mut self,
1525 status: BtStatus,
1526 addr: RawAddress,
1527 num_properties: i32,
1528 properties: Vec<BluetoothProperty>,
1529 ) {
1530 }
1531
1532 #[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, )1533 fn acl_state(
1534 &mut self,
1535 status: BtStatus,
1536 addr: RawAddress,
1537 state: BtAclState,
1538 link_type: BtTransport,
1539 hci_reason: BtHciErrorCode,
1540 conn_direction: BtConnectionDirection,
1541 acl_handle: u16,
1542 ) {
1543 }
1544
1545 #[btif_callback(LeRandCallback)]
le_rand_cb(&mut self, random: u64)1546 fn le_rand_cb(&mut self, random: u64) {}
1547
1548 #[btif_callback(PinRequest)]
pin_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, min_16_digit: bool, )1549 fn pin_request(
1550 &mut self,
1551 remote_addr: RawAddress,
1552 remote_name: String,
1553 cod: u32,
1554 min_16_digit: bool,
1555 ) {
1556 }
1557
1558 #[btif_callback(ThreadEvent)]
thread_event(&mut self, event: BtThreadEvent)1559 fn thread_event(&mut self, event: BtThreadEvent) {}
1560
1561 #[btif_callback(KeyMissing)]
key_missing(&mut self, addr: RawAddress)1562 fn key_missing(&mut self, addr: RawAddress) {}
1563 }
1564
1565 #[btif_callbacks_dispatcher(dispatch_hid_host_callbacks, HHCallbacks)]
1566 pub(crate) trait BtifHHCallbacks {
1567 #[btif_callback(ConnectionState)]
connection_state( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, state: BthhConnectionState, )1568 fn connection_state(
1569 &mut self,
1570 address: RawAddress,
1571 address_type: BtAddrType,
1572 transport: BtTransport,
1573 state: BthhConnectionState,
1574 );
1575
1576 #[btif_callback(HidInfo)]
hid_info( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, info: BthhHidInfo, )1577 fn hid_info(
1578 &mut self,
1579 address: RawAddress,
1580 address_type: BtAddrType,
1581 transport: BtTransport,
1582 info: BthhHidInfo,
1583 );
1584
1585 #[btif_callback(ProtocolMode)]
protocol_mode( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, mode: BthhProtocolMode, )1586 fn protocol_mode(
1587 &mut self,
1588 address: RawAddress,
1589 address_type: BtAddrType,
1590 transport: BtTransport,
1591 status: BthhStatus,
1592 mode: BthhProtocolMode,
1593 );
1594
1595 #[btif_callback(IdleTime)]
idle_time( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, idle_rate: i32, )1596 fn idle_time(
1597 &mut self,
1598 address: RawAddress,
1599 address_type: BtAddrType,
1600 transport: BtTransport,
1601 status: BthhStatus,
1602 idle_rate: i32,
1603 );
1604
1605 #[btif_callback(GetReport)]
get_report( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, data: Vec<u8>, size: i32, )1606 fn get_report(
1607 &mut self,
1608 address: RawAddress,
1609 address_type: BtAddrType,
1610 transport: BtTransport,
1611 status: BthhStatus,
1612 data: Vec<u8>,
1613 size: i32,
1614 );
1615
1616 #[btif_callback(Handshake)]
handshake( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, )1617 fn handshake(
1618 &mut self,
1619 address: RawAddress,
1620 address_type: BtAddrType,
1621 transport: BtTransport,
1622 status: BthhStatus,
1623 );
1624 }
1625
1626 #[btif_callbacks_dispatcher(dispatch_sdp_callbacks, SdpCallbacks)]
1627 pub(crate) trait BtifSdpCallbacks {
1628 #[btif_callback(SdpSearch)]
sdp_search( &mut self, status: BtStatus, address: RawAddress, uuid: Uuid, count: i32, records: Vec<BtSdpRecord>, )1629 fn sdp_search(
1630 &mut self,
1631 status: BtStatus,
1632 address: RawAddress,
1633 uuid: Uuid,
1634 count: i32,
1635 records: Vec<BtSdpRecord>,
1636 );
1637 }
1638
get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher1639 pub fn get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher {
1640 BaseCallbacksDispatcher { dispatch: make_message_dispatcher(tx, Message::Base) }
1641 }
1642
1643 impl BtifBluetoothCallbacks for Bluetooth {
1644 #[log_cb_args]
adapter_state_changed(&mut self, state: BtState)1645 fn adapter_state_changed(&mut self, state: BtState) {
1646 let prev_state = self.state.clone();
1647 self.state = state;
1648 metrics::adapter_state_changed(self.state.clone());
1649
1650 // If it's the same state as before, no further action
1651 if self.state == prev_state {
1652 return;
1653 }
1654
1655 match self.state {
1656 BtState::Off => {
1657 self.properties.clear();
1658 match self.remove_pid_file() {
1659 Err(err) => warn!("remove_pid_file() error: {}", err),
1660 _ => (),
1661 }
1662
1663 self.clear_uhid();
1664
1665 // Let the signal notifier know we are turned off.
1666 *self.sig_notifier.enabled.lock().unwrap() = false;
1667 self.sig_notifier.enabled_notify.notify_all();
1668 }
1669
1670 BtState::On => {
1671 // Initialize core profiles
1672 self.init_profiles();
1673
1674 // Trigger properties update
1675 self.intf.lock().unwrap().get_adapter_properties();
1676
1677 // Also need to manually request some properties
1678 self.intf.lock().unwrap().get_adapter_property(BtPropertyType::ClassOfDevice);
1679 let mut controller = controller::Controller::new();
1680 self.le_supported_states = controller.get_ble_supported_states();
1681 self.le_local_supported_features = controller.get_ble_local_supported_features();
1682
1683 // Update connectable mode so that disconnected bonded classic device can reconnect
1684 self.update_connectable_mode();
1685
1686 // Spawn a freshness check job in the background.
1687 if let Some(h) = self.freshness_check.take() {
1688 h.abort()
1689 }
1690 let txl = self.tx.clone();
1691 self.freshness_check = Some(tokio::spawn(async move {
1692 loop {
1693 time::sleep(FOUND_DEVICE_FRESHNESS).await;
1694 let _ = txl
1695 .send(Message::AdapterActions(AdapterActions::DeviceFreshnessCheck))
1696 .await;
1697 }
1698 }));
1699
1700 if self.get_wake_allowed_device_bonded() {
1701 self.create_uhid_for_suspend_wakesource();
1702 }
1703 // Notify the signal notifier that we are turned on.
1704 *self.sig_notifier.enabled.lock().unwrap() = true;
1705 self.sig_notifier.enabled_notify.notify_all();
1706
1707 // Signal that the stack is up and running.
1708 match self.create_pid_file() {
1709 Err(err) => warn!("create_pid_file() error: {}", err),
1710 _ => (),
1711 }
1712
1713 // Inform the rest of the stack we're ready.
1714 let txl = self.tx.clone();
1715 let api_txl = self.api_tx.clone();
1716 tokio::spawn(async move {
1717 let _ = txl.send(Message::AdapterReady).await;
1718 });
1719 tokio::spawn(async move {
1720 let _ = api_txl.send(APIMessage::IsReady(BluetoothAPI::Adapter)).await;
1721 });
1722 // Log LL privacy states.
1723 // LL privacy is set according to feature flag when initializing chrome. When the
1724 // sysprop override file is updated, the adapter is powered off/on to read the new
1725 // settings. As a result, log the LL privacy state at adapter on.
1726 // Multiple users may have different LL privacy settings, and the user setting is
1727 // applied at user login.
1728 let llp_state =
1729 u32::from(sysprop::get_bool(sysprop::PropertyBool::LePrivacyEnabled));
1730 let rpa_state = u32::from(sysprop::get_bool(
1731 sysprop::PropertyBool::LePrivacyOwnAddressTypeEnabled,
1732 ));
1733 metrics::ll_privacy_state(llp_state, rpa_state);
1734 }
1735 }
1736 }
1737
1738 #[allow(unused_variables)]
1739 #[log_cb_args]
adapter_properties_changed( &mut self, status: BtStatus, num_properties: i32, properties: Vec<BluetoothProperty>, )1740 fn adapter_properties_changed(
1741 &mut self,
1742 status: BtStatus,
1743 num_properties: i32,
1744 properties: Vec<BluetoothProperty>,
1745 ) {
1746 if status != BtStatus::Success {
1747 return;
1748 }
1749
1750 // Update local property cache
1751 for prop in properties {
1752 self.properties.insert(prop.get_type(), prop.clone());
1753
1754 match &prop {
1755 BluetoothProperty::BdAddr(bdaddr) => {
1756 self.update_local_address(*bdaddr);
1757 }
1758 BluetoothProperty::AdapterBondedDevices(bondlist) => {
1759 for addr in bondlist.iter() {
1760 self.remote_devices
1761 .entry(*addr)
1762 .and_modify(|d| d.bond_state = BtBondState::Bonded)
1763 .or_insert(BluetoothDeviceContext::new(
1764 BtBondState::Bonded,
1765 BtAclState::Disconnected,
1766 BtAclState::Disconnected,
1767 BluetoothDevice::new(*addr, "".to_string()),
1768 Instant::now(),
1769 vec![],
1770 ));
1771 }
1772
1773 // Update the connectable mode since bonded device list might be updated.
1774 self.update_connectable_mode();
1775 }
1776 BluetoothProperty::BdName(bdname) => {
1777 self.callbacks.for_all_callbacks(|callback| {
1778 callback.on_name_changed(bdname.clone());
1779 });
1780 }
1781 _ => {}
1782 }
1783
1784 self.callbacks.for_all_callbacks(|callback| {
1785 callback.on_adapter_property_changed(prop.get_type());
1786 });
1787 }
1788 }
1789
1790 #[log_cb_args]
device_found(&mut self, _n: i32, properties: Vec<BluetoothProperty>)1791 fn device_found(&mut self, _n: i32, properties: Vec<BluetoothProperty>) {
1792 let device_info = BluetoothDevice::from_properties(&properties);
1793 self.check_new_property_and_potentially_connect_profiles(device_info.address, &properties);
1794
1795 let device_info = self
1796 .remote_devices
1797 .entry(device_info.address)
1798 .and_modify(|d| {
1799 d.update_properties(&properties);
1800 d.seen();
1801 })
1802 .or_insert(BluetoothDeviceContext::new(
1803 BtBondState::NotBonded,
1804 BtAclState::Disconnected,
1805 BtAclState::Disconnected,
1806 device_info,
1807 Instant::now(),
1808 properties,
1809 ))
1810 .info
1811 .clone();
1812
1813 self.callbacks.for_all_callbacks(|callback| {
1814 callback.on_device_found(device_info.clone());
1815 });
1816 }
1817
1818 #[log_cb_args]
discovery_state(&mut self, state: BtDiscoveryState)1819 fn discovery_state(&mut self, state: BtDiscoveryState) {
1820 let is_discovering = &state == &BtDiscoveryState::Started;
1821
1822 // No-op if we're updating the state to the same value again.
1823 if &is_discovering == &self.is_discovering {
1824 return;
1825 }
1826
1827 // Cache discovering state
1828 self.is_discovering = &state == &BtDiscoveryState::Started;
1829 if self.is_discovering {
1830 self.discovering_started = Instant::now();
1831 }
1832
1833 // Prevent sending out discovering changes or freshness checks when
1834 // suspending. Clients don't need to be notified of discovery pausing
1835 // during suspend. They will probably try to restore it and fail.
1836 let discovery_suspend_mode = self.get_discovery_suspend_mode();
1837 if discovery_suspend_mode != SuspendMode::Normal
1838 && discovery_suspend_mode != SuspendMode::Resuming
1839 {
1840 return;
1841 }
1842
1843 self.callbacks.for_all_callbacks(|callback| {
1844 callback.on_discovering_changed(state == BtDiscoveryState::Started);
1845 });
1846
1847 // Start or stop BLE scanning based on discovering state
1848 if let (Some(gatt), Some(scanner_id)) = (self.bluetooth_gatt.as_ref(), self.ble_scanner_id)
1849 {
1850 if is_discovering {
1851 gatt.lock().unwrap().start_active_scan(scanner_id);
1852 } else {
1853 gatt.lock().unwrap().stop_active_scan(scanner_id);
1854 }
1855 }
1856
1857 if !self.is_discovering && self.pending_create_bond.is_some() {
1858 debug!("Invoking delayed CreateBond");
1859 let tx = self.tx.clone();
1860 tokio::spawn(async move {
1861 let _ = tx.send(Message::AdapterActions(AdapterActions::CreateBond)).await;
1862 });
1863 }
1864 }
1865
1866 #[log_cb_args]
ssp_request(&mut self, remote_addr: RawAddress, variant: BtSspVariant, passkey: u32)1867 fn ssp_request(&mut self, remote_addr: RawAddress, variant: BtSspVariant, passkey: u32) {
1868 // Accept the Just-Works pairing that we initiated, reject otherwise.
1869 if variant == BtSspVariant::Consent {
1870 let initiated_by_us = Some(remote_addr) == self.active_pairing_address;
1871 self.set_pairing_confirmation(
1872 BluetoothDevice::new(remote_addr, "".to_string()),
1873 initiated_by_us,
1874 );
1875 return;
1876 }
1877
1878 // Currently this supports many agent because we accept many callbacks.
1879 // TODO(b/274706838): We need a way to select the default agent.
1880 self.callbacks.for_all_callbacks(|callback| {
1881 // TODO(b/336960912): libbluetooth changed their API so that we no longer
1882 // get the Device name and CoD, which were included in our DBus API.
1883 // Now we simply put random values since we aren't ready to change our DBus API
1884 // and it works because our Clients are not using these anyway.
1885 callback.on_ssp_request(
1886 BluetoothDevice::new(remote_addr, "".to_string()),
1887 0,
1888 variant.clone(),
1889 passkey,
1890 );
1891 });
1892 }
1893
1894 #[log_cb_args]
pin_request( &mut self, remote_addr: RawAddress, remote_name: String, cod: u32, min_16_digit: bool, )1895 fn pin_request(
1896 &mut self,
1897 remote_addr: RawAddress,
1898 remote_name: String,
1899 cod: u32,
1900 min_16_digit: bool,
1901 ) {
1902 let device = BluetoothDevice::new(remote_addr, remote_name.clone());
1903
1904 let digits = match min_16_digit {
1905 true => 16,
1906 false => 6,
1907 };
1908
1909 if is_cod_hid_keyboard(cod) || is_cod_hid_combo(cod) {
1910 debug!("auto gen pin for device {} (cod={:#x})", DisplayAddress(&remote_addr), cod);
1911 // generate a random pin code to display.
1912 let pin = rand::random::<u64>() % pow(10, digits);
1913 let display_pin = format!("{:06}", pin);
1914
1915 // Currently this supports many agent because we accept many callbacks.
1916 // TODO(b/274706838): We need a way to select the default agent.
1917 self.callbacks.for_all_callbacks(|callback| {
1918 callback.on_pin_display(device.clone(), display_pin.clone());
1919 });
1920
1921 let pin_vec = display_pin.chars().map(|d| d.try_into().unwrap()).collect::<Vec<u8>>();
1922
1923 self.set_pin(device, true, pin_vec);
1924 } else {
1925 debug!(
1926 "sending pin request for device {} (cod={:#x}) to clients",
1927 DisplayAddress(&remote_addr),
1928 cod
1929 );
1930 // Currently this supports many agent because we accept many callbacks.
1931 // TODO(b/274706838): We need a way to select the default agent.
1932 self.callbacks.for_all_callbacks(|callback| {
1933 callback.on_pin_request(device.clone(), cod, min_16_digit);
1934 });
1935 }
1936 }
1937
1938 #[log_cb_args]
bond_state( &mut self, status: BtStatus, addr: RawAddress, bond_state: BtBondState, fail_reason: i32, )1939 fn bond_state(
1940 &mut self,
1941 status: BtStatus,
1942 addr: RawAddress,
1943 bond_state: BtBondState,
1944 fail_reason: i32,
1945 ) {
1946 // Get the device type before the device is potentially deleted.
1947 let device_type = self.get_remote_type(BluetoothDevice::new(addr, "".to_string()));
1948
1949 // Clear the pairing lock if this call corresponds to the
1950 // active pairing device.
1951 if bond_state != BtBondState::Bonding && self.active_pairing_address == Some(addr) {
1952 self.active_pairing_address = None;
1953 }
1954
1955 if self.get_bond_state_by_addr(&addr) == bond_state {
1956 debug!("[{}]: Unchanged bond_state", DisplayAddress(&addr));
1957 } else {
1958 let entry =
1959 self.remote_devices.entry(addr).and_modify(|d| d.bond_state = bond_state.clone());
1960 match bond_state {
1961 BtBondState::NotBonded => {
1962 if !self.get_wake_allowed_device_bonded() {
1963 self.clear_uhid();
1964 }
1965 // Update the connectable mode since bonded list is changed.
1966 self.update_connectable_mode();
1967 }
1968 BtBondState::Bonded => {
1969 let device = entry.or_insert(BluetoothDeviceContext::new(
1970 BtBondState::Bonded,
1971 BtAclState::Disconnected,
1972 BtAclState::Disconnected,
1973 BluetoothDevice::new(addr, "".to_string()),
1974 Instant::now(),
1975 vec![],
1976 ));
1977 let device_info = device.info.clone();
1978 // Since this is a newly bonded device, we also need to trigger SDP on it.
1979 self.fetch_remote_uuids(device_info);
1980 if self.get_wake_allowed_device_bonded() {
1981 self.create_uhid_for_suspend_wakesource();
1982 }
1983 // Update the connectable mode since bonded list is changed.
1984 self.update_connectable_mode();
1985 }
1986 BtBondState::Bonding => {}
1987 }
1988 }
1989
1990 // Modification to |self.remote_devices| has done, ok to fire the change event.
1991 self.fire_device_connection_or_bonded_state_changed(addr);
1992
1993 // Resume discovery once the bonding process is complete. Discovery was paused before the
1994 // bond request to avoid ACL connection from interfering with active inquiry.
1995 if bond_state == BtBondState::NotBonded || bond_state == BtBondState::Bonded {
1996 self.resume_discovery();
1997 }
1998
1999 // Send bond state changed notifications
2000 self.callbacks.for_all_callbacks(|callback| {
2001 callback.on_bond_state_changed(
2002 status.to_u32().unwrap(),
2003 addr,
2004 bond_state.to_u32().unwrap(),
2005 );
2006 });
2007
2008 // Don't emit the metrics event if we were cancelling the bond.
2009 // It is ok to not send the pairing complete event as the server should ignore the dangling
2010 // pairing attempt event.
2011 // This behavior aligns with BlueZ.
2012 if !self.cancelling_devices.remove(&addr) {
2013 metrics::bond_state_changed(addr, device_type, status, bond_state, fail_reason);
2014 }
2015 }
2016
2017 #[log_cb_args]
remote_device_properties_changed( &mut self, _status: BtStatus, addr: RawAddress, _num_properties: i32, properties: Vec<BluetoothProperty>, )2018 fn remote_device_properties_changed(
2019 &mut self,
2020 _status: BtStatus,
2021 addr: RawAddress,
2022 _num_properties: i32,
2023 properties: Vec<BluetoothProperty>,
2024 ) {
2025 self.check_new_property_and_potentially_connect_profiles(addr, &properties);
2026 let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new(
2027 BtBondState::NotBonded,
2028 BtAclState::Disconnected,
2029 BtAclState::Disconnected,
2030 BluetoothDevice::new(addr, String::from("")),
2031 Instant::now(),
2032 vec![],
2033 ));
2034
2035 device.update_properties(&properties);
2036 device.seen();
2037
2038 Bluetooth::send_metrics_remote_device_info(device);
2039
2040 let info = device.info.clone();
2041
2042 self.callbacks.for_all_callbacks(|callback| {
2043 callback.on_device_properties_changed(
2044 info.clone(),
2045 properties.clone().into_iter().map(|x| x.get_type()).collect(),
2046 );
2047 });
2048
2049 // Only care about device type property changed on bonded device.
2050 // If the property change happens during bonding, it will be updated after bonding complete anyway.
2051 if self.get_bond_state_by_addr(&addr) == BtBondState::Bonded
2052 && properties.iter().any(|prop| match prop {
2053 BluetoothProperty::TypeOfDevice(_) => true,
2054 _ => false,
2055 })
2056 {
2057 // Update the connectable mode since the device type is changed.
2058 self.update_connectable_mode();
2059 }
2060 }
2061
2062 #[log_cb_args]
acl_state( &mut self, status: BtStatus, addr: RawAddress, state: BtAclState, link_type: BtTransport, hci_reason: BtHciErrorCode, conn_direction: BtConnectionDirection, _acl_handle: u16, )2063 fn acl_state(
2064 &mut self,
2065 status: BtStatus,
2066 addr: RawAddress,
2067 state: BtAclState,
2068 link_type: BtTransport,
2069 hci_reason: BtHciErrorCode,
2070 conn_direction: BtConnectionDirection,
2071 _acl_handle: u16,
2072 ) {
2073 // If discovery was previously paused at connect_all_enabled_profiles to avoid an outgoing
2074 // ACL connection colliding with an ongoing inquiry, resume it.
2075 self.resume_discovery();
2076
2077 if status != BtStatus::Success {
2078 warn!(
2079 "Connection to [{}] failed. Status: {:?}, Reason: {:?}",
2080 DisplayAddress(&addr),
2081 status,
2082 hci_reason
2083 );
2084 metrics::acl_connection_state_changed(
2085 addr,
2086 link_type,
2087 status,
2088 BtAclState::Disconnected,
2089 conn_direction,
2090 hci_reason,
2091 );
2092 self.connection_callbacks.for_all_callbacks(|callback| {
2093 callback.on_device_connection_failed(
2094 BluetoothDevice::new(addr, String::from("")),
2095 status,
2096 );
2097 });
2098 return;
2099 }
2100
2101 let device = self.remote_devices.entry(addr).or_insert(BluetoothDeviceContext::new(
2102 BtBondState::NotBonded,
2103 BtAclState::Disconnected,
2104 BtAclState::Disconnected,
2105 BluetoothDevice::new(addr, String::from("")),
2106 Instant::now(),
2107 vec![],
2108 ));
2109
2110 // Only notify if there's been a change in state
2111 if !device.set_transport_state(&link_type, &state) {
2112 return;
2113 }
2114
2115 let info = device.info.clone();
2116 device.acl_reported_transport = link_type;
2117
2118 metrics::acl_connection_state_changed(
2119 addr,
2120 link_type,
2121 BtStatus::Success,
2122 state.clone(),
2123 conn_direction,
2124 hci_reason,
2125 );
2126
2127 match state {
2128 BtAclState::Connected => {
2129 Bluetooth::send_metrics_remote_device_info(device);
2130 self.connection_callbacks.for_all_callbacks(|callback| {
2131 callback.on_device_connected(info.clone());
2132 });
2133 }
2134 BtAclState::Disconnected => {
2135 if !device.is_connected() {
2136 self.connection_callbacks.for_all_callbacks(|callback| {
2137 callback.on_device_disconnected(info.clone());
2138 });
2139 device.connect_to_new_profiles = false;
2140 }
2141 }
2142 };
2143
2144 // Modification to |self.remote_devices| has done, ok to fire the change event.
2145 self.fire_device_connection_or_bonded_state_changed(addr);
2146
2147 // If we are bonding, skip the update here as we will update it after bonding complete anyway.
2148 // This is necessary for RTK controllers, which will break RNR after |Write Scan Enable|
2149 // command. Although this is a bug of RTK controllers, but as we could avoid unwanted page
2150 // scan, it makes sense to extend it to all BT controllers here.
2151 if Some(addr) != self.active_pairing_address {
2152 // Update the connectable since the connected state could be changed.
2153 self.update_connectable_mode();
2154 }
2155 }
2156
2157 #[log_cb_args]
thread_event(&mut self, event: BtThreadEvent)2158 fn thread_event(&mut self, event: BtThreadEvent) {
2159 match event {
2160 BtThreadEvent::Associate => {
2161 // Let the signal notifier know stack is initialized.
2162 *self.sig_notifier.thread_attached.lock().unwrap() = true;
2163 self.sig_notifier.thread_notify.notify_all();
2164 }
2165 BtThreadEvent::Disassociate => {
2166 // Let the signal notifier know stack is done.
2167 *self.sig_notifier.thread_attached.lock().unwrap() = false;
2168 self.sig_notifier.thread_notify.notify_all();
2169 }
2170 }
2171 }
2172
key_missing(&mut self, addr: RawAddress)2173 fn key_missing(&mut self, addr: RawAddress) {
2174 if let Some(d) = self.remote_devices.get(&addr) {
2175 self.callbacks.for_all_callbacks(|callback| {
2176 callback.on_device_key_missing(d.info.clone());
2177 });
2178 }
2179 }
2180 }
2181
2182 struct BleDiscoveryCallbacks {
2183 tx: Sender<Message>,
2184 }
2185
2186 impl BleDiscoveryCallbacks {
new(tx: Sender<Message>) -> Self2187 fn new(tx: Sender<Message>) -> Self {
2188 Self { tx }
2189 }
2190 }
2191
2192 // Handle BLE scanner results.
2193 impl IScannerCallback for BleDiscoveryCallbacks {
2194 #[log_cb_args]
on_scanner_registered(&mut self, uuid: Uuid, scanner_id: u8, status: GattStatus)2195 fn on_scanner_registered(&mut self, uuid: Uuid, scanner_id: u8, status: GattStatus) {
2196 let tx = self.tx.clone();
2197 tokio::spawn(async move {
2198 let _ = tx
2199 .send(Message::AdapterActions(AdapterActions::BleDiscoveryScannerRegistered(
2200 uuid, scanner_id, status,
2201 )))
2202 .await;
2203 });
2204 }
2205
2206 #[log_cb_args]
on_scan_result(&mut self, scan_result: ScanResult)2207 fn on_scan_result(&mut self, scan_result: ScanResult) {
2208 let tx = self.tx.clone();
2209 tokio::spawn(async move {
2210 let _ = tx
2211 .send(Message::AdapterActions(AdapterActions::BleDiscoveryScannerResult(
2212 scan_result,
2213 )))
2214 .await;
2215 });
2216 }
2217
on_advertisement_found(&mut self, _scanner_id: u8, _scan_result: ScanResult)2218 fn on_advertisement_found(&mut self, _scanner_id: u8, _scan_result: ScanResult) {}
on_advertisement_lost(&mut self, _scanner_id: u8, _scan_result: ScanResult)2219 fn on_advertisement_lost(&mut self, _scanner_id: u8, _scan_result: ScanResult) {}
2220 #[log_cb_args]
on_suspend_mode_change(&mut self, _suspend_mode: SuspendMode)2221 fn on_suspend_mode_change(&mut self, _suspend_mode: SuspendMode) {}
2222 }
2223
2224 impl RPCProxy for BleDiscoveryCallbacks {
get_object_id(&self) -> String2225 fn get_object_id(&self) -> String {
2226 "BLE Discovery Callback".to_string()
2227 }
2228 }
2229
2230 // TODO: Add unit tests for this implementation
2231 impl IBluetooth for Bluetooth {
register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) -> u322232 fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) -> u32 {
2233 self.callbacks.add_callback(callback)
2234 }
2235
unregister_callback(&mut self, callback_id: u32) -> bool2236 fn unregister_callback(&mut self, callback_id: u32) -> bool {
2237 self.callbacks.remove_callback(callback_id)
2238 }
2239
register_connection_callback( &mut self, callback: Box<dyn IBluetoothConnectionCallback + Send>, ) -> u322240 fn register_connection_callback(
2241 &mut self,
2242 callback: Box<dyn IBluetoothConnectionCallback + Send>,
2243 ) -> u32 {
2244 self.connection_callbacks.add_callback(callback)
2245 }
2246
unregister_connection_callback(&mut self, callback_id: u32) -> bool2247 fn unregister_connection_callback(&mut self, callback_id: u32) -> bool {
2248 self.connection_callbacks.remove_callback(callback_id)
2249 }
2250
init(&mut self, hci_index: i32) -> bool2251 fn init(&mut self, hci_index: i32) -> bool {
2252 self.intf.lock().unwrap().initialize(get_bt_dispatcher(self.tx.clone()), hci_index)
2253 }
2254
enable(&mut self) -> bool2255 fn enable(&mut self) -> bool {
2256 self.disabling = false;
2257 self.intf.lock().unwrap().enable() == 0
2258 }
2259
disable(&mut self) -> bool2260 fn disable(&mut self) -> bool {
2261 self.shutdown_adapter(false)
2262 }
2263
cleanup(&mut self)2264 fn cleanup(&mut self) {
2265 self.intf.lock().unwrap().cleanup();
2266 }
2267
get_address(&self) -> RawAddress2268 fn get_address(&self) -> RawAddress {
2269 self.local_address.unwrap_or_default()
2270 }
2271
get_uuids(&self) -> Vec<Uuid>2272 fn get_uuids(&self) -> Vec<Uuid> {
2273 match self.properties.get(&BtPropertyType::Uuids) {
2274 Some(prop) => match prop {
2275 BluetoothProperty::Uuids(uuids) => uuids.clone(),
2276 _ => vec![],
2277 },
2278 _ => vec![],
2279 }
2280 }
2281
get_name(&self) -> String2282 fn get_name(&self) -> String {
2283 match self.properties.get(&BtPropertyType::BdName) {
2284 Some(prop) => match prop {
2285 BluetoothProperty::BdName(name) => name.clone(),
2286 _ => String::new(),
2287 },
2288 _ => String::new(),
2289 }
2290 }
2291
set_name(&self, name: String) -> bool2292 fn set_name(&self, name: String) -> bool {
2293 if self.get_name() == name {
2294 return true;
2295 }
2296 self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::BdName(name)) == 0
2297 }
2298
get_bluetooth_class(&self) -> u322299 fn get_bluetooth_class(&self) -> u32 {
2300 match self.properties.get(&BtPropertyType::ClassOfDevice) {
2301 Some(prop) => match prop {
2302 BluetoothProperty::ClassOfDevice(cod) => *cod,
2303 _ => 0,
2304 },
2305 _ => 0,
2306 }
2307 }
2308
set_bluetooth_class(&self, cod: u32) -> bool2309 fn set_bluetooth_class(&self, cod: u32) -> bool {
2310 self.intf.lock().unwrap().set_adapter_property(BluetoothProperty::ClassOfDevice(cod)) == 0
2311 }
2312
get_discoverable(&self) -> bool2313 fn get_discoverable(&self) -> bool {
2314 self.get_discoverable_mode_internal() != BtDiscMode::NonDiscoverable
2315 }
2316
get_discoverable_timeout(&self) -> u322317 fn get_discoverable_timeout(&self) -> u32 {
2318 self.discoverable_duration
2319 }
2320
set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool2321 fn set_discoverable(&mut self, mode: BtDiscMode, duration: u32) -> bool {
2322 let intf = self.intf.lock().unwrap();
2323
2324 // Checks if the duration is valid.
2325 if mode == BtDiscMode::LimitedDiscoverable && (duration > 60 || duration == 0) {
2326 warn!("Invalid duration for setting the device into limited discoverable mode. The valid duration is 1~60 seconds.");
2327 return false;
2328 }
2329
2330 // Don't really set the mode when suspend. The mode would be instead restored on resume.
2331 // However, we still need to set the discoverable timeout so it would properly reset
2332 // |self.discoverable_mode| after resume.
2333 if self.get_scan_suspend_mode() == SuspendMode::Normal {
2334 let scan_mode = match mode {
2335 BtDiscMode::LimitedDiscoverable => BtScanMode::ConnectableLimitedDiscoverable,
2336 BtDiscMode::GeneralDiscoverable => BtScanMode::ConnectableDiscoverable,
2337 BtDiscMode::NonDiscoverable => match self.is_connectable {
2338 true => BtScanMode::Connectable,
2339 false => BtScanMode::None_,
2340 },
2341 };
2342 intf.set_scan_mode(scan_mode);
2343 }
2344
2345 self.callbacks.for_all_callbacks(|callback| {
2346 callback.on_discoverable_changed(mode == BtDiscMode::GeneralDiscoverable);
2347 });
2348 self.discoverable_mode = mode.clone();
2349 self.discoverable_duration = duration;
2350
2351 // The old timer should be overwritten regardless of what the new mode is.
2352 if let Some(handle) = self.discoverable_timeout.take() {
2353 handle.abort();
2354 }
2355
2356 if mode != BtDiscMode::NonDiscoverable && duration != 0 {
2357 let txl = self.tx.clone();
2358 self.discoverable_timeout = Some(tokio::spawn(async move {
2359 time::sleep(Duration::from_secs(duration.into())).await;
2360 let _ = txl.send(Message::AdapterActions(AdapterActions::ResetDiscoverable)).await;
2361 }));
2362 }
2363
2364 true
2365 }
2366
is_multi_advertisement_supported(&self) -> bool2367 fn is_multi_advertisement_supported(&self) -> bool {
2368 match self.properties.get(&BtPropertyType::LocalLeFeatures) {
2369 Some(prop) => match prop {
2370 BluetoothProperty::LocalLeFeatures(llf) => {
2371 llf.max_adv_instance >= MIN_ADV_INSTANCES_FOR_MULTI_ADV
2372 }
2373 _ => false,
2374 },
2375 _ => false,
2376 }
2377 }
2378
is_le_extended_advertising_supported(&self) -> bool2379 fn is_le_extended_advertising_supported(&self) -> bool {
2380 match self.properties.get(&BtPropertyType::LocalLeFeatures) {
2381 Some(prop) => match prop {
2382 BluetoothProperty::LocalLeFeatures(llf) => llf.le_extended_advertising_supported,
2383 _ => false,
2384 },
2385 _ => false,
2386 }
2387 }
2388
start_discovery(&mut self) -> bool2389 fn start_discovery(&mut self) -> bool {
2390 // Short-circuit to avoid sending multiple start discovery calls.
2391 if self.is_discovering {
2392 return true;
2393 }
2394
2395 // Short-circuit if paused and add the discovery intent to the queue.
2396 if self.is_discovery_paused {
2397 self.pending_discovery = true;
2398 debug!("Queue the discovery request during paused state");
2399 return true;
2400 }
2401
2402 let discovery_suspend_mode = self.get_discovery_suspend_mode();
2403 if discovery_suspend_mode != SuspendMode::Normal
2404 && discovery_suspend_mode != SuspendMode::Resuming
2405 {
2406 log::warn!("start_discovery is not allowed when suspending or suspended.");
2407 return false;
2408 }
2409
2410 self.intf.lock().unwrap().start_discovery() == 0
2411 }
2412
cancel_discovery(&mut self) -> bool2413 fn cancel_discovery(&mut self) -> bool {
2414 // Client no longer want to discover, clear the request
2415 if self.is_discovery_paused {
2416 self.pending_discovery = false;
2417 debug!("Cancel the discovery request during paused state");
2418 }
2419
2420 // Reject the cancel discovery request if the underlying stack is not in a discovering
2421 // state. For example, previous start discovery was enqueued for ongoing discovery.
2422 if !self.is_discovering {
2423 debug!("Reject cancel_discovery as it's not in discovering state.");
2424 return false;
2425 }
2426
2427 let discovery_suspend_mode = self.get_discovery_suspend_mode();
2428 if discovery_suspend_mode != SuspendMode::Normal
2429 && discovery_suspend_mode != SuspendMode::Suspending
2430 {
2431 log::warn!("cancel_discovery is not allowed when resuming or suspended.");
2432 return false;
2433 }
2434
2435 self.intf.lock().unwrap().cancel_discovery() == 0
2436 }
2437
is_discovering(&self) -> bool2438 fn is_discovering(&self) -> bool {
2439 self.is_discovering
2440 }
2441
get_discovery_end_millis(&self) -> u642442 fn get_discovery_end_millis(&self) -> u64 {
2443 if !self.is_discovering {
2444 return 0;
2445 }
2446
2447 let elapsed_ms = self.discovering_started.elapsed().as_millis() as u64;
2448 if elapsed_ms >= DEFAULT_DISCOVERY_TIMEOUT_MS {
2449 0
2450 } else {
2451 DEFAULT_DISCOVERY_TIMEOUT_MS - elapsed_ms
2452 }
2453 }
2454
create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus2455 fn create_bond(&mut self, device: BluetoothDevice, transport: BtTransport) -> BtStatus {
2456 let device_type = match transport {
2457 BtTransport::Bredr => BtDeviceType::Bredr,
2458 BtTransport::Le => BtDeviceType::Ble,
2459 _ => self.get_remote_type(device.clone()),
2460 };
2461 let address = device.address;
2462
2463 if let Some(active_address) = self.active_pairing_address {
2464 warn!(
2465 "Bonding requested for {} while already bonding {}, rejecting",
2466 DisplayAddress(&address),
2467 DisplayAddress(&active_address)
2468 );
2469 return BtStatus::Busy;
2470 }
2471
2472 if self.pending_create_bond.is_some() {
2473 warn!("Delayed CreateBond is still pending");
2474 return BtStatus::Busy;
2475 }
2476
2477 // There could be a race between bond complete and bond cancel, which makes
2478 // |cancelling_devices| in a wrong state. Remove the device just in case.
2479 if self.cancelling_devices.remove(&address) {
2480 warn!("Device {} is also cancelling the bond.", DisplayAddress(&address));
2481 }
2482
2483 // BREDR connection won't work when Inquiry / Remote Name Request is in progress.
2484 // If is_discovering, delay the request until discovery state change.
2485 if self.is_discovering {
2486 debug!("Discovering. Delay the CreateBond request until discovery is done.");
2487 self.pause_discovery();
2488 self.pending_create_bond = Some((device, transport));
2489 return BtStatus::Success;
2490 }
2491
2492 // We explicitly log the attempt to start the bonding separate from logging the bond state.
2493 // The start of the attempt is critical to help identify a bonding/pairing session.
2494 metrics::bond_create_attempt(address, device_type.clone());
2495
2496 self.active_pairing_address = Some(address);
2497 let status = self.intf.lock().unwrap().create_bond(&address, transport);
2498
2499 if status != 0 {
2500 metrics::bond_state_changed(
2501 address,
2502 device_type,
2503 BtStatus::from(status as u32),
2504 BtBondState::NotBonded,
2505 0,
2506 );
2507 return BtStatus::from(status as u32);
2508 }
2509
2510 // Creating bond automatically create ACL connection as well, therefore also log metrics
2511 // ACL connection attempt here.
2512 if !self.get_acl_state_by_addr(&address) {
2513 metrics::acl_connect_attempt(address, BtAclState::Connected);
2514 }
2515
2516 BtStatus::Success
2517 }
2518
cancel_bond_process(&mut self, device: BluetoothDevice) -> bool2519 fn cancel_bond_process(&mut self, device: BluetoothDevice) -> bool {
2520 if !self.cancelling_devices.insert(device.address) {
2521 warn!(
2522 "Device {} has been added to cancelling_device.",
2523 DisplayAddress(&device.address)
2524 );
2525 }
2526
2527 self.intf.lock().unwrap().cancel_bond(&device.address) == 0
2528 }
2529
remove_bond(&mut self, device: BluetoothDevice) -> bool2530 fn remove_bond(&mut self, device: BluetoothDevice) -> bool {
2531 let address = device.address;
2532
2533 // There could be a race between bond complete and bond cancel, which makes
2534 // |cancelling_devices| in a wrong state. Remove the device just in case.
2535 if self.cancelling_devices.remove(&address) {
2536 warn!("Device {} is also cancelling the bond.", DisplayAddress(&address));
2537 }
2538
2539 let status = self.intf.lock().unwrap().remove_bond(&address);
2540
2541 if status != 0 {
2542 return false;
2543 }
2544
2545 // Removing bond also disconnects the ACL if is connected. Therefore, also log ACL
2546 // disconnection attempt here.
2547 if self.get_acl_state_by_addr(&address) {
2548 metrics::acl_connect_attempt(address, BtAclState::Disconnected);
2549 }
2550
2551 true
2552 }
2553
get_bonded_devices(&self) -> Vec<BluetoothDevice>2554 fn get_bonded_devices(&self) -> Vec<BluetoothDevice> {
2555 self.remote_devices
2556 .values()
2557 .filter_map(|d| {
2558 if d.bond_state == BtBondState::Bonded {
2559 Some(d.info.clone())
2560 } else {
2561 None
2562 }
2563 })
2564 .collect()
2565 }
2566
get_bond_state(&self, device: BluetoothDevice) -> BtBondState2567 fn get_bond_state(&self, device: BluetoothDevice) -> BtBondState {
2568 self.get_bond_state_by_addr(&device.address)
2569 }
2570
set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool2571 fn set_pin(&self, device: BluetoothDevice, accept: bool, pin_code: Vec<u8>) -> bool {
2572 if self.get_bond_state_by_addr(&device.address) != BtBondState::Bonding {
2573 warn!("Can't set pin. Device {} isn't bonding.", DisplayAddress(&device.address));
2574 return false;
2575 }
2576
2577 let mut btpin = BtPinCode { pin: array_utils::to_sized_array(&pin_code) };
2578
2579 self.intf.lock().unwrap().pin_reply(
2580 &device.address,
2581 accept as u8,
2582 pin_code.len() as u8,
2583 &mut btpin,
2584 ) == 0
2585 }
2586
set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool2587 fn set_passkey(&self, device: BluetoothDevice, accept: bool, passkey: Vec<u8>) -> bool {
2588 if self.get_bond_state_by_addr(&device.address) != BtBondState::Bonding {
2589 warn!("Can't set passkey. Device {} isn't bonding.", DisplayAddress(&device.address));
2590 return false;
2591 }
2592
2593 let mut tmp: [u8; 4] = [0; 4];
2594 tmp.copy_from_slice(passkey.as_slice());
2595 let passkey = u32::from_ne_bytes(tmp);
2596
2597 self.intf.lock().unwrap().ssp_reply(
2598 &device.address,
2599 BtSspVariant::PasskeyEntry,
2600 accept as u8,
2601 passkey,
2602 ) == 0
2603 }
2604
set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool2605 fn set_pairing_confirmation(&self, device: BluetoothDevice, accept: bool) -> bool {
2606 self.intf.lock().unwrap().ssp_reply(
2607 &device.address,
2608 BtSspVariant::PasskeyConfirmation,
2609 accept as u8,
2610 0,
2611 ) == 0
2612 }
2613
get_remote_name(&self, device: BluetoothDevice) -> String2614 fn get_remote_name(&self, device: BluetoothDevice) -> String {
2615 match self.get_remote_device_property(&device, &BtPropertyType::BdName) {
2616 Some(BluetoothProperty::BdName(name)) => name.clone(),
2617 _ => "".to_string(),
2618 }
2619 }
2620
get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType2621 fn get_remote_type(&self, device: BluetoothDevice) -> BtDeviceType {
2622 match self.get_remote_device_property(&device, &BtPropertyType::TypeOfDevice) {
2623 Some(BluetoothProperty::TypeOfDevice(device_type)) => device_type,
2624 _ => BtDeviceType::Unknown,
2625 }
2626 }
2627
get_remote_alias(&self, device: BluetoothDevice) -> String2628 fn get_remote_alias(&self, device: BluetoothDevice) -> String {
2629 match self.get_remote_device_property(&device, &BtPropertyType::RemoteFriendlyName) {
2630 Some(BluetoothProperty::RemoteFriendlyName(name)) => name.clone(),
2631 _ => "".to_string(),
2632 }
2633 }
2634
set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String)2635 fn set_remote_alias(&mut self, device: BluetoothDevice, new_alias: String) {
2636 let _ = self.set_remote_device_property(
2637 &device,
2638 BtPropertyType::RemoteFriendlyName,
2639 BluetoothProperty::RemoteFriendlyName(new_alias),
2640 );
2641 }
2642
get_remote_class(&self, device: BluetoothDevice) -> u322643 fn get_remote_class(&self, device: BluetoothDevice) -> u32 {
2644 match self.get_remote_device_property(&device, &BtPropertyType::ClassOfDevice) {
2645 Some(BluetoothProperty::ClassOfDevice(class)) => class,
2646 _ => 0,
2647 }
2648 }
2649
get_remote_appearance(&self, device: BluetoothDevice) -> u162650 fn get_remote_appearance(&self, device: BluetoothDevice) -> u16 {
2651 match self.get_remote_device_property(&device, &BtPropertyType::Appearance) {
2652 Some(BluetoothProperty::Appearance(appearance)) => appearance,
2653 _ => 0,
2654 }
2655 }
2656
get_remote_connected(&self, device: BluetoothDevice) -> bool2657 fn get_remote_connected(&self, device: BluetoothDevice) -> bool {
2658 self.get_connection_state(device) != BtConnectionState::NotConnected
2659 }
2660
get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool2661 fn get_remote_wake_allowed(&self, device: BluetoothDevice) -> bool {
2662 // Wake is allowed if the device supports HIDP or HOGP only.
2663 match self.get_remote_device_property(&device, &BtPropertyType::Uuids) {
2664 Some(BluetoothProperty::Uuids(uuids)) => {
2665 return uuids.iter().any(|&uuid| {
2666 UuidHelper::is_known_profile(&uuid).map_or(false, |profile| {
2667 profile == Profile::Hid || profile == Profile::Hogp
2668 })
2669 });
2670 }
2671 _ => false,
2672 }
2673 }
2674
get_remote_vendor_product_info(&self, device: BluetoothDevice) -> BtVendorProductInfo2675 fn get_remote_vendor_product_info(&self, device: BluetoothDevice) -> BtVendorProductInfo {
2676 match self.get_remote_device_property(&device, &BtPropertyType::VendorProductInfo) {
2677 Some(BluetoothProperty::VendorProductInfo(p)) => p,
2678 _ => BtVendorProductInfo { vendor_id_src: 0, vendor_id: 0, product_id: 0, version: 0 },
2679 }
2680 }
2681
get_remote_address_type(&self, device: BluetoothDevice) -> BtAddrType2682 fn get_remote_address_type(&self, device: BluetoothDevice) -> BtAddrType {
2683 match self.get_remote_device_property(&device, &BtPropertyType::RemoteAddrType) {
2684 Some(BluetoothProperty::RemoteAddrType(addr_type)) => addr_type,
2685 _ => BtAddrType::Unknown,
2686 }
2687 }
2688
get_remote_rssi(&self, device: BluetoothDevice) -> i82689 fn get_remote_rssi(&self, device: BluetoothDevice) -> i8 {
2690 match self.get_remote_device_property(&device, &BtPropertyType::RemoteRssi) {
2691 Some(BluetoothProperty::RemoteRssi(rssi)) => rssi,
2692 _ => INVALID_RSSI,
2693 }
2694 }
2695
get_connected_devices(&self) -> Vec<BluetoothDevice>2696 fn get_connected_devices(&self) -> Vec<BluetoothDevice> {
2697 self.remote_devices
2698 .values()
2699 .filter_map(|d| if d.is_connected() { Some(d.info.clone()) } else { None })
2700 .collect()
2701 }
2702
get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState2703 fn get_connection_state(&self, device: BluetoothDevice) -> BtConnectionState {
2704 // The underlying api adds whether this is ENCRYPTED_BREDR or ENCRYPTED_LE.
2705 // As long as it is non-zero, it is connected.
2706 self.intf.lock().unwrap().get_connection_state(&device.address)
2707 }
2708
get_profile_connection_state(&self, profile: Uuid) -> ProfileConnectionState2709 fn get_profile_connection_state(&self, profile: Uuid) -> ProfileConnectionState {
2710 if let Some(known) = UuidHelper::is_known_profile(&profile) {
2711 match known {
2712 Profile::A2dpSink | Profile::A2dpSource => self
2713 .bluetooth_media
2714 .as_ref()
2715 .map_or(ProfileConnectionState::Disconnected, |media| {
2716 media.lock().unwrap().get_a2dp_connection_state()
2717 }),
2718 Profile::Hfp | Profile::HfpAg => self
2719 .bluetooth_media
2720 .as_ref()
2721 .map_or(ProfileConnectionState::Disconnected, |media| {
2722 media.lock().unwrap().get_hfp_connection_state()
2723 }),
2724 // TODO: (b/223431229) Profile::Hid and Profile::Hogp
2725 _ => ProfileConnectionState::Disconnected,
2726 }
2727 } else {
2728 ProfileConnectionState::Disconnected
2729 }
2730 }
2731
get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid>2732 fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid> {
2733 match self.get_remote_device_property(&device, &BtPropertyType::Uuids) {
2734 Some(BluetoothProperty::Uuids(uuids)) => uuids,
2735 _ => vec![],
2736 }
2737 }
2738
fetch_remote_uuids(&self, remote_device: BluetoothDevice) -> bool2739 fn fetch_remote_uuids(&self, remote_device: BluetoothDevice) -> bool {
2740 let Some(device) = self.remote_devices.get(&remote_device.address) else {
2741 warn!("Won't fetch UUIDs on unknown device");
2742 return false;
2743 };
2744
2745 let transport = match self.get_remote_type(device.info.clone()) {
2746 BtDeviceType::Bredr => BtTransport::Bredr,
2747 BtDeviceType::Ble => BtTransport::Le,
2748 _ => device.acl_reported_transport,
2749 };
2750
2751 self.intf.lock().unwrap().get_remote_services(&mut device.info.address.clone(), transport)
2752 == 0
2753 }
2754
sdp_search(&self, mut device: BluetoothDevice, uuid: Uuid) -> bool2755 fn sdp_search(&self, mut device: BluetoothDevice, uuid: Uuid) -> bool {
2756 if let Some(sdp) = self.sdp.as_ref() {
2757 return sdp.sdp_search(&mut device.address, &uuid) == BtStatus::Success;
2758 }
2759 false
2760 }
2761
create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool2762 fn create_sdp_record(&mut self, sdp_record: BtSdpRecord) -> bool {
2763 let mut handle: i32 = -1;
2764 let mut sdp_record = sdp_record;
2765 match self.sdp.as_ref().unwrap().create_sdp_record(&mut sdp_record, &mut handle) {
2766 BtStatus::Success => {
2767 let record_clone = sdp_record.clone();
2768 self.callbacks.for_all_callbacks(|callback| {
2769 callback.on_sdp_record_created(record_clone.clone(), handle);
2770 });
2771 true
2772 }
2773 _ => false,
2774 }
2775 }
2776
remove_sdp_record(&self, handle: i32) -> bool2777 fn remove_sdp_record(&self, handle: i32) -> bool {
2778 self.sdp.as_ref().unwrap().remove_sdp_record(handle) == BtStatus::Success
2779 }
2780
connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus2781 fn connect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> BtStatus {
2782 // Profile init must be complete before this api is callable
2783 if !self.profiles_ready {
2784 return BtStatus::NotReady;
2785 }
2786
2787 // Check all remote uuids to see if they match enabled profiles and connect them.
2788 let uuids = self.get_remote_uuids(device.clone());
2789 self.connect_profiles_internal(&uuids, device.clone());
2790
2791 // Also connect to profiles discovered in the future.
2792 if let Some(d) = self.remote_devices.get_mut(&device.address) {
2793 d.connect_to_new_profiles = true;
2794 }
2795
2796 BtStatus::Success
2797 }
2798
disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool2799 fn disconnect_all_enabled_profiles(&mut self, device: BluetoothDevice) -> bool {
2800 if !self.profiles_ready {
2801 return false;
2802 }
2803 let addr = device.address;
2804
2805 // log ACL disconnection attempt if it's not already disconnected.
2806 if self.get_acl_state_by_addr(&addr) {
2807 metrics::acl_connect_attempt(addr, BtAclState::Disconnected);
2808 }
2809
2810 let uuids = self.get_remote_uuids(device.clone());
2811 let mut has_classic_media_profile = false;
2812 let mut has_le_media_profile = false;
2813 for uuid in uuids.iter() {
2814 match UuidHelper::is_known_profile(uuid) {
2815 Some(p) => {
2816 if UuidHelper::is_profile_supported(&p) {
2817 match p {
2818 Profile::Hid | Profile::Hogp => {
2819 // TODO(b/328675014): Use BtAddrType
2820 // and BtTransport from
2821 // BluetoothDevice instead of default
2822
2823 // TODO(b/329837967): Determine
2824 // correct reconnection behavior based
2825 // on device instead of the default
2826 self.hh.as_ref().unwrap().disconnect(
2827 &mut addr.clone(),
2828 BtAddrType::Public,
2829 BtTransport::Auto,
2830 /*reconnect_allowed=*/ true,
2831 );
2832 }
2833
2834 // TODO(b/317682584): implement policy to disconnect from LEA, VC, and CSIS
2835 Profile::LeAudio | Profile::VolumeControl | Profile::CoordinatedSet
2836 if !has_le_media_profile =>
2837 {
2838 has_le_media_profile = true;
2839 let txl = self.tx.clone();
2840 topstack::get_runtime().spawn(async move {
2841 let _ = txl
2842 .send(Message::Media(
2843 MediaActions::DisconnectLeaGroupByMemberAddress(addr),
2844 ))
2845 .await;
2846 });
2847 }
2848
2849 Profile::A2dpSink
2850 | Profile::A2dpSource
2851 | Profile::Hfp
2852 | Profile::AvrcpController
2853 if !has_classic_media_profile =>
2854 {
2855 has_classic_media_profile = true;
2856 let txl = self.tx.clone();
2857 topstack::get_runtime().spawn(async move {
2858 let _ = txl
2859 .send(Message::Media(MediaActions::Disconnect(addr)))
2860 .await;
2861 });
2862 }
2863
2864 // We don't connect most profiles
2865 _ => (),
2866 }
2867 }
2868 }
2869 _ => {}
2870 }
2871 }
2872
2873 // Disconnect all socket connections
2874 let txl = self.tx.clone();
2875 topstack::get_runtime().spawn(async move {
2876 let _ =
2877 txl.send(Message::SocketManagerActions(SocketActions::DisconnectAll(addr))).await;
2878 });
2879
2880 // Disconnect all GATT connections
2881 let txl = self.tx.clone();
2882 topstack::get_runtime().spawn(async move {
2883 let _ = txl.send(Message::GattActions(GattActions::Disconnect(device))).await;
2884 });
2885
2886 if let Some(d) = self.remote_devices.get_mut(&addr) {
2887 d.connect_to_new_profiles = false;
2888 }
2889
2890 true
2891 }
2892
is_wbs_supported(&self) -> bool2893 fn is_wbs_supported(&self) -> bool {
2894 self.intf.lock().unwrap().get_wbs_supported()
2895 }
2896
is_swb_supported(&self) -> bool2897 fn is_swb_supported(&self) -> bool {
2898 self.intf.lock().unwrap().get_swb_supported()
2899 }
2900
get_supported_roles(&self) -> Vec<BtAdapterRole>2901 fn get_supported_roles(&self) -> Vec<BtAdapterRole> {
2902 let mut roles: Vec<BtAdapterRole> = vec![];
2903
2904 // See Core 5.3, Vol 4, Part E, 7.8.27 for detailed state information
2905 if self.le_supported_states >> 35 & 1 == 1u64 {
2906 roles.push(BtAdapterRole::Central);
2907 }
2908 if self.le_supported_states >> 38 & 1 == 1u64 {
2909 roles.push(BtAdapterRole::Peripheral);
2910 }
2911 if self.le_supported_states >> 28 & 1 == 1u64 {
2912 roles.push(BtAdapterRole::CentralPeripheral);
2913 }
2914
2915 roles
2916 }
2917
is_coding_format_supported(&self, coding_format: EscoCodingFormat) -> bool2918 fn is_coding_format_supported(&self, coding_format: EscoCodingFormat) -> bool {
2919 self.intf.lock().unwrap().is_coding_format_supported(coding_format as u8)
2920 }
2921
is_le_audio_supported(&self) -> bool2922 fn is_le_audio_supported(&self) -> bool {
2923 // We determine LE Audio support by checking CIS Central support
2924 // See Core 5.3, Vol 6, 4.6 FEATURE SUPPORT
2925 self.le_local_supported_features >> 28 & 1 == 1u64
2926 }
2927
is_dual_mode_audio_sink_device(&self, device: BluetoothDevice) -> bool2928 fn is_dual_mode_audio_sink_device(&self, device: BluetoothDevice) -> bool {
2929 fn is_dual_mode(uuids: Vec<Uuid>) -> bool {
2930 fn get_unwrapped_uuid(profile: Profile) -> Uuid {
2931 *UuidHelper::get_profile_uuid(&profile).unwrap_or(&Uuid::empty())
2932 }
2933
2934 uuids.contains(&get_unwrapped_uuid(Profile::LeAudio))
2935 && (uuids.contains(&get_unwrapped_uuid(Profile::A2dpSink))
2936 || uuids.contains(&get_unwrapped_uuid(Profile::Hfp)))
2937 }
2938
2939 let Some(media) = self.bluetooth_media.as_ref() else {
2940 return false;
2941 };
2942 let media = media.lock().unwrap();
2943 let group_id = media.get_group_id(device.address);
2944 if group_id == LEA_UNKNOWN_GROUP_ID {
2945 return is_dual_mode(self.get_remote_uuids(device));
2946 }
2947
2948 // Check if any device in the CSIP group is a dual mode audio sink device
2949 media.get_group_devices(group_id).iter().any(|addr| {
2950 is_dual_mode(self.get_remote_uuids(BluetoothDevice::new(*addr, "".to_string())))
2951 })
2952 }
2953
get_dumpsys(&self) -> String2954 fn get_dumpsys(&self) -> String {
2955 OpenOptions::new()
2956 .write(true)
2957 .create(true)
2958 .truncate(true)
2959 .open(DUMPSYS_LOG)
2960 .and_then(|file| {
2961 let fd = file.as_raw_fd();
2962 self.intf.lock().unwrap().dump(fd);
2963 Ok(format!("dump to {}", DUMPSYS_LOG))
2964 })
2965 .unwrap_or_default()
2966 }
2967 }
2968
2969 impl BtifSdpCallbacks for Bluetooth {
2970 #[log_cb_args]
sdp_search( &mut self, status: BtStatus, address: RawAddress, uuid: Uuid, _count: i32, records: Vec<BtSdpRecord>, )2971 fn sdp_search(
2972 &mut self,
2973 status: BtStatus,
2974 address: RawAddress,
2975 uuid: Uuid,
2976 _count: i32,
2977 records: Vec<BtSdpRecord>,
2978 ) {
2979 let device_info = match self.remote_devices.get(&address) {
2980 Some(d) => d.info.clone(),
2981 None => BluetoothDevice::new(address, "".to_string()),
2982 };
2983
2984 // The SDP records we get back do not populate the UUID so we populate it ourselves before
2985 // sending them on.
2986 let mut records = records;
2987 records.iter_mut().for_each(|record| {
2988 match record {
2989 BtSdpRecord::HeaderOverlay(header) => header.uuid = uuid,
2990 BtSdpRecord::MapMas(record) => record.hdr.uuid = uuid,
2991 BtSdpRecord::MapMns(record) => record.hdr.uuid = uuid,
2992 BtSdpRecord::PbapPse(record) => record.hdr.uuid = uuid,
2993 BtSdpRecord::PbapPce(record) => record.hdr.uuid = uuid,
2994 BtSdpRecord::OppServer(record) => record.hdr.uuid = uuid,
2995 BtSdpRecord::SapServer(record) => record.hdr.uuid = uuid,
2996 BtSdpRecord::Dip(record) => record.hdr.uuid = uuid,
2997 BtSdpRecord::Mps(record) => record.hdr.uuid = uuid,
2998 };
2999 });
3000 self.callbacks.for_all_callbacks(|callback| {
3001 callback.on_sdp_search_complete(device_info.clone(), uuid, records.clone());
3002 });
3003 debug!(
3004 "Sdp search result found: Status={:?} Address={} Uuid={}",
3005 status,
3006 DisplayAddress(&address),
3007 DisplayUuid(&uuid)
3008 );
3009 }
3010 }
3011
3012 impl BtifHHCallbacks for Bluetooth {
3013 #[log_cb_args]
connection_state( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, state: BthhConnectionState, )3014 fn connection_state(
3015 &mut self,
3016 address: RawAddress,
3017 address_type: BtAddrType,
3018 transport: BtTransport,
3019 state: BthhConnectionState,
3020 ) {
3021 // HID or HOG is not differentiated by the hid host when callback this function. Assume HOG
3022 // if the device is LE only and HID if classic only. And assume HOG if UUID said so when
3023 // device type is dual or unknown.
3024 let device = BluetoothDevice::new(address, "".to_string());
3025 let profile = match self.get_remote_type(device.clone()) {
3026 BtDeviceType::Ble => Profile::Hogp,
3027 BtDeviceType::Bredr => Profile::Hid,
3028 _ => {
3029 if self
3030 .get_remote_uuids(device)
3031 .contains(UuidHelper::get_profile_uuid(&Profile::Hogp).unwrap())
3032 {
3033 Profile::Hogp
3034 } else {
3035 Profile::Hid
3036 }
3037 }
3038 };
3039
3040 metrics::profile_connection_state_changed(
3041 address,
3042 profile as u32,
3043 BtStatus::Success,
3044 state as u32,
3045 );
3046
3047 let tx = self.tx.clone();
3048 self.remote_devices.entry(address).and_modify(|context| {
3049 if context.is_initiated_hh_connection
3050 && (state != BthhConnectionState::Connected
3051 && state != BthhConnectionState::Connecting)
3052 {
3053 tokio::spawn(async move {
3054 let _ = tx.send(Message::ProfileDisconnected(address)).await;
3055 });
3056 }
3057 context.is_initiated_hh_connection =
3058 state == BthhConnectionState::Connected || state == BthhConnectionState::Connecting;
3059 });
3060
3061 if BtBondState::Bonded != self.get_bond_state_by_addr(&address)
3062 && (state != BthhConnectionState::Disconnecting
3063 && state != BthhConnectionState::Disconnected)
3064 {
3065 warn!(
3066 "[{}]: Rejecting a unbonded device's attempt to connect to HID/HOG profiles",
3067 DisplayAddress(&address)
3068 );
3069 // TODO(b/329837967): Determine correct reconnection
3070 // behavior based on device instead of the default
3071 let mut address = address;
3072 self.hh.as_ref().unwrap().disconnect(
3073 &mut address,
3074 address_type,
3075 transport,
3076 /*reconnect_allowed=*/ true,
3077 );
3078 }
3079 }
3080
3081 #[log_cb_args]
hid_info( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, info: BthhHidInfo, )3082 fn hid_info(
3083 &mut self,
3084 address: RawAddress,
3085 address_type: BtAddrType,
3086 transport: BtTransport,
3087 info: BthhHidInfo,
3088 ) {
3089 }
3090
3091 #[log_cb_args]
protocol_mode( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, mode: BthhProtocolMode, )3092 fn protocol_mode(
3093 &mut self,
3094 address: RawAddress,
3095 address_type: BtAddrType,
3096 transport: BtTransport,
3097 status: BthhStatus,
3098 mode: BthhProtocolMode,
3099 ) {
3100 }
3101
3102 #[log_cb_args]
idle_time( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, idle_rate: i32, )3103 fn idle_time(
3104 &mut self,
3105 address: RawAddress,
3106 address_type: BtAddrType,
3107 transport: BtTransport,
3108 status: BthhStatus,
3109 idle_rate: i32,
3110 ) {
3111 }
3112
3113 #[log_cb_args]
get_report( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, _data: Vec<u8>, size: i32, )3114 fn get_report(
3115 &mut self,
3116 address: RawAddress,
3117 address_type: BtAddrType,
3118 transport: BtTransport,
3119 status: BthhStatus,
3120 _data: Vec<u8>,
3121 size: i32,
3122 ) {
3123 }
3124
3125 #[log_cb_args]
handshake( &mut self, address: RawAddress, address_type: BtAddrType, transport: BtTransport, status: BthhStatus, )3126 fn handshake(
3127 &mut self,
3128 address: RawAddress,
3129 address_type: BtAddrType,
3130 transport: BtTransport,
3131 status: BthhStatus,
3132 ) {
3133 }
3134 }
3135
3136 // TODO(b/261143122): Remove these once we migrate to BluetoothQA entirely
3137 impl IBluetoothQALegacy for Bluetooth {
get_connectable(&self) -> bool3138 fn get_connectable(&self) -> bool {
3139 self.get_connectable_internal()
3140 }
3141
set_connectable(&mut self, mode: bool) -> bool3142 fn set_connectable(&mut self, mode: bool) -> bool {
3143 self.set_connectable_internal(mode)
3144 }
3145
get_alias(&self) -> String3146 fn get_alias(&self) -> String {
3147 self.get_alias_internal()
3148 }
3149
get_modalias(&self) -> String3150 fn get_modalias(&self) -> String {
3151 format!("bluetooth:v00E0pC405d{:04x}", FLOSS_VER)
3152 }
3153
get_hid_report( &mut self, addr: RawAddress, report_type: BthhReportType, report_id: u8, ) -> BtStatus3154 fn get_hid_report(
3155 &mut self,
3156 addr: RawAddress,
3157 report_type: BthhReportType,
3158 report_id: u8,
3159 ) -> BtStatus {
3160 self.get_hid_report_internal(addr, report_type, report_id)
3161 }
3162
set_hid_report( &mut self, addr: RawAddress, report_type: BthhReportType, report: String, ) -> BtStatus3163 fn set_hid_report(
3164 &mut self,
3165 addr: RawAddress,
3166 report_type: BthhReportType,
3167 report: String,
3168 ) -> BtStatus {
3169 self.set_hid_report_internal(addr, report_type, report)
3170 }
3171
send_hid_data(&mut self, addr: RawAddress, data: String) -> BtStatus3172 fn send_hid_data(&mut self, addr: RawAddress, data: String) -> BtStatus {
3173 self.send_hid_data_internal(addr, data)
3174 }
3175 }
3176