Loading system/gd/rust/linux/stack/src/bluetooth.rs +73 −14 Original line number Diff line number Diff line Loading @@ -308,6 +308,9 @@ pub enum DelayedActions { /// Scanner for BLE discovery is reporting a result. BleDiscoveryScannerResult(ScanResult), /// Update the connectable mode to allow or disallow classic reconnect UpdateConnectableMode(bool), } /// Serializable device used in various apis. Loading Loading @@ -602,6 +605,35 @@ impl Bluetooth { } } fn update_connectable_mode(&mut self, is_sock_listening: bool) { // Set connectable if // - there is bredr socket listening, or // - there is a classic device bonded and not connected self.set_connectable_internal( is_sock_listening || self.bonded_devices.iter().any(|(_name, ctx)| { ctx.acl_state == BtAclState::Disconnected && ctx .properties .get(&BtPropertyType::TypeOfDevice) .and_then(|prop| match prop { BluetoothProperty::TypeOfDevice(transport) => { Some(*transport != BtDeviceType::Ble) } _ => None, }) .unwrap_or(false) }), ); } fn trigger_update_connectable_mode(&self) { let txl = self.tx.clone(); tokio::spawn(async move { let _ = txl.send(Message::TriggerUpdateConnectableMode).await; }); } fn disable_profile(&mut self, profile: &Profile) { if !UuidHelper::is_profile_supported(profile) { return; Loading Loading @@ -1074,6 +1106,9 @@ impl Bluetooth { self.found_devices.insert(address.clone(), device_with_props); } } DelayedActions::UpdateConnectableMode(is_sock_listening) => { self.update_connectable_mode(is_sock_listening); } } } Loading Loading @@ -1400,8 +1435,8 @@ impl BtifBluetoothCallbacks for Bluetooth { self.ble_scanner_uuid = Some(self.bluetooth_gatt.lock().unwrap().register_scanner(callback_id)); // Ensure device is connectable so that disconnected device can reconnect self.set_connectable(true); // Update connectable mode so that disconnected bonded classic device can reconnect self.trigger_update_connectable_mode(); // Spawn a freshness check job in the background. self.freshness_check.take().map(|h| h.abort()); Loading Loading @@ -1487,6 +1522,9 @@ impl BtifBluetoothCallbacks for Bluetooth { self.bonded_devices.entry(address.clone()).or_insert(device).bond_state = BtBondState::Bonded; } // Update the connectable mode since bonded device list might be updated. self.trigger_update_connectable_mode(); } BluetoothProperty::BdName(bdname) => { self.callbacks.for_all_callbacks(|callback| { Loading Loading @@ -1715,6 +1753,8 @@ impl BtifBluetoothCallbacks for Bluetooth { // bond request to avoid ACL connection from interfering with active inquiry. if &bond_state == &BtBondState::NotBonded || &bond_state == &BtBondState::Bonded { self.resume_discovery(); // Update the connectable mode since bonded list is changed. self.trigger_update_connectable_mode(); } // Send bond state changed notifications Loading Loading @@ -1744,6 +1784,7 @@ impl BtifBluetoothCallbacks for Bluetooth { ) { let address = addr.to_string(); let txl = self.tx.clone(); let device = match self.get_remote_device_if_found_mut(&address) { None => { self.found_devices.insert( Loading Loading @@ -1785,8 +1826,9 @@ impl BtifBluetoothCallbacks for Bluetooth { d.wait_to_connect = false; let sent_info = info.clone(); let tx = txl.clone(); tokio::spawn(async move { let _ = txl let _ = tx .send(Message::DelayedAdapterActions( DelayedActions::ConnectAllProfiles(sent_info), )) Loading @@ -1809,6 +1851,17 @@ impl BtifBluetoothCallbacks for Bluetooth { } None => (), } // Only care about device type property changed on bonded device. // If the property change happens during bonding, it will be updated after bonding complete anyway. if self.get_bond_state_by_addr(&address) == BtBondState::Bonded && properties.iter().any(|prop| match prop { BluetoothProperty::TypeOfDevice(_) => true, _ => false, }) { // Update the connectable mode since the device type is changed. self.trigger_update_connectable_mode(); } } fn acl_state( Loading Loading @@ -1843,6 +1896,7 @@ impl BtifBluetoothCallbacks for Bluetooth { return; } let txl = self.tx.clone(); let address = addr.to_string(); let device = match self.get_remote_device_if_found_mut(&address) { None => { Loading Loading @@ -1888,12 +1942,12 @@ impl BtifBluetoothCallbacks for Bluetooth { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_connected(device.clone()); }); let tx = self.tx.clone(); let transport = match self.get_remote_type(bluetooth_device.clone()) { BtDeviceType::Bredr => BtTransport::Bredr, BtDeviceType::Ble => BtTransport::Le, _ => acl_reported_transport, }; let tx = txl.clone(); tokio::spawn(async move { let _ = tx .send(Message::OnAclConnected(bluetooth_device, transport)) Loading @@ -1904,12 +1958,20 @@ impl BtifBluetoothCallbacks for Bluetooth { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(device.clone()); }); let tx = self.tx.clone(); let tx = txl.clone(); tokio::spawn(async move { let _ = tx.send(Message::OnAclDisconnected(device.clone())).await; }); } }; // If we are bonding, skip the update here as we will update it after bonding complete anyway. // This is necessary for RTK controllers, which will break RNR after |Write Scan Enable| // command. Although this is a bug of RTK controllers, but as we could avoid unwanted page // scan, it makes sense to extend it to all BT controllers here. if Some(addr) != self.active_pairing_address { // Update the connectable since the connected state could be changed. self.trigger_update_connectable_mode(); } } } None => (), Loading Loading @@ -2097,13 +2159,13 @@ impl IBluetooth for Bluetooth { return false; } let off_mode = if self.is_connectable { BtScanMode::Connectable } else { BtScanMode::None_ }; let new_mode = match mode { BtDiscMode::LimitedDiscoverable => BtScanMode::ConnectableLimitedDiscoverable, BtDiscMode::GeneralDiscoverable => BtScanMode::ConnectableDiscoverable, BtDiscMode::NonDiscoverable => off_mode.clone(), BtDiscMode::NonDiscoverable => match self.is_connectable { true => BtScanMode::Connectable, false => BtScanMode::None_, }, }; // The old timer should be overwritten regardless of what the new mode is. Loading @@ -2119,13 +2181,10 @@ impl IBluetooth for Bluetooth { } if (mode != BtDiscMode::NonDiscoverable) && (duration != 0) { let intf_clone = self.intf.clone(); let txl = self.tx.clone(); self.discoverable_timeout = Some(tokio::spawn(async move { time::sleep(Duration::from_secs(duration.into())).await; intf_clone .lock() .unwrap() .set_adapter_property(BluetoothProperty::AdapterScanMode(off_mode)); let _ = txl.send(Message::TriggerUpdateConnectableMode).await; })); } Loading system/gd/rust/linux/stack/src/lib.rs +8 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ pub enum Message { ConnectionCallbackDisconnected(u32), // Some delayed actions for the adapter. TriggerUpdateConnectableMode, DelayedAdapterActions(DelayedActions), // Follows IBluetooth's on_device_(dis)connected callback but doesn't require depending on Loading Loading @@ -317,6 +318,13 @@ impl Stack { bluetooth.lock().unwrap().connection_callback_disconnected(id); } Message::TriggerUpdateConnectableMode => { let is_listening = bluetooth_socketmgr.lock().unwrap().is_listening(); bluetooth.lock().unwrap().handle_delayed_actions( DelayedActions::UpdateConnectableMode(is_listening), ); } Message::DelayedAdapterActions(action) => { bluetooth.lock().unwrap().handle_delayed_actions(action); } Loading system/gd/rust/linux/stack/src/socket_manager.rs +23 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,19 @@ impl BluetoothSocketManager { self.sock = Some(socket::BtSocket::new(&intf.lock().unwrap())); } /// Check if there is any listening socket. pub fn is_listening(&self) -> bool { self.listening.values().any(|vs| !vs.is_empty()) } /// Trigger adapter to update connectable mode. fn trigger_update_connectable_mode(&self) { let txl = self.tx.clone(); tokio::spawn(async move { let _ = txl.send(Message::TriggerUpdateConnectableMode).await; }); } // TODO(abps) - We need to save information about who the caller is so that // we can pipe it down to the lower levels. This needs to be // provided by the projection layer and is currently missing. Loading Loading @@ -652,6 +665,9 @@ impl BluetoothSocketManager { .or_default() .push(InternalListeningSocket::new(cbid, id, runner_tx, uuid, joinhandle)); // Update the connectable mode since the list of listening socket has changed. self.trigger_update_connectable_mode(); SocketResult::new(status, id) } Err(_) => { Loading Loading @@ -1172,6 +1188,9 @@ impl BluetoothSocketManager { .entry(cbid) .and_modify(|v| v.retain(|s| s.socket_id != socket_id)); } // Update the connectable mode since the list of listening socket has changed. self.trigger_update_connectable_mode(); } SocketActions::OnHandleIncomingConnection(cbid, socket_id, socket) => { Loading Loading @@ -1245,6 +1264,10 @@ impl BluetoothSocketManager { }); } }); // Update the connectable mode since the list of listening socket has changed. self.trigger_update_connectable_mode(); self.callbacks.remove_callback(callback); } Loading Loading
system/gd/rust/linux/stack/src/bluetooth.rs +73 −14 Original line number Diff line number Diff line Loading @@ -308,6 +308,9 @@ pub enum DelayedActions { /// Scanner for BLE discovery is reporting a result. BleDiscoveryScannerResult(ScanResult), /// Update the connectable mode to allow or disallow classic reconnect UpdateConnectableMode(bool), } /// Serializable device used in various apis. Loading Loading @@ -602,6 +605,35 @@ impl Bluetooth { } } fn update_connectable_mode(&mut self, is_sock_listening: bool) { // Set connectable if // - there is bredr socket listening, or // - there is a classic device bonded and not connected self.set_connectable_internal( is_sock_listening || self.bonded_devices.iter().any(|(_name, ctx)| { ctx.acl_state == BtAclState::Disconnected && ctx .properties .get(&BtPropertyType::TypeOfDevice) .and_then(|prop| match prop { BluetoothProperty::TypeOfDevice(transport) => { Some(*transport != BtDeviceType::Ble) } _ => None, }) .unwrap_or(false) }), ); } fn trigger_update_connectable_mode(&self) { let txl = self.tx.clone(); tokio::spawn(async move { let _ = txl.send(Message::TriggerUpdateConnectableMode).await; }); } fn disable_profile(&mut self, profile: &Profile) { if !UuidHelper::is_profile_supported(profile) { return; Loading Loading @@ -1074,6 +1106,9 @@ impl Bluetooth { self.found_devices.insert(address.clone(), device_with_props); } } DelayedActions::UpdateConnectableMode(is_sock_listening) => { self.update_connectable_mode(is_sock_listening); } } } Loading Loading @@ -1400,8 +1435,8 @@ impl BtifBluetoothCallbacks for Bluetooth { self.ble_scanner_uuid = Some(self.bluetooth_gatt.lock().unwrap().register_scanner(callback_id)); // Ensure device is connectable so that disconnected device can reconnect self.set_connectable(true); // Update connectable mode so that disconnected bonded classic device can reconnect self.trigger_update_connectable_mode(); // Spawn a freshness check job in the background. self.freshness_check.take().map(|h| h.abort()); Loading Loading @@ -1487,6 +1522,9 @@ impl BtifBluetoothCallbacks for Bluetooth { self.bonded_devices.entry(address.clone()).or_insert(device).bond_state = BtBondState::Bonded; } // Update the connectable mode since bonded device list might be updated. self.trigger_update_connectable_mode(); } BluetoothProperty::BdName(bdname) => { self.callbacks.for_all_callbacks(|callback| { Loading Loading @@ -1715,6 +1753,8 @@ impl BtifBluetoothCallbacks for Bluetooth { // bond request to avoid ACL connection from interfering with active inquiry. if &bond_state == &BtBondState::NotBonded || &bond_state == &BtBondState::Bonded { self.resume_discovery(); // Update the connectable mode since bonded list is changed. self.trigger_update_connectable_mode(); } // Send bond state changed notifications Loading Loading @@ -1744,6 +1784,7 @@ impl BtifBluetoothCallbacks for Bluetooth { ) { let address = addr.to_string(); let txl = self.tx.clone(); let device = match self.get_remote_device_if_found_mut(&address) { None => { self.found_devices.insert( Loading Loading @@ -1785,8 +1826,9 @@ impl BtifBluetoothCallbacks for Bluetooth { d.wait_to_connect = false; let sent_info = info.clone(); let tx = txl.clone(); tokio::spawn(async move { let _ = txl let _ = tx .send(Message::DelayedAdapterActions( DelayedActions::ConnectAllProfiles(sent_info), )) Loading @@ -1809,6 +1851,17 @@ impl BtifBluetoothCallbacks for Bluetooth { } None => (), } // Only care about device type property changed on bonded device. // If the property change happens during bonding, it will be updated after bonding complete anyway. if self.get_bond_state_by_addr(&address) == BtBondState::Bonded && properties.iter().any(|prop| match prop { BluetoothProperty::TypeOfDevice(_) => true, _ => false, }) { // Update the connectable mode since the device type is changed. self.trigger_update_connectable_mode(); } } fn acl_state( Loading Loading @@ -1843,6 +1896,7 @@ impl BtifBluetoothCallbacks for Bluetooth { return; } let txl = self.tx.clone(); let address = addr.to_string(); let device = match self.get_remote_device_if_found_mut(&address) { None => { Loading Loading @@ -1888,12 +1942,12 @@ impl BtifBluetoothCallbacks for Bluetooth { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_connected(device.clone()); }); let tx = self.tx.clone(); let transport = match self.get_remote_type(bluetooth_device.clone()) { BtDeviceType::Bredr => BtTransport::Bredr, BtDeviceType::Ble => BtTransport::Le, _ => acl_reported_transport, }; let tx = txl.clone(); tokio::spawn(async move { let _ = tx .send(Message::OnAclConnected(bluetooth_device, transport)) Loading @@ -1904,12 +1958,20 @@ impl BtifBluetoothCallbacks for Bluetooth { self.connection_callbacks.for_all_callbacks(|callback| { callback.on_device_disconnected(device.clone()); }); let tx = self.tx.clone(); let tx = txl.clone(); tokio::spawn(async move { let _ = tx.send(Message::OnAclDisconnected(device.clone())).await; }); } }; // If we are bonding, skip the update here as we will update it after bonding complete anyway. // This is necessary for RTK controllers, which will break RNR after |Write Scan Enable| // command. Although this is a bug of RTK controllers, but as we could avoid unwanted page // scan, it makes sense to extend it to all BT controllers here. if Some(addr) != self.active_pairing_address { // Update the connectable since the connected state could be changed. self.trigger_update_connectable_mode(); } } } None => (), Loading Loading @@ -2097,13 +2159,13 @@ impl IBluetooth for Bluetooth { return false; } let off_mode = if self.is_connectable { BtScanMode::Connectable } else { BtScanMode::None_ }; let new_mode = match mode { BtDiscMode::LimitedDiscoverable => BtScanMode::ConnectableLimitedDiscoverable, BtDiscMode::GeneralDiscoverable => BtScanMode::ConnectableDiscoverable, BtDiscMode::NonDiscoverable => off_mode.clone(), BtDiscMode::NonDiscoverable => match self.is_connectable { true => BtScanMode::Connectable, false => BtScanMode::None_, }, }; // The old timer should be overwritten regardless of what the new mode is. Loading @@ -2119,13 +2181,10 @@ impl IBluetooth for Bluetooth { } if (mode != BtDiscMode::NonDiscoverable) && (duration != 0) { let intf_clone = self.intf.clone(); let txl = self.tx.clone(); self.discoverable_timeout = Some(tokio::spawn(async move { time::sleep(Duration::from_secs(duration.into())).await; intf_clone .lock() .unwrap() .set_adapter_property(BluetoothProperty::AdapterScanMode(off_mode)); let _ = txl.send(Message::TriggerUpdateConnectableMode).await; })); } Loading
system/gd/rust/linux/stack/src/lib.rs +8 −0 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ pub enum Message { ConnectionCallbackDisconnected(u32), // Some delayed actions for the adapter. TriggerUpdateConnectableMode, DelayedAdapterActions(DelayedActions), // Follows IBluetooth's on_device_(dis)connected callback but doesn't require depending on Loading Loading @@ -317,6 +318,13 @@ impl Stack { bluetooth.lock().unwrap().connection_callback_disconnected(id); } Message::TriggerUpdateConnectableMode => { let is_listening = bluetooth_socketmgr.lock().unwrap().is_listening(); bluetooth.lock().unwrap().handle_delayed_actions( DelayedActions::UpdateConnectableMode(is_listening), ); } Message::DelayedAdapterActions(action) => { bluetooth.lock().unwrap().handle_delayed_actions(action); } Loading
system/gd/rust/linux/stack/src/socket_manager.rs +23 −0 Original line number Diff line number Diff line Loading @@ -554,6 +554,19 @@ impl BluetoothSocketManager { self.sock = Some(socket::BtSocket::new(&intf.lock().unwrap())); } /// Check if there is any listening socket. pub fn is_listening(&self) -> bool { self.listening.values().any(|vs| !vs.is_empty()) } /// Trigger adapter to update connectable mode. fn trigger_update_connectable_mode(&self) { let txl = self.tx.clone(); tokio::spawn(async move { let _ = txl.send(Message::TriggerUpdateConnectableMode).await; }); } // TODO(abps) - We need to save information about who the caller is so that // we can pipe it down to the lower levels. This needs to be // provided by the projection layer and is currently missing. Loading Loading @@ -652,6 +665,9 @@ impl BluetoothSocketManager { .or_default() .push(InternalListeningSocket::new(cbid, id, runner_tx, uuid, joinhandle)); // Update the connectable mode since the list of listening socket has changed. self.trigger_update_connectable_mode(); SocketResult::new(status, id) } Err(_) => { Loading Loading @@ -1172,6 +1188,9 @@ impl BluetoothSocketManager { .entry(cbid) .and_modify(|v| v.retain(|s| s.socket_id != socket_id)); } // Update the connectable mode since the list of listening socket has changed. self.trigger_update_connectable_mode(); } SocketActions::OnHandleIncomingConnection(cbid, socket_id, socket) => { Loading Loading @@ -1245,6 +1264,10 @@ impl BluetoothSocketManager { }); } }); // Update the connectable mode since the list of listening socket has changed. self.trigger_update_connectable_mode(); self.callbacks.remove_callback(callback); } Loading