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

Commit 2b1b626c authored by Hsin-chen Chuang's avatar Hsin-chen Chuang
Browse files

Floss: Adv: Reuse the reg IDs to restrict the ID in a small range

LibBluetooth hard-coded 0xff as a reg ID that won't generate any
callback. To prevent from conflicting with some special IDs, restrict
the IDs in a smaller range by reusing them.

Bug: 301220519
Tag: #floss
Test: mmm packages/modules/Bluetooth
Test: Deployed and verified the reg_id is reused in small range
Test: Manually tested Cross Device features
Change-Id: Ia6ec1c9a6f3b75c90ad8edbc769a679464cb35a4
parent 2f4a9664
Loading
Loading
Loading
Loading
+35 −16
Original line number Original line Diff line number Diff line
@@ -7,7 +7,6 @@ use itertools::Itertools;
use log::warn;
use log::warn;
use num_traits::clamp;
use num_traits::clamp;
use std::collections::HashMap;
use std::collections::HashMap;
use std::sync::atomic::{AtomicIsize, Ordering};
use tokio::sync::mpsc::Sender;
use tokio::sync::mpsc::Sender;


use crate::callbacks::Callbacks;
use crate::callbacks::Callbacks;
@@ -375,9 +374,6 @@ impl Into<bt_topshim::profiles::gatt::PeriodicAdvertisingParameters>
    }
    }
}
}


/// Monotonically increasing counter for reg_id.
static REG_ID_COUNTER: AtomicIsize = AtomicIsize::new(0);

// Keeps information of an advertising set.
// Keeps information of an advertising set.
#[derive(Debug, PartialEq, Copy, Clone)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub(crate) struct AdvertisingSetInfo {
pub(crate) struct AdvertisingSetInfo {
@@ -418,11 +414,8 @@ impl AdvertisingSetInfo {
        adv_timeout: u16,
        adv_timeout: u16,
        adv_events: u8,
        adv_events: u8,
        legacy: bool,
        legacy: bool,
        reg_id: RegId,
    ) -> Self {
    ) -> 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 {
        AdvertisingSetInfo {
            adv_id: None,
            adv_id: None,
            callback_id,
            callback_id,
@@ -519,6 +512,13 @@ impl Advertisers {
        }
        }
    }
    }


    // Returns the minimum unoccupied register ID from 0.
    pub(crate) fn new_reg_id(&mut self) -> RegId {
        (0..)
            .find(|id| !self.sets.contains_key(id))
            .expect("There must be an unoccupied register ID")
    }

    /// Adds an advertising set.
    /// Adds an advertising set.
    pub(crate) fn add(&mut self, s: AdvertisingSetInfo) {
    pub(crate) fn add(&mut self, s: AdvertisingSetInfo) {
        if let Some(old) = self.sets.insert(s.reg_id(), s) {
        if let Some(old) = self.sets.insert(s.reg_id(), s) {
@@ -667,7 +667,6 @@ impl Advertisers {
#[cfg(test)]
#[cfg(test)]
mod tests {
mod tests {
    use super::*;
    use super::*;
    use std::collections::HashSet;
    use std::iter::FromIterator;
    use std::iter::FromIterator;


    #[test]
    #[test]
@@ -694,12 +693,31 @@ mod tests {
    }
    }


    #[test]
    #[test]
    fn test_new_advising_set_info() {
    fn test_add_remove_advising_set_info() {
        let mut uniq = HashSet::new();
        let (tx, _rx) = crate::Stack::create_channel();
        for callback_id in 0..256 {
        let mut advertisers = Advertisers::new(tx.clone());
            let s = AdvertisingSetInfo::new(callback_id, 0, 0, false);
        for i in 0..35 {
            assert_eq!(s.callback_id(), callback_id);
            let reg_id = i * 2 as RegId;
            assert_eq!(uniq.insert(s.reg_id()), true);
            let s = AdvertisingSetInfo::new(0 as CallbackId, 0, 0, false, reg_id);
            advertisers.add(s);
        }
        for i in 0..35 {
            let expected_reg_id = i * 2 + 1 as RegId;
            let reg_id = advertisers.new_reg_id();
            assert_eq!(reg_id, expected_reg_id);
            let s = AdvertisingSetInfo::new(0 as CallbackId, 0, 0, false, reg_id);
            advertisers.add(s);
        }
        for i in 0..35 {
            let reg_id = i * 2 as RegId;
            assert!(advertisers.remove_by_reg_id(reg_id).is_some());
        }
        for i in 0..35 {
            let expected_reg_id = i * 2 as RegId;
            let reg_id = advertisers.new_reg_id();
            assert_eq!(reg_id, expected_reg_id);
            let s = AdvertisingSetInfo::new(0 as CallbackId, 0, 0, false, reg_id);
            advertisers.add(s);
        }
        }
    }
    }


@@ -712,7 +730,8 @@ mod tests {
        for i in 0..size {
        for i in 0..size {
            let callback_id: CallbackId = i as CallbackId;
            let callback_id: CallbackId = i as CallbackId;
            let adv_id: AdvertiserId = i as AdvertiserId;
            let adv_id: AdvertiserId = i as AdvertiserId;
            let mut s = AdvertisingSetInfo::new(callback_id, 0, 0, false);
            let reg_id = advertisers.new_reg_id();
            let mut s = AdvertisingSetInfo::new(callback_id, 0, 0, false, reg_id);
            s.set_adv_id(Some(adv_id));
            s.set_adv_id(Some(adv_id));
            advertisers.add(s);
            advertisers.add(s);
        }
        }
+2 −2
Original line number Original line Diff line number Diff line
@@ -2042,8 +2042,8 @@ impl IBluetoothGatt for BluetoothGatt {
        let adv_timeout = clamp(duration, 0, 0xffff) as u16;
        let adv_timeout = clamp(duration, 0, 0xffff) as u16;
        let adv_events = clamp(max_ext_adv_events, 0, 0xff) as u8;
        let adv_events = clamp(max_ext_adv_events, 0, 0xff) as u8;


        let s = AdvertisingSetInfo::new(callback_id, adv_timeout, adv_events, is_legacy);
        let reg_id = self.advertisers.new_reg_id();
        let reg_id = s.reg_id();
        let s = AdvertisingSetInfo::new(callback_id, adv_timeout, adv_events, is_legacy, reg_id);
        self.advertisers.add(s);
        self.advertisers.add(s);


        self.gatt.as_ref().unwrap().lock().unwrap().advertiser.start_advertising_set(
        self.gatt.as_ref().unwrap().lock().unwrap().advertiser.start_advertising_set(