From 3d872bbaf7749f649365a234fe000fca6ceed9d0 Mon Sep 17 00:00:00 2001
From: shihchienc <shihchienc@google.com>
Date: Fri, 5 May 2023 08:25:55 +0000
Subject: [PATCH] BTM: Let CSIS active scanning take effect

Currently when there is an ongoing background scanning like 10% or 25%,
CSIS active scannning would not take effect since the first scanning
come first. This makes finding coordinate members more difficult as the
scanning % is not enough.

This Patch checks if current scan is for CSIS then stops any ongoing
scanning and uses low latency scanning for finding coordinate members.
This increases paring speed and also decreases the failure that we
do not find coordinate members.

Bug: 273958309
Test: make sure we find csis member with 100% scanning
Change-Id: I4b469166690f20306fcdcb57d7ca4a311d5969bc
---
 system/bta/csis/csis_client.cc              |  2 +-
 system/bta/dm/bta_dm_act.cc                 | 13 ++++---
 system/bta/dm/bta_dm_api.cc                 |  8 ++--
 system/bta/dm/bta_dm_int.h                  |  2 +-
 system/bta/include/bta_api.h                |  4 +-
 system/bta/test/common/bta_dm_api_mock.cc   |  4 +-
 system/bta/test/common/bta_dm_api_mock.h    |  6 ++-
 system/stack/btm/btm_ble_gap.cc             | 41 +++++++++++++++++----
 system/stack/include/btm_ble_api.h          |  5 ++-
 system/stack/include/btm_client_interface.h |  3 +-
 system/test/mock/mock_bta_dm_api.cc         |  4 +-
 system/test/mock/mock_bta_dm_api.h          | 10 +++--
 system/test/mock/mock_stack_btm.cc          |  3 +-
 system/test/mock/mock_stack_btm_ble_gap.cc  |  2 +-
 14 files changed, 75 insertions(+), 32 deletions(-)

diff --git a/system/bta/csis/csis_client.cc b/system/bta/csis/csis_client.cc
index 187a1fcb309..a615c87d022 100644
--- a/system/bta/csis/csis_client.cc
+++ b/system/bta/csis/csis_client.cc
@@ -1281,7 +1281,7 @@ class CsisClientImpl : public CsisClient {
 
           instance->OnActiveScanResult(&p_data->inq_res);
         });
