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

Commit 0734b40f authored by Abhishek Pandit-Subedi's avatar Abhishek Pandit-Subedi Committed by Abhishek Pandit-Subedi
Browse files

floss: Implement service discovery

This implements the following adapter apis:
* FetchRemoteUuids
* GetRemoteUuids
* SdpSearch

Bug: 196887189
Tag: #floss
Test: dbus-send on ChromeOS
Change-Id: Ied7c1325b1b37aad2947a94afc43f3a85433ffe6
parent fbf2c67d
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -281,6 +281,24 @@ impl IBluetooth for BluetoothDBus {
    fn get_bond_state(&self, device: BluetoothDevice) -> u32 {
        self.client_proxy.method("GetBondState", (BluetoothDevice::to_dbus(device).unwrap(),))
    }

    fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
        let result: Vec<Vec<u8>> = self
            .client_proxy
            .method("GetRemoteUuids", (BluetoothDevice::to_dbus(device).unwrap(),));
        <Vec<Uuid128Bit> as DBusArg>::from_dbus(result, None, None, None).unwrap()
    }

    fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool {
        self.client_proxy.method("FetchRemoteUuids", (BluetoothDevice::to_dbus(device).unwrap(),))
    }

    fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
        self.client_proxy.method(
            "SdpSearch",
            (BluetoothDevice::to_dbus(device).unwrap(), Uuid128Bit::to_dbus(uuid).unwrap()),
        )
    }
}

#[dbus_propmap(AdapterWithEnabled)]
+15 −0
Original line number Diff line number Diff line
@@ -137,4 +137,19 @@ impl IBluetooth for IBluetoothDBus {
    fn get_bond_state(&self, _device: BluetoothDevice) -> u32 {
        0
    }

    #[dbus_method("GetRemoteUuids")]
    fn get_remote_uuids(&self, _device: BluetoothDevice) -> Vec<Uuid128Bit> {
        vec![]
    }

    #[dbus_method("FetchRemoteUuids")]
    fn fetch_remote_uuids(&self, _device: BluetoothDevice) -> bool {
        true
    }

    #[dbus_method("SdpSearch")]
    fn sdp_search(&self, _device: BluetoothDevice, _uuid: Uuid128Bit) -> bool {
        true
    }
}
+106 −0
Original line number Diff line number Diff line
@@ -77,6 +77,15 @@ pub trait IBluetooth {

    /// Gets the bond state of a single device.
    fn get_bond_state(&self, device: BluetoothDevice) -> u32;

    /// Returns the cached UUIDs of a remote device.
    fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit>;

    /// Triggers SDP to get UUIDs of a remote device.
    fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool;

    /// Triggers SDP and searches for a specific UUID on a remote device.
    fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool;
}

#[derive(Debug, FromPrimitive, ToPrimitive)]
@@ -303,6 +312,15 @@ pub(crate) trait BtifBluetoothCallbacks {
        bond_state: BtBondState,
        fail_reason: i32,
    );

    #[btif_callback(RemoteDeviceProperties)]
    fn remote_device_properties_changed(
        &mut self,
        status: BtStatus,
        addr: RawAddress,
        num_properties: i32,
        properties: Vec<BluetoothProperty>,
    );
}

#[btif_callbacks_dispatcher(Bluetooth, dispatch_sdp_callbacks, SdpCallbacks)]
@@ -502,6 +520,36 @@ impl BtifBluetoothCallbacks for Bluetooth {
            );
        });
    }

    fn remote_device_properties_changed(
        &mut self,
        status: BtStatus,
        addr: RawAddress,
        _num_properties: i32,
        properties: Vec<BluetoothProperty>,
    ) {
        let address = addr.to_string();
        // Device should be in either found devices or bonded devices
        // If it isn't in either, create it and put it found devices.
        let device = if self.bonded_devices.contains_key(&address) {
            self.bonded_devices.get_mut(&address)
        } else if self.found_devices.contains_key(&address) {
            self.found_devices.get_mut(&address)
        } else {
            self.found_devices.insert(
                address.clone(),
                BluetoothDeviceContext::new(
                    BtBondState::NotBonded,
                    BluetoothDevice::new(address.clone(), String::from("")),
                    vec![],
                ),
            );

            self.found_devices.get_mut(&address)
        };

        device.unwrap().update_properties(properties);
    }
}

// TODO: Add unit tests for this implementation
@@ -654,6 +702,64 @@ impl IBluetooth for Bluetooth {
            None => BtBondState::NotBonded.to_u32().unwrap(),
        }
    }

    fn get_remote_uuids(&self, device: BluetoothDevice) -> Vec<Uuid128Bit> {
        // Device must exist in either bonded or found list
        let device = self
            .bonded_devices
            .get(&device.address)
            .or_else(|| self.found_devices.get(&device.address));

        // Extract property from the device
        return device
            .and_then(|d| {
                if let Some(u) = d.properties.get(&BtPropertyType::Uuids) {
                    match u {
                        BluetoothProperty::Uuids(uuids) => {
                            return Some(
                                uuids.iter().map(|&x| x.uu.clone()).collect::<Vec<Uuid128Bit>>(),
                            );
                        }
                        _ => (),
                    }
                }

                None
            })
            .unwrap_or(vec![]);
    }

    fn fetch_remote_uuids(&self, device: BluetoothDevice) -> bool {
        if !self.bonded_devices.contains_key(&device.address)
            && !self.found_devices.contains_key(&device.address)
        {
            warn!("Won't fetch UUIDs on unknown device {}", device.address);
            return false;
        }

        let addr = RawAddress::from_string(device.address.clone());
        if addr.is_none() {
            warn!("Can't fetch UUIDs. Address {} is not valid.", device.address);
            return false;
        }
        self.intf.lock().unwrap().get_remote_services(&mut addr.unwrap(), BtTransport::Auto) == 0
    }

    fn sdp_search(&self, device: BluetoothDevice, uuid: Uuid128Bit) -> bool {
        if self.sdp.is_none() {
            warn!("SDP is not initialized. Can't do SDP search.");
            return false;
        }

        let addr = RawAddress::from_string(device.address.clone());
        if addr.is_none() {
            warn!("Can't SDP search. Address {} is not valid.", device.address);
            return false;
        }

        let uu = Uuid { uu: uuid };
        self.sdp.as_ref().unwrap().sdp_search(&mut addr.unwrap(), &uu) == BtStatus::Success
    }
}

impl BtifSdpCallbacks for Bluetooth {
+7 −2
Original line number Diff line number Diff line
@@ -29,14 +29,14 @@ impl From<bindings::bt_state_t> for BtState {
#[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
#[repr(u32)]
pub enum BtTransport {
    Invalid = 0,
    Auto = 0,
    Bredr,
    Le,
}

impl From<i32> for BtTransport {
    fn from(item: i32) -> Self {
        BtTransport::from_i32(item).unwrap_or_else(|| BtTransport::Invalid)
        BtTransport::from_i32(item).unwrap_or_else(|| BtTransport::Auto)
    }
}

@@ -855,6 +855,11 @@ impl BluetoothInterface {
        ccall!(self, set_remote_device_property, ffi_addr, &prop_pair.1)
    }

    pub fn get_remote_services(&self, addr: &mut RawAddress, transport: BtTransport) -> i32 {
        let ffi_addr = cast_to_ffi_address!(addr as *const RawAddress);
        ccall!(self, get_remote_services, ffi_addr, transport.to_i32().unwrap())
    }

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