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

Commit 5876b981 authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi Committed by Abhishek Pandit-Subedi
Browse files

floss: Refactor callback registration

Rather than have every callback registration mechanism provide its own
id generator, have RpcProxy::register_disconnection return an id that is
unique to that instance of DisconnectionWatcher (global for btadapterd).

Bug: 201599762
Tag: #floss
Test: Open btclient and monitor dbus returned callback id

Change-Id: I50fd04002cc5122270db48255779f062d2b054ad
parent f43df148
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -39,7 +39,9 @@ impl IBluetoothManagerCallback for BtManagerCallback {
}

impl manager_service::RPCProxy for BtManagerCallback {
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
@@ -166,7 +168,9 @@ impl IBluetoothCallback for BtCallback {
}

impl RPCProxy for BtCallback {
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
@@ -199,7 +203,9 @@ impl IBluetoothConnectionCallback for BtConnectionCallback {
}

impl RPCProxy for BtConnectionCallback {
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
@@ -350,7 +356,9 @@ impl IBluetoothGattCallback for BtGattCallback {
}

impl RPCProxy for BtGattCallback {
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }

    fn get_object_id(&self) -> String {
        self.objpath.clone()
+12 −4
Original line number Diff line number Diff line
@@ -148,7 +148,9 @@ struct IBluetoothCallbackDBus {}

impl btstack::RPCProxy for IBluetoothCallbackDBus {
    // Dummy implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
@@ -190,7 +192,9 @@ struct IBluetoothConnectionCallbackDBus {}

impl btstack::RPCProxy for IBluetoothConnectionCallbackDBus {
    // Dummy implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
@@ -470,7 +474,9 @@ struct IBluetoothManagerCallbackDBus {}

impl manager_service::RPCProxy for IBluetoothManagerCallbackDBus {
    // Placeholder implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
@@ -698,7 +704,9 @@ struct IBluetoothGattCallbackDBus {}

impl btstack::RPCProxy for IBluetoothGattCallbackDBus {
    // Placeholder implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _id: u32, _f: Box<dyn Fn(u32) + Send>) {}
    fn register_disconnect(&mut self, _f: Box<dyn Fn(u32) + Send>) -> u32 {
        0
    }
    fn get_object_id(&self) -> String {
        String::from("")
    }
+3 −3
Original line number Diff line number Diff line
@@ -431,7 +431,7 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {
        #ori_item

        impl RPCProxy for #self_ty {
            fn register_disconnect(&mut self, _id: u32, _disconnect_callback: Box<dyn Fn(u32) + Send>) {}
            fn register_disconnect(&mut self, _disconnect_callback: Box<dyn Fn(u32) + Send>) -> u32 { 0 }
            fn get_object_id(&self) -> String {
                String::from("")
            }
@@ -450,8 +450,8 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {
        }

        impl RPCProxy for #struct_ident {
            fn register_disconnect(&mut self, id: u32, disconnect_callback: Box<dyn Fn(u32) + Send>) {
                self.disconnect_watcher.lock().unwrap().add(self.remote.clone(), id, disconnect_callback);
            fn register_disconnect(&mut self, disconnect_callback: Box<dyn Fn(u32) + Send>) -> u32 {
                return self.disconnect_watcher.lock().unwrap().add(self.remote.clone(), disconnect_callback);
            }

            fn get_object_id(&self) -> String {
+33 −12
Original line number Diff line number Diff line
@@ -54,25 +54,41 @@ use std::collections::HashMap;
use std::sync::{Arc, Mutex};

/// A D-Bus "NameOwnerChanged" handler that continuously monitors client disconnects.
///
/// When the watched bus address disconnects, all the callbacks associated with it are called with
/// their associated ids.
pub struct DisconnectWatcher {
    callbacks: Arc<Mutex<HashMap<BusName<'static>, Vec<(u32, Box<dyn Fn(u32) + Send>)>>>>,
    /// Global counter to provide a unique id every time `get_next_id` is called.
    next_id: u32,

    /// Map of disconnect callbacks by bus address and callback id.
    callbacks: Arc<Mutex<HashMap<BusName<'static>, HashMap<u32, Box<dyn Fn(u32) + Send>>>>>,
}

impl DisconnectWatcher {
    /// Creates a new DisconnectWatcher with empty callbacks.
    pub fn new() -> DisconnectWatcher {
        DisconnectWatcher { callbacks: Arc::new(Mutex::new(HashMap::new())) }
        DisconnectWatcher { next_id: 0, callbacks: Arc::new(Mutex::new(HashMap::new())) }
    }

    /// Get the next unique id for this watcher.
    fn get_next_id(&mut self) -> u32 {
        self.next_id = self.next_id + 1;
        self.next_id
    }
}

impl DisconnectWatcher {
    /// Adds a client address to be monitored for disconnect events.
    pub fn add(&mut self, address: BusName<'static>, id: u32, callback: Box<dyn Fn(u32) + Send>) {
    pub fn add(&mut self, address: BusName<'static>, callback: Box<dyn Fn(u32) + Send>) -> u32 {
        if !self.callbacks.lock().unwrap().contains_key(&address) {
            self.callbacks.lock().unwrap().insert(address.clone(), vec![]);
            self.callbacks.lock().unwrap().insert(address.clone(), HashMap::new());
        }

        (*self.callbacks.lock().unwrap().get_mut(&address).unwrap()).push((id, callback));
        let id = self.get_next_id();
        (*self.callbacks.lock().unwrap().get_mut(&address).unwrap()).insert(id, callback);

        return id;
    }

    /// Sets up the D-Bus handler that monitors client disconnects.
@@ -104,7 +120,7 @@ impl DisconnectWatcher {
                    return true;
                }

                for (id, callback) in &callbacks_map.lock().unwrap()[&addr] {
                for (id, callback) in callbacks_map.lock().unwrap()[&addr].iter() {
                    callback(*id);
                }

@@ -116,17 +132,22 @@ impl DisconnectWatcher {
    }

    /// Removes callback by id if owned by the specific busname.
    ///
    /// If the callback can be removed, the callback will be called before being removed.
    pub fn remove(&mut self, address: BusName<'static>, target_id: u32) -> bool {
        if !self.callbacks.lock().unwrap().contains_key(&address) {
            return false;
        }

        match self.callbacks.lock().unwrap()[&address].iter().position(|x| x.0 == target_id) {
            Some(index) => {
                let (id, callback) = &self.callbacks.lock().unwrap()[&address][index];
                callback(*id);
                let _ =
                    self.callbacks.lock().unwrap().get_mut(&address).unwrap().swap_remove(index);
        match self.callbacks.lock().unwrap().get(&address).and_then(|m| m.get(&target_id)) {
            Some(cb) => {
                cb(target_id);
                let _ = self
                    .callbacks
                    .lock()
                    .unwrap()
                    .get_mut(&address)
                    .and_then(|m| m.remove(&target_id));
                true
            }
            None => false,
+10 −23
Original line number Diff line number Diff line
@@ -15,8 +15,7 @@ const BLUEZ_INIT_TARGET: &str = "bluetoothd";
/// Implementation of IBluetoothManager.
pub struct BluetoothManager {
    manager_context: ManagerContext,
    callbacks: Vec<(u32, Box<dyn IBluetoothManagerCallback + Send>)>,
    callbacks_last_id: u32,
    callbacks: HashMap<u32, Box<dyn IBluetoothManagerCallback + Send>>,
    cached_devices: HashMap<i32, bool>,
}

@@ -24,8 +23,7 @@ impl BluetoothManager {
    pub(crate) fn new(manager_context: ManagerContext) -> BluetoothManager {
        BluetoothManager {
            manager_context,
            callbacks: vec![],
            callbacks_last_id: 0,
            callbacks: HashMap::new(),
            cached_devices: HashMap::new(),
        }
    }
@@ -60,13 +58,8 @@ impl BluetoothManager {
        }
    }

    fn get_next_id(&mut self) -> u32 {
        self.callbacks_last_id += 1;
        self.callbacks_last_id
    }

    pub(crate) fn callback_disconnected(&mut self, id: u32) {
        self.callbacks.retain(|x| x.0 != id);
        self.callbacks.remove(&id);
    }
}

@@ -111,20 +104,14 @@ impl IBluetoothManager for BluetoothManager {
    fn register_callback(&mut self, mut callback: Box<dyn IBluetoothManagerCallback + Send>) {
        let tx = self.manager_context.proxy.get_tx();

        let id = self.get_next_id();

        callback.register_disconnect(
            id,
            Box::new(move |cb_id| {
        let id = callback.register_disconnect(Box::new(move |cb_id| {
            let tx = tx.clone();
            tokio::spawn(async move {
                    let _result =
                        tx.send(state_machine::Message::CallbackDisconnected(cb_id)).await;
                let _result = tx.send(state_machine::Message::CallbackDisconnected(cb_id)).await;
            });
            }),
        );
        }));

        self.callbacks.push((id, callback));
        self.callbacks.insert(id, callback);
    }

    fn get_floss_enabled(&mut self) -> bool {
Loading