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

Commit 28e1e4e6 authored by howardchung's avatar howardchung
Browse files

Floss: Implement admin callback client in btclient

This registers a super basic callbacks when entering btclient which just
print what it gets in debug format.

Bug: 239470860
Test: test it with the following procedures.
1. start btclient. Pair with a Classic KBD, and Classic headset.
2. set allowlist to A2DP+HFP+AVRCP. Check btclient gets notification of
   new allowlist and the policy effect of devices are correct.
3. start scan in btclient and check if it gets notifications of policy
   effect change of new devices.

Change-Id: I0d26c70b67393a92d05f6c9598fa97db83cfa2b8
parent 868b8824
Loading
Loading
Loading
Loading
+57 −4
Original line number Diff line number Diff line
use crate::dbus_iface::{
    export_advertising_set_callback_dbus_intf, export_bluetooth_callback_dbus_intf,
    export_bluetooth_connection_callback_dbus_intf, export_bluetooth_gatt_callback_dbus_intf,
    export_bluetooth_manager_callback_dbus_intf, export_scanner_callback_dbus_intf,
    export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf,
    export_admin_policy_callback_dbus_intf, export_advertising_set_callback_dbus_intf,
    export_bluetooth_callback_dbus_intf, export_bluetooth_connection_callback_dbus_intf,
    export_bluetooth_gatt_callback_dbus_intf, export_bluetooth_manager_callback_dbus_intf,
    export_scanner_callback_dbus_intf, export_socket_callback_dbus_intf,
    export_suspend_callback_dbus_intf,
};
use crate::ClientContext;
use crate::{console_red, console_yellow, print_error, print_info};
@@ -11,6 +12,7 @@ use bt_topshim::profiles::gatt::{GattStatus, LePhy};
use btstack::bluetooth::{
    BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
};
use btstack::bluetooth_admin::{IBluetoothAdminPolicyCallback, PolicyEffect};
use btstack::bluetooth_adv::IAdvertisingSetCallback;
use btstack::bluetooth_gatt::{
    BluetoothGattService, IBluetoothGattCallback, IScannerCallback, ScanResult,
@@ -349,6 +351,57 @@ impl RPCProxy for ScannerCallback {
    }
}

pub(crate) struct AdminCallback {
    objpath: String,

    dbus_connection: Arc<SyncConnection>,
    dbus_crossroads: Arc<Mutex<Crossroads>>,
}

impl AdminCallback {
    pub(crate) fn new(
        objpath: String,
        dbus_connection: Arc<SyncConnection>,
        dbus_crossroads: Arc<Mutex<Crossroads>>,
    ) -> Self {
        Self { objpath, dbus_connection, dbus_crossroads }
    }
}

impl IBluetoothAdminPolicyCallback for AdminCallback {
    fn on_service_allowlist_changed(&self, allowlist: Vec<Uuid128Bit>) {
        print_info!("new allowlist: {:?}", allowlist);
    }

    fn on_device_policy_effect_changed(
        &self,
        device: BluetoothDevice,
        new_policy_effect: Option<PolicyEffect>,
    ) {
        print_info!(
            "new device policy effect. Device: {:?}. New Effect: {:?}",
            device,
            new_policy_effect
        );
    }
}

impl RPCProxy for AdminCallback {
    fn get_object_id(&self) -> String {
        self.objpath.clone()
    }

    fn export_for_rpc(self: Box<Self>) {
        let cr = self.dbus_crossroads.clone();
        let iface = export_admin_policy_callback_dbus_intf(
            self.dbus_connection.clone(),
            &mut cr.lock().unwrap(),
            Arc::new(Mutex::new(DisconnectWatcher::new())),
        );
        cr.lock().unwrap().insert(self.get_object_id(), &[iface], Arc::new(Mutex::new(self)));
    }
}

