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

Commit f073d57f authored by Sonny Sasaka's avatar Sonny Sasaka Committed by Gerrit Code Review
Browse files

Merge changes I28120e4c,I516888a5,Icd173aa6,If042a9d1,I231f1021, ...

* changes:
  floss: Change signature of DBusArg::from_dbus
  floss: Support Vec<T> in D-Bus projection property-map
  floss: Handle congestion_cb callback
  floss: Handle read_descriptor_cb, write_descriptor_cb, execute_write_cb
  floss: Handle read_characteristic_cb and write_characteristic_cb
  floss: Handle callbacks from btgatt_client_callbacks_t
parents 86341252 f455e151
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -252,13 +252,7 @@ impl IBluetoothManager for BluetoothManagerDBus {

    fn get_available_adapters(&mut self) -> Vec<AdapterWithEnabled> {
        let props: Vec<dbus::arg::PropMap> = self.client_proxy.method("GetAvailableAdapters", ());
        <Vec<AdapterWithEnabled> as DBusArg>::from_dbus(
            props,
            self.client_proxy.conn.clone(),
            dbus::strings::BusName::new(":1.0").unwrap(), // unused
            Arc::new(Mutex::new(DisconnectWatcher::new())),
        )
        .unwrap()
        <Vec<AdapterWithEnabled> as DBusArg>::from_dbus(props, None, None, None).unwrap()
    }
}

+57 −38
Original line number Diff line number Diff line
@@ -117,9 +117,9 @@ pub fn generate_dbus_exporter(attr: TokenStream, item: TokenStream) -> TokenStre
                            #make_args
                            let #ident = <#arg_type as DBusArg>::from_dbus(
                                #dbus_input_arg,
                                conn_clone.clone(),
                                ctx.message().sender().unwrap().into_static(),
                                dc_watcher_clone.clone(),
                                Some(conn_clone.clone()),
                                Some(ctx.message().sender().unwrap().into_static()),
                                Some(dc_watcher_clone.clone()),
                            );

                            if let Result::Err(e) = #ident {
@@ -241,18 +241,17 @@ pub fn dbus_propmap(attr: TokenStream, item: TokenStream) -> TokenStream {

        let field_str = field_ident.as_ref().unwrap().clone().to_string();

        let field_type_str = if let Type::Path(t) = field.ty {
            t.path.get_ident().unwrap().to_string()
        let field_type = if let Type::Path(t) = field.ty {
            t
        } else {
            String::from("")
            continue;
        };

        let field_type_ident = format_ident!("{}", field_type_str);

        field_idents = quote! {
            #field_idents #field_ident,
        };

        let field_type_name = format_ident! {"{}_type_", field_str};
        let make_field = quote! {
            match #field_ident.arg_type() {
                dbus::arg::ArgType::Variant => {}
@@ -263,11 +262,12 @@ pub fn dbus_propmap(attr: TokenStream, item: TokenStream) -> TokenStream {
                    )))));
                }
            };
            let #field_ident = <<#field_type_ident as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust(
                #field_ident,
            let #field_ident = <<#field_type as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust(
                #field_ident.as_static_inner(0).unwrap(),
                format!("{}.{}", #struct_str, #field_str),
            )?;
            let #field_ident = #field_type_ident::from_dbus(
            type #field_type_name = #field_type;
            let #field_ident = #field_type_name::from_dbus(
                #field_ident,
                conn__.clone(),
                remote__.clone(),
