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

Commit 59d2b955 authored by Sonny Sasaka's avatar Sonny Sasaka
Browse files

Add btclient client DBus proxy for IBluetoothManager

Bug: 188718349
Tag: #floss
Test: Build floss on Linux

Change-Id: I962e7aeb396fa5df638e4e7f01aa7104bfb14056
parent 1202de09
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ edition = "2018"
rustyline = "8.0"
bt_topshim = { path = "../../topshim" }
btstack = { path = "../stack" }
manager_service = { path = "../mgmt" }

dbus = "0.9.2"
dbus-crossroads = "0.4.0"
+120 −20
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
use bt_topshim::btif::BtSspVariant;

use btstack::bluetooth::{BluetoothDevice, BluetoothTransport, IBluetooth, IBluetoothCallback};
use btstack::RPCProxy;

use dbus::arg::{AppendAll, RefArg};
use dbus::nonblock::SyncConnection;
@@ -14,6 +13,8 @@ use dbus_projection::{impl_dbus_arg_enum, DisconnectWatcher};

use dbus_macros::{dbus_method, dbus_propmap, generate_dbus_exporter};

use manager_service::iface_bluetooth_manager::{IBluetoothManager, IBluetoothManagerCallback};

use num_traits::{FromPrimitive, ToPrimitive};

use std::sync::{Arc, Mutex};
@@ -28,22 +29,20 @@ pub struct BluetoothDeviceDBus {
    address: String,
}

