Add BLE to chre stress test.

Bug: 238394142
Test: On-device test
Change-Id: Iacc2db427eb50e53bfd6d2aba79eb8af7f598602
diff --git a/apps/test/common/chre_stress_test/Makefile b/apps/test/common/chre_stress_test/Makefile
index 9c38bda..42f4e88 100644
--- a/apps/test/common/chre_stress_test/Makefile
+++ b/apps/test/common/chre_stress_test/Makefile
@@ -17,7 +17,7 @@
 NANOAPP_NAME = chre_stress_test
 NANOAPP_ID = 0x476f6f675400000a
 NANOAPP_NAME_STRING = \"CHRE\ Stress\ Test\"
-NANOAPP_VERSION = 0x00000006
+NANOAPP_VERSION = 0x00000007
 
 NANOAPP_PATH = $(CHRE_PREFIX)/apps/test/common/chre_stress_test
 TEST_SHARED_PATH = $(CHRE_PREFIX)/apps/test/common/shared
@@ -37,6 +37,7 @@
 COMMON_SRCS += $(NANOAPP_PATH)/src/chre_stress_test_manager.cc
 COMMON_SRCS += $(TEST_SHARED_PATH)/src/send_message.cc
 COMMON_SRCS += $(CHRE_PREFIX)/util/nanoapp/callbacks.cc
+COMMON_SRCS += $(CHRE_PREFIX)/util/nanoapp/ble.cc
 
 # Compiler Flags ###############################################################
 
@@ -54,6 +55,7 @@
 CHRE_NANOAPP_USES_GNSS = true
 CHRE_NANOAPP_USES_WWAN = true
 CHRE_NANOAPP_USES_AUDIO = true
+CHRE_NANOAPP_USES_BLE = true
 
 # Makefile Includes ############################################################
 
