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

Commit 2aa1265f authored by Sarvesh Kalwit's avatar Sarvesh Kalwit Committed by Gerrit Code Review
Browse files

Merge "floss: Support Battery Manager within btclient" into main

parents 90dbdde3 9a89e897
Loading
Loading
Loading
Loading
+67 −6
Original line number Diff line number Diff line
use crate::command_handler::SocketSchedule;
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_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,
    export_battery_manager_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_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};
@@ -14,6 +14,7 @@ use bt_topshim::btif::{BtBondState, BtPropertyType, BtSspVariant, BtStatus, Uuid
use bt_topshim::profiles::gatt::{AdvertisingStatus, GattStatus, LePhy};
use bt_topshim::profiles::hfp::HfpCodecId;
use bt_topshim::profiles::sdp::BtSdpRecord;
use btstack::battery_manager::{BatterySet, IBatteryManagerCallback};
use btstack::bluetooth::{
    BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
};
@@ -1468,3 +1469,63 @@ impl RPCProxy for TelephonyCallback {
        cr.lock().unwrap().insert(self.get_object_id(), &[iface], Arc::new(Mutex::new(self)));
    }
}

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

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

impl BatteryManagerCallback {
    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 IBatteryManagerCallback for BatteryManagerCallback {
    fn on_battery_info_updated(&mut self, remote_address: String, battery_set: BatterySet) {
        let address = remote_address.to_uppercase();
        if self.context.lock().unwrap().battery_address_filter.contains(&address) {
            if battery_set.batteries.len() == 0 {
                print_info!(
                    "Battery info for address '{}' updated with empty battery set. \
                    The batteries for this device may have been removed.",
                    address.clone()
                );
                return;
            }
            print_info!(
                "Battery data for '{}' from source '{}' and uuid '{}' changed to:",
                address.clone(),
                battery_set.source_uuid.clone(),
                battery_set.source_info.clone()
            );
            for battery in battery_set.batteries {
                print_info!("   {}%, variant: '{}'", battery.percentage, battery.variant);
            }
        }
    }
}

impl RPCProxy for BatteryManagerCallback {
    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_battery_manager_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)));
    }
}
+92 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ use bt_topshim::btif::{BtConnectionState, BtDiscMode, BtStatus, BtTransport, INV
use bt_topshim::profiles::hid_host::BthhReportType;
use bt_topshim::profiles::sdp::{BtSdpMpsRecord, BtSdpRecord};
use bt_topshim::profiles::{gatt::LePhy, ProfileConnectionState};
use btstack::battery_manager::IBatteryManager;
use btstack::bluetooth::{BluetoothDevice, IBluetooth};
use btstack::bluetooth_gatt::{GattWriteType, IBluetoothGatt};
use btstack::bluetooth_media::{IBluetoothMedia, IBluetoothTelephony};
@@ -138,6 +139,24 @@ fn build_commands() -> HashMap<String, CommandOption> {
            function_pointer: CommandHandler::cmd_adapter,
        },
    );
    command_options.insert(
        String::from("battery"),
        CommandOption {
            rules: vec![
                String::from("battery status <address>"),
                String::from("battery track <address>"),
                String::from("battery untrack <address>"),
            ],
            description: String::from(
                "
                status: Current battery status of a given device.\n
                track: Track a given device to monitor battery updates.\n
                untrack: Stop tracking a device for battery updates.
            ",
            ),
            function_pointer: CommandHandler::cmd_battery,
        },
    );
    command_options.insert(
        String::from("bond"),
        CommandOption {
@@ -641,6 +660,79 @@ impl CommandHandler {
        Ok(())
    }

    fn cmd_battery(&mut self, args: &Vec<String>) -> CommandResult {
        if !self.lock_context().adapter_ready {
            return Err(self.adapter_not_ready());
        }

        let command = get_arg(args, 0)?;
        let address = get_arg(args, 1)?.to_uppercase();

        match &command[..] {
            "status" => {
                match self
                    .lock_context()
                    .battery_manager_dbus
                    .as_ref()
                    .unwrap()
                    .get_battery_information(address.clone())
                {
                    None => println!(
                        "Battery status for device {} could not be fetched",
                        address.clone()
                    ),
                    Some(set) => {
                        if set.batteries.len() == 0 {
                            println!("Battery set for device {} is empty", set.address.clone());
                            return Ok(());
                        }

                        println!(
                            "Battery data for '{}' from source '{}' and uuid '{}':",
                            set.address.clone(),
                            set.source_uuid.clone(),
                            set.source_info.clone()
                        );
                        for battery in set.batteries {
                            println!("   {}%, variant: '{}'", battery.percentage, battery.variant);
                        }
                    }
                }
            }
            "track" => {
                if self.lock_context().battery_address_filter.contains(&address) {
                    println!("Already tracking {}", address.clone());
                    return Ok(());
                }
                self.lock_context().battery_address_filter.insert(address.clone());

                println!("Currently tracking:");
                for addr in self.lock_context().battery_address_filter.iter() {
                    println!("{}", addr);
                }
            }
            "untrack" => {
                if !self.lock_context().battery_address_filter.remove(&address) {
                    println!("Not tracking {}", address.clone());
                    return Ok(());
                }
                println!("Stopped tracking {}", address.clone());

                if self.lock_context().battery_address_filter.len() == 0 {
                    println!("No longer tracking any addresses for battery status updates");
                    return Ok(());
                }

                println!("Currently tracking:");
                for addr in self.lock_context().battery_address_filter.iter() {
                    println!("{}", addr);
                }
            }
            _ => return Err(CommandError::InvalidArgs),
        }
        Ok(())
    }

    fn cmd_bond(&mut self, args: &Vec<String>) -> CommandResult {
        if !self.lock_context().adapter_ready {
            return Err(self.adapter_not_ready());
+78 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ use bt_topshim::profiles::sdp::{
use bt_topshim::profiles::socket::SocketType;
use bt_topshim::profiles::ProfileConnectionState;

use btstack::battery_manager::{Battery, BatterySet, IBatteryManager, IBatteryManagerCallback};
use btstack::bluetooth::{
    BluetoothDevice, IBluetooth, IBluetoothCallback, IBluetoothConnectionCallback,
    IBluetoothQALegacy,
@@ -2734,3 +2735,80 @@ impl IBluetoothMediaCallback for IBluetoothMediaCallbackDBus {
    ) {
    }
}

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

pub(crate) struct BatteryManagerDBus {
    client_proxy: ClientDBusProxy,
    pub rpc: BatteryManagerDBusRPC,
}

impl BatteryManagerDBus {
    fn make_client_proxy(conn: Arc<SyncConnection>, index: i32) -> ClientDBusProxy {
        ClientDBusProxy::new(
            conn.clone(),
            String::from("org.chromium.bluetooth"),
            make_object_path(index, "battery_manager"),
            String::from("org.chromium.bluetooth.BatteryManager"),
        )
    }

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

#[generate_dbus_interface_client(BatteryManagerDBusRPC)]
impl IBatteryManager for BatteryManagerDBus {
    #[dbus_method("RegisterBatteryCallback")]
    fn register_battery_callback(
        &mut self,
        battery_manager_callback: Box<dyn IBatteryManagerCallback + Send>,
    ) -> u32 {
        dbus_generated!()
    }

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

    #[dbus_method("GetBatteryInformation")]
    fn get_battery_information(&self, remote_address: String) -> Option<BatterySet> {
        dbus_generated!()
    }
}

#[dbus_propmap(BatterySet)]
pub struct BatterySetDBus {
    address: String,
    source_uuid: String,
    source_info: String,
    batteries: Vec<Battery>,
}

#[dbus_propmap(Battery)]
pub struct BatteryDBus {
    percentage: u32,
    variant: String,
}

struct IBatteryManagerCallbackDBus {}

impl RPCProxy for IBatteryManagerCallbackDBus {}

#[generate_dbus_exporter(
    export_battery_manager_callback_dbus_intf,
    "org.chromium.bluetooth.BatteryManagerCallback"
)]
impl IBatteryManagerCallback for IBatteryManagerCallbackDBus {
    #[dbus_method("OnBatteryInfoUpdated")]
    fn on_battery_info_updated(&mut self, remote_address: String, battery_set: BatterySet) {}
}
+34 −6
Original line number Diff line number Diff line
@@ -14,15 +14,15 @@ use tokio::time::{sleep, timeout};
use crate::bt_adv::AdvSet;
use crate::bt_gatt::GattClientContext;
use crate::callbacks::{
    AdminCallback, AdvertisingSetCallback, BtCallback, BtConnectionCallback, BtManagerCallback,
    BtSocketManagerCallback, MediaCallback, QACallback, ScannerCallback, SuspendCallback,
    TelephonyCallback,
    AdminCallback, AdvertisingSetCallback, BatteryManagerCallback, BtCallback,
    BtConnectionCallback, BtManagerCallback, BtSocketManagerCallback, MediaCallback, QACallback,
    ScannerCallback, SuspendCallback, TelephonyCallback,
};
use crate::command_handler::{CommandHandler, SocketSchedule};
use crate::dbus_iface::{
    BluetoothAdminDBus, BluetoothDBus, BluetoothGattDBus, BluetoothManagerDBus, BluetoothMediaDBus,
    BluetoothQADBus, BluetoothQALegacyDBus, BluetoothSocketManagerDBus, BluetoothTelephonyDBus,
    SuspendDBus,
    BatteryManagerDBus, BluetoothAdminDBus, BluetoothDBus, BluetoothGattDBus, BluetoothManagerDBus,
    BluetoothMediaDBus, BluetoothQADBus, BluetoothQALegacyDBus, BluetoothSocketManagerDBus,
    BluetoothTelephonyDBus, SuspendDBus,
};
use crate::editor::AsyncEditor;
use bt_topshim::topstack;
@@ -102,6 +102,9 @@ pub(crate) struct ClientContext {
    /// Proxy for Media interface.
    pub(crate) media_dbus: Option<BluetoothMediaDBus>,

    /// Proxy for battery manager interface.
    pub(crate) battery_manager_dbus: Option<BatteryManagerDBus>,

    /// Channel to send actions to take in the foreground
    fg: mpsc::Sender<ForegroundActions>,

@@ -146,6 +149,9 @@ pub(crate) struct ClientContext {

    /// The set of client commands that need to wait for callbacks.
    client_commands_with_callbacks: Vec<String>,

    /// A set of addresses whose battery changes are being tracked.
    pub(crate) battery_address_filter: HashSet<String>,
}

impl ClientContext {
@@ -180,6 +186,7 @@ impl ClientContext {
            socket_manager_dbus: None,
            telephony_dbus: None,
            media_dbus: None,
            battery_manager_dbus: None,
            fg: tx,
            dbus_connection,
            dbus_crossroads,
@@ -195,6 +202,7 @@ impl ClientContext {
            socket_test_schedule: None,
            mps_sdp_handle: None,
            client_commands_with_callbacks,
            battery_address_filter: HashSet::new(),
        }
    }

@@ -243,6 +251,8 @@ impl ClientContext {

        self.media_dbus = Some(BluetoothMediaDBus::new(conn.clone(), idx));

        self.battery_manager_dbus = Some(BatteryManagerDBus::new(conn.clone(), idx));

        // Trigger callback registration in the foreground
        let fg = self.fg.clone();
        tokio::spawn(async move {
@@ -548,6 +558,8 @@ async fn handle_client_command(
                    "/org/chromium/bluetooth/client/{}/bluetooth_telephony_callback",
                    adapter
                );
                let battery_cb_objpath: String =
                    format!("/org/chromium/bluetooth/client/{}/battery_manager_callback", adapter);

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

                context
                    .lock()
                    .unwrap()
                    .battery_manager_dbus
                    .as_mut()
                    .unwrap()
                    .rpc
                    .register_battery_callback(Box::new(BatteryManagerCallback::new(
                        battery_cb_objpath,
                        context.clone(),
                        dbus_connection.clone(),
                        dbus_crossroads.clone(),
                    )))
                    .await
                    .expect("D-Bus error on IBatteryManagerDBus::RegisterBatteryCallback");

                context.lock().unwrap().adapter_ready = true;
                let adapter_address = context.lock().unwrap().update_adapter_address();
                context.lock().unwrap().update_bonded_devices();