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

Commit 39e67c97 authored by Ying Hsu's avatar Ying Hsu Committed by Gerrit Code Review
Browse files

Merge "floss: Pause active advertising sets for suspend"

parents 772d56d1 8deee9ad
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -535,6 +535,10 @@ impl IAdvertisingSetCallback for AdvertisingSetCallback {
            status
        );
    }

    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode) {
        print_info!("on_suspend_mode_change: advertising suspend_mode = {:?}", suspend_mode);
    }
}

impl RPCProxy for AdvertisingSetCallback {
+3 −0
Original line number Diff line number Diff line
@@ -796,6 +796,9 @@ impl IAdvertisingSetCallback for IAdvertisingSetCallbackDBus {
        status: GattStatus,
    ) {
    }

    #[dbus_method("OnSuspendModeChange")]
    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode) {}
}

#[dbus_propmap(AdvertisingSetParameters)]
+5 −0
Original line number Diff line number Diff line
@@ -398,6 +398,11 @@ impl IAdvertisingSetCallback for AdvertisingSetCallbackDBus {
    ) {
        dbus_generated!()
    }

    #[dbus_method("OnSuspendModeChange")]
    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode) {
        dbus_generated!()
    }
}

#[dbus_propmap(AdvertisingSetParameters)]
+93 −2
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ use tokio::sync::mpsc::Sender;

use crate::callbacks::Callbacks;
use crate::uuid::UuidHelper;
use crate::{Message, RPCProxy};
use crate::{Message, RPCProxy, SuspendMode};

pub type AdvertiserId = i32;
pub type CallbackId = u32;
@@ -136,6 +136,9 @@ pub trait IAdvertisingSetCallback: RPCProxy {
    /// Callback triggered in response to `set_periodic_advertising_enable` indicating result of
    /// the operation.
    fn on_periodic_advertising_enabled(&self, advertiser_id: i32, enable: bool, status: GattStatus);

    /// When advertising module changes its suspend mode due to system suspend/resume.
    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode);
}

