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

Commit 24282e63 authored by Jack He's avatar Jack He
Browse files

Metrics: Add metrics item for profile usage

Item A: Add messages to log profile connections
* Add ProfileUsageStats message in bluetooth.proto
* Add BluetoothProfileId enum to represent each profile
* Add num_times_connected item to log how many times a profile is
  connected

Item B: Add messages to log headset profile connections for HSP and HFP
* Add HeadsetProfileConnectionStats message in bluetooth.proto
* Add HeadsetProfileType enum to represent each headset profile type
* Add num_times_connected item to log how many times each headset
  profile is connected

* Add unit tests in metrics_tests
* Remove "clear" flag in various metrics dumping methods to make sure
  that we clean up metrics every time we dump

Bug: 77476285
Test: make, net_test_osi, BtFunhausMetricsTest,
      adb shell dumpsys bluetooth_manager --proto-bin
Change-Id: Ib18948c50ddb98ab7472f7b51a9bb98d153071c7
Merged-In: Ib18948c50ddb98ab7472f7b51a9bb98d153071c7
(cherry picked from commit 3277682289843134738a51708b5b4928479c36f6)
parent 007add9c
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -51,6 +51,12 @@ message BluetoothLog {

  // Number of ScanEvent including discarded ones beyond capacity
  optional int64 num_scan_event = 9;

  // Statistics about Bluetooth profile connections
  repeated ProfileConnectionStats profile_connection_stats = 10;

  // Statistics about Headset profile connections
  repeated HeadsetProfileConnectionStats headset_profile_connection_stats = 11;
}

// The information about the device.
@@ -229,3 +235,52 @@ message ScanEvent {
  optional int64 event_time_millis =
      5;  // [(datapol.semantic_type) = ST_TIMESTAMP];
}

// Profile IDs defined in BluetoothProfile API class
// Values must match API class values
enum ProfileId {
  PROFILE_UNKNOWN = 0;
  HEADSET = 1;
  A2DP = 2;
  HEALTH = 3;
  HID_HOST = 4;
  PAN = 5;
  PBAP = 6;
  GATT = 7;
  GATT_SERVER = 8;
  MAP = 9;
  SAP = 10;
  A2DP_SINK = 11;
  AVRCP_CONTROLLER = 12;
  AVRCP = 13;
  HEADSET_CLIENT = 16;
  PBAP_CLIENT = 17;
  MAP_CLIENT = 18;
  HID_DEVICE = 19;
  OPP = 20;
  HEARING_AID = 21;
}

// Statistics about Bluetooth profile connections
message ProfileConnectionStats {
  // Profile id defined in BluetoothProfile.java
  optional ProfileId profile_id = 1;

  // Number of times that this profile is connected since last metrics dump
  optional int32 num_times_connected = 2;
}

enum HeadsetProfileType {
  HEADSET_PROFILE_UNKNOWN = 0;
  HSP = 1;
  HFP = 2;
}

// Statistics about headset profile connections
message HeadsetProfileConnectionStats {
  // Type of headset profile connected
  optional HeadsetProfileType headset_profile_type = 1;

  // Number of times this type of headset profile is connected
  optional int32 num_times_connected = 2;
}
 No newline at end of file
+1 −2
Original line number Diff line number Diff line
@@ -328,8 +328,7 @@ static void dump(int fd, const char** arguments) {
}

static void dumpMetrics(std::string* output) {
  system_bt_osi::BluetoothMetricsLogger::GetInstance()->WriteString(output,
                                                                    true);
  system_bt_osi::BluetoothMetricsLogger::GetInstance()->WriteString(output);
}

