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

Commit aac711c2 authored by Jack He's avatar Jack He
Browse files

A2DP Offload: Log audio duration and codec metrics

* Add A2dpOffloadAudioStats class to store metrics for A2DP offload
* Add logging statements to log A2DP start/suspend/stop events when A2DP
  offload is enabled
* Separate software encoding logging from hardware encoding logging

Bug: 109953464
Test: make, run A2DP in offload mode and dump metrics
Change-Id: I1a19c64c6b1ee530e5927dd3d13e31b00729850b
parent 16d5d8bd
Loading
Loading
Loading
Loading
+99 −5
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@
#define LOG_TAG "btif_a2dp_audio_interface"

#include "btif_a2dp_audio_interface.h"

#include <mutex>

#include <a2dp_vendor.h>
#include <a2dp_vendor_ldac_constants.h>
#include <android/hardware/bluetooth/a2dp/1.0/IBluetoothAudioHost.h>
@@ -37,8 +40,12 @@
#include "btif_av.h"
#include "btif_av_co.h"
#include "btif_hf.h"
#include "osi/include/metrics.h"
#include "osi/include/osi.h"

using system_bt_osi::A2dpSessionMetrics;
using system_bt_osi::BluetoothMetricsLogger;

using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
using android::hardware::bluetooth::a2dp::V1_0::Status;
@@ -63,11 +70,66 @@ uint8_t btif_a2dp_audio_process_request(uint8_t cmd);

static void btif_a2dp_audio_send_start_req();
static void btif_a2dp_audio_send_suspend_req();
static void btif_a2dp_audio_send_stop_req();
static void btif_a2dp_audio_interface_init();
static void btif_a2dp_audio_interface_deinit();
// Delay reporting
// static void btif_a2dp_audio_send_sink_latency();

class A2dpOffloadAudioStats {
 public:
  A2dpOffloadAudioStats() { Reset(); }
  void Reset() {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    ResetPreserveSession();
    codec_index_ = -1;
  }
  void ResetPreserveSession() {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    audio_start_time_ms_ = -1;
    audio_stop_time_ms_ = -1;
  }
  void StoreMetrics() {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    if (audio_start_time_ms_ < 0 || audio_stop_time_ms_ < 0) {
      return;
    }
    A2dpSessionMetrics metrics;
    metrics.codec_index = codec_index_;
    metrics.is_a2dp_offload = true;
    if (audio_stop_time_ms_ > audio_start_time_ms_) {
      metrics.audio_duration_ms = audio_stop_time_ms_ - audio_start_time_ms_;
    }
    BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics);
  }
  void LogAudioStart() {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    audio_start_time_ms_ = time_get_os_boottime_ms();
  }
  void LogAudioStop() {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    audio_stop_time_ms_ = time_get_os_boottime_ms();
  }
  void LogAudioStopMetricsAndReset() {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    LogAudioStop();
    StoreMetrics();
    ResetPreserveSession();
  }
  void SetCodecIndex(int64_t codec_index) {
    std::lock_guard<std::recursive_mutex> lock(lock_);
    codec_index_ = codec_index;
  }

 private:
  std::recursive_mutex lock_;
  int64_t audio_start_time_ms_ = -1;
  int64_t audio_stop_time_ms_ = -1;
  int64_t codec_index_ = -1;
};

static A2dpOffloadAudioStats a2dp_offload_audio_stats;

