Populate Tx Power for Legacy BLE Adv Reports

Bug: 309912569
Test: Verify using ble_world and pixel buds that Tx Power is populated
Change-Id: I8cb005bd30c716c3391a9c1c743b1838ca185205
diff --git a/core/ble_request_manager.cc b/core/ble_request_manager.cc
index 7eac94d..0b1237f 100644
--- a/core/ble_request_manager.cc
+++ b/core/ble_request_manager.cc
@@ -21,6 +21,7 @@
 #include "chre/platform/log.h"
 #include "chre/util/fixed_size_vector.h"
 #include "chre/util/nested_data_ptr.h"
+#include "chre/util/system/ble_util.h"
 #include "chre/util/system/event_callbacks.h"
 
 namespace chre {
@@ -273,6 +274,10 @@
 
 void BleRequestManager::handleAdvertisementEvent(
     struct chreBleAdvertisementEvent *event) {
+  for (uint16_t i = 0; i < event->numReports; i++) {
+    populateLegacyAdvertisingReportFields(
+        const_cast<chreBleAdvertisingReport &>(event->reports[i]));
+  }
   EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
       CHRE_EVENT_BLE_ADVERTISEMENT, event, freeAdvertisingEventCallback);
 }
diff --git a/util/include/chre/util/system/ble_util.h b/util/include/chre/util/system/ble_util.h
new file mode 100644
index 0000000..5072008
--- /dev/null
+++ b/util/include/chre/util/system/ble_util.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CHRE_UTIL_SYSTEM_BLE_UTIL_H_
+#define CHRE_UTIL_SYSTEM_BLE_UTIL_H_
+
+#include "chre_api/chre.h"
+
+namespace chre {
+
+/**
+ * Populates a legacy chreBleAdvertisingReport's fields with values from the
+ * payload. The chreBleAdvertisingReport is based on the LE Extended Advertising
+ * Report Event defined in the BT Core Spec v5.3, Vol 4, Part E,
+ * Section 7.7.65.13. But for legacy LE Advertising Report Events (BT Core Spec
+ * v5.3, Vol 4, Part E, Section 7.7.65.2), some of these fields are only
+ * included in the payload. We parse out these fields to make it easier for the
+ * nanoapp to access this data.
+ *
+ * @param report CHRE BLE Advertising Report
+ */
+void populateLegacyAdvertisingReportFields(chreBleAdvertisingReport &report);
+
+}  // namespace chre
+
+#endif  // CHRE_UTIL_SYSTEM_BLE_UTIL_H_
diff --git a/util/system/ble_util.cc b/util/system/ble_util.cc
new file mode 100644
index 0000000..eb61426
--- /dev/null
+++ b/util/system/ble_util.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "chre/util/system/ble_util.h"
+
+#include <cinttypes>
+
+#include "chre/platform/log.h"
+
+namespace chre {
+
+namespace {
+
+// Tx Power Level AD Type defined in the BT Core Spec v5.3 Assigned Numbers,
+// Generic Access Profile (ref:
+// https://www.bluetooth.com/specifications/assigned-numbers/).
+constexpr uint8_t kTxPowerLevelAdType = 0x0A;
+constexpr uint8_t kAdTypeOffset = 1;
+constexpr uint8_t kExpectedAdDataLength = 2;
+
+/**
+ * Gets the TX Power from the data field of legacy AD reports. This function
+ * parses the advertising data which is defined in the BT Core Spec v5.3, Vol 3,
+ * Part C, Section 11, Advertising and Scan Response Data Format, and checks for
+ * the presence of the Tx Power Level AD Type.
+ *
+ * @param data Advertising data.
+ * @param dataLength Length of advertising data.
+ * @return int8_t Tx Power value.
+ */
+int8_t getTxPowerFromLegacyReport(const uint8_t *data, size_t dataLength) {
+  size_t i = 0;
+  while (i < dataLength) {
+    uint8_t adDataLength = data[i];
+    if (adDataLength == 0 || (adDataLength >= dataLength - i)) {
+      break;
+    }
+    if (data[i + kAdTypeOffset] == kTxPowerLevelAdType &&
+        adDataLength == kExpectedAdDataLength) {
+      return static_cast<int8_t>(data[i + kExpectedAdDataLength]);
+    }
+    i += kAdTypeOffset + adDataLength;
+  }
+  return CHRE_BLE_TX_POWER_NONE;
+}
+
+}  // namespace
+
+void populateLegacyAdvertisingReportFields(chreBleAdvertisingReport &report) {
+  if ((report.eventTypeAndDataStatus & CHRE_BLE_EVENT_TYPE_FLAG_LEGACY) != 0 &&
+      report.txPower == CHRE_BLE_TX_POWER_NONE) {
+    report.txPower = getTxPowerFromLegacyReport(report.data, report.dataLength);
+  }
+}
+
+}  // namespace chre
diff --git a/util/tests/ble_util_test.cc b/util/tests/ble_util_test.cc
new file mode 100644
index 0000000..762a6aa
--- /dev/null
+++ b/util/tests/ble_util_test.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include <string.h>
+
+#include "chre/util/system/ble_util.h"
+
+TEST(BleUtil, PopulateTxPower) {
+  chreBleAdvertisingReport report;
+  memset(&report, 0, sizeof(report));
+  report.txPower = CHRE_BLE_TX_POWER_NONE;
+  report.eventTypeAndDataStatus = CHRE_BLE_EVENT_TYPE_FLAG_LEGACY;
+  int8_t txPower = -11;
+  uint8_t data[3] = {0x02, 0x0A, static_cast<uint8_t>(txPower)};
+  report.data = data;
+  report.dataLength = 3;
+  chre::populateLegacyAdvertisingReportFields(report);
+  EXPECT_EQ(report.txPower, txPower);
+}
diff --git a/util/util.mk b/util/util.mk
index 2baf4f4..1a7ae3e 100644
--- a/util/util.mk
+++ b/util/util.mk
@@ -18,6 +18,7 @@
 COMMON_SRCS += $(CHRE_PREFIX)/util/nanoapp/debug.cc
 COMMON_SRCS += $(CHRE_PREFIX)/util/nanoapp/string.cc
 COMMON_SRCS += $(CHRE_PREFIX)/util/nanoapp/wifi.cc
+COMMON_SRCS += $(CHRE_PREFIX)/util/system/ble_util.cc
 COMMON_SRCS += $(CHRE_PREFIX)/util/system/event_callbacks.cc
 COMMON_SRCS += $(CHRE_PREFIX)/util/system/debug_dump.cc