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

Commit 1ed5f88b authored by Michael Sun's avatar Michael Sun
Browse files

floss: metrics: A2DP Sink profile connection state handling

Route the A2DP Sink profile connection events route to the metrics
processing unit. Then, parse the event into structured metrics
compatible format.

BUG: 240781725
Tag: #floss
Test: emerge-${BOARD} floss
BYPASS_LONG_LINES_REASON: Bluetooth likes 120 lines

Change-Id: I685d9c2962b62aa9cb1a70cd12900f93a81b4424
parent 0192f70c
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include "hci/hci_packets.h"
#include "include/hardware/bluetooth.h"
#include "include/hardware/bt_av.h"
#include "include/hardware/bt_hh.h"

namespace bluetooth {
@@ -29,7 +30,9 @@ namespace metrics {
typedef bt_bond_state_t BtBondState;
// topshim::btif::BtStatus is a copy of hardware/bluetooth.h:bt_status_t
typedef bt_status_t BtStatus;
// topshim::profile::hid_host::BthhConnectionState is a copy of hardware/bluetooth.h:bthh_connection_state_t
// topshim::profile::a2dp::BtavConnectionState is a copy of hardware/bt_av.h:btav_connection_state_t
typedef btav_connection_state_t BtavConnectionState;
// topshim::profile::hid_host::BthhConnectionState is a copy of hardware/bt_hh.h:bthh_connection_state_t
typedef bthh_connection_state_t BthhConnectionState;

// A normalized connection state ENUM definition all profiles
@@ -298,7 +301,26 @@ static std::pair<uint32_t, uint32_t> ToProfileConnectionState(uint32_t profile,
  std::pair<uint32_t, uint32_t> output;

  switch ((ProfilesFloss)profile) {
    // case ProfilesFloss::A2dpSink:
    case ProfilesFloss::A2dpSink:
      output.first = (uint32_t)Profile::A2DP;
      switch ((BtavConnectionState)state) {
        case BtavConnectionState::BTAV_CONNECTION_STATE_CONNECTED:
          output.second = (uint32_t)ProfilesConnectionState::CONNECTED;
          break;
        case BtavConnectionState::BTAV_CONNECTION_STATE_CONNECTING:
          output.second = (uint32_t)ProfilesConnectionState::CONNECTING;
          break;
        case BtavConnectionState::BTAV_CONNECTION_STATE_DISCONNECTED:
          output.second = (uint32_t)ProfilesConnectionState::DISCONNECTED;
          break;
        case BtavConnectionState::BTAV_CONNECTION_STATE_DISCONNECTING:
          output.second = (uint32_t)ProfilesConnectionState::DISCONNECTING;
          break;
        default:
          output.second = (uint32_t)ProfilesConnectionState::UNKNOWN;
          break;
      }
      break;
    // case ProfilesFloss::A2dpSource:
    // case ProfilesFloss::AdvAudioDist:
    // case ProfilesFloss::Hsp:
+64 −9
Original line number Diff line number Diff line
//! Anything related to audio and media API.

use bt_topshim::btif::{BluetoothInterface, RawAddress};
use bt_topshim::btif::{BluetoothInterface, BtStatus, RawAddress};
use bt_topshim::profiles::a2dp::{
    A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
    A2dpCodecConfig, A2dpCodecSampleRate, BtavAudioState, BtavConnectionState,
@@ -11,7 +11,7 @@ use bt_topshim::profiles::hfp::{
    BthfAudioState, BthfConnectionState, Hfp, HfpCallbacks, HfpCallbacksDispatcher,
    HfpCodecCapability,
};
use bt_topshim::topstack;
use bt_topshim::{metrics, topstack};
use bt_utils::uinput::UInput;

use log::{info, warn};
@@ -28,6 +28,7 @@ use tokio::time::{sleep, Duration, Instant};
use crate::bluetooth::{Bluetooth, BluetoothDevice, IBluetooth};
use crate::callbacks::Callbacks;
use crate::uuid;
use crate::uuid::Profile;
use crate::{Message, RPCProxy};

// The timeout we have to wait for all supported profiles to connect after we
@@ -198,12 +199,18 @@ impl BluetoothMedia {

    pub fn dispatch_a2dp_callbacks(&mut self, cb: A2dpCallbacks) {
        match cb {
            A2dpCallbacks::ConnectionState(addr, state, _error) => {
            A2dpCallbacks::ConnectionState(addr, state, error) => {
                if !self.a2dp_states.get(&addr).is_none()
                    && state == *self.a2dp_states.get(&addr).unwrap()
                {
                    return;
                }
                metrics::profile_connection_state_changed(
                    addr,
                    Profile::A2dpSink as u32,
                    error.status,
                    state.clone() as u32,
                );
                match state {
                    BtavConnectionState::Connected => {
                        info!("[{}]: a2dp connected.", addr.to_string());
@@ -725,9 +732,33 @@ impl IBluetoothMedia for BluetoothMedia {
        for profile in missing_profiles {
            match profile {
                uuid::Profile::A2dpSink => {
                    metrics::profile_connection_state_changed(
                        addr,
                        Profile::A2dpSink as u32,
                        BtStatus::Success,
                        BtavConnectionState::Connecting as u32,
                    );
                    match self.a2dp.as_mut() {
                        Some(a2dp) => a2dp.connect(addr),
                        None => warn!("Uninitialized A2DP to connect {}", address),
                        Some(a2dp) => {
                            let status: BtStatus = a2dp.connect(addr);
                            if BtStatus::Success != status {
                                metrics::profile_connection_state_changed(
                                    addr,
                                    Profile::A2dpSink as u32,
                                    status,
                                    BtavConnectionState::Disconnected as u32,
                                );
                            }
                        }
                        None => {
                            warn!("Uninitialized A2DP to connect {}", address);
                            metrics::profile_connection_state_changed(
                                addr,
                                Profile::A2dpSink as u32,
                                BtStatus::NotReady,
                                BtavConnectionState::Disconnected as u32,
                            );
                        }
                    };
                }
                uuid::Profile::Hfp => {
@@ -742,7 +773,7 @@ impl IBluetoothMedia for BluetoothMedia {
                        None => warn!("Uninitialized AVRCP to connect {}", address),
                    };
                }
                _ => warn!("Unknown profile."),
                _ => warn!("Unknown profile: {:?}", profile),
            }
        }
    }
@@ -774,9 +805,33 @@ impl IBluetoothMedia for BluetoothMedia {
        for profile in connected_profiles {
            match profile {
                uuid::Profile::A2dpSink => {
                    metrics::profile_connection_state_changed(
                        addr,
                        Profile::A2dpSink as u32,
                        BtStatus::Success,
                        BtavConnectionState::Disconnecting as u32,
                    );
                    match self.a2dp.as_mut() {
                        Some(a2dp) => a2dp.disconnect(addr),
                        None => warn!("Uninitialized A2DP to disconnect {}", address),
                        Some(a2dp) => {
                            let status: BtStatus = a2dp.disconnect(addr);
                            if BtStatus::Success != status {
                                metrics::profile_connection_state_changed(
                                    addr,
                                    Profile::A2dpSource as u32,
                                    status,
                                    BtavConnectionState::Disconnected as u32,
                                );
                            }
                        }
                        None => {
                            warn!("Uninitialized A2DP to disconnect {}", address);
                            metrics::profile_connection_state_changed(
                                addr,
                                Profile::A2dpSource as u32,
                                BtStatus::NotReady,
                                BtavConnectionState::Disconnected as u32,
                            );
                        }
                    };
                }
                uuid::Profile::Hfp => {
@@ -791,7 +846,7 @@ impl IBluetoothMedia for BluetoothMedia {
                        None => warn!("Uninitialized AVRCP to disconnect {}", address),
                    };
                }
                _ => warn!("Unknown profile."),
                _ => warn!("Unknown profile: {:?}", profile),
            }
        }
    }
+2 −2
Original line number Diff line number Diff line
@@ -217,11 +217,11 @@ int A2dpIntf::init() const {
  return intf_->init(&internal::g_callbacks, 1, a, b);
}

int A2dpIntf::connect(RustRawAddress bt_addr) const {
uint32_t A2dpIntf::connect(RustRawAddress bt_addr) const {
  RawAddress addr = rusty::CopyFromRustAddress(bt_addr);
  return intf_->connect(addr);
}
int A2dpIntf::disconnect(RustRawAddress bt_addr) const {
uint32_t A2dpIntf::disconnect(RustRawAddress bt_addr) const {
  RawAddress addr = rusty::CopyFromRustAddress(bt_addr);
  return intf_->disconnect(addr);
}
+2 −2
Original line number Diff line number Diff line
@@ -39,8 +39,8 @@ class A2dpIntf {

  // interface for Settings
  int init() const;
  int connect(RustRawAddress bt_addr) const;
  int disconnect(RustRawAddress bt_addr) const;
  uint32_t connect(RustRawAddress bt_addr) const;
  uint32_t disconnect(RustRawAddress bt_addr) const;
  int set_silence_device(RustRawAddress bt_addr, bool silent) const;
  int set_active_device(RustRawAddress bt_addr) const;
  int config_codec(RustRawAddress bt_addr, ::rust::Vec<A2dpCodecConfig> codec_preferences) const;
+7 −7
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ use num_traits::cast::FromPrimitive;
use std::sync::{Arc, Mutex};
use topshim_macros::cb_variant;

#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)]
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd, Clone)]
#[repr(u32)]
pub enum BtavConnectionState {
    Disconnected = 0,
@@ -183,8 +183,8 @@ pub mod ffi {
        unsafe fn GetA2dpProfile(btif: *const u8) -> UniquePtr<A2dpIntf>;

        fn init(self: &A2dpIntf) -> i32;
        fn connect(self: &A2dpIntf, bt_addr: RustRawAddress) -> i32;
        fn disconnect(self: &A2dpIntf, bt_addr: RustRawAddress) -> i32;
        fn connect(self: &A2dpIntf, bt_addr: RustRawAddress) -> u32;
        fn disconnect(self: &A2dpIntf, bt_addr: RustRawAddress) -> u32;
        fn set_silence_device(self: &A2dpIntf, bt_addr: RustRawAddress, silent: bool) -> i32;
        fn set_active_device(self: &A2dpIntf, bt_addr: RustRawAddress) -> i32;
        fn config_codec(
@@ -323,16 +323,16 @@ impl A2dp {
        true
    }

    pub fn connect(&mut self, addr: RawAddress) {
        self.internal.connect(addr.into());
    pub fn connect(&mut self, addr: RawAddress) -> BtStatus {
        BtStatus::from(self.internal.connect(addr.into()))
    }

    pub fn set_active_device(&mut self, addr: RawAddress) {
        self.internal.set_active_device(addr.into());
    }

    pub fn disconnect(&mut self, addr: RawAddress) {
        self.internal.disconnect(addr.into());
    pub fn disconnect(&mut self, addr: RawAddress) -> BtStatus {
        BtStatus::from(self.internal.disconnect(addr.into()))
    }

    pub fn set_audio_config(&self, sample_rate: i32, bits_per_sample: i32, channel_mode: i32) {