diff --git a/apps/test/common/chre_stress_test/inc/chre_stress_test_manager.h b/apps/test/common/chre_stress_test/inc/chre_stress_test_manager.h
index 076706b..5604323 100644
--- a/apps/test/common/chre_stress_test/inc/chre_stress_test_manager.h
+++ b/apps/test/common/chre_stress_test/inc/chre_stress_test_manager.h
@@ -30,6 +30,13 @@
 
 namespace stress_test {
 
+//! Lists types of BLE scan request.
+enum BleScanRequestType {
+  NO_FILTER = 0,
+  SERVICE_DATA_16 = 1,
+  STOP_SCAN = 2,
+};
+
 /**
  * A class to manage a CHRE stress test session.
  */
@@ -120,6 +127,7 @@
   void handleWifiScanMonitoringCommand(bool start);
   void handleSensorStartCommand(bool start);
   void handleAudioStartCommand(bool start);
+  void handleBleStartCommand(bool start);
 
   /**
    * @param result The WiFi async result from CHRE.
@@ -226,6 +234,29 @@
    */
   void makeAudioRequest();
 
+  /**
+   * @param event The BLE advertisement event from CHRE.
+   */
+  void handleBleAdvertismentEvent(const chreBleAdvertisementEvent *event);
+
+  /**
+   * @param event The BLE event from CHRE.
+   */
+  void handleBleAsyncResult(const chreAsyncResult *result);
+
+  /**
+   * Makes the next Ble request.
+   */
+  void makeBleScanRequest();
+
+  /**
+   * @param scanRequestType The current BLE scan request type.
+   *
+   * @return The pointer to a chreBleScanFilter that corresponds to the scan
+   * request type.
+   */
+  chreBleScanFilter *getBleScanFilter(BleScanRequestType &scanRequestType);
+
   //! The host endpoint of the current test host.
   Optional<uint16_t> mHostEndpoint;
 
@@ -240,6 +271,7 @@
   uint32_t mWifiScanMonitorAsyncTimerHandle = CHRE_TIMER_INVALID;
   uint32_t mSensorTimerHandle = CHRE_TIMER_INVALID;
   uint32_t mAudioTimerHandle = CHRE_TIMER_INVALID;
+  uint32_t mBleScanTimerHandle = CHRE_TIMER_INVALID;
 
   //! true if the test has been started for the feature.
   bool mWifiTestStarted = false;
@@ -248,6 +280,7 @@
   bool mWwanTestStarted = false;
   bool mSensorTestStarted = false;
   bool mAudioTestStarted = false;
+  bool mBleTestStarted = false;
 
   //! true if scan monitor is enabled for the nanoapp.
   bool mWifiScanMonitorEnabled = false;
@@ -255,6 +288,9 @@
   //! True if audio is enabled for the nanoapp.
   bool mAudioEnabled = false;
 
+  //! True if ble is enabled for the nanoapp.
+  bool mBleEnabled = false;
+
   //! The cookie to use for requests.
   const uint32_t kOnDemandWifiScanCookie = 0xface;
   const uint32_t kGnssLocationCookie = 0xbeef;
@@ -276,8 +312,15 @@
   uint64_t mPrevGyroEventTimestampNs = 0;
   uint64_t mPrevInstantMotionEventTimestampNs = 0;
   uint64_t mPrevAudioEventTimestampMs = 0;
+  uint64_t mPrevBleAdTimestampMs = 0;
 
-  //! The sensor sampling status
+  //! Number of ble scan mode.
+  static constexpr uint32_t kNumBleScanModes = 3;
+
+  //! List of all ble scan mode.
+  const chreBleScanMode kScanModes[kNumBleScanModes] = {
+      CHRE_BLE_SCAN_MODE_BACKGROUND, CHRE_BLE_SCAN_MODE_FOREGROUND,
+      CHRE_BLE_SCAN_MODE_AGGRESSIVE};
 
   //! Current number of sensors tested.
   static constexpr uint32_t kNumSensors = 3;
diff --git a/apps/test/common/chre_stress_test/src/chre_stress_test_manager.cc b/apps/test/common/chre_stress_test/src/chre_stress_test_manager.cc
index 1fb284a..9699fad 100644
--- a/apps/test/common/chre_stress_test/src/chre_stress_test_manager.cc
+++ b/apps/test/common/chre_stress_test/src/chre_stress_test_manager.cc
@@ -20,9 +20,12 @@
 #include <pb_encode.h>
 
 #include "chre/util/macros.h"
+#include "chre/util/memory.h"
 #include "chre/util/nanoapp/audio.h"
+#include "chre/util/nanoapp/ble.h"
 #include "chre/util/nanoapp/callbacks.h"
 #include "chre/util/nanoapp/log.h"
+#include "chre/util/unique_ptr.h"
 #include "chre_stress_test.nanopb.h"
 #include "send_message.h"
 
@@ -43,12 +46,16 @@
 
 constexpr chre::Nanoseconds kWifiScanInterval = chre::Seconds(5);
 constexpr chre::Nanoseconds kSensorRequestInterval = chre::Seconds(5);
-constexpr uint64_t kSensorSamplingDelayNs = 0;
 constexpr chre::Nanoseconds kAudioRequestInterval = chre::Seconds(5);
+constexpr chre::Nanoseconds kBleRequestInterval = chre::Seconds(5);
+constexpr uint64_t kSensorSamplingDelayNs = 0;
 constexpr uint8_t kAccelSensorIndex = 0;
 constexpr uint8_t kGyroSensorIndex = 1;
 constexpr uint8_t kInstantMotionSensorIndex = 1;
 
+//! Report delay for BLE scans.
+constexpr uint32_t gBleBatchDurationMs = 0;
+
 bool isRequestTypeForLocation(uint8_t requestType) {
   return (requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_START) ||
          (requestType == CHRE_GNSS_REQUEST_TYPE_LOCATION_SESSION_STOP);
@@ -59,6 +66,27 @@
          (requestType == CHRE_GNSS_REQUEST_TYPE_MEASUREMENT_SESSION_STOP);
 }
 
+bool enableBleScans() {
+  chreBleGenericFilter scanFilters[2];
+  uint8_t mask[2] = {0xFF, 0xFF};
+  // Google eddystone UUID.
+  uint8_t uuid1[2] = {0xFE, 0xAA};
+  scanFilters[0] = createBleGenericFilter(
+      CHRE_BLE_AD_TYPE_SERVICE_DATA_WITH_UUID_16, 2, uuid1, mask);
+  // Google nearby fastpair UUID.
+  uint8_t uuid2[2] = {0xFE, 0x2C};
+  scanFilters[1] = createBleGenericFilter(
+      CHRE_BLE_AD_TYPE_SERVICE_DATA_WITH_UUID_16, 2, uuid2, mask);
+  const struct chreBleScanFilter filter = {
+      .rssiThreshold = -128, .scanFilterCount = 2, .scanFilters = scanFilters};
+  return chreBleStartScanAsync(CHRE_BLE_SCAN_MODE_BACKGROUND,
+                               gBleBatchDurationMs, &filter);
+}
+
+bool disableBleScans() {
+  return chreBleStopScanAsync();
+}
+
 }  // anonymous namespace
 
 void Manager::handleEvent(uint32_t senderInstanceId, uint16_t eventType,
@@ -139,6 +167,10 @@
           handleAudioStartCommand(testCommand.start);
           break;
         }