static const void* get_profile_interface(const char* profile_id) {
+3 −2
Original line number Diff line number Diff line
@@ -31,19 +31,18 @@
#include <cstring>
#include <ctime>

#include <bta/include/bta_ag_api.h>
#include <hardware/bluetooth.h>
#include <hardware/bluetooth_headset_callbacks.h>
#include <hardware/bluetooth_headset_interface.h>
#include <hardware/bt_hf.h>

#include "bta/include/bta_ag_api.h"
#include "bta/include/utl.h"
#include "bta_ag_api.h"
#include "btif_common.h"
#include "btif_hf.h"
#include "btif_profile_queue.h"
#include "btif_util.h"
#include "osi/include/metrics.h"

namespace bluetooth {
namespace headset {
@@ -320,6 +319,8 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
        btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
        btif_hf_cb[idx].peer_feat = 0;
        clear_phone_state_multihf(idx);
        system_bt_osi::BluetoothMetricsLogger::GetInstance()
            ->LogHeadsetProfileRfcConnection(p_data->open.service_id);
      } else if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_CONNECTING) {
        LOG(ERROR) << __func__ << ": AG open failed for "
                   << btif_hf_cb[idx].connected_bda << ", status "
+13 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#pragma once

#include <bta/include/bta_api.h>
#include <stdint.h>
#include <memory>
#include <string>
@@ -209,13 +210,20 @@ class BluetoothMetricsLogger {
   */
  void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);

  /**
   * Log Headset profile RFCOMM connection event
   *
   * @param service_id the BTA service ID for this headset connection
   */
  void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);

  /*
   * Writes the metrics, in base64 protobuf format, into the descriptor FD
   * If CLEAR is true, metrics events are cleared afterwards.
   * Writes the metrics, in base64 protobuf format, into the descriptor FD,
   * metrics events are always cleared after dump
   */
  void WriteBase64(int fd, bool clear);
  void WriteBase64String(std::string* serialized, bool clear);
  void WriteString(std::string* serialized, bool clear);
  void WriteBase64(int fd);
  void WriteBase64String(std::string* serialized);
  void WriteString(std::string* serialized);

  /*
   * Reset the metrics logger by cleaning up its staging queues and existing
+48 −11
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <unistd.h>
#include <algorithm>
#include <array>
#include <cerrno>
#include <chrono>
#include <cstdint>
@@ -55,7 +56,12 @@ using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;

using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE;
using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid;
using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
/*
 * Get current OS boot time in millisecond
 */
@@ -233,6 +239,7 @@ struct BluetoothMetricsLogger::impl {
        wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)),
        scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) {
    bluetooth_log_ = BluetoothLog::default_instance().New();
    headset_profile_connection_counts_.fill(0);
    bluetooth_session_ = nullptr;
    bluetooth_session_start_time_ms_ = 0;
    a2dp_session_metrics_ = A2dpSessionMetrics();
@@ -240,6 +247,8 @@ struct BluetoothMetricsLogger::impl {

  /* Bluetooth log lock protected */
  BluetoothLog* bluetooth_log_;
  std::array<int, HeadsetProfileType_ARRAYSIZE>
      headset_profile_connection_counts_;
  std::recursive_mutex bluetooth_log_lock_;
  /* End Bluetooth log lock protected */
  /* Bluetooth session lock protected */
@@ -397,29 +406,44 @@ void BluetoothMetricsLogger::LogA2dpSession(
      pimpl_->a2dp_session_metrics_.buffer_underruns_count);
}

void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(
    tBTA_SERVICE_ID service_id) {
  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
  switch (service_id) {
    case BTA_HSP_SERVICE_ID:
      pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++;
      break;
    case BTA_HFP_SERVICE_ID:
      pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++;
      break;
    default:
      pimpl_->headset_profile_connection_counts_
          [HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++;
      break;
  }
  return;
}

void BluetoothMetricsLogger::WriteString(std::string* serialized) {
  std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
  LOG_DEBUG(LOG_TAG, "%s building metrics", __func__);
  Build();
  LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__);
  if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
    LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__);
    return;
  }
  if (clear) {
  // Always clean up log objects
  pimpl_->bluetooth_log_->Clear();
}
}

void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
                                               bool clear) {
  this->WriteString(serialized, clear);
void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) {
  this->WriteString(serialized);
  base::Base64Encode(*serialized, serialized);
}

void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
void BluetoothMetricsLogger::WriteBase64(int fd) {
  std::string protoBase64;
  this->WriteBase64String(&protoBase64, clear);
  this->WriteBase64String(&protoBase64);
  ssize_t ret;
  OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
  if (ret == -1) {
@@ -476,6 +500,19 @@ void BluetoothMetricsLogger::Build() {
    bluetooth_log->mutable_wake_event()->AddAllocated(
        pimpl_->wake_event_queue_->Dequeue());
  }
  for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) {
    int num_times_connected = pimpl_->headset_profile_connection_counts_[i];
    if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) {
      HeadsetProfileConnectionStats* headset_profile_connection_stats =
          bluetooth_log->add_headset_profile_connection_stats();
      // Able to static_cast because HeadsetProfileType_IsValid(i) is true
      headset_profile_connection_stats->set_headset_profile_type(
          static_cast<HeadsetProfileType>(i));
      headset_profile_connection_stats->set_num_times_connected(
          num_times_connected);
    }
  }
  pimpl_->headset_profile_connection_counts_.fill(0);
}

void BluetoothMetricsLogger::ResetSession() {
Loading