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

Commit 7a53dc18 authored by Frédéric Danis's avatar Frédéric Danis
Browse files

Floss: Call IBluetoothTelephonyCallback method on UHid Open/Close events

The new added telephony callback expose the "in use" state, the main user
is the audio server to decide which of HFP and A2DP to use for audio.

Bug: 277693919
Test: Conduct the following manual tests.
  start btclient
  pair Bluetooth Headset
  load https://google.git.io/libhidtelephoony/ with Chrome
  click on "Start", select the headset then "Connect"
  "Inputs Reports" and "Output Reports" are correct
  btclient displays "Telephony use changed: …" events
Test: atest bluetooth_test_gd

Change-Id: Iabd179b72d1dba4ba75c95761a90ffb65e1bd41f
parent 1cb90b0b
Loading
Loading
Loading
Loading
+48 −4
Original line number Diff line number Diff line
@@ -3,9 +3,10 @@ use crate::dbus_iface::{
    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_bluetooth_media_callback_dbus_intf, export_gatt_server_callback_dbus_intf,
    export_qa_callback_dbus_intf, export_scanner_callback_dbus_intf,
    export_socket_callback_dbus_intf, export_suspend_callback_dbus_intf,
    export_bluetooth_media_callback_dbus_intf, export_bluetooth_telephony_callback_dbus_intf,
    export_gatt_server_callback_dbus_intf, export_qa_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};
@@ -22,7 +23,9 @@ use btstack::bluetooth_gatt::{
    BluetoothGattService, IBluetoothGattCallback, IBluetoothGattServerCallback, IScannerCallback,
    ScanResult,
};
use btstack::bluetooth_media::{BluetoothAudioDevice, IBluetoothMediaCallback};
use btstack::bluetooth_media::{
    BluetoothAudioDevice, IBluetoothMediaCallback, IBluetoothTelephonyCallback,
};
use btstack::bluetooth_qa::IBluetoothQACallback;
use btstack::socket_manager::{
    BluetoothServerSocket, BluetoothSocket, IBluetoothSocketManager,
@@ -1424,3 +1427,44 @@ impl RPCProxy for MediaCallback {
        cr.lock().unwrap().insert(self.get_object_id(), &[iface], Arc::new(Mutex::new(self)));
    }
}

