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

Commit 0f07321a authored by Hsin-chen Chuang's avatar Hsin-chen Chuang Committed by Gerrit Code Review
Browse files

Merge "floss: Guarantee the execution order of GATT client callbacks" into main

parents 9bd5935a bc3004ee
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::cast::{FromPrimitive, ToPrimitive};
use rand::rngs::SmallRng;
use rand::{RngCore, SeedableRng};
use std::collections::{HashMap, HashSet};
use std::collections::{HashMap, HashSet, VecDeque};
use std::convert::{TryFrom, TryInto};
use std::sync::{Arc, Mutex, MutexGuard};
use tokio::sync::mpsc::Sender;
@@ -1486,11 +1486,23 @@ impl BluetoothGatt {
    pub fn init_profiles(&mut self, tx: Sender<Message>, api_tx: Sender<APIMessage>) {
        self.gatt = Gatt::new(&self.intf.lock().unwrap()).map(|gatt| Arc::new(Mutex::new(gatt)));

        // TODO(b/353643607): Make this dispatch_queue design more general for all profiles.
        let tx_clone = tx.clone();
        let async_mutex = Arc::new(tokio::sync::Mutex::new(()));
        let dispatch_queue = Arc::new(Mutex::new(VecDeque::new()));
        let gatt_client_callbacks_dispatcher = GattClientCallbacksDispatcher {
            dispatch: Box::new(move |cb| {
                let tx_clone = tx_clone.clone();
                let async_mutex = async_mutex.clone();
                let dispatch_queue = dispatch_queue.clone();
                // Enqueue the callbacks at the synchronized block to ensure the order.
                dispatch_queue.lock().unwrap().push_back(cb);
                topstack::get_runtime().spawn(async move {
                    // Acquire the lock first to ensure |pop_front| and |tx_clone.send| not
                    // interrupted by the other async threads.
                    let _guard = async_mutex.lock().await;
                    // Consume exactly one callback.
                    let cb = dispatch_queue.lock().unwrap().pop_front().unwrap();
                    let _ = tx_clone.send(Message::GattClient(cb)).await;
                });
            }),