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

Commit 91585a75 authored by shihchienc's avatar shihchienc
Browse files

Avoid active scanning if device is discovered but not connected

If the device is connected but not yet added to group since sirk exchange
is not completed, we cannot start active scan because this device would
be in the group eventually. Open the second active scan is not necessary
if all members in the group are found and being processed.

Test: atest -c bluetooth_csis_test
Bug: 315392056
Tag: feature
Flag: Exempt, regression covered with unit tests, new unit test added
Change-Id: Ibbb0a8e98bcf475b4f294b1fbba6bf135606c23a
parent 5902ad25
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -902,7 +902,15 @@ class CsisClientImpl : public CsisClient {
        auto g = FindCsisGroup(group_id_to_discover);
        LOG_DEBUG("Group size  %d  target size %d", g->GetDesiredSize(),
                  g->GetCurrentSize());
        if (g->GetDesiredSize() > g->GetCurrentSize()) {

        auto dev_waiting_for_bonding_cnt =
            GetNumOfKnownExpectedDevicesWaitingForBonding(g->GetGroupId());
        LOG_DEBUG("Group size: %d, desired size: %d, waiting for bonding: %d",
                  g->GetCurrentSize(), g->GetDesiredSize(),
                  dev_waiting_for_bonding_cnt);

        if (g->GetDesiredSize() >
            g->GetCurrentSize() + dev_waiting_for_bonding_cnt) {
          CsisActiveDiscovery(g);
        }
      }
@@ -1304,6 +1312,14 @@ class CsisClientImpl : public CsisClient {
    return std::move(devices);
  }

  int GetNumOfKnownExpectedDevicesWaitingForBonding(int group_id) {
    return std::count_if(
        devices_.begin(), devices_.end(), [group_id](const auto& device) {
          return device->GetExpectedGroupIdMember() == group_id &&
                 !device->GetCsisInstanceByGroupId(group_id);
        });
  }

  void CacheAndAdvertiseExpectedMember(const RawAddress& address,
                                       int group_id) {
    auto device = FindDeviceByAddress(address);
+94 −0
Original line number Diff line number Diff line
@@ -1089,6 +1089,100 @@ TEST_F(CsisClientTest, test_get_set_sirk) {
  ASSERT_EQ(g_1->GetSirk(), sirk);
}

TEST_F(CsisClientTest,
       test_not_open_duplicate_active_scan_while_bonding_set_member) {
  uint16_t conn_id = 0x0001;
  EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _)).Times(1);
  SetSampleDatabaseCsis(conn_id, 1, 1);
  TestAppRegister();

  // Here we handle background scan request
  Mock::VerifyAndClearExpectations(&dm_interface);

  TestConnect(test_address);
  InjectConnectedEvent(test_address, 1);

  auto ReadCharacteristicCbGenerator = []() {
    return [](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb,
              void* cb_data) -> void {
      std::vector<uint8_t> value;
      switch (handle) {
        case 0x0003:
          // device name
          value.resize(20);
          break;
        case 0x0021:
          // plain sirk
          value.resize(17);
          value.assign(17, 1);
          break;
        case 0x0024:
          // size
          value.resize(1);
          value.assign(1, 2);
          break;
        case 0x0027:
          // lock
          value.resize(2);
          break;
        case 0x0030:
          // rank
          value.resize(1);
          value.assign(1, 1);
          break;
        default:
          FAIL();
          return;
      }
      if (cb) {
        cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
      }
    };
  };

  // We should read 4 times for sirk, rank, size, and lock characteristics
  EXPECT_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
      .Times(4)
      .WillOnce(Invoke(ReadCharacteristicCbGenerator()))
      .WillOnce(Invoke(ReadCharacteristicCbGenerator()))
      .WillOnce(Invoke(ReadCharacteristicCbGenerator()))
      .WillOnce(Invoke(ReadCharacteristicCbGenerator()));

  // Here is actual active scan request for the first device
  tBTA_DM_SEARCH_CBACK* p_results_cb = nullptr;
  EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _))
      .Times(1)
      .WillOnce(DoAll(SaveArg<1>(&p_results_cb)));

  GetSearchCompleteEvent(conn_id);

  Mock::VerifyAndClearExpectations(&dm_interface);

  // Simulate we find the set member
  tBTA_DM_SEARCH result;
  result.inq_res.include_rsi = true;
  std::vector<uint8_t> rsi = {0x07, 0x2e, 0x00, 0xed, 0x1a, 0x00, 0x00, 0x00};
  result.inq_res.p_eir = rsi.data();
  result.inq_res.eir_len = 8;
  result.inq_res.bd_addr = test_address2;

  // CSIS client should process set member event to JNI
  EXPECT_CALL(*callbacks, OnSetMemberAvailable(test_address2, 1));

  p_results_cb(BTA_DM_INQ_RES_EVT, &result);

  Mock::VerifyAndClearExpectations(&dm_interface);

  EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _)).Times(0);

  // Simulate getting duplicate response from remote for the first device
  // At this momoment we should not open second active scan because the set
  // member is already cached and waiting for bonding
  GetSearchCompleteEvent(conn_id);

  Mock::VerifyAndClearExpectations(&dm_interface);
}

TEST_F(CsisClientTest, test_csis_member_not_found) {
  EXPECT_CALL(dm_interface, BTA_DmBleCsisObserve(true, _)).Times(1);
  SetSampleDatabaseDoubleCsis(0x001, 1, 2);