-    BTA_DmBleScan(enable, bluetooth::csis::kDefaultScanDurationS);
+    BTA_DmBleScan(enable, bluetooth::csis::kDefaultScanDurationS, true);
 
     /* Need to call it by ourselfs */
     if (!enable) {
diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc
index 61e02208671..a17058eb216 100644
--- a/system/bta/dm/bta_dm_act.cc
+++ b/system/bta/dm/bta_dm_act.cc
@@ -4016,9 +4016,11 @@ void bta_dm_ble_config_local_privacy(bool privacy_enable) {
   BTM_BleConfigPrivacy(privacy_enable);
 }
 
-static void bta_dm_start_scan(uint8_t duration_sec) {
-  tBTM_STATUS status = BTM_BleObserve(
-      true, duration_sec, bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb);
+static void bta_dm_start_scan(uint8_t duration_sec,
+                              bool low_latency_scan = false) {
+  tBTM_STATUS status =
+      BTM_BleObserve(true, duration_sec, bta_dm_observe_results_cb,
+                     bta_dm_observe_cmpl_cb, low_latency_scan);
 
   if (status != BTM_CMD_STARTED) {
     tBTA_DM_SEARCH data = {
@@ -4051,7 +4053,8 @@ void bta_dm_ble_observe(bool start, uint8_t duration,
   bta_dm_start_scan(duration);
 }
 
-void bta_dm_ble_scan(bool start, uint8_t duration_sec) {
+void bta_dm_ble_scan(bool start, uint8_t duration_sec,
+                     bool low_latency_scan = false) {
   /* Start or stop only if there is no active main scanner */
   if (bta_dm_search_cb.p_scan_cback != NULL) return;
 
@@ -4060,7 +4063,7 @@ void bta_dm_ble_scan(bool start, uint8_t duration_sec) {
     return;
   }
 
-  bta_dm_start_scan(duration_sec);
+  bta_dm_start_scan(duration_sec, low_latency_scan);
 }
 
 void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback) {
diff --git a/system/bta/dm/bta_dm_api.cc b/system/bta/dm/bta_dm_api.cc
index 325d82ef75b..72a99d47fae 100644
--- a/system/bta/dm/bta_dm_api.cc
+++ b/system/bta/dm/bta_dm_api.cc
@@ -605,14 +605,16 @@ void BTA_DmBleObserve(bool start, uint8_t duration,
  * Parameters       start: start or stop the scan procedure,
  *                  duration_sec: Duration of the scan. Continuous scan if 0 is
  *                                passed,
+ *                  low_latency_scan: whether this is an low latency scan,
+ *                                    default is false.
  *
  * Returns          void
  *
  ******************************************************************************/
-void BTA_DmBleScan(bool start, uint8_t duration_sec) {
+void BTA_DmBleScan(bool start, uint8_t duration_sec, bool low_latency_scan) {
   APPL_TRACE_API("%s:start = %d ", __func__, start);
-  do_in_main_thread(FROM_HERE,
-                    base::Bind(bta_dm_ble_scan, start, duration_sec));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_ble_scan, start, duration_sec,
+                                          low_latency_scan));
 }
 
 /*******************************************************************************
diff --git a/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h
index 947d5ab5a7b..96f1f16ad0a 100644
--- a/system/bta/dm/bta_dm_int.h
+++ b/system/bta/dm/bta_dm_int.h
@@ -538,7 +538,7 @@ void bta_dm_ble_set_conn_params(const RawAddress&, uint16_t, uint16_t, uint16_t,
                                 uint16_t);
 void bta_dm_close_gatt_conn(tBTA_DM_MSG* p_data);
 void bta_dm_ble_observe(bool, uint8_t, tBTA_DM_SEARCH_CBACK*);
-void bta_dm_ble_scan(bool, uint8_t);
+void bta_dm_ble_scan(bool, uint8_t, bool);
 void bta_dm_ble_csis_observe(bool, tBTA_DM_SEARCH_CBACK*);
 void bta_dm_ble_update_conn_params(const RawAddress&, uint16_t, uint16_t,
                                    uint16_t, uint16_t, uint16_t, uint16_t);
diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h
index 97a57487316..c395672f55f 100644
--- a/system/bta/include/bta_api.h
+++ b/system/bta/include/bta_api.h
@@ -1146,11 +1146,13 @@ void BTA_DmBleObserve(bool start, uint8_t duration,
  * Parameters       start: start or stop the scan procedure,
  *                  duration_sec: Duration of the scan. Continuous scan if 0 is
  *                                passed,
+ *                  low_latency_scan: whether this is a low latency scan,
+ *                                    default is false,
  *
  * Returns          void
  *
  ******************************************************************************/
-void BTA_DmBleScan(bool start, uint8_t duration);
+void BTA_DmBleScan(bool start, uint8_t duration, bool low_latency_scan = false);
 
 /*******************************************************************************
  *
diff --git a/system/bta/test/common/bta_dm_api_mock.cc b/system/bta/test/common/bta_dm_api_mock.cc
index 6a89920fee0..e0c9941e3ff 100644
--- a/system/bta/test/common/bta_dm_api_mock.cc
+++ b/system/bta/test/common/bta_dm_api_mock.cc
@@ -23,9 +23,9 @@ void dm::SetMockBtaDmInterface(MockBtaDmInterface* mock_bta_dm_interface) {
   dm_interface = mock_bta_dm_interface;
 }
 
-void BTA_DmBleScan(bool start, uint8_t duration) {
+void BTA_DmBleScan(bool start, uint8_t duration, bool low_latency_scan) {
   LOG_ASSERT(dm_interface) << "Mock BTA DM interface not set!";
-  return dm_interface->BTA_DmBleScan(start, duration);
+  return dm_interface->BTA_DmBleScan(start, duration, low_latency_scan);
 }
 
 void BTA_DmBleCsisObserve(bool observe, tBTA_DM_SEARCH_CBACK* p_results_cb) {
diff --git a/system/bta/test/common/bta_dm_api_mock.h b/system/bta/test/common/bta_dm_api_mock.h
index 9be98faaca2..9093bd3b296 100644
--- a/system/bta/test/common/bta_dm_api_mock.h
+++ b/system/bta/test/common/bta_dm_api_mock.h
@@ -26,7 +26,8 @@ namespace dm {
 
 class BtaDmInterface {
  public:
-  virtual void BTA_DmBleScan(bool start, uint8_t duration) = 0;
+  virtual void BTA_DmBleScan(bool start, uint8_t duration,
+                             bool low_latency_scan) = 0;
   virtual void BTA_DmBleCsisObserve(bool observe,
                                     tBTA_DM_SEARCH_CBACK* p_results_cb) = 0;
   virtual ~BtaDmInterface() = default;
@@ -34,7 +35,8 @@ class BtaDmInterface {
 
 class MockBtaDmInterface : public BtaDmInterface {
  public:
-  MOCK_METHOD((void), BTA_DmBleScan, (bool start, uint8_t duration));
+  MOCK_METHOD((void), BTA_DmBleScan,
+              (bool start, uint8_t duration, bool low_latency_scan));
   MOCK_METHOD((void), BTA_DmBleCsisObserve,
               (bool observe, tBTA_DM_SEARCH_CBACK* p_results_cb));
 };
diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc
index 40440259a94..0f630763846 100644
--- a/system/stack/btm/btm_ble_gap.cc
+++ b/system/stack/btm/btm_ble_gap.cc
@@ -492,13 +492,15 @@ void BTM_BleTargetAnnouncementObserve(bool enable,
  *                  duration: how long the scan should last, in seconds. 0 means
  *                  scan without timeout. Starting the scan second time without
  *                  timeout will disable the timer.
+ *                  low_latency_scan: whether this is a low latency scan,
+ *                                    default is false.
  *
  * Returns          void
  *
  ******************************************************************************/
 tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
                            tBTM_INQ_RESULTS_CB* p_results_cb,
-                           tBTM_CMPL_CB* p_cmpl_cb) {
+                           tBTM_CMPL_CB* p_cmpl_cb, bool low_latency_scan) {
   tBTM_BLE_INQ_CB* p_inq = &btm_cb.ble_ctr_cb.inq_var;
   tBTM_STATUS status = BTM_WRONG_MODE;
 
@@ -507,13 +509,21 @@ tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
   uint32_t scan_window =
       !p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window;
 
+  // use low latency scanning if the scanning is active
+  if (low_latency_scan) {
+    scan_interval = BTM_BLE_LOW_LATENCY_SCAN_INT;
+    scan_window = BTM_BLE_LOW_LATENCY_SCAN_WIN;
+  }
+
   BTM_TRACE_EVENT("%s : scan_type:%d, %d, %d", __func__, p_inq->scan_type,
-                  p_inq->scan_interval, p_inq->scan_window);
+                  scan_interval, scan_window);
 
   if (!controller_get_interface()->supports_ble()) return BTM_ILLEGAL_VALUE;
 
   if (start) {
-    /* shared inquiry database, do not allow observe if any inquiry is active */
+    /* shared inquiry database, do not allow observe if any inquiry is active.
+     * except we are doing CSIS active scanning
+     */
     if (btm_cb.ble_ctr_cb.is_ble_observe_active()) {
       if (duration == 0) {
         if (alarm_is_scheduled(btm_cb.ble_ctr_cb.observer_timer)) {
@@ -522,12 +532,26 @@ tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
           BTM_TRACE_ERROR("%s Scan with no duration started twice!", __func__);
         }
       } else {
-        if (alarm_is_scheduled(btm_cb.ble_ctr_cb.observer_timer)) {
+        if (!low_latency_scan &&
+            alarm_is_scheduled(btm_cb.ble_ctr_cb.observer_timer)) {
           BTM_TRACE_ERROR("%s Scan with duration started twice!", __func__);
         }
       }
-      BTM_TRACE_WARNING("%s Observer was already active", __func__);
-      return BTM_CMD_STARTED;
+      /*
+       * we stop current observation request for below scenarios
+       * 1. if the scan we wish to start is not low latency
+       * 2. current ongoing scanning is low latency
+       */
+      bool is_ongoing_low_latency =
+          p_inq->scan_interval == BTM_BLE_GAP_DISC_SCAN_INT &&
+          p_inq->scan_window == BTM_BLE_LOW_LATENCY_SCAN_WIN;
+      if (!low_latency_scan || is_ongoing_low_latency) {
+        BTM_TRACE_WARNING("%s Observer was already active, is_low_latency: %d",
+                          __func__, is_ongoing_low_latency);
+        return BTM_CMD_STARTED;
+      }
+      // stop any scan without low latency config
+      btm_ble_stop_observe();
     }
 
     btm_cb.ble_ctr_cb.p_obs_results_cb = p_results_cb;
@@ -552,7 +576,10 @@ tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
         .start_time_ms = timestamper_in_milliseconds.GetTimestamp(),
         .results = 0,
     };
-    BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Le observe started");
+
+    BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Le observe started",
+                   base::StringPrintf("low latency scanning enabled: %d",
+                                      low_latency_scan));
 
     if (status == BTM_CMD_STARTED) {
       btm_cb.ble_ctr_cb.set_ble_observe_active();
diff --git a/system/stack/include/btm_ble_api.h b/system/stack/include/btm_ble_api.h
index dadfdaf6417..d204dc2582b 100644
--- a/system/stack/include/btm_ble_api.h
+++ b/system/stack/include/btm_ble_api.h
@@ -165,13 +165,16 @@ void BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK* p_track_cback,
  *                  duration: how long the scan should last, in seconds. 0 means
  *                  scan without timeout. Starting the scan second time without
  *                  timeout will disable the timer.
+ *                  low_latency_scan: whether this is a low latency scan,
+ *                                    default is false.
  *
  * Returns          void
  *
  ******************************************************************************/
 tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
                            tBTM_INQ_RESULTS_CB* p_results_cb,
-                           tBTM_CMPL_CB* p_cmpl_cb);
+                           tBTM_CMPL_CB* p_cmpl_cb,
+                           bool low_latency_scan = false);
 
 /*******************************************************************************
  *
diff --git a/system/stack/include/btm_client_interface.h b/system/stack/include/btm_client_interface.h
index ca333dfe7db..24669beef29 100644
--- a/system/stack/include/btm_client_interface.h
+++ b/system/stack/include/btm_client_interface.h
@@ -166,7 +166,8 @@ struct btm_client_interface_t {
     tBTM_STATUS (*BTM_BleGetEnergyInfo)(tBTM_BLE_ENERGY_INFO_CBACK* callback);
     tBTM_STATUS (*BTM_BleObserve)(bool start, uint8_t duration,
                                   tBTM_INQ_RESULTS_CB* p_results_cb,
-                                  tBTM_CMPL_CB* p_cmpl_cb);
+                                  tBTM_CMPL_CB* p_cmpl_cb,
+                                  bool low_latency_scan);
     tBTM_STATUS (*BTM_SetBleDataLength)(const RawAddress& bd_addr,
                                         uint16_t tx_pdu_length);
     void (*BTM_BleConfirmReply)(const RawAddress& bd_addr, uint8_t res);
diff --git a/system/test/mock/mock_bta_dm_api.cc b/system/test/mock/mock_bta_dm_api.cc
index c61070b7159..8b54c589627 100644
--- a/system/test/mock/mock_bta_dm_api.cc
+++ b/system/test/mock/mock_bta_dm_api.cc
@@ -123,9 +123,9 @@ void BTA_DmBleRequestMaxTxDataLength(const RawAddress& remote_device) {
   inc_func_call_count(__func__);
   test::mock::bta_dm_api::BTA_DmBleRequestMaxTxDataLength(remote_device);
 }
-void BTA_DmBleScan(bool start, uint8_t duration) {
+void BTA_DmBleScan(bool start, uint8_t duration, bool low_latency_scan) {
   inc_func_call_count(__func__);
-  test::mock::bta_dm_api::BTA_DmBleScan(start, duration);
+  test::mock::bta_dm_api::BTA_DmBleScan(start, duration, low_latency_scan);
 }
 void BTA_DmBleSecurityGrant(const RawAddress& bd_addr,
                             tBTA_DM_BLE_SEC_GRANT res) {
diff --git a/system/test/mock/mock_bta_dm_api.h b/system/test/mock/mock_bta_dm_api.h
index cd3473ee745..1be9353e025 100644
--- a/system/test/mock/mock_bta_dm_api.h
+++ b/system/test/mock/mock_bta_dm_api.h
@@ -186,12 +186,14 @@ struct BTA_DmBleRequestMaxTxDataLength {
 extern struct BTA_DmBleRequestMaxTxDataLength BTA_DmBleRequestMaxTxDataLength;
 
 // Name: BTA_DmBleScan
-// Params: bool start, uint8_t duration
+// Params: bool start, uint8_t duration, bool low_latency_scan
 // Return: void
 struct BTA_DmBleScan {
-  std::function<void(bool start, uint8_t duration)> body{
-      [](bool start, uint8_t duration) {}};
-  void operator()(bool start, uint8_t duration) { body(start, duration); };
+  std::function<void(bool start, uint8_t duration, bool low_latency_scan)> body{
+      [](bool start, uint8_t duration, bool low_latency_scan) {}};
+  void operator()(bool start, uint8_t duration, bool low_latency_scan) {
+    body(start, duration, low_latency_scan);
+  };
 };
 extern struct BTA_DmBleScan BTA_DmBleScan;
 
diff --git a/system/test/mock/mock_stack_btm.cc b/system/test/mock/mock_stack_btm.cc
index 90a8669d1d9..475a45780c7 100644
--- a/system/test/mock/mock_stack_btm.cc
+++ b/system/test/mock/mock_stack_btm.cc
@@ -203,7 +203,8 @@ struct btm_client_interface_t btm_client_interface = {
                                    tBTM_BLE_LOCAL_KEYS* p_key) {},
         .BTM_BleObserve =
             [](bool start, uint8_t duration, tBTM_INQ_RESULTS_CB* p_results_cb,
-               tBTM_CMPL_CB* p_cmpl_cb) -> tBTM_STATUS { return BTM_SUCCESS; },
+               tBTM_CMPL_CB* p_cmpl_cb,
+               bool low_latency_scan) -> tBTM_STATUS { return BTM_SUCCESS; },
         .BTM_BlePasskeyReply = [](const RawAddress& bd_addr, uint8_t res,
                                   uint32_t passkey) {},
         .BTM_BleReadControllerFeatures =
diff --git a/system/test/mock/mock_stack_btm_ble_gap.cc b/system/test/mock/mock_stack_btm_ble_gap.cc
index a69a0e642d8..82c99df7bb1 100644
--- a/system/test/mock/mock_stack_btm_ble_gap.cc
+++ b/system/test/mock/mock_stack_btm_ble_gap.cc
@@ -90,7 +90,7 @@ bool btm_ble_topology_check(tBTM_BLE_STATE_MASK request_state_mask) {
 }
 tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
                            tBTM_INQ_RESULTS_CB* p_results_cb,
-                           tBTM_CMPL_CB* p_cmpl_cb) {
+                           tBTM_CMPL_CB* p_cmpl_cb, bool low_latency_scan) {
   inc_func_call_count(__func__);
   return BTM_SUCCESS;
 }
-- 
GitLab