class BluetoothAudioHost : public IBluetoothAudioHost {
 public:
  Return<void> startStream() {
@@ -79,7 +141,7 @@ class BluetoothAudioHost : public IBluetoothAudioHost {
    return Void();
  }
  Return<void> stopStream() {
    btif_a2dp_audio_process_request(A2DP_CTRL_CMD_STOP);
    btif_a2dp_audio_send_stop_req();
    return Void();
  }

@@ -118,6 +180,7 @@ static void btif_a2dp_get_codec_configuration(
  a2dpCodecConfig->getCodecSpecificConfig(&a2dp_offload);
  btav_a2dp_codec_config_t codec_config;
  codec_config = a2dpCodecConfig->getCodecConfig();
  a2dp_offload_audio_stats.SetCodecIndex(a2dpCodecConfig->codecIndex());
  switch (codec_config.codec_type) {
    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
      p_codec_info->codecType =
@@ -204,6 +267,9 @@ static void btif_a2dp_audio_interface_deinit() {

void btif_a2dp_audio_interface_start_session() {
  LOG_INFO(LOG_TAG, "%s", __func__);
  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
  a2dp_offload_audio_stats.Reset();
  btif_a2dp_audio_interface_init();
  CHECK(btAudio != nullptr);
  CodecConfiguration codec_info;
@@ -214,6 +280,10 @@ void btif_a2dp_audio_interface_start_session() {

void btif_a2dp_audio_interface_end_session() {
  LOG_INFO(LOG_TAG, "%s", __func__);
  a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
  BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
  a2dp_offload_audio_stats.Reset();
  if (btAudio == nullptr) return;
  auto ret = btAudio->endSession();
  if (!ret.isOk()) {
@@ -227,7 +297,11 @@ void btif_a2dp_audio_on_started(tBTA_AV_STATUS status) {
  if (btAudio != nullptr) {
    if (a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
      LOG_INFO(LOG_TAG, "%s: calling method onStarted", __func__);
      btAudio->streamStarted(mapToStatus(status));
      auto hal_status = mapToStatus(status);
      btAudio->streamStarted(hal_status);
      if (hal_status == Status::SUCCESS) {
        a2dp_offload_audio_stats.LogAudioStart();
      }
    }
  }
}
@@ -237,7 +311,11 @@ void btif_a2dp_audio_on_suspended(tBTA_AV_STATUS status) {
  if (btAudio != nullptr) {
    if (a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND) {
      LOG_INFO(LOG_TAG, "calling method onSuspended");
      btAudio->streamSuspended(mapToStatus(status));
      auto hal_status = mapToStatus(status);
      btAudio->streamSuspended(hal_status);
      if (hal_status == Status::SUCCESS) {
        a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
      }
    }
  }
}
@@ -248,6 +326,7 @@ void btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status) {
    LOG_INFO(LOG_TAG, "%s: Remote disconnected when start under progress",
             __func__);
    btAudio->streamStarted(mapToStatus(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS));
    a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
  }
}
void btif_a2dp_audio_send_start_req() {
@@ -255,7 +334,11 @@ void btif_a2dp_audio_send_start_req() {
  uint8_t resp;
  resp = btif_a2dp_audio_process_request(A2DP_CTRL_CMD_START);
  if (btAudio != nullptr) {
    auto ret = btAudio->streamStarted(mapToStatus(resp));
    auto status = mapToStatus(resp);
    auto ret = btAudio->streamStarted(status);
    if (status == Status::SUCCESS) {
      a2dp_offload_audio_stats.LogAudioStart();
    }
    if (!ret.isOk()) LOG_ERROR(LOG_TAG, "HAL server died");
  }
}
@@ -264,10 +347,21 @@ void btif_a2dp_audio_send_suspend_req() {
  uint8_t resp;
  resp = btif_a2dp_audio_process_request(A2DP_CTRL_CMD_SUSPEND);
  if (btAudio != nullptr) {
    auto ret = btAudio->streamSuspended(mapToStatus(resp));
    auto status = mapToStatus(resp);
    auto ret = btAudio->streamSuspended(status);
    if (status == Status::SUCCESS) {
      a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
    }
    if (!ret.isOk()) LOG_ERROR(LOG_TAG, "HAL server died");
  }
}

void btif_a2dp_audio_send_stop_req() {
  LOG_INFO(LOG_TAG, "%s", __func__);
  btif_a2dp_audio_process_request(A2DP_CTRL_CMD_STOP);
  a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
}

/*void btif_a2dp_audio_send_sink_latency()
{
  LOG_INFO(LOG_TAG, "%s", __func__);
+7 −4
Original line number Diff line number Diff line
@@ -453,10 +453,11 @@ static void btif_a2dp_source_start_session_delayed(
  }
  if (btif_av_is_a2dp_offload_enabled()) {
    btif_a2dp_audio_interface_start_session();
  }
  } else {
    BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
        system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
  }
}

bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
                                      const RawAddress& new_peer_address) {
@@ -503,8 +504,10 @@ static void btif_a2dp_source_end_session_delayed(
    const RawAddress& peer_address) {
  LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
           peer_address.ToString().c_str());
  if (!btif_av_is_a2dp_offload_enabled()) {
    BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
        system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
  }
  if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateRunning) {
    LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
    return;