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

Commit 5aeb0544 authored by En-Shuo Hsu's avatar En-Shuo Hsu Committed by En-Shuo Hsu
Browse files

floss: Implement AVRCP volume interface

 - Fill in VolumeInterfaceImpl implementation.
 - Add AVRCP callback disptach

BUG: 194854406
Tag: #floss
Test: Manual test with audio server changes &&
dbus-send --system  --type=method_call \
--print-reply --dest=org.chromium.bluetooth \
/org/chromium/bluetooth/hci0/media \
org.chromium.bluetooth.BluetoothMedia.SetVolume  int32:100
to verify the headset volume is changed

Change-Id: I753095effd4d2235c6d47e8453b90455a4eb467e
parent 6c493ac9
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -29,6 +29,12 @@ impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus {

    #[dbus_method("OnBluetoothAudioDeviceRemoved")]
    fn on_bluetooth_audio_device_removed(&self, addr: String) {}

    #[dbus_method("OnAbsoluteVolumeSupportedChanged")]
    fn on_absolute_volume_supported_changed(&self, supported: bool) {}

    #[dbus_method("OnAbsoluteVolumeChanged")]
    fn on_absolute_volume_changed(&self, volume: i32) {}
}

#[allow(dead_code)]
+35 −2
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ use bt_topshim::profiles::a2dp::{
    A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, BtavConnectionState,
    PresentationPosition,
};
use bt_topshim::profiles::avrcp::Avrcp;
use bt_topshim::profiles::avrcp::{Avrcp, AvrcpCallbacks, AvrcpCallbacksDispatcher};
use bt_topshim::topstack;

use std::collections::HashMap;
@@ -55,6 +55,12 @@ pub trait IBluetoothMediaCallback {

    ///
    fn on_bluetooth_audio_device_removed(&self, addr: String);

    ///
    fn on_absolute_volume_supported_changed(&self, supported: bool);

    ///
    fn on_absolute_volume_changed(&self, volume: i32);
}

