Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 171968e8 authored by Yun-Hao Chung's avatar Yun-Hao Chung Committed by Yun-hao Chung
Browse files

Floss: Only enable page scan when necessary

Currently we always enable page scan upon adapter is on. This causes
some chipset, ex. QCA6174A5, to have performance drop on inquiry
compairing to BlueZ.

Since page scan is used to allow classic device to reconnect, this
CL make Floss to only enable page scan when
1. there is at least 1 non-connected, bonded classic device, or
2. there is at least 1 l2cap or rfcomm socket listening.
This aligns with BlueZ.

Bug: 321519705
Test: manual test
Test: run tauto.bluetooth_AdapterCLHealth.cl_adapter_pairing_test.floss on dewatt
Test: m -j
Tag: #floss
Flag: EXEMPT, Floss only change
Change-Id: I9b804745c1836089e854206dd4b35e5f31cdf08e
parent ab8f9b20
Loading
Loading
Loading
Loading
+73 −14
Original line number Diff line number Diff line
@@ -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.
@@ -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;
@@ -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);
            }
        }
    }

@@ -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());
@@ -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| {
@@ -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
@@ -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(
@@ -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),
                            ))
@@ -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(
@@ -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 => {
@@ -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))
@@ -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 => (),
@@ -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.
@@ -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;
            }));
        }

+8 −0
Original line number Diff line number Diff line
@@ -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
@@ -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);
                }
+23 −0
Original line number Diff line number Diff line
@@ -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.
@@ -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(_) => {
@@ -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) => {
@@ -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);
    }