Metrics: Log A2DP playback related atoms to StatsLog

* BluetoothA2dpAudioOverrunReported
  - Logs when A2DP failed send encoded data to the remote device fast
    enough such that the transmit buffer queue is full and we have to
    drop data
* BluetoothA2dpAudioUnderrunReported
  - Logs when A2DP failed to read from PCM source
* BluetoothDeviceRssiReported
  - Logged when remote device's RSSI level is reported by the controller
* BluetoothDeviceFailedContactCounterReported
  - Logged when ACL transmit queue was flushed by the controller
  - This is normally disabled unless we set automatic flush timeout was
    set to a non-zero value
  - However, when this event is reported, the connection quality must
    be very bad
* BluetoothDeviceTxPowerLevelReported
  - Logged when transmit power level is reported for a particular
    connection

Note on num_dropped_nanoseconds entry:
  - This is the duration of audio dropped and is calculated by
    multiplying the number of encoding actions with length of encoding
    interval

Bug: 112969790
Test: make, testdrive with statsd
Change-Id: Ie6aa5ee71dea213e452497dd181fee91eea8f7b4
diff --git a/system/common/metrics.cc b/system/common/metrics.cc
index 8461626..9cbef5e 100644
--- a/system/common/metrics.cc
+++ b/system/common/metrics.cc
@@ -619,6 +619,122 @@
                  << ", subversion " << loghex(subversion) << ", error " << ret;
   }
 }
+
+void LogA2dpAudioUnderrunEvent(const RawAddress& address,
+                               uint64_t encoding_interval_millis,
+                               int num_missing_pcm_bytes) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED, bytes_field,
+      encoding_interval_nanos, num_missing_pcm_bytes);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address
+                 << ", encoding_interval_nanos " << encoding_interval_nanos
+                 << ", num_missing_pcm_bytes " << num_missing_pcm_bytes
+                 << ", error " << ret;
+  }
+}
+
+void LogA2dpAudioOverrunEvent(const RawAddress& address,
+                              uint64_t encoding_interval_millis,
+                              int num_dropped_buffers,
+                              int num_dropped_encoded_frames,
+                              int num_dropped_encoded_bytes) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED, bytes_field,
+      encoding_interval_nanos, num_dropped_buffers, num_dropped_encoded_frames,
+      num_dropped_encoded_bytes);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed to log for " << address
+                 << ", encoding_interval_nanos " << encoding_interval_nanos
+                 << ", num_dropped_buffers " << num_dropped_buffers
+                 << ", num_dropped_encoded_frames "
+                 << num_dropped_encoded_frames << ", num_dropped_encoded_bytes "
+                 << num_dropped_encoded_bytes << ", error " << ret;
+  }
+}
+
+void LogReadRssiResult(const RawAddress& address, uint16_t handle,
+                       uint32_t cmd_status, int8_t rssi) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret =
+      android::util::stats_write(android::util::BLUETOOTH_DEVICE_RSSI_REPORTED,
+                                 bytes_field, handle, cmd_status, rssi);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
+                 << handle << ", status " << loghex(cmd_status) << ", rssi "
+                 << rssi << " dBm, error " << ret;
+  }
+}
+
+void LogReadFailedContactCounterResult(const RawAddress& address,
+                                       uint16_t handle, uint32_t cmd_status,
+                                       int32_t failed_contact_counter) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED,
+      bytes_field, handle, cmd_status, failed_contact_counter);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
+                 << handle << ", status " << loghex(cmd_status)
+                 << ", failed_contact_counter " << failed_contact_counter
+                 << " packets, error " << ret;
+  }
+}
+
+void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle,
+                               uint32_t cmd_status,
+                               int32_t transmit_power_level) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED, bytes_field,
+      handle, cmd_status, transmit_power_level);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
+                 << handle << ", status " << loghex(cmd_status)
+                 << ", transmit_power_level " << transmit_power_level
+                 << " packets, error " << ret;
+  }
+}
+
 }  // namespace common
 
 }  // namespace bluetooth