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

Commit ca3bce0b authored by Martin Brabham's avatar Martin Brabham
Browse files

Floss: Add in async waiting for random number.

Bug: 232547719
Test: ./build.py
Test: mma -j $(nproc)
Test: system/gd/cert/run --clean --topshim SuspendTest
Tag: #floss
Change-Id: I29a878a6944954ad1018c2ba506c81cdfddab00c
parent f1f42cbb
Loading
Loading
Loading
Loading
+32 −5
Original line number Diff line number Diff line
@@ -14,14 +14,16 @@ use bt_topshim::{

use btif_macros::{btif_callback, btif_callbacks_dispatcher};

use log::{debug, warn};
use log::{debug, error, warn};
use num_traits::cast::ToPrimitive;
use std::collections::HashMap;
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use std::time::Instant;
use tokio::sync::mpsc::Sender;
use tokio::sync::oneshot::Sender as OneShotSender;
use tokio::task::JoinHandle;
use tokio::time;

@@ -38,6 +40,10 @@ const MIN_ADV_INSTANCES_FOR_MULTI_ADV: u8 = 5;
/// clear event should be sent to clients.
const FOUND_DEVICE_FRESHNESS: Duration = Duration::from_secs(30);

/// This is the value returned from Bluetooth Interface calls.
// TODO(241930383): Add enum to topshim
const BTM_SUCCESS: i32 = 0;

/// Defines the adapter API.
pub trait IBluetooth {
    /// Adds a callback from a client who wishes to observe adapter events.
@@ -318,6 +324,8 @@ pub struct Bluetooth {
    uuid_helper: UuidHelper,
    /// Used to delay connection until we have SDP results.
    wait_to_connect: bool,
    // Internal API members
    internal_le_rand_queue: VecDeque<OneShotSender<u64>>,
}

impl Bluetooth {
@@ -350,6 +358,8 @@ impl Bluetooth {
            tx,
            uuid_helper: UuidHelper::new(),
            wait_to_connect: false,
            // Internal API members
            internal_le_rand_queue: VecDeque::<OneShotSender<u64>>::new(),
        }
    }

@@ -508,6 +518,19 @@ impl Bluetooth {
            }));
        }
    }

    /// Makes an LE_RAND call to the Bluetooth interface.  This call is asynchronous, and uses an
    /// asynchronous callback, but is synchonized on a |OneShotSender|
    /// If generating a random isn't successful, a 0 will be sent to the callback.
    pub fn le_rand(&mut self, promise: OneShotSender<u64>) {
        if self.intf.lock().unwrap().le_rand() != BTM_SUCCESS {
            debug!("Call to BTIF failed.");
            // Send 0 to caller indicating failure to generate a RANDOM
            let _ = promise.send(0);
        } else {
            self.internal_le_rand_queue.push_back(promise);
        }
    }
}

#[btif_callbacks_dispatcher(Bluetooth, dispatch_base_callbacks, BaseCallbacks)]
@@ -596,10 +619,6 @@ pub fn get_bt_dispatcher(tx: Sender<Message>) -> BaseCallbacksDispatcher {
}

impl BtifBluetoothCallbacks for Bluetooth {
    fn le_rand_cb(&mut self, random: u64) {
        println!("Random: {:?}", random);
    }

    fn adapter_state_changed(&mut self, state: BtState) {
        let prev_state = self.state.clone();
        self.state = state;
@@ -921,6 +940,14 @@ impl BtifBluetoothCallbacks for Bluetooth {
            None => (),
        };
    }

    fn le_rand_cb(&mut self, random: u64) {
        debug!("Random: {:?}", random);
        let _ = match self.internal_le_rand_queue.pop_back() {
            Some(promise) => promise.send(random),
            None => Ok(error!("LE Rand callback received but no sender available!")),
        };
    }
}

// TODO: Add unit tests for this implementation
+40 −14
Original line number Diff line number Diff line
//! Suspend/Resume API.

use crate::bluetooth::Bluetooth;
use crate::callbacks::Callbacks;
use crate::{Message, RPCProxy};
use bt_topshim::btif::BluetoothInterface;
use crate::{bluetooth_gatt::IBluetoothGatt, BluetoothGatt, Message, RPCProxy};
use bt_topshim::{btif::BluetoothInterface, topstack};
use log::warn;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc::Sender;
use tokio::sync::oneshot::channel as OneShotChannel;

