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

Commit 7c732aeb authored by Jesse Melhuish's avatar Jesse Melhuish Committed by Jesse Melhuish
Browse files

Floss: Disconnect GATT connections eagerly

There's no reason to keep these connections around.
Bug: 295577710
Bug: 339529897
Tag: #Floss
Test: mma -j80
Test: manual
FLAG: EXEMPT, floss-only

Change-Id: I5f90a6932c2e4d48d771e2511a0e8afed9b5b8f0
parent 535348cc
Loading
Loading
Loading
Loading
+73 −46
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ use crate::bluetooth_gatt::{
    BluetoothGatt, BluetoothGattService, IBluetoothGatt, IBluetoothGattCallback,
};
use crate::callbacks::Callbacks;
use crate::uuid::UuidHelper;
use crate::Message;
use crate::RPCProxy;
use crate::{uuid, APIMessage, BluetoothAPI};
@@ -162,63 +163,53 @@ impl BatteryService {
                        DisplayAddress(&addr),
                        status
                    );
                    self.drop_device(addr);
                    return;
                }
                let (bas_uuid, battery_level_uuid) = match (
                    Uuid::from_string(uuid::BAS),
                    Uuid::from_string(CHARACTERISTIC_BATTERY_LEVEL),
                ) {
                    (Some(bas_uuid), Some(battery_level_uuid)) => (bas_uuid, battery_level_uuid),
                    _ => return,
                };
                // TODO(b/233101174): handle multiple instances of BAS
                let bas = match services.iter().find(|service| service.uuid == bas_uuid) {
                    Some(bas) => bas,
                    None => {
                let handle = match self.get_battery_level_handle(addr.clone(), services) {
                    Ok(battery_level_handle) => battery_level_handle,
                    Err(status) => {
                        if let Some(BatteryServiceStatus::BatteryServiceNotSupported) = status {
                            self.callbacks.for_all_callbacks(|callback| {
                                callback.on_battery_service_status_updated(
                                addr,
                                    addr.clone(),
                                    BatteryServiceStatus::BatteryServiceNotSupported,
                                )
                            });
                        return;
                        }
                };
                let battery_level = match bas
                    .characteristics
                    .iter()
                    .find(|characteristic| characteristic.uuid == battery_level_uuid)
                {
                    Some(battery_level) => battery_level,
                    None => {
                        debug!(
                            "Device {} has no BatteryLevel characteristic",
                            DisplayAddress(&addr)
                        );
                        self.drop_device(addr);
                        return;
                    }
                };
                let client_id = match self.client_id {
                    Some(id) => id,
                    None => return,
                    None => {
                        self.drop_device(addr);
                        return;
                    }
                };
                let handle = battery_level.instance_id;
                self.handles.insert(addr, handle.clone());
                self.gatt.lock().unwrap().register_for_notification(client_id, addr, handle, true);
                if let None = self.battery_sets.get(&addr) {
                    self.gatt.lock().unwrap().read_characteristic(
                        client_id,
                        addr,
                        battery_level.instance_id,
                        0,
                    );
                    self.gatt.lock().unwrap().read_characteristic(client_id, addr, handle, 0);
                }
            }

            BatteryServiceActions::OnCharacteristicRead(addr, status, _handle, value) => {
            BatteryServiceActions::OnCharacteristicRead(addr, status, handle, value) => {
                if status != GattStatus::Success {
                    return;
                }
                match self.handles.get(&addr) {
                    Some(stored_handle) => {
                        if *stored_handle != handle {
                            return;
                        }
                    }
                    None => {
                        self.drop_device(addr);
                        return;
                    }
                }
                let battery_info = self.set_battery_info(&addr, &value);
                self.callbacks.for_all_callbacks(|callback| {
                    callback.on_battery_info_updated(addr, battery_info.clone());
@@ -281,6 +272,15 @@ impl BatteryService {
    }

    fn drop_device(&mut self, remote_address: RawAddress) {
        if self.handles.contains_key(&remote_address) {
            // Let BatteryProviderManager know that BAS no longer has a battery for this device.
            self.battery_provider_manager.lock().unwrap().remove_battery_info(
                self.battery_provider_id,
                remote_address.clone(),
                uuid::BAS.to_string(),
            );
        }
        self.battery_sets.remove(&remote_address);
        self.handles.remove(&remote_address);
        match self.client_id {
            Some(client_id) => {
@@ -288,13 +288,40 @@ impl BatteryService {
            }
            None => return,
        }
        // Let BatteryProviderManager know that BAS no longer has a battery for this device.
        self.battery_provider_manager.lock().unwrap().remove_battery_info(
            self.battery_provider_id,
            remote_address,
            uuid::BAS.to_string(),
    }

    fn get_battery_level_handle(
        &mut self,
        remote_address: RawAddress,
        services: Vec<BluetoothGattService>,
    ) -> Result<i32, Option<BatteryServiceStatus>> {
        let (bas_uuid, battery_level_uuid) =
            match (Uuid::from_string(uuid::BAS), Uuid::from_string(CHARACTERISTIC_BATTERY_LEVEL)) {
                (Some(bas_uuid), Some(battery_level_uuid)) => (bas_uuid, battery_level_uuid),
                _ => {
                    return Err(None);
                }
            };
        // TODO(b/233101174): handle multiple instances of BAS
        let bas = match services.iter().find(|service| service.uuid == bas_uuid) {
            Some(bas) => bas,
            None => return Err(Some(BatteryServiceStatus::BatteryServiceNotSupported)),
        };
        let battery_level = match bas
            .characteristics
            .iter()
            .find(|characteristic| characteristic.uuid == battery_level_uuid)
        {
            Some(battery_level) => battery_level,
            None => {
                debug!(
                    "Device {} has no BatteryLevel characteristic",
                    DisplayAddress(&remote_address)
                );
        self.battery_sets.remove(&remote_address);
                return Err(None);
            }
        };
        Ok(battery_level.instance_id)
    }

    /// Perform an explicit read on all devices BAS knows about.