pub(crate) struct AdvertisingSetCallback {
    objpath: String,
    context: Arc<Mutex<ClientContext>>,
+96 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ use bt_topshim::profiles::socket::SocketType;
use btstack::bluetooth::{
    BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback, IBluetoothQA,
};
use btstack::bluetooth_admin::{IBluetoothAdmin, IBluetoothAdminPolicyCallback, PolicyEffect};
use btstack::bluetooth_adv::{
    AdvertiseData, AdvertisingSetParameters, IAdvertisingSetCallback, ManfId,
    PeriodicAdvertisingParameters,
@@ -828,6 +829,101 @@ pub struct PeriodicAdvertisingParametersDBus {
    pub interval: i32,
}

pub(crate) struct BluetoothAdminDBusRPC {
    client_proxy: ClientDBusProxy,
}

pub(crate) struct BluetoothAdminDBus {
    client_proxy: ClientDBusProxy,
    pub rpc: BluetoothAdminDBusRPC,
}

impl BluetoothAdminDBus {
    fn make_client_proxy(conn: Arc<SyncConnection>, index: i32) -> ClientDBusProxy {
        ClientDBusProxy::new(
            conn,
            String::from("org.chromium.bluetooth"),
            make_object_path(index, "admin"),
            String::from("org.chromium.bluetooth.BluetoothAdmin"),
        )
    }

    pub(crate) fn new(conn: Arc<SyncConnection>, index: i32) -> BluetoothAdminDBus {
        BluetoothAdminDBus {
            client_proxy: Self::make_client_proxy(conn.clone(), index),
            rpc: BluetoothAdminDBusRPC {
                client_proxy: Self::make_client_proxy(conn.clone(), index),
            },
        }
    }
}

#[generate_dbus_interface_client(BluetoothAdminDBusRPC)]
impl IBluetoothAdmin for BluetoothAdminDBus {
    #[dbus_method("IsServiceAllowed")]
    fn is_service_allowed(&self, uuid: Uuid128Bit) -> bool {
        dbus_generated!()
    }

    #[dbus_method("SetAllowedServices")]
    fn set_allowed_services(&mut self, services: Vec<Uuid128Bit>) -> bool {
        dbus_generated!()
    }

    #[dbus_method("GetAllowedServices")]
    fn get_allowed_services(&self) -> Vec<Uuid128Bit> {
        dbus_generated!()
    }

    #[dbus_method("GetDevicePolicyEffect")]
    fn get_device_policy_effect(&self, device: BluetoothDevice) -> Option<PolicyEffect> {
        dbus_generated!()
    }

    #[dbus_method("RegisterAdminPolicyCallback")]
    fn register_admin_policy_callback(
        &mut self,
        callback: Box<dyn IBluetoothAdminPolicyCallback + Send>,
    ) -> u32 {
        dbus_generated!()
    }

    #[dbus_method("UnregisterAdminPolicyCallback")]
    fn unregister_admin_policy_callback(&mut self, callback_id: u32) -> bool {
        dbus_generated!()
    }
}

#[dbus_propmap(PolicyEffect)]
pub struct PolicyEffectDBus {
    pub service_blocked: Vec<Uuid128Bit>,
    pub affected: bool,
}

struct IBluetoothAdminPolicyCallbackDBus {}

impl RPCProxy for IBluetoothAdminPolicyCallbackDBus {}

#[generate_dbus_exporter(
    export_admin_policy_callback_dbus_intf,
    "org.chromium.bluetooth.AdminPolicyCallback"
)]
impl IBluetoothAdminPolicyCallback for IBluetoothAdminPolicyCallbackDBus {
    #[dbus_method("OnServiceAllowlistChanged")]
    fn on_service_allowlist_changed(&self, allowed_list: Vec<Uuid128Bit>) {
        dbus_generated!()
    }

    #[dbus_method("OnDevicePolicyEffectChanged")]
    fn on_device_policy_effect_changed(
        &self,
        device: BluetoothDevice,
        new_policy_effect: Option<PolicyEffect>,
    ) {
        dbus_generated!()
    }
}

pub(crate) struct BluetoothGattDBusRPC {
    client_proxy: ClientDBusProxy,
}
+31 −2
Original line number Diff line number Diff line
@@ -8,12 +8,12 @@ use dbus_crossroads::Crossroads;
use tokio::sync::mpsc;