/// Defines the Suspend/Resume API.
///
@@ -58,7 +60,9 @@ pub enum SuspendType {

/// Implementation of the suspend API.
pub struct Suspend {
    bt: Arc<Mutex<Box<Bluetooth>>>,
    intf: Arc<Mutex<BluetoothInterface>>,
    gatt: Arc<Mutex<Box<BluetoothGatt>>>,
    tx: Sender<Message>,
    callbacks: Callbacks<dyn ISuspendCallback + Send>,
    is_connected_suspend: bool,
@@ -66,9 +70,16 @@ pub struct Suspend {
}

impl Suspend {
    pub fn new(intf: Arc<Mutex<BluetoothInterface>>, tx: Sender<Message>) -> Suspend {
    pub fn new(
        bt: Arc<Mutex<Box<Bluetooth>>>,
        intf: Arc<Mutex<BluetoothInterface>>,
        gatt: Arc<Mutex<Box<BluetoothGatt>>>,
        tx: Sender<Message>,
    ) -> Suspend {
        Self {
            bt: bt,
            intf: intf,
            gatt: gatt,
            tx: tx.clone(),
            callbacks: Callbacks::new(tx.clone(), Message::SuspendCallbackDisconnected),
            is_connected_suspend: false,
@@ -105,6 +116,17 @@ impl ISuspend for Suspend {
    }

    fn suspend(&self, suspend_type: SuspendType) {
        // self.was_a2dp_connected = TODO(230604670): check if A2DP is connected
        // self.current_advertiser_ids = TODO(224603198): save all advertiser ids
        self.intf.lock().unwrap().clear_event_mask();
        self.intf.lock().unwrap().clear_event_filter();
        self.intf.lock().unwrap().clear_filter_accept_list();
        // self.gatt.lock().unwrap().advertising_disable(); TODO(224602924): suspend all adv.
        self.gatt.lock().unwrap().stop_scan(0);
        self.intf.lock().unwrap().disconnect_all_acls();

        // Handle wakeful cases (Connected/Other)
        // Treat Other the same as Connected
        match suspend_type {
            SuspendType::Connected => {
                // TODO(231345733): API For allowing classic HID only
@@ -115,36 +137,40 @@ impl ISuspend for Suspend {
                self.intf.lock().unwrap().clear_event_filter();
                self.intf.lock().unwrap().clear_event_mask();
            }
            SuspendType::Other => {
                // TODO(231438120): Decide what to do about Other suspend type
                // For now perform disconnected suspend flow
                self.intf.lock().unwrap().clear_event_filter();
                self.intf.lock().unwrap().clear_event_mask();
            _ => {
                self.intf.lock().unwrap().allow_wake_by_hid();
            }
        }
        self.intf.lock().unwrap().clear_filter_accept_list();
        self.intf.lock().unwrap().disconnect_all_acls();
        self.intf.lock().unwrap().le_rand();
        // Wait on LE Rand before firing callbacks
        let (p, mut c) = OneShotChannel::<u64>();
        self.bt.lock().unwrap().le_rand(p);
        let rt = topstack::get_runtime();
        rt.block_on(async {
            let _ = c.try_recv();
        });
        self.callbacks.for_all_callbacks(|callback| {
            callback.on_suspend_ready(1 as u32);
        });
    }

    fn resume(&self) -> bool {
        let suspend_id = 1;
        self.intf.lock().unwrap().set_event_filter_inquiry_result_all_devices();
        self.intf.lock().unwrap().set_default_event_mask();
        self.intf.lock().unwrap().set_event_filter_inquiry_result_all_devices();
        if self.is_connected_suspend {
            if self.was_a2dp_connected {
                // TODO(230604670): self.intf.lock().unwrap().restore_filter_accept_list();
                // TODO(230604670): reconnect to a2dp device if connected before
                // TODO(230604670): reconnect to a2dp device
            }
            // TODO(224603198): start all advertising again
        }
        self.intf.lock().unwrap().le_rand();

        self.callbacks.for_all_callbacks(|callback| {
            callback.on_resumed(suspend_id);
            callback.on_resumed(1);
        });
        return true;

        true
    }
}
+0 −12
Original line number Diff line number Diff line
@@ -1100,22 +1100,10 @@ impl BluetoothInterface {
        ccall!(self, allow_wake_by_hid)
    }

    /*async*/
    pub fn le_rand(&self) -> i32 {
        // global_future = Future()
        ccall!(self, le_rand)
        // await glogal_future
        // result = global_future.result()
        // global_future = null
        // return result
    }

    /*
    pub fn le_rand_cb(&self, random: u64) {
        global_future.set_result(random)
    }
    */

    pub fn restore_filter_accept_list(&self) -> i32 {
        ccall!(self, restore_filter_accept_list)
    }