pub(crate) struct TelephonyCallback {
    objpath: String,
    context: Arc<Mutex<ClientContext>>,

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

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

impl IBluetoothTelephonyCallback for TelephonyCallback {
    fn on_telephony_use(&mut self, addr: String, state: bool) {
        print_info!("Telephony use changed: [{}] state: {}", addr, state);
    }
}

impl RPCProxy for TelephonyCallback {
    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_bluetooth_telephony_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)));
    }
}
+43 −7
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ use btstack::bluetooth_gatt::{
};
use btstack::bluetooth_media::{
    BluetoothAudioDevice, IBluetoothMedia, IBluetoothMediaCallback, IBluetoothTelephony,
    IBluetoothTelephonyCallback,
};
use btstack::bluetooth_qa::IBluetoothQA;
use btstack::socket_manager::{
@@ -2263,25 +2264,45 @@ impl ISuspendCallback for ISuspendCallbackDBus {
    fn on_resumed(&mut self, suspend_id: i32) {}
}

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

pub(crate) struct BluetoothTelephonyDBus {
    client_proxy: ClientDBusProxy,
    pub rpc: BluetoothTelephonyDBusRPC,
}

impl BluetoothTelephonyDBus {
    pub(crate) fn new(conn: Arc<SyncConnection>, index: i32) -> BluetoothTelephonyDBus {
        BluetoothTelephonyDBus {
            client_proxy: ClientDBusProxy::new(
    fn make_client_proxy(conn: Arc<SyncConnection>, index: i32) -> ClientDBusProxy {
        ClientDBusProxy::new(
            conn.clone(),
            String::from("org.chromium.bluetooth"),
            make_object_path(index, "telephony"),
            String::from("org.chromium.bluetooth.BluetoothTelephony"),
            ),
        )
    }

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

#[generate_dbus_interface_client]
#[generate_dbus_interface_client(BluetoothTelephonyDBusRPC)]
impl IBluetoothTelephony for BluetoothTelephonyDBus {
    #[dbus_method("RegisterTelephonyCallback")]
    fn register_telephony_callback(
        &mut self,
        callback: Box<dyn IBluetoothTelephonyCallback + Send>,
    ) -> bool {
        dbus_generated!()
    }

    #[dbus_method("SetNetworkAvailable")]
    fn set_network_available(&mut self, network_available: bool) {
        dbus_generated!()
@@ -2352,6 +2373,21 @@ impl IBluetoothTelephony for BluetoothTelephonyDBus {
    }
}

struct IBluetoothTelephonyCallbackDBus {}

impl RPCProxy for IBluetoothTelephonyCallbackDBus {}

#[generate_dbus_exporter(
    export_bluetooth_telephony_callback_dbus_intf,
    "org.chromium.bluetooth.BluetoothTelephonyCallback"
)]
impl IBluetoothTelephonyCallback for IBluetoothTelephonyCallbackDBus {
    #[dbus_method("OnTelephonyUse")]
    fn on_telephony_use(&mut self, addr: String, state: bool) {
        dbus_generated!()
    }
}

pub(crate) struct BluetoothQADBusRPC {
    client_proxy: ClientDBusProxy,
}
+21 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ use crate::bt_gatt::GattClientContext;
use crate::callbacks::{
    AdminCallback, AdvertisingSetCallback, BtCallback, BtConnectionCallback, BtManagerCallback,
    BtSocketManagerCallback, MediaCallback, QACallback, ScannerCallback, SuspendCallback,
    TelephonyCallback,
};
use crate::command_handler::{CommandHandler, SocketSchedule};
use crate::dbus_iface::{
@@ -540,6 +541,10 @@ async fn handle_client_command(
                    format!("/org/chromium/bluetooth/client/{}/qa_manager_callback", adapter);
                let media_cb_objpath: String =
                    format!("/org/chromium/bluetooth/client/{}/bluetooth_media_callback", adapter);
                let telephony_cb_objpath: String = format!(
                    "/org/chromium/bluetooth/client/{}/bluetooth_telephony_callback",
                    adapter
                );

                let dbus_connection = context.lock().unwrap().dbus_connection.clone();
                let dbus_crossroads = context.lock().unwrap().dbus_crossroads.clone();
@@ -687,6 +692,22 @@ async fn handle_client_command(
                    .await
                    .expect("D-Bus error on IBluetoothMedia::RegisterCallback");

                context
                    .lock()
                    .unwrap()
                    .telephony_dbus
                    .as_mut()
                    .unwrap()
                    .rpc
                    .register_telephony_callback(Box::new(TelephonyCallback::new(
                        telephony_cb_objpath,
                        context.clone(),
                        dbus_connection.clone(),
                        dbus_crossroads.clone(),
                    )))
                    .await
                    .expect("D-Bus error on IBluetoothMedia::RegisterTelephonyCallback");

                context.lock().unwrap().adapter_ready = true;
                let adapter_address = context.lock().unwrap().update_adapter_address();
                context.lock().unwrap().update_bonded_devices();
+24 −2
Original line number Diff line number Diff line
use btstack::bluetooth_media::IBluetoothTelephony;
use btstack::bluetooth_media::{IBluetoothTelephony, IBluetoothTelephonyCallback};
use btstack::RPCProxy;

use dbus_macros::{dbus_method, generate_dbus_exporter};
use dbus::Path;

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

use dbus_projection::dbus_generated;

use crate::dbus_arg::DBusArg;

#[allow(dead_code)]
struct BluetoothTelephonyCallbackDBus {}

#[dbus_proxy_obj(BluetoothTelephonyCallback, "org.chromium.bluetooth.BluetoothTelephonyCallback")]
impl IBluetoothTelephonyCallback for BluetoothTelephonyCallbackDBus {
    #[dbus_method("OnTelephonyUse")]
    fn on_telephony_use(&mut self, addr: String, state: bool) {
        dbus_generated!()
    }
}

#[allow(dead_code)]
struct IBluetoothTelephonyDBus {}

@@ -14,6 +28,14 @@ struct IBluetoothTelephonyDBus {}
    "org.chromium.bluetooth.BluetoothTelephony"
)]
impl IBluetoothTelephony for IBluetoothTelephonyDBus {
    #[dbus_method("RegisterTelephonyCallback")]
    fn register_telephony_callback(
        &mut self,
        callback: Box<dyn IBluetoothTelephonyCallback + Send>,
    ) -> bool {
        dbus_generated!()
    }

    #[dbus_method("SetNetworkAvailable")]
    fn set_network_available(&mut self, network_available: bool) {
        dbus_generated!()
+56 −2
Original line number Diff line number Diff line
@@ -191,6 +191,12 @@ pub trait IBluetoothMediaCallback: RPCProxy {
}

pub trait IBluetoothTelephony {
    ///
    fn register_telephony_callback(
        &mut self,
        callback: Box<dyn IBluetoothTelephonyCallback + Send>,
    ) -> bool;

    /// Sets whether the device is connected to the cellular network.
    fn set_network_available(&mut self, network_available: bool);
    /// Sets whether the device is roaming.
@@ -229,6 +235,10 @@ pub trait IBluetoothTelephony {
    fn audio_disconnect(&mut self, address: String);
}

pub trait IBluetoothTelephonyCallback: RPCProxy {
    fn on_telephony_use(&mut self, addr: String, state: bool);
}

/// Serializable device used in.
#[derive(Debug, Default, Clone)]
pub struct BluetoothAudioDevice {
@@ -278,6 +288,7 @@ pub struct BluetoothMedia {
    battery_provider_id: u32,
    initialized: bool,
    callbacks: Arc<Mutex<Callbacks<dyn IBluetoothMediaCallback + Send>>>,
    telephony_callbacks: Arc<Mutex<Callbacks<dyn IBluetoothTelephonyCallback + Send>>>,
    tx: Sender<Message>,
    adapter: Option<Arc<Mutex<Box<Bluetooth>>>>,
    a2dp: Option<A2dp>,
@@ -327,6 +338,10 @@ impl BluetoothMedia {
                tx.clone(),
                Message::MediaCallbackDisconnected,
            ))),
            telephony_callbacks: Arc::new(Mutex::new(Callbacks::new(
                tx.clone(),
                Message::TelephonyCallbackDisconnected,
            ))),
            tx,
            adapter: None,
            a2dp: None,
@@ -1082,6 +1097,10 @@ impl BluetoothMedia {
        self.callbacks.lock().unwrap().remove_callback(id)
    }

    pub fn remove_telephony_callback(&mut self, id: u32) -> bool {
        self.telephony_callbacks.lock().unwrap().remove_callback(id)
    }

    fn uhid_create(&mut self, addr: RawAddress) {
        debug!(
            "[{}]: UHID create: PhoneOpsEnabled {}",
@@ -1111,8 +1130,20 @@ impl BluetoothMedia {
                    self.adapter_get_remote_name(addr),
                    move |m| {
                        match m {
                            OutputEvent::Close => debug!("UHID: Close"),
                            OutputEvent::Open => debug!("UHID: Open"),
                            OutputEvent::Close => {
                                txl.blocking_send(Message::UHidTelephonyUseCallback(
                                    remote_addr.clone(),
                                    false,
                                ))
                                .unwrap();
                            }
                            OutputEvent::Open => {
                                txl.blocking_send(Message::UHidTelephonyUseCallback(
                                    remote_addr.clone(),
                                    true,
                                ))
                                .unwrap();
                            }
                            OutputEvent::Output { data } => {
                                txl.blocking_send(Message::UHidHfpOutputCallback(
                                    remote_addr.clone(),
@@ -1225,6 +1256,21 @@ impl BluetoothMedia {
        }
    }

    pub fn dispatch_uhid_telephony_use_callback(&mut self, address: String, state: bool) {
        let addr = match RawAddress::from_string(address.clone()) {
            None => {
                warn!("UHID: Invalid device address for dispatch_uhid_telephony_use_callback");
                return;
            }
            Some(addr) => addr,
        };

        debug!("[{}]: UHID: Telephony use: {}", DisplayAddress(&addr), state);
        self.telephony_callbacks.lock().unwrap().for_all_callbacks(|callback| {
            callback.on_telephony_use(address.to_string(), state);
        });
    }

    fn set_hfp_mic_volume(&mut self, volume: u8, addr: RawAddress) {
        let vol = match i8::try_from(volume) {
            Ok(val) if val <= 15 => val,
@@ -2720,6 +2766,14 @@ impl IBluetoothMedia for BluetoothMedia {
}

impl IBluetoothTelephony for BluetoothMedia {
    fn register_telephony_callback(
        &mut self,
        callback: Box<dyn IBluetoothTelephonyCallback + Send>,
    ) -> bool {
        let _id = self.telephony_callbacks.lock().unwrap().add_callback(callback);
        true
    }

    fn set_network_available(&mut self, network_available: bool) {
        if self.telephony_device_status.network_available == network_available {
            return;
Loading