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

Commit eaf456e5 authored by Sonny Sasaka's avatar Sonny Sasaka Committed by Automerger Merge Worker
Browse files

Merge "Floss: Refactor callback management using `Callbacks`" am: 9f85225b

parents f0e2475d 9f85225b
Loading
Loading
Loading
Loading
+31 −78
Original line number Diff line number Diff line
@@ -25,8 +25,9 @@ use tokio::task::JoinHandle;
use tokio::time;

use crate::bluetooth_media::{BluetoothMedia, IBluetoothMedia, MediaActions};
use crate::callbacks::Callbacks;
use crate::uuid::{Profile, UuidHelper};
use crate::{BluetoothCallbackType, Message, RPCProxy};
use crate::{Message, RPCProxy};

const DEFAULT_DISCOVERY_TIMEOUT_MS: u64 = 12800;
const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5;
@@ -299,8 +300,8 @@ pub struct Bluetooth {

    bonded_devices: HashMap<String, BluetoothDeviceContext>,
    bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
    callbacks: HashMap<u32, Box<dyn IBluetoothCallback + Send>>,
    connection_callbacks: HashMap<u32, Box<dyn IBluetoothConnectionCallback + Send>>,
    callbacks: Callbacks<dyn IBluetoothCallback + Send>,
    connection_callbacks: Callbacks<dyn IBluetoothConnectionCallback + Send>,
    discovering_started: Instant,
    hh: Option<HidHost>,
    is_connectable: bool,
@@ -327,8 +328,11 @@ impl Bluetooth {
    ) -> Bluetooth {
        Bluetooth {
            bonded_devices: HashMap::new(),
            callbacks: HashMap::new(),
            connection_callbacks: HashMap::new(),
            callbacks: Callbacks::new(tx.clone(), Message::AdapterCallbackDisconnected),
            connection_callbacks: Callbacks::new(
                tx.clone(),
                Message::ConnectionCallbackDisconnected,
            ),
            hh: None,
            bluetooth_media,
            discovering_started: Instant::now(),
@@ -378,26 +382,11 @@ impl Bluetooth {
    fn update_local_address(&mut self, addr: &RawAddress) {
        self.local_address = Some(*addr);

        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_address_changed(self.local_address.unwrap().to_string());
        });
    }

    fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothCallback + Send>)>(&self, f: F) {
        for (_, callback) in self.callbacks.iter() {
            f(&callback);
        }
    }

    fn for_all_connection_callbacks<F: Fn(&Box<dyn IBluetoothConnectionCallback + Send>)>(
        &self,
        f: F,
    ) {
        for (_, callback) in self.connection_callbacks.iter() {
            f(&callback);
        }
    }

    pub fn get_connectable(&self) -> bool {
        match self.properties.get(&BtPropertyType::AdapterScanMode) {
            Some(prop) => match prop {
@@ -421,15 +410,12 @@ impl Bluetooth {
        )) == 0
    }

    pub(crate) fn callback_disconnected(&mut self, id: u32, cb_type: BluetoothCallbackType) {
        match cb_type {
            BluetoothCallbackType::Adapter => {
                self.callbacks.remove(&id);
    pub(crate) fn adapter_callback_disconnected(&mut self, id: u32) {
        self.callbacks.remove_callback(id);
    }
            BluetoothCallbackType::Connection => {
                self.connection_callbacks.remove(&id);
            }
        };

    pub(crate) fn connection_callback_disconnected(&mut self, id: u32) {
        self.connection_callbacks.remove_callback(id);
    }

    fn get_remote_device_if_found(&self, address: &str) -> Option<&BluetoothDeviceContext> {
@@ -506,7 +492,7 @@ impl Bluetooth {
        self.found_devices.retain(|_, d| is_fresh(d, &now));

        for d in stale_devices {
            self.for_all_callbacks(|callback| {
            self.callbacks.for_all_callbacks(|callback| {
                callback.on_device_cleared(d.clone());
            });
        }
@@ -669,12 +655,12 @@ impl BtifBluetoothCallbacks for Bluetooth {
                    }
                }
                BluetoothProperty::BdName(bdname) => {
                    self.for_all_callbacks(|callback| {
                    self.callbacks.for_all_callbacks(|callback| {
                        callback.on_name_changed(bdname.clone());
                    });
                }
                BluetoothProperty::AdapterScanMode(mode) => {
                    self.for_all_callbacks(|callback| {
                    self.callbacks.for_all_callbacks(|callback| {
                        callback
                            .on_discoverable_changed(*mode == BtScanMode::ConnectableDiscoverable);
                    });
@@ -684,7 +670,7 @@ impl BtifBluetoothCallbacks for Bluetooth {

            self.properties.insert(prop.get_type(), prop.clone());

            self.for_all_callbacks(|callback| {
            self.callbacks.for_all_callbacks(|callback| {
                callback.on_adapter_property_changed(prop.get_type());
            });
        }
@@ -710,7 +696,7 @@ impl BtifBluetoothCallbacks for Bluetooth {

        let device = self.found_devices.get(&address).unwrap();

        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_device_found(device.info.clone());
        });
    }
@@ -729,7 +715,7 @@ impl BtifBluetoothCallbacks for Bluetooth {
            self.discovering_started = Instant::now();
        }

        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_discovering_changed(state == BtDiscoveryState::Started);
        });

@@ -751,7 +737,7 @@ impl BtifBluetoothCallbacks for Bluetooth {
    ) {
        // Currently this supports many agent because we accept many callbacks.
        // TODO: We need a way to select the default agent.
        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_ssp_request(
                BluetoothDevice::new(remote_addr.to_string(), remote_name.clone()),
                cod,
@@ -806,7 +792,7 @@ impl BtifBluetoothCallbacks for Bluetooth {
        }

        // Send bond state changed notifications
        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_bond_state_changed(
                status.to_u32().unwrap(),
                address.clone(),
@@ -898,12 +884,12 @@ impl BtifBluetoothCallbacks for Bluetooth {

                    match state {
                        BtAclState::Connected => {
                            self.for_all_connection_callbacks(|callback| {
                            self.connection_callbacks.for_all_callbacks(|callback| {
                                callback.on_device_connected(device.clone());
                            });
                        }
                        BtAclState::Disconnected => {
                            self.for_all_connection_callbacks(|callback| {
                            self.connection_callbacks.for_all_callbacks(|callback| {
                                callback.on_device_disconnected(device.clone());
                            });
                        }
@@ -917,52 +903,19 @@ impl BtifBluetoothCallbacks for Bluetooth {

// TODO: Add unit tests for this implementation
impl IBluetooth for Bluetooth {
    fn register_callback(&mut self, mut callback: Box<dyn IBluetoothCallback + Send>) {
        let tx = self.tx.clone();

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

        self.callbacks.insert(id, callback);
    fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) {
        self.callbacks.add_callback(callback);
    }

    fn register_connection_callback(
        &mut self,
        mut callback: Box<dyn IBluetoothConnectionCallback + Send>,
        callback: Box<dyn IBluetoothConnectionCallback + Send>,
    ) -> u32 {
        let tx = self.tx.clone();

        let id = callback.register_disconnect(Box::new(move |cb_id| {
            let tx = tx.clone();
            tokio::spawn(async move {
                let _ = tx
                    .send(Message::BluetoothCallbackDisconnected(
                        cb_id,
                        BluetoothCallbackType::Connection,
                    ))
                    .await;
            });
        }));

        self.connection_callbacks.insert(id, callback);

        id
        self.connection_callbacks.add_callback(callback)
    }

    fn unregister_connection_callback(&mut self, callback_id: u32) -> bool {
        match self.connection_callbacks.get_mut(&callback_id) {
            Some(cb) => cb.unregister(callback_id),
            None => false,
        }
        self.connection_callbacks.remove_callback(callback_id)
    }

    fn enable(&mut self) -> bool {
+21 −22
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ use tokio::task::JoinHandle;
use tokio::time::{sleep, Duration};

use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth};
use crate::Message;
use crate::callbacks::Callbacks;
use crate::{Message, RPCProxy};

const DEFAULT_PROFILE_DISCOVERY_TIMEOUT_SEC: u64 = 5;

@@ -64,7 +65,7 @@ pub trait IBluetoothMedia {
    fn stop_sco_call(&mut self, address: String);
}

pub trait IBluetoothMediaCallback {
pub trait IBluetoothMediaCallback: RPCProxy {
    /// Triggered when a Bluetooth audio device is ready to be used. This should
    /// only be triggered once for a device and send an event to clients. If the
    /// device supports both HFP and A2DP, both should be ready when this is
@@ -119,8 +120,7 @@ pub enum MediaActions {
pub struct BluetoothMedia {
    intf: Arc<Mutex<BluetoothInterface>>,
    initialized: bool,
    callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>,
    callback_last_id: u32,
    callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>,
    tx: Sender<Message>,
    adapter: Option<Arc<Mutex<Box<Bluetooth>>>>,
    a2dp: Option<A2dp>,
@@ -139,8 +139,10 @@ impl BluetoothMedia {
        BluetoothMedia {
            intf,
            initialized: false,
            callbacks: Arc::new(Mutex::new(vec![])),
            callback_last_id: 0,
            callbacks: Arc::new(Mutex::new(Callbacks::new(
                tx.clone(),
                Message::MediaCallbackDisconnected,
            ))),
            tx,
            adapter: None,
            a2dp: None,
@@ -196,12 +198,12 @@ impl BluetoothMedia {
        match cb {
            AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled(supported) => {
                self.absolute_volume = supported;
                self.for_all_callbacks(|callback| {
                self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
                    callback.on_absolute_volume_supported_changed(supported);
                });
            }
            AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => {
                self.for_all_callbacks(|callback| {
                self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
                    callback.on_absolute_volume_changed(volume);
                });
            }
@@ -279,27 +281,31 @@ impl BluetoothMedia {
                }
            }
            HfpCallbacks::VolumeUpdate(volume, addr) => {
                self.for_all_callbacks(|callback| {
                self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
                    callback.on_hfp_volume_changed(volume, addr.to_string());
                });
            }
        }
    }

    pub fn remove_callback(&mut self, id: u32) -> bool {
        self.callbacks.lock().unwrap().remove_callback(id)
    }

    fn notify_media_capability_added(&self, addr: RawAddress) {
        // Return true if the device added message is sent by the call.
        fn dedup_added_cb(
            device_added_tasks: Arc<Mutex<HashMap<RawAddress, Option<JoinHandle<()>>>>>,
            addr: RawAddress,
            callbacks: Arc<Mutex<Vec<(u32, Box<dyn IBluetoothMediaCallback + Send>)>>>,
            callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>,
            device: BluetoothAudioDevice,
            is_delayed: bool,
        ) -> bool {
            // Closure used to lock and trigger the device added callbacks.
            let trigger_device_added = || {
                for callback in &*callbacks.lock().unwrap() {
                    callback.1.on_bluetooth_audio_device_added(device.clone());
                }
                callbacks.lock().unwrap().for_all_callbacks(|callback| {
                    callback.on_bluetooth_audio_device_added(device.clone());
                });
            };
            let mut guard = device_added_tasks.lock().unwrap();
            let task = guard.insert(addr, None);
@@ -390,7 +396,7 @@ impl BluetoothMedia {
                // Abort what is pending
                Some(handler) => handler.abort(),
                // This addr has been added so tell audio server to remove it
                None => self.for_all_callbacks(|callback| {
                None => self.callbacks.lock().unwrap().for_all_callbacks(|callback| {
                    callback.on_bluetooth_audio_device_removed(addr.to_string());
                }),
            }
@@ -399,12 +405,6 @@ impl BluetoothMedia {
        }
    }

    fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothMediaCallback + Send>)>(&self, f: F) {
        for callback in &*self.callbacks.lock().unwrap() {
            f(&callback.1);
        }
    }

    fn adapter_get_remote_name(&self, addr: RawAddress) -> String {
        let device = BluetoothDevice::new(
            addr.to_string(),
@@ -472,8 +472,7 @@ fn get_hfp_dispatcher(tx: Sender<Message>) -> HfpCallbacksDispatcher {

impl IBluetoothMedia for BluetoothMedia {
    fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool {
        self.callback_last_id += 1;
        self.callbacks.lock().unwrap().push((self.callback_last_id, callback));
        let _id = self.callbacks.lock().unwrap().add_callback(callback);
        true
    }

+13 −9
Original line number Diff line number Diff line
@@ -31,12 +31,6 @@ use bt_topshim::{
    },
};

#[derive(Clone, Debug)]
pub enum BluetoothCallbackType {
    Adapter,
    Connection,
}

/// Message types that are sent to the stack main dispatch loop.
pub enum Message {
    // Callbacks from libbluetooth
@@ -51,9 +45,11 @@ pub enum Message {

    // Actions within the stack
    Media(MediaActions),
    MediaCallbackDisconnected(u32),

    // Client callback disconnections
    BluetoothCallbackDisconnected(u32, BluetoothCallbackType),
    AdapterCallbackDisconnected(u32),
    ConnectionCallbackDisconnected(u32),

    // Update list of found devices and remove old instances.
    DeviceFreshnessCheck,
@@ -130,8 +126,16 @@ impl Stack {
                    bluetooth_media.lock().unwrap().dispatch_media_actions(action);
                }

                Message::BluetoothCallbackDisconnected(id, cb_type) => {
                    bluetooth.lock().unwrap().callback_disconnected(id, cb_type);
                Message::MediaCallbackDisconnected(cb_id) => {
                    bluetooth_media.lock().unwrap().remove_callback(cb_id);
                }

                Message::AdapterCallbackDisconnected(id) => {
                    bluetooth.lock().unwrap().adapter_callback_disconnected(id);
                }

                Message::ConnectionCallbackDisconnected(id) => {
                    bluetooth.lock().unwrap().connection_callback_disconnected(id);
                }

                Message::DeviceFreshnessCheck => {
+10 −31
Original line number Diff line number Diff line
//! Suspend/Resume API.

use crate::callbacks::Callbacks;
use crate::{Message, RPCProxy};
use bt_topshim::btif::BluetoothInterface;
use log::warn;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc::Sender;

@@ -60,7 +60,7 @@ pub enum SuspendType {
pub struct Suspend {
    intf: Arc<Mutex<BluetoothInterface>>,
    tx: Sender<Message>,
    callbacks: HashMap<u32, Box<dyn ISuspendCallback + Send>>,
    callbacks: Callbacks<dyn ISuspendCallback + Send>,
    is_connected_suspend: bool,
    was_a2dp_connected: bool,
}
@@ -69,55 +69,34 @@ impl Suspend {
    pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Suspend {
        Self {
            intf: intf,
            tx,
            callbacks: HashMap::new(),
            tx: tx.clone(),
            callbacks: Callbacks::new(tx.clone(), Message::SuspendCallbackDisconnected),
            is_connected_suspend: false,
            was_a2dp_connected: false,
        }
    }

    pub(crate) fn callback_registered(&mut self, id: u32) {
        match self.callbacks.get(&id) {
        match self.callbacks.get_by_id(id) {
            Some(callback) => callback.on_callback_registered(id),
            None => warn!("Suspend callback {} does not exist", id),
        }
    }

    pub(crate) fn remove_callback(&mut self, id: u32) -> bool {
        match self.callbacks.get_mut(&id) {
            Some(callback) => {
                callback.unregister(id);
                self.callbacks.remove(&id);
                true
            }
            None => false,
        }
    }

    fn for_all_callbacks<F: Fn(&Box<dyn ISuspendCallback + Send>)>(&self, f: F) {
        for (_, callback) in self.callbacks.iter() {
            f(&callback);
        }
        self.callbacks.remove_callback(id)
    }
}

impl ISuspend for Suspend {
    fn register_callback(&mut self, mut callback: Box<dyn ISuspendCallback + Send>) -> bool {
        let tx = self.tx.clone();

        let id = callback.register_disconnect(Box::new(move |cb_id| {
            let tx = tx.clone();
            tokio::spawn(async move {
                let _result = tx.send(Message::SuspendCallbackDisconnected(cb_id)).await;
            });
        }));
    fn register_callback(&mut self, callback: Box<dyn ISuspendCallback + Send>) -> bool {
        let id = self.callbacks.add_callback(callback);

        let tx = self.tx.clone();
        tokio::spawn(async move {
            let _result = tx.send(Message::SuspendCallbackRegistered(id)).await;
        });

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

@@ -147,7 +126,7 @@ impl ISuspend for Suspend {
        self.intf.lock().unwrap().clear_filter_accept_list();
        // TODO(231435700): self.intf.lock().unwrap().disconnect_all_acls();
        self.intf.lock().unwrap().le_rand();
        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_suspend_ready(suspend_id);
        });
        return 1;
@@ -165,7 +144,7 @@ impl ISuspend for Suspend {
            // TODO(224603198): start all advertising again
        }
        self.intf.lock().unwrap().le_rand();
        self.for_all_callbacks(|callback| {
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_resumed(suspend_id);
        });
        return true;