// Advertising interval range.
@@ -180,6 +183,9 @@ const SOLICIT_AD_TYPES: [u8; 3] = [
// Invalid advertising set id.
const INVALID_ADV_ID: i32 = 0xff;

// Invalid advertising set id.
pub const INVALID_REG_ID: i32 = -1;

impl Into<bt_topshim::profiles::gatt::AdvertiseParameters> for AdvertisingSetParameters {
    fn into(self) -> bt_topshim::profiles::gatt::AdvertiseParameters {
        let mut props: u16 = 0;
@@ -364,6 +370,9 @@ pub(crate) struct AdvertisingSetInfo {
    /// Whether the advertising set has been enabled.
    enabled: bool,

    /// Whether the advertising set has been paused.
    paused: bool,

    /// Advertising duration, in 10 ms unit.
    adv_timeout: u16,

@@ -374,11 +383,16 @@ pub(crate) struct AdvertisingSetInfo {

impl AdvertisingSetInfo {
    pub(crate) fn new(callback_id: CallbackId, adv_timeout: u16, adv_events: u8) -> Self {
        let mut reg_id = REG_ID_COUNTER.fetch_add(1, Ordering::SeqCst) as RegId;
        if reg_id == INVALID_REG_ID {
            reg_id = REG_ID_COUNTER.fetch_add(1, Ordering::SeqCst) as RegId;
        }
        AdvertisingSetInfo {
            adv_id: None,
            callback_id,
            reg_id: REG_ID_COUNTER.fetch_add(1, Ordering::SeqCst) as RegId,
            reg_id,
            enabled: false,
            paused: false,
            adv_timeout,
            adv_events,
        }
@@ -415,6 +429,16 @@ impl AdvertisingSetInfo {
        self.enabled
    }

    /// Marks the advertising set as paused or not.
    pub(crate) fn set_paused(&mut self, paused: bool) {
        self.paused = paused;
    }

    /// Returns true if the advertising set has been paused, false otherwise.
    pub(crate) fn is_paused(&self) -> bool {
        self.paused
    }

    /// Gets adv_timeout.
    pub(crate) fn adv_timeout(&self) -> u16 {
        self.adv_timeout
@@ -430,6 +454,7 @@ impl AdvertisingSetInfo {
pub(crate) struct Advertisers {
    callbacks: Callbacks<dyn IAdvertisingSetCallback + Send>,
    sets: HashMap<RegId, AdvertisingSetInfo>,
    suspend_mode: SuspendMode,
}

impl Advertisers {
@@ -437,6 +462,7 @@ impl Advertisers {
        Advertisers {
            callbacks: Callbacks::new(tx, Message::AdvertiserCallbackDisconnected),
            sets: HashMap::new(),
            suspend_mode: SuspendMode::Normal,
        }
    }

@@ -447,6 +473,31 @@ impl Advertisers {
        }
    }

    /// Returns an iterator of valid advertising sets.
    pub(crate) fn valid_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo> {
        self.sets.iter().filter_map(|(_, s)| s.adv_id.map(|_| s))
    }

    /// Returns a mutable iterator of valid advertising sets.
    pub(crate) fn valid_sets_mut(&mut self) -> impl Iterator<Item = &mut AdvertisingSetInfo> {
        self.sets.iter_mut().filter_map(|(_, s)| s.adv_id.map(|_| s))
    }

    /// Returns an iterator of enabled advertising sets.
    pub(crate) fn enabled_sets(&self) -> impl Iterator<Item = &AdvertisingSetInfo> {
        self.valid_sets().filter(|s| s.is_enabled())
    }

    /// Returns a mutable iterator of enabled advertising sets.
    pub(crate) fn enabled_sets_mut(&mut self) -> impl Iterator<Item = &mut AdvertisingSetInfo> {
        self.valid_sets_mut().filter(|s| s.is_enabled())
    }

    /// Returns a mutable iterator of paused advertising sets.
    pub(crate) fn paused_sets_mut(&mut self) -> impl Iterator<Item = &mut AdvertisingSetInfo> {
        self.valid_sets_mut().filter(|s| s.is_paused())
    }

    fn find_reg_id(&self, adv_id: AdvertiserId) -> Option<RegId> {
        for (_, s) in &self.sets {
            if s.adv_id == Some(adv_id) {
@@ -532,6 +583,26 @@ impl Advertisers {

        self.callbacks.remove_callback(callback_id)
    }

    /// Update suspend mode.
    pub(crate) fn set_suspend_mode(&mut self, suspend_mode: SuspendMode) {
        if suspend_mode != self.suspend_mode {
            self.suspend_mode = suspend_mode;
            self.notify_suspend_mode();
        }
    }

    /// Gets current suspend mode.
    pub(crate) fn suspend_mode(&mut self) -> SuspendMode {
        self.suspend_mode.clone()
    }

    /// Notify current suspend mode to all active callbacks.
    fn notify_suspend_mode(&mut self) {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_suspend_mode_change(self.suspend_mode.clone());
        });
    }
}

#[cfg(test)]
@@ -573,6 +644,26 @@ mod tests {
        }
    }

    #[test]
    fn test_iterate_adving_set_info() {
        let (tx, _rx) = crate::Stack::create_channel();
        let mut advertisers = Advertisers::new(tx.clone());

        let size = 256;
        for i in 0..size {
            let callback_id: CallbackId = i as CallbackId;
            let adv_id: AdvertiserId = i as AdvertiserId;
            let mut s = AdvertisingSetInfo::new(callback_id, 0, 0);
            s.set_adv_id(Some(adv_id));
            advertisers.add(s);
        }

        assert_eq!(advertisers.valid_sets().count(), size);
        for s in advertisers.valid_sets() {
            assert_eq!(s.callback_id() as u32, s.adv_id() as u32);
        }
    }

    #[test]
    fn test_append_service_uuids() {
        let mut bytes = Vec::<u8>::new();
+83 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ use bt_utils::adv_parser;
use crate::bluetooth::{Bluetooth, IBluetooth};
use crate::bluetooth_adv::{
    AdvertiseData, Advertisers, AdvertisingSetInfo, AdvertisingSetParameters,
    IAdvertisingSetCallback, PeriodicAdvertisingParameters,
    IAdvertisingSetCallback, PeriodicAdvertisingParameters, INVALID_REG_ID,
};
use crate::callbacks::Callbacks;
use crate::uuid::UuidHelper;
@@ -904,6 +904,42 @@ impl BluetoothGatt {
        // Always remove callback.
        self.context_map.remove_callback(callback_id);
    }

    /// Enters suspend mode for LE advertising.
    pub fn advertising_enter_suspend(&mut self) {
        self.advertisers.set_suspend_mode(SuspendMode::Suspending);

        let mut pausing_cnt = 0;
        for s in self.advertisers.enabled_sets_mut() {
            s.set_paused(true);
            self.gatt.as_mut().unwrap().advertiser.enable(
                s.adv_id(),
                false,
                s.adv_timeout(),
                s.adv_events(),
            );
            pausing_cnt += 1;
        }

        if pausing_cnt == 0 {
            self.advertisers.set_suspend_mode(SuspendMode::Suspended);
        }
    }

    /// Exits suspend mode for LE advertising.
    pub fn advertising_exit_suspend(&mut self) {
        for s in self.advertisers.paused_sets_mut() {
            s.set_paused(false);
            self.gatt.as_mut().unwrap().advertiser.enable(
                s.adv_id(),
                true,
                s.adv_timeout(),
                s.adv_events(),
            );
        }

        self.advertisers.set_suspend_mode(SuspendMode::Normal);
    }
}

#[derive(Debug, FromPrimitive, ToPrimitive)]
@@ -1031,6 +1067,10 @@ impl IBluetoothGatt for BluetoothGatt {
        max_ext_adv_events: i32,
        callback_id: u32,
    ) -> i32 {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return INVALID_REG_ID;
        }

        let device_name = self.get_adapter_name();
        let params = parameters.into();
        let adv_bytes = advertise_data.make_with(&device_name);
@@ -1064,6 +1104,10 @@ impl IBluetoothGatt for BluetoothGatt {
    }

    fn stop_advertising_set(&mut self, advertiser_id: i32) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let s = self.advertisers.get_by_advertiser_id(advertiser_id);
        if None == s {
            return;
@@ -1079,6 +1123,10 @@ impl IBluetoothGatt for BluetoothGatt {
    }

    fn get_own_address(&mut self, advertiser_id: i32) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        if let Some(s) = self.advertisers.get_by_advertiser_id(advertiser_id) {
            self.gatt.as_mut().unwrap().advertiser.get_own_address(s.adv_id());
        }
@@ -1091,6 +1139,10 @@ impl IBluetoothGatt for BluetoothGatt {
        duration: i32,
        max_ext_adv_events: i32,
    ) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let adv_timeout = clamp(duration, 0, 0xffff) as u16;
        let adv_events = clamp(max_ext_adv_events, 0, 0xff) as u8;

@@ -1105,6 +1157,10 @@ impl IBluetoothGatt for BluetoothGatt {
    }

    fn set_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let device_name = self.get_adapter_name();
        let bytes = data.make_with(&device_name);

@@ -1114,6 +1170,10 @@ impl IBluetoothGatt for BluetoothGatt {
    }

    fn set_scan_response_data(&mut self, advertiser_id: i32, data: AdvertiseData) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let device_name = self.get_adapter_name();
        let bytes = data.make_with(&device_name);

@@ -1127,6 +1187,10 @@ impl IBluetoothGatt for BluetoothGatt {
        advertiser_id: i32,
        parameters: AdvertisingSetParameters,
    ) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let params = parameters.into();

        if let Some(s) = self.advertisers.get_by_advertiser_id(advertiser_id) {
@@ -1156,6 +1220,10 @@ impl IBluetoothGatt for BluetoothGatt {
        advertiser_id: i32,
        parameters: PeriodicAdvertisingParameters,
    ) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let params = parameters.into();

        if let Some(s) = self.advertisers.get_by_advertiser_id(advertiser_id) {
@@ -1168,6 +1236,10 @@ impl IBluetoothGatt for BluetoothGatt {
    }

    fn set_periodic_advertising_data(&mut self, advertiser_id: i32, data: AdvertiseData) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        let device_name = self.get_adapter_name();
        let bytes = data.make_with(&device_name);

@@ -1177,6 +1249,10 @@ impl IBluetoothGatt for BluetoothGatt {
    }

    fn set_periodic_advertising_enable(&mut self, advertiser_id: i32, enable: bool) {
        if self.advertisers.suspend_mode() != SuspendMode::Normal {
            return;
        }

        if let Some(s) = self.advertisers.get_by_advertiser_id(advertiser_id) {
            self.gatt
                .as_mut()
@@ -2467,6 +2543,12 @@ impl BtifGattAdvCallbacks for BluetoothGatt {
        if let Some(cb) = self.advertisers.get_callback(&s) {
            cb.on_advertising_enabled(advertiser_id, enabled, status);
        }

        if self.advertisers.suspend_mode() == SuspendMode::Suspending {
            if self.advertisers.enabled_sets().count() == 0 {
                self.advertisers.set_suspend_mode(SuspendMode::Suspended);
            }
        }
    }

    fn on_advertising_data_set(&mut self, adv_id: u8, status: GattStatus) {
Loading