pub struct BluetoothMedia {
@@ -131,6 +137,21 @@ impl BluetoothMedia {
        }
    }

    pub fn dispatch_avrcp_callbacks(&mut self, cb: AvrcpCallbacks) {
        match cb {
            AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled(supported) => {
                self.for_all_callbacks(|callback| {
                    callback.on_absolute_volume_supported_changed(supported);
                });
            }
            AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate(volume) => {
                self.for_all_callbacks(|callback| {
                    callback.on_absolute_volume_changed(i32::from(volume));
                });
            }
        }
    }

    fn for_all_callbacks<F: Fn(&Box<dyn IBluetoothMediaCallback + Send>)>(&self, f: F) {
        for callback in &self.callbacks {
            f(&callback.1);
@@ -149,6 +170,17 @@ fn get_a2dp_dispatcher(tx: Sender<Message>) -> A2dpCallbacksDispatcher {
    }
}

fn get_avrcp_dispatcher(tx: Sender<Message>) -> AvrcpCallbacksDispatcher {
    AvrcpCallbacksDispatcher {
        dispatch: Box::new(move |cb| {
            let txl = tx.clone();
            topstack::get_runtime().spawn(async move {
                let _ = txl.send(Message::Avrcp(cb)).await;
            });
        }),
    }
}

impl IBluetoothMedia for BluetoothMedia {
    fn register_callback(&mut self, callback: Box<dyn IBluetoothMediaCallback + Send>) -> bool {
        self.callback_last_id += 1;
@@ -165,8 +197,9 @@ impl IBluetoothMedia for BluetoothMedia {
        self.a2dp.as_mut().unwrap().initialize(a2dp_dispatcher);

        // AVRCP
        let avrcp_dispatcher = get_avrcp_dispatcher(self.tx.clone());
        self.avrcp = Some(Avrcp::new(&self.intf.lock().unwrap()));
        self.avrcp.as_mut().unwrap().initialize();
        self.avrcp.as_mut().unwrap().initialize(avrcp_dispatcher);
        true
    }

+6 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ pub mod bluetooth_media;

use bt_topshim::btif::BaseCallbacks;
use bt_topshim::profiles::a2dp::A2dpCallbacks;
use bt_topshim::profiles::avrcp::AvrcpCallbacks;
use bt_topshim::profiles::gatt::GattClientCallbacks;
use bt_topshim::profiles::gatt::GattServerCallbacks;

@@ -30,6 +31,7 @@ use crate::bluetooth_media::BluetoothMedia;
/// Message types that are sent to the stack main dispatch loop.
pub enum Message {
    A2dp(A2dpCallbacks),
    Avrcp(AvrcpCallbacks),
    Base(BaseCallbacks),
    GattClient(GattClientCallbacks),
    GattServer(GattServerCallbacks),
@@ -65,6 +67,10 @@ impl Stack {
                    bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a);
                }

                Message::Avrcp(av) => {
                    bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av);
                }

                Message::Base(b) => {
                    bluetooth.lock().unwrap().dispatch_base_callbacks(b);
                }
+29 −7
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@
#include "base/callback.h"
#include "rust/cxx.h"
#include "src/profiles/a2dp.rs.h"
#include "src/profiles/avrcp.rs.h"

namespace rusty = ::bluetooth::topshim::rust;

namespace bluetooth::avrcp {
class AvrcpMediaInterfaceImpl : public MediaInterface {
@@ -60,13 +63,34 @@ class AvrcpMediaInterfaceImpl : public MediaInterface {

class VolumeInterfaceImpl : public VolumeInterface {
 public:
  void DeviceConnected([[maybe_unused]] const RawAddress& bdaddr) override {}
  void DeviceConnected([[maybe_unused]] const RawAddress& bdaddr) override {
    rusty::avrcp_absolute_volume_enabled(false);
  }

  void DeviceConnected([[maybe_unused]] const RawAddress& bdaddr, VolumeChangedCb cb) override {
    volumeCb = std::move(cb);
    rusty::avrcp_absolute_volume_enabled(true);
  }

  void DeviceDisconnected([[maybe_unused]] const RawAddress& bdaddr) override {
    volumeCb.Reset();
    rusty::avrcp_absolute_volume_enabled(false);
  }

  // Set TG's (Android, ChromeOS) volume.
  void SetVolume(int8_t volume) override {
    rusty::avrcp_absolute_volume_update(volume);
  }

  void DeviceConnected([[maybe_unused]] const RawAddress& bdaddr, [[maybe_unused]] VolumeChangedCb cb) override {}
  // Set CT's (headsets, speakers) volume.
  void SetDeviceVolume(int8_t volume) {
    if (!volumeCb || volume < 0) return;

  void DeviceDisconnected([[maybe_unused]] const RawAddress& bdaddr) override {}
    volumeCb.Run(volume);
  }

  void SetVolume([[maybe_unused]] int8_t volume) override {}
 private:
  VolumeInterface::VolumeChangedCb volumeCb;
};

}  // namespace bluetooth::avrcp
@@ -78,8 +102,6 @@ namespace internal {
static A2dpIntf* g_a2dpif;
static AvrcpIntf* g_avrcpif;

namespace rusty = ::bluetooth::topshim::rust;

static RustRawAddress to_rust_address(const RawAddress& address) {
  RustRawAddress raddr;
  std::copy(std::begin(address.address), std::end(address.address), std::begin(raddr.address));
@@ -272,7 +294,7 @@ int AvrcpIntf::disconnect(RustRawAddress bt_addr) {
}

void AvrcpIntf::set_volume(int8_t volume) {
  return mVolumeInterface.SetVolume(volume);
  return mVolumeInterface.SetDeviceVolume(volume);
}
}  // namespace rust
}  // namespace topshim
+6 −2
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

use bt_topshim::btif::BluetoothInterface;
use bt_topshim::profiles::a2dp::{A2dp, A2dpCallbacksDispatcher, A2dpSink};
use bt_topshim::profiles::avrcp::Avrcp;
use bt_topshim::profiles::avrcp::{Avrcp, AvrcpCallbacksDispatcher};
use bt_topshim_facade_protobuf::facade::{
    A2dpSourceConnectRequest, A2dpSourceConnectResponse, StartA2dpRequest, StartA2dpResponse,
};
@@ -17,6 +17,10 @@ fn get_a2dp_dispatcher() -> A2dpCallbacksDispatcher {
    A2dpCallbacksDispatcher { dispatch: Box::new(move |_cb| {}) }
}

fn get_avrcp_dispatcher() -> AvrcpCallbacksDispatcher {
    AvrcpCallbacksDispatcher { dispatch: Box::new(move |_cb| {}) }
}

/// Main object for Media facade service
#[derive(Clone)]
pub struct MediaServiceImpl {
@@ -33,7 +37,7 @@ impl MediaServiceImpl {
        let btif_a2dp_sink = A2dpSink::new(&btif_intf.lock().unwrap());
        let mut btif_avrcp = Avrcp::new(&btif_intf.lock().unwrap());
        btif_a2dp.initialize(get_a2dp_dispatcher());
        btif_avrcp.initialize();
        btif_avrcp.initialize(get_avrcp_dispatcher());

        create_media_service(Self {
            rt,
Loading