@@ -306,9 +306,9 @@ pub fn dbus_propmap(attr: TokenStream, item: TokenStream) -> TokenStream {

            fn from_dbus(
                data__: dbus::arg::PropMap,
                conn__: std::sync::Arc<SyncConnection>,
                remote__: dbus::strings::BusName<'static>,
                disconnect_watcher__: std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
                conn__: Option<std::sync::Arc<SyncConnection>>,
                remote__: Option<dbus::strings::BusName<'static>>,
                disconnect_watcher__: Option<std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>>,
            ) -> Result<#struct_ident, Box<dyn std::error::Error>> {
                #make_fields

@@ -457,15 +457,15 @@ pub fn dbus_proxy_obj(attr: TokenStream, item: TokenStream) -> TokenStream {

            fn from_dbus(
                objpath__: Path<'static>,
                conn__: std::sync::Arc<SyncConnection>,
                remote__: dbus::strings::BusName<'static>,
                disconnect_watcher__: std::sync::Arc<std::sync::Mutex<DisconnectWatcher>>,
                conn__: Option<std::sync::Arc<SyncConnection>>,
                remote__: Option<dbus::strings::BusName<'static>>,
                disconnect_watcher__: Option<std::sync::Arc<std::sync::Mutex<DisconnectWatcher>>>,
            ) -> Result<Box<dyn #trait_ + Send>, Box<dyn std::error::Error>> {
                Ok(Box::new(#struct_ident {
                    conn: conn__,
                    remote: remote__,
                    conn: conn__.unwrap(),
                    remote: remote__.unwrap(),
                    objpath: objpath__,
                    disconnect_watcher: disconnect_watcher__,
                    disconnect_watcher: disconnect_watcher__.unwrap(),
                }))
            }