use crate::callbacks::{
    AdvertisingSetCallback, BtCallback, BtConnectionCallback, BtManagerCallback,
    AdminCallback, AdvertisingSetCallback, BtCallback, BtConnectionCallback, BtManagerCallback,
    BtSocketManagerCallback, ScannerCallback, SuspendCallback,
};
use crate::command_handler::CommandHandler;
use crate::dbus_iface::{
    BluetoothDBus, BluetoothGattDBus, BluetoothManagerDBus, BluetoothQADBus,
    BluetoothAdminDBus, BluetoothDBus, BluetoothGattDBus, BluetoothManagerDBus, BluetoothQADBus,
    BluetoothSocketManagerDBus, SuspendDBus,
};
use crate::editor::AsyncEditor;
@@ -77,6 +77,9 @@ pub(crate) struct ClientContext {
    /// Proxy for GATT interface.
    pub(crate) gatt_dbus: Option<BluetoothGattDBus>,

    /// Proxy for Admin interface.
    pub(crate) admin_dbus: Option<BluetoothAdminDBus>,

    /// Proxy for suspend interface.
    pub(crate) suspend_dbus: Option<SuspendDBus>,

@@ -98,6 +101,9 @@ pub(crate) struct ClientContext {
    /// Identifies the callback to receive IAdvertisingSetCallback method calls.
    advertiser_callback_id: Option<u32>,

    /// Identifies the callback to receive IBluetoothAdminPolicyCallback method calls.
    admin_callback_id: Option<u32>,

    /// Keeps track of active LE scanners.
    active_scanner_ids: HashSet<u8>,

@@ -133,6 +139,7 @@ impl ClientContext {
            adapter_dbus: None,
            qa_dbus: None,
            gatt_dbus: None,
            admin_dbus: None,
            suspend_dbus: None,
            socket_manager_dbus: None,
            fg: tx,
@@ -140,6 +147,7 @@ impl ClientContext {
            dbus_crossroads,
            scanner_callback_id: None,
            advertiser_callback_id: None,
            admin_callback_id: None,
            active_scanner_ids: HashSet::new(),
            adv_sets: HashMap::new(),
            socket_manager_callback_id: None,
@@ -178,6 +186,9 @@ impl ClientContext {
        let gatt_dbus = BluetoothGattDBus::new(conn.clone(), idx);
        self.gatt_dbus = Some(gatt_dbus);

        let admin_dbus = BluetoothAdminDBus::new(conn.clone(), idx);
        self.admin_dbus = Some(admin_dbus);

        let socket_manager_dbus = BluetoothSocketManagerDBus::new(conn.clone(), idx);
        self.socket_manager_dbus = Some(socket_manager_dbus);

@@ -405,6 +416,8 @@ async fn start_interactive_shell(
                    format!("/org/chromium/bluetooth/client/{}/scanner_callback", adapter);
                let advertiser_cb_objpath: String =
                    format!("/org/chromium/bluetooth/client/{}/advertising_set_callback", adapter);
                let admin_cb_objpath: String =
                    format!("/org/chromium/bluetooth/client/{}/admin_callback", adapter);
                let socket_manager_cb_objpath: String =
                    format!("/org/chromium/bluetooth/client/{}/socket_manager_callback", adapter);

@@ -477,6 +490,22 @@ async fn start_interactive_shell(
                    .expect("D-Bus error on IBluetoothGatt::RegisterAdvertiserCallback");
                context.lock().unwrap().advertiser_callback_id = Some(advertiser_callback_id);

                let admin_callback_id = context
                    .lock()
                    .unwrap()
                    .admin_dbus
                    .as_mut()
                    .unwrap()
                    .rpc
                    .register_admin_policy_callback(Box::new(AdminCallback::new(
                        admin_cb_objpath.clone(),
                        dbus_connection.clone(),
                        dbus_crossroads.clone(),
                    )))
                    .await
                    .expect("D-Bus error on IBluetoothAdmin::RegisterAdminCallback");
                context.lock().unwrap().admin_callback_id = Some(admin_callback_id);

                let socket_manager_callback_id = context
                    .lock()
                    .unwrap()
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ pub trait IBluetoothAdmin {
}

/// Information of the effects to a remote device by the admin policies
#[derive(PartialEq, Clone)]
#[derive(PartialEq, Clone, Debug)]
pub struct PolicyEffect {
    /// Array of services that are blocked by policy
    pub service_blocked: Vec<Uuid128Bit>,