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

Commit f0a5106d authored by Hsin-Yu Chao's avatar Hsin-Yu Chao
Browse files

topshim: a2dp - Pass selectable capabilities to client

 - Implement missing a2dp disconnected state callback.
 - Pass selectable capabilities to audio server through
  OnBluetoothAudioDeviceAdded callback.
 - Change A2dpCodecIndex enum from i32

Bug: 189497374
Tag: #floss
Test: Manual test with audio server changes
Change-Id: If132c570275def19d37f70d2522d51505f1d4aee
parent 6ba85f1b
Loading
Loading
Loading
Loading
+8 −1
Original line number Original line Diff line number Diff line
@@ -16,7 +16,14 @@ struct BluetoothMediaCallbackDBus {}
#[dbus_proxy_obj(BluetoothMediaCallback, "org.chromium.bluetooth.BluetoothMediaCallback")]
#[dbus_proxy_obj(BluetoothMediaCallback, "org.chromium.bluetooth.BluetoothMediaCallback")]
impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus {
impl IBluetoothMediaCallback for BluetoothMediaCallbackDBus {
    #[dbus_method("OnBluetoothAudioDeviceAdded")]
    #[dbus_method("OnBluetoothAudioDeviceAdded")]
    fn on_bluetooth_audio_device_added(&self, addr: String) {}
    fn on_bluetooth_audio_device_added(
        &self,
        addr: String,
        sample_rate: i32,
        bits_per_sample: i32,
        channel_mode: i32,
    ) {
    }


    #[dbus_method("OnBluetoothAudioDeviceRemoved")]
    #[dbus_method("OnBluetoothAudioDeviceRemoved")]
    fn on_bluetooth_audio_device_removed(&self, addr: String) {}
    fn on_bluetooth_audio_device_removed(&self, addr: String) {}
+55 −16
Original line number Original line Diff line number Diff line
//! Anything related to audio and media API.
//! Anything related to audio and media API.


use bt_topshim::btif::BluetoothInterface;
use bt_topshim::btif::{BluetoothInterface, RawAddress};
use bt_topshim::profiles::a2dp::{
use bt_topshim::profiles::a2dp::{
    A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
    A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
    A2dpCodecSampleRate, BtavConnectionState,
    A2dpCodecConfig, A2dpCodecIndex, A2dpCodecSampleRate, BtavConnectionState,
};
};
use bt_topshim::profiles::avrcp::Avrcp;
use bt_topshim::profiles::avrcp::Avrcp;
use bt_topshim::topstack;
use bt_topshim::topstack;


use std::convert::TryFrom;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::Mutex;


@@ -41,7 +41,13 @@ pub trait IBluetoothMedia {


pub trait IBluetoothMediaCallback {
pub trait IBluetoothMediaCallback {
    ///
    ///
    fn on_bluetooth_audio_device_added(&self, addr: String);
    fn on_bluetooth_audio_device_added(
        &self,
        addr: String,
        sample_rate: i32,
        bits_per_sample: i32,
        channel_mode: i32,
    );


    ///
    ///
    fn on_bluetooth_audio_device_removed(&self, addr: String);
    fn on_bluetooth_audio_device_removed(&self, addr: String);
@@ -55,6 +61,8 @@ pub struct BluetoothMedia {
    tx: Sender<Message>,
    tx: Sender<Message>,
    a2dp: Option<A2dp>,
    a2dp: Option<A2dp>,
    avrcp: Option<Avrcp>,
    avrcp: Option<Avrcp>,
    a2dp_states: HashMap<RawAddress, BtavConnectionState>,
    selectable_caps: HashMap<RawAddress, Vec<A2dpCodecConfig>>,
}
}


impl BluetoothMedia {
impl BluetoothMedia {
@@ -67,24 +75,55 @@ impl BluetoothMedia {
            tx,
            tx,
            a2dp: None,
            a2dp: None,
            avrcp: None,
            avrcp: None,
            a2dp_states: HashMap::new(),
            selectable_caps: HashMap::new(),
        }
        }
    }
    }


    pub fn dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks) {
    pub fn dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks) {
        match cb {
        match cb {
            A2dpCallbacks::ConnectionState(addr, state) => match BtavConnectionState::from(state) {
            A2dpCallbacks::ConnectionState(addr, state) => {
                if !self.a2dp_states.get(&addr).is_none()
                    && state == *self.a2dp_states.get(&addr).unwrap()
                {
                    return;
                }
                match state {
                    BtavConnectionState::Connected => {
                    BtavConnectionState::Connected => {
                        if let Some(caps) = self.selectable_caps.get(&addr) {
                            for cap in caps {
                                // TODO: support codecs other than SBC.
                                if A2dpCodecIndex::SrcSbc != A2dpCodecIndex::from(cap.codec_type) {
                                    continue;
                                }

                                self.for_all_callbacks(|callback| {
                                self.for_all_callbacks(|callback| {
                        callback.on_bluetooth_audio_device_added(addr.to_string());
                                    callback.on_bluetooth_audio_device_added(
                                        addr.to_string(),
                                        cap.sample_rate,
                                        cap.bits_per_sample,
                                        cap.channel_mode,
                                    );
                                });
                                });
                                return;
                            }
                        }
                    }
                    }
                    BtavConnectionState::Connecting => {}
                    BtavConnectionState::Connecting => {}
                BtavConnectionState::Disconnected => {}
                    BtavConnectionState::Disconnected => {
                        self.for_all_callbacks(|callback| {
                            callback.on_bluetooth_audio_device_removed(addr.to_string());
                        });
                    }
                    BtavConnectionState::Disconnecting => {}
                    BtavConnectionState::Disconnecting => {}
            },
                };
            A2dpCallbacks::AudioState(addr, state) => {}
                self.a2dp_states.insert(addr, state);
            A2dpCallbacks::AudioConfig(addr, config, local_caps, selectable_caps) => {}
            }
            A2dpCallbacks::MandatoryCodecPreferred(addr) => {}
            A2dpCallbacks::AudioState(_addr, _state) => {}
            A2dpCallbacks::AudioConfig(addr, _config, _local_caps, selectable_caps) => {
                self.selectable_caps.insert(addr, selectable_caps);
            }
            A2dpCallbacks::MandatoryCodecPreferred(_addr) => {}
        }
        }
    }
    }


+1 −1
Original line number Original line Diff line number Diff line
@@ -268,7 +268,7 @@ type FfiAddress = bindings::RawAddress;
/// A shared address structure that has the same representation as
/// A shared address structure that has the same representation as
/// bindings::RawAddress. Macros `deref_ffi_address` and `cast_to_ffi_address`
/// bindings::RawAddress. Macros `deref_ffi_address` and `cast_to_ffi_address`
/// are used for transforming between bindings::RawAddress at ffi boundaries.
/// are used for transforming between bindings::RawAddress at ffi boundaries.
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
#[repr(C)]
#[repr(C)]
pub struct RawAddress {
pub struct RawAddress {
    pub val: [u8; 6],
    pub val: [u8; 6],
+3 −3
Original line number Original line Diff line number Diff line
@@ -57,9 +57,9 @@ impl A2dpCodecIndex {
    pub const MIN: A2dpCodecIndex = A2dpCodecIndex::SrcSbc;
    pub const MIN: A2dpCodecIndex = A2dpCodecIndex::SrcSbc;
}
}


impl From<u32> for A2dpCodecIndex {
impl From<i32> for A2dpCodecIndex {
    fn from(item: u32) -> Self {
    fn from(item: i32) -> Self {
        A2dpCodecIndex::from_u32(item).unwrap_or_else(|| A2dpCodecIndex::MIN)
        A2dpCodecIndex::from_i32(item).unwrap_or_else(|| A2dpCodecIndex::MIN)
    }
    }
}
}