+        case chre_stress_test_TestCommand_Feature_BLE: {
+          handleBleStartCommand(testCommand.start);
+          break;
+        }
         default: {
           LOGE("Unknown feature %d", testCommand.feature);
           success = false;
@@ -223,6 +255,15 @@
           static_cast<const chreAudioSourceStatusEvent *>(eventData));
       break;
 
+    case CHRE_EVENT_BLE_ADVERTISEMENT:
+      handleBleAdvertismentEvent(
+          static_cast<const chreBleAdvertisementEvent *>(eventData));
+      break;
+
+    case CHRE_EVENT_BLE_ASYNC_RESULT:
+      handleBleAsyncResult(static_cast<const chreAsyncResult *>(eventData));
+      break;
+
     default:
       LOGW("Unknown event type %" PRIu16, eventType);
       break;
@@ -248,6 +289,8 @@
     sendFailure("GNSS measurement async result timed out");
   } else if (*handle == mWwanTimerHandle) {
     makeWwanCellInfoRequest();
+  } else if (*handle == mBleScanTimerHandle) {
+    makeBleScanRequest();
   } else if (*handle == mWifiScanMonitorAsyncTimerHandle) {
     sendFailure("WiFi scan monitor request timed out");
   } else if (*handle == mAudioTimerHandle) {
@@ -352,6 +395,29 @@
   request.reset();
 }
 
+void Manager::handleBleAdvertismentEvent(
+    const chreBleAdvertisementEvent *event) {
+  for (uint8_t i = 0; i < event->numReports; i++) {
+    uint64_t timestamp =
+        event->reports[i].timestamp / chre::kOneMillisecondInNanoseconds;
+
+    checkTimestamp(timestamp, mPrevBleAdTimestampMs);
+    mPrevBleAdTimestampMs = timestamp;
+  }
+}
+
+void Manager::handleBleAsyncResult(const chreAsyncResult *result) {
+  const char *requestType =
+      result->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN ? "start"
+                                                              : "stop";
+  if (result->success) {
+    LOGI("BLE %s scan success", requestType);
+    mBleEnabled = (result->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN);
+  } else {
+    LOGW("BLE %s scan failure: %" PRIu8, requestType, result->errorCode);
+  }
+}
+
 void Manager::checkTimestamp(uint64_t timestamp, uint64_t pastTimestamp) {
   if (timestamp < pastTimestamp) {
     sendFailure("Timestamp was too old");
@@ -624,6 +690,20 @@
   }
 }
 
+void Manager::handleBleStartCommand(bool start) {
+  if (chreBleGetCapabilities() & CHRE_BLE_CAPABILITIES_SCAN) {
+    mBleTestStarted = start;
+
+    if (start) {
+      makeBleScanRequest();
+    } else {
+      cancelTimer(&mBleScanTimerHandle);
+    }
+  } else {
+    sendFailure("Platform has no BLE capability");
+  }
+}
+
 void Manager::setTimer(uint64_t delayNs, bool oneShot, uint32_t *timerHandle) {
   *timerHandle = chreTimerSet(delayNs, timerHandle, oneShot);
   if (*timerHandle == CHRE_TIMER_INVALID) {
@@ -694,6 +774,23 @@
   }
 }
 
+void Manager::makeBleScanRequest() {
+  bool success = false;
+
+  if (!mBleEnabled) {
+    success = enableBleScans();
+  } else {
+    success = disableBleScans();
+  }
+
+  if (!success) {
+    LOGE("Failed to send BLE %s scan request", !mBleEnabled ? "start" : "stop");
+  } else {
+    setTimer(kBleRequestInterval.toRawNanoseconds(), true /* oneShot */,
+             &mBleScanTimerHandle);
+  }
+}
+
 void Manager::makeGnssLocationRequest() {
   // The list of location intervals to iterate; wraps around.
   static const uint32_t kMinIntervalMsList[] = {1000, 0};
diff --git a/apps/test/common/proto/chre_stress_test.proto b/apps/test/common/proto/chre_stress_test.proto
index a240d85..557ace9 100644
--- a/apps/test/common/proto/chre_stress_test.proto
+++ b/apps/test/common/proto/chre_stress_test.proto
@@ -54,6 +54,8 @@
     SENSORS = 6;
     // Audio stress testing.
     AUDIO = 7;
+    // Enables BLE test only.
+    BLE = 8;
   }
 
   // The feature to test.