pub(crate) struct BluetoothDBus {
struct ClientDBusProxy {
    conn: Arc<SyncConnection>,
    cr: Arc<Mutex<Crossroads>>,
    bus_name: String,
    objpath: dbus::Path<'static>,
    interface: String,
}

impl BluetoothDBus {
    pub(crate) fn new(conn: Arc<SyncConnection>, cr: Arc<Mutex<Crossroads>>) -> BluetoothDBus {
        BluetoothDBus { conn: conn.clone(), cr: cr }
    }

impl ClientDBusProxy {
    fn create_proxy(&self) -> dbus::nonblock::Proxy<Arc<SyncConnection>> {
        let conn = self.conn.clone();
        // TODO: Adapter path should have hci number, e.g. /org/chromium/bluetooth/adapter/hci0.
        dbus::nonblock::Proxy::new(
            "org.chromium.bluetooth",
            "/org/chromium/bluetooth/adapter",
            self.bus_name.clone(),
            self.objpath.clone(),
            std::time::Duration::from_secs(2),
            conn,
        )
@@ -57,7 +56,7 @@ impl BluetoothDBus {
        let proxy = self.create_proxy();
        // We know that all APIs return immediately, so we can block on it for simplicity.
        let (ret,): (T,) = futures::executor::block_on(async {
            proxy.method_call("org.chromium.bluetooth.Bluetooth", member, args).await
            proxy.method_call(self.interface.clone(), member, args).await
        })
        .unwrap();

@@ -68,7 +67,7 @@ impl BluetoothDBus {
        let proxy = self.create_proxy();
        // We know that all APIs return immediately, so we can block on it for simplicity.
        let _: () = futures::executor::block_on(async {
            proxy.method_call("org.chromium.bluetooth.Bluetooth", member, args).await
            proxy.method_call(self.interface.clone(), member, args).await
        })
        .unwrap();
    }
@@ -77,7 +76,7 @@ impl BluetoothDBus {
#[allow(dead_code)]
struct IBluetoothCallbackDBus {}

impl RPCProxy for IBluetoothCallbackDBus {
impl btstack::RPCProxy for IBluetoothCallbackDBus {
    // Dummy implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn get_object_id(&self) -> String {
@@ -113,6 +112,25 @@ impl IBluetoothCallback for IBluetoothCallbackDBus {
    }
}

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

impl BluetoothDBus {
    pub(crate) fn new(conn: Arc<SyncConnection>, cr: Arc<Mutex<Crossroads>>) -> BluetoothDBus {
        // TODO: Adapter path should have hci number, e.g. /org/chromium/bluetooth/adapter/hci0.
        BluetoothDBus {
            client_proxy: ClientDBusProxy {
                conn: conn.clone(),
                cr: cr,
                bus_name: String::from("org.chromium.bluetooth"),
                objpath: dbus::Path::new("/org/chromium/bluetooth/adapter").unwrap(),
                interface: String::from("org.chromium.bluetooth.Bluetooth"),
            },
        }
    }
}

// TODO: These are boilerplate codes, consider creating a macro to generate.
impl IBluetooth for BluetoothDBus {
    fn register_callback(&mut self, callback: Box<dyn IBluetoothCallback + Send>) {
@@ -120,13 +138,13 @@ impl IBluetooth for BluetoothDBus {
        let path = dbus::Path::new(path_string.clone()).unwrap();
        export_bluetooth_callback_dbus_obj(
            path_string,
            self.conn.clone(),
            &mut self.cr.lock().unwrap(),
            self.client_proxy.conn.clone(),
            &mut self.client_proxy.cr.lock().unwrap(),
            Arc::new(Mutex::new(callback)),
            Arc::new(Mutex::new(DisconnectWatcher::new())),
        );

        self.method_noreturn("RegisterCallback", (path,))
        self.client_proxy.method_noreturn("RegisterCallback", (path,))
    }

    fn enable(&mut self) -> bool {
@@ -140,19 +158,19 @@ impl IBluetooth for BluetoothDBus {
    }

    fn get_address(&self) -> String {
        self.method("GetAddress", ())
        self.client_proxy.method("GetAddress", ())
    }

    fn start_discovery(&self) -> bool {
        self.method("StartDiscovery", ())
        self.client_proxy.method("StartDiscovery", ())
    }

    fn cancel_discovery(&self) -> bool {
        self.method("CancelDiscovery", ())
        self.client_proxy.method("CancelDiscovery", ())
    }

    fn create_bond(&self, device: BluetoothDevice, transport: BluetoothTransport) -> bool {
        self.method(
        self.client_proxy.method(
            "CreateBond",
            (
                BluetoothDevice::to_dbus(device).unwrap(),
@@ -161,3 +179,85 @@ impl IBluetooth for BluetoothDBus {
        )
    }
}

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

impl BluetoothManagerDBus {
    pub(crate) fn new(
        conn: Arc<SyncConnection>,
        cr: Arc<Mutex<Crossroads>>,
    ) -> BluetoothManagerDBus {
        BluetoothManagerDBus {
            client_proxy: ClientDBusProxy {
                conn: conn.clone(),
                cr: cr,
                bus_name: String::from("org.chromium.bluetooth.Manager"),
                objpath: dbus::Path::new("/org/chromium/bluetooth/Manager").unwrap(),
                interface: String::from("org.chromium.bluetooth.Manager"),
            },
        }
    }
}

// TODO: These are boilerplate codes, consider creating a macro to generate.
impl IBluetoothManager for BluetoothManagerDBus {
    fn start(&mut self, hci_interface: i32) {
        self.client_proxy.method_noreturn("Start", (hci_interface,))
    }

    fn stop(&mut self, hci_interface: i32) {
        self.client_proxy.method_noreturn("Stop", (hci_interface,))
    }

    fn get_state(&mut self) -> i32 {
        self.client_proxy.method("GetState", ())
    }

    fn register_callback(&mut self, callback: Box<dyn IBluetoothManagerCallback + Send>) {
        let path_string = callback.get_object_id();
        let path = dbus::Path::new(path_string.clone()).unwrap();
        export_bluetooth_manager_callback_dbus_obj(
            path_string,
            self.client_proxy.conn.clone(),
            &mut self.client_proxy.cr.lock().unwrap(),
            Arc::new(Mutex::new(callback)),
            Arc::new(Mutex::new(DisconnectWatcher::new())),
        );

        self.client_proxy.method_noreturn("RegisterCallback", (path,))
    }

    fn get_floss_enabled(&mut self) -> bool {
        self.client_proxy.method("GetFlossEnabled", ())
    }

    fn set_floss_enabled(&mut self, enabled: bool) {
        self.client_proxy.method_noreturn("SetFlossEnabled", (enabled,))
    }

    fn list_hci_devices(&mut self) -> Vec<i32> {
        self.client_proxy.method("ListHciDevices", ())
    }
}

#[allow(dead_code)]
struct IBluetoothManagerCallbackDBus {}

impl manager_service::RPCProxy for IBluetoothManagerCallbackDBus {
    // Placeholder implementations just to satisfy impl RPCProxy requirements.
    fn register_disconnect(&mut self, _f: Box<dyn Fn() + Send>) {}
    fn get_object_id(&self) -> String {
        String::from("")
    }
}

#[generate_dbus_exporter(
    export_bluetooth_manager_callback_dbus_obj,
    "org.chromium.bluetooth.ManagerCallback"
)]
impl IBluetoothManagerCallback for IBluetoothManagerCallbackDBus {
    #[dbus_method("OnHciDeviceChanged")]
    fn on_hci_device_changed(&self, hci_interface: i32, present: bool) {}
}