@@ -521,19 +521,18 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

        pub(crate) trait RefArgToRust {
            type RustType;
            fn ref_arg_to_rust<U: 'static + dbus::arg::RefArg + ?Sized>(
                arg: &U,
            fn ref_arg_to_rust(
                arg: &(dyn dbus::arg::RefArg + 'static),
                name: String,
            ) -> Result<Self::RustType, Box<dyn Error>>;
        }

        impl<T: 'static + Clone + DirectDBus> RefArgToRust for T {
            type RustType = T;
            fn ref_arg_to_rust<U: 'static + dbus::arg::RefArg + ?Sized>(
                arg: &U,
            fn ref_arg_to_rust(
                arg: &(dyn dbus::arg::RefArg + 'static),
                name: String,
            ) -> Result<Self::RustType, Box<dyn Error>> {
                let arg = arg.as_static_inner(0).unwrap();
                let any = arg.as_any();
                if !any.is::<<Self as DBusArg>::DBusType>() {
                    return Err(Box::new(DBusArgError::new(String::from(format!(
@@ -550,13 +549,12 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

        impl RefArgToRust for dbus::arg::PropMap {
            type RustType = dbus::arg::PropMap;
            fn ref_arg_to_rust<U: 'static + dbus::arg::RefArg + ?Sized>(
                arg: &U,
            fn ref_arg_to_rust(
                arg: &(dyn dbus::arg::RefArg + 'static),
                _name: String,
            ) -> Result<Self::RustType, Box<dyn Error>> {
                let mut map: dbus::arg::PropMap = std::collections::HashMap::new();
                let mut outer_iter = arg.as_iter().unwrap();
                let mut iter = outer_iter.next().unwrap().as_iter().unwrap();
                let mut iter = arg.as_iter().unwrap();
                let mut key = iter.next();
                let mut val = iter.next();
                while !key.is_none() && !val.is_none() {
@@ -570,14 +568,35 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {
            }
        }

        // A vector is convertible from DBus' dynamic type RefArg to Rust's Vec, if the elements
        // of the vector are also convertible themselves recursively.
        impl<T: 'static + RefArgToRust<RustType = T>> RefArgToRust for Vec<T> {
            type RustType = Vec<T>;
            fn ref_arg_to_rust(
                arg: &(dyn dbus::arg::RefArg + 'static),
                _name: String,
            ) -> Result<Self::RustType, Box<dyn Error>> {
                let mut vec: Vec<T> = vec![];
                let mut iter = arg.as_iter().unwrap();
                let mut val = iter.next();
                while !val.is_none() {
                    let arg = val.unwrap().box_clone();
                    let arg = <T as RefArgToRust>::ref_arg_to_rust(&arg, _name.clone() + " element")?;
                    vec.push(arg);
                    val = iter.next();
                }
                return Ok(vec);
            }
        }

        pub(crate) trait DBusArg {
            type DBusType;

            fn from_dbus(
                x: Self::DBusType,
                conn: Arc<SyncConnection>,
                remote: BusName<'static>,
                disconnect_watcher: Arc<Mutex<DisconnectWatcher>>,
                conn: Option<Arc<SyncConnection>>,
                remote: Option<BusName<'static>>,
                disconnect_watcher: Option<Arc<Mutex<DisconnectWatcher>>>,
            ) -> Result<Self, Box<dyn Error>>
            where
                Self: Sized;
@@ -600,9 +619,9 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

            fn from_dbus(
                data: T,
                _conn: Arc<SyncConnection>,
                _remote: BusName<'static>,
                _disconnect_watcher: Arc<Mutex<DisconnectWatcher>>,
                _conn: Option<Arc<SyncConnection>>,
                _remote: Option<BusName<'static>>,
                _disconnect_watcher: Option<Arc<Mutex<DisconnectWatcher>>>,
            ) -> Result<T, Box<dyn Error>> {
                return Ok(data);
            }
@@ -617,9 +636,9 @@ pub fn generate_dbus_arg(_item: TokenStream) -> TokenStream {

            fn from_dbus(
                data: Vec<T::DBusType>,
                conn: Arc<SyncConnection>,
                remote: BusName<'static>,
                disconnect_watcher: Arc<Mutex<DisconnectWatcher>>,
                conn: Option<Arc<SyncConnection>>,
                remote: Option<BusName<'static>>,
                disconnect_watcher: Option<Arc<Mutex<DisconnectWatcher>>>,
            ) -> Result<Vec<T>, Box<dyn Error>> {
                let mut list: Vec<T> = vec![];
                for prop in data {
+5 −3
Original line number Diff line number Diff line
@@ -80,9 +80,11 @@ macro_rules! impl_dbus_arg_enum {
            type DBusType = i32;
            fn from_dbus(
                data: i32,
                _conn: Arc<SyncConnection>,
                _remote: dbus::strings::BusName<'static>,
                _disconnect_watcher: Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
                _conn: Option<Arc<SyncConnection>>,
                _remote: Option<dbus::strings::BusName<'static>>,
                _disconnect_watcher: Option<
                    Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
                >,
            ) -> Result<$enum_type, Box<dyn std::error::Error>> {
                match <$enum_type>::from_i32(data) {
                    Some(x) => Ok(x),
+18 −0
Original line number Diff line number Diff line
@@ -46,6 +46,24 @@ impl IBluetoothGattCallback for BluetoothGattCallbackDBus {
    #[dbus_method("OnPhyRead")]
    fn on_phy_read(&self, addr: String, tx_phy: LePhy, rx_phy: LePhy, status: GattStatus) {}

    #[dbus_method("OnCharacteristicRead")]
    fn on_characteristic_read(&self, addr: String, status: i32, handle: i32, value: Vec<u8>) {}

    #[dbus_method("OnCharacteristicWrite")]
    fn on_characteristic_write(&self, addr: String, status: i32, handle: i32) {}

    #[dbus_method("OnExecuteWrite")]
    fn on_execute_write(&self, addr: String, status: i32) {}

    #[dbus_method("OnDescriptorRead")]
    fn on_descriptor_read(&self, addr: String, status: i32, handle: i32, value: Vec<u8>) {}

    #[dbus_method("OnDescriptorWrite")]
    fn on_descriptor_write(&self, addr: String, status: i32, handle: i32) {}

    #[dbus_method("OnNotify")]
    fn on_notify(&self, addr: String, handle: i32, value: Vec<u8>) {}

    #[dbus_method("OnReadRemoteRssi")]
    fn on_read_remote_rssi(&self, addr: String, rssi: i32, status: i32) {}

+250 −3
Original line number Diff line number Diff line
@@ -5,8 +5,8 @@ use btif_macros::{btif_callback, btif_callbacks_dispatcher};
use bt_topshim::bindings::root::bluetooth::Uuid;
use bt_topshim::btif::{BluetoothInterface, RawAddress};
use bt_topshim::profiles::gatt::{
    Gatt, GattClientCallbacks, GattClientCallbacksDispatcher, GattServerCallbacksDispatcher,
    GattStatus,
    BtGattNotifyParams, BtGattReadParams, Gatt, GattClientCallbacks, GattClientCallbacksDispatcher,
    GattServerCallbacksDispatcher, GattStatus,
};
use bt_topshim::topstack;

@@ -23,6 +23,10 @@ struct Client {
    id: Option<i32>,
    uuid: Uuid128Bit,
    callback: Box<dyn IBluetoothGattCallback + Send>,
    is_congested: bool,

    // Queued on_characteristic_write callback.
    congestion_queue: Vec<(String, i32, i32)>,
}

struct Connection {
@@ -51,6 +55,12 @@ impl ContextMap {
        self.clients.iter().find(|client| client.id.is_some() && client.id.unwrap() == client_id)
    }

    fn get_by_client_id_mut(&mut self, client_id: i32) -> Option<&mut Client> {
        self.clients
            .iter_mut()
            .find(|client| client.id.is_some() && client.id.unwrap() == client_id)
    }

    fn get_address_by_conn_id(&self, conn_id: i32) -> Option<String> {
        match self.connections.iter().find(|conn| conn.conn_id == conn_id) {
            None => None,
@@ -65,12 +75,27 @@ impl ContextMap {
        }
    }

    fn get_client_by_conn_id_mut(&mut self, conn_id: i32) -> Option<&mut Client> {
        let client_id = match self.connections.iter().find(|conn| conn.conn_id == conn_id) {
            None => return None,
            Some(conn) => conn.client_id,
        };

        self.get_by_client_id_mut(client_id)
    }

    fn add(&mut self, uuid: &Uuid128Bit, callback: Box<dyn IBluetoothGattCallback + Send>) {
        if self.get_by_uuid(uuid).is_some() {
            return;
        }

        self.clients.push(Client { id: None, uuid: uuid.clone(), callback });
        self.clients.push(Client {
            id: None,
            uuid: uuid.clone(),
            callback,
            is_congested: false,
            congestion_queue: vec![],
        });
    }

    fn remove(&mut self, id: i32) {
@@ -94,6 +119,10 @@ impl ContextMap {
        self.connections.push(Connection { conn_id, address: address.clone(), client_id });
    }

    fn remove_connection(&mut self, _client_id: i32, conn_id: i32) {
        self.connections.retain(|conn| conn.conn_id != conn_id);
    }

    fn get_conn_id_from_address(&self, client_id: i32, address: &String) -> Option<i32> {
        match self
            .connections
@@ -249,6 +278,24 @@ pub trait IBluetoothGattCallback: RPCProxy {
    /// The completion of IBluetoothGatt::read_phy.
    fn on_phy_read(&self, addr: String, tx_phy: LePhy, rx_phy: LePhy, status: GattStatus);

    /// The completion of IBluetoothGatt::read_characteristic.
    fn on_characteristic_read(&self, addr: String, status: i32, handle: i32, value: Vec<u8>);

    /// The completion of IBluetoothGatt::write_characteristic.
    fn on_characteristic_write(&self, addr: String, status: i32, handle: i32);

    /// When a reliable write is completed.
    fn on_execute_write(&self, addr: String, status: i32);

    /// The completion of IBluetoothGatt::read_descriptor.
    fn on_descriptor_read(&self, addr: String, status: i32, handle: i32, value: Vec<u8>);

    /// The completion of IBluetoothGatt::write_descriptor.
    fn on_descriptor_write(&self, addr: String, status: i32, handle: i32);

    /// When notification or indication is received.
    fn on_notify(&self, addr: String, handle: i32, value: Vec<u8>);

    /// The completion of IBluetoothGatt::read_remote_rssi.
    fn on_read_remote_rssi(&self, addr: String, rssi: i32, status: i32);

@@ -738,12 +785,48 @@ pub(crate) trait BtifGattClientCallbacks {
    #[btif_callback(Connect)]
    fn connect_cb(&mut self, conn_id: i32, status: i32, client_id: i32, addr: RawAddress);

    #[btif_callback(Disconnect)]
    fn disconnect_cb(&mut self, conn_id: i32, status: i32, client_id: i32, addr: RawAddress);

    #[btif_callback(SearchComplete)]
    fn search_complete_cb(&mut self, conn_id: i32, status: i32);

    #[btif_callback(RegisterForNotification)]
    fn register_for_notification_cb(
        &mut self,
        conn_id: i32,
        registered: i32,
        status: i32,
        handle: u16,
    );

    #[btif_callback(Notify)]
    fn notify_cb(&mut self, conn_id: i32, data: BtGattNotifyParams);

    #[btif_callback(ReadCharacteristic)]
    fn read_characteristic_cb(&mut self, conn_id: i32, status: i32, data: BtGattReadParams);

    #[btif_callback(WriteCharacteristic)]
    fn write_characteristic_cb(&mut self, conn_id: i32, status: i32, handle: u16);

    #[btif_callback(ReadDescriptor)]
    fn read_descriptor_cb(&mut self, conn_id: i32, status: i32, data: BtGattReadParams);

    #[btif_callback(WriteDescriptor)]
    fn write_descriptor_cb(&mut self, conn_id: i32, status: i32, handle: u16);

    #[btif_callback(ExecuteWrite)]
    fn execute_write_cb(&mut self, conn_id: i32, status: i32);

    #[btif_callback(ReadRemoteRssi)]
    fn read_remote_rssi_cb(&mut self, client_id: i32, addr: RawAddress, rssi: i32, status: i32);

    #[btif_callback(ConfigureMtu)]
    fn configure_mtu_cb(&mut self, conn_id: i32, status: i32, mtu: i32);

    #[btif_callback(Congestion)]
    fn congestion_cb(&mut self, conn_id: i32, congested: bool);

    #[btif_callback(PhyUpdated)]
    fn phy_updated_cb(&mut self, conn_id: i32, tx_phy: u8, rx_phy: u8, status: u8);

@@ -798,6 +881,153 @@ impl BtifGattClientCallbacks for BluetoothGatt {
        );
    }

    fn disconnect_cb(&mut self, conn_id: i32, status: i32, client_id: i32, addr: RawAddress) {
        self.context_map.remove_connection(client_id, conn_id);
        let client = self.context_map.get_by_client_id(client_id);
        if client.is_none() {
            return;
        }

        client.unwrap().callback.on_client_connection_state(
            status,
            client_id,
            match GattStatus::from_i32(status) {
                None => false,
                Some(gatt_status) => gatt_status == GattStatus::Success,
            },
            addr.to_string(),
        );
    }

    fn search_complete_cb(&mut self, conn_id: i32, _status: i32) {
        // Gatt DB is ready!
        self.gatt.as_ref().unwrap().client.get_gatt_db(conn_id);
    }

    fn register_for_notification_cb(
        &mut self,
        _conn_id: i32,
        _registered: i32,
        _status: i32,
        _handle: u16,
    ) {
        // No-op.
    }

    fn notify_cb(&mut self, conn_id: i32, data: BtGattNotifyParams) {
        let client = self.context_map.get_client_by_conn_id(conn_id);
        if client.is_none() {
            return;
        }

        client.unwrap().callback.on_notify(
            RawAddress { val: data.bda.address }.to_string(),
            data.handle as i32,
            data.value[0..data.len as usize].to_vec(),
        );
    }

    fn read_characteristic_cb(&mut self, conn_id: i32, status: i32, data: BtGattReadParams) {
        let address = self.context_map.get_address_by_conn_id(conn_id);
        if address.is_none() {
            return;
        }

        let client = self.context_map.get_client_by_conn_id(conn_id);
        if client.is_none() {
            return;
        }

        client.unwrap().callback.on_characteristic_read(
            address.unwrap().to_string(),
            status,
            data.handle as i32,
            data.value.value[0..data.value.len as usize].to_vec(),
        );
    }

    fn write_characteristic_cb(&mut self, conn_id: i32, mut status: i32, handle: u16) {
        let address = self.context_map.get_address_by_conn_id(conn_id);
        if address.is_none() {
            return;
        }

        // TODO(b/193685325): Handle increasing permit.

        let client = self.context_map.get_client_by_conn_id_mut(conn_id);
        if client.is_none() {
            return;
        }

        let client = client.unwrap();

        if client.is_congested {
            if status == GattStatus::Congested.to_i32().unwrap() {
                status = GattStatus::Success.to_i32().unwrap();
            }

            client.congestion_queue.push((address.unwrap().to_string(), status, handle as i32));
            return;
        }

        client.callback.on_characteristic_write(
            address.unwrap().to_string(),
            status,
            handle as i32,
        );
    }

    fn read_descriptor_cb(&mut self, conn_id: i32, status: i32, data: BtGattReadParams) {
        let address = self.context_map.get_address_by_conn_id(conn_id);
        if address.is_none() {
            return;
        }

        let client = self.context_map.get_client_by_conn_id(conn_id);
        if client.is_none() {
            return;
        }

        client.unwrap().callback.on_descriptor_read(
            address.unwrap().to_string(),
            status,
            data.handle as i32,
            data.value.value[0..data.value.len as usize].to_vec(),
        );
    }

    fn write_descriptor_cb(&mut self, conn_id: i32, status: i32, handle: u16) {
        let address = self.context_map.get_address_by_conn_id(conn_id);
        if address.is_none() {
            return;
        }

        let client = self.context_map.get_client_by_conn_id(conn_id);
        if client.is_none() {
            return;
        }

        client.unwrap().callback.on_descriptor_write(
            address.unwrap().to_string(),
            status,
            handle as i32,
        );
    }

    fn execute_write_cb(&mut self, conn_id: i32, status: i32) {
        let address = self.context_map.get_address_by_conn_id(conn_id);
        if address.is_none() {
            return;
        }

        let client = self.context_map.get_client_by_conn_id(conn_id);
        if client.is_none() {
            return;
        }

        client.unwrap().callback.on_execute_write(address.unwrap().to_string(), status);
    }

    fn read_remote_rssi_cb(&mut self, client_id: i32, addr: RawAddress, rssi: i32, status: i32) {
        let client = self.context_map.get_by_client_id(client_id);
        if client.is_none() {
@@ -821,6 +1051,23 @@ impl BtifGattClientCallbacks for BluetoothGatt {
        client.unwrap().callback.on_configure_mtu(addr.unwrap(), mtu, status);
    }

    fn congestion_cb(&mut self, conn_id: i32, congested: bool) {
        let client = self.context_map.get_client_by_conn_id_mut(conn_id);
        if client.is_none() {
            return;
        }

        let client = client.unwrap();

        client.is_congested = congested;
        if !client.is_congested {
            for callback in client.congestion_queue.iter() {
                client.callback.on_characteristic_write(callback.0.clone(), callback.1, callback.2);
            }
            client.congestion_queue.clear();
        }
    }

    fn phy_updated_cb(&mut self, conn_id: i32, tx_phy: u8, rx_phy: u8, status: u8) {
        let client = self.context_map.get_client_by_conn_id(conn_id);
        if client.is_none() {