1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <base/functional/bind.h>
18 #include <base/location.h>
19 #include <bluetooth/log.h>
20 #include <com_android_bluetooth_flags.h>
21 #include <flag_macros.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 
25 #include <format>
26 #include <string>
27 
28 #include "bta/dm/bta_dm_device_search_int.h"
29 #include "bta/dm/bta_dm_disc.h"
30 #include "bta/dm/bta_dm_int.h"
31 #include "bta/dm/bta_dm_pm.cc"
32 #include "bta/dm/bta_dm_sec_int.h"
33 #include "bta/hf_client/bta_hf_client_int.h"
34 #include "bta/include/bta_api.h"
35 #include "bta/test/bta_test_fixtures.h"
36 #include "hci/controller_interface_mock.h"
37 #include "hci/le_rand_callback.h"
38 #include "stack/include/btm_status.h"
39 #include "test/common/main_handler.h"
40 #include "test/common/mock_functions.h"
41 #include "test/mock/mock_main_shim_entry.h"
42 #include "test/mock/mock_osi_alarm.h"
43 #include "test/mock/mock_osi_allocator.h"
44 #include "test/mock/mock_osi_properties.h"
45 #include "test/mock/mock_stack_acl.h"
46 #include "test/mock/mock_stack_btm_interface.h"
47 
48 #define TEST_BT com::android::bluetooth::flags
49 
50 using namespace std::chrono_literals;
51 using namespace bluetooth;
52 
53 namespace {
54 constexpr uint8_t kUnusedTimer = BTA_ID_MAX;
55 const RawAddress kRawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
56 const RawAddress kRawAddress2({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
57 
58 constexpr char kRemoteName[] = "TheRemoteName";
59 
60 }  // namespace
61 
62 namespace bluetooth::legacy::testing {
63 
64 tBTA_DM_SEARCH_CB& bta_dm_disc_search_cb();
65 void bta_dm_deinit_cb();
66 void bta_dm_init_cb();
67 void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg);
68 
69 }  // namespace bluetooth::legacy::testing
70 
71 class BtaDmTest : public BtaWithContextTest {
72 protected:
SetUp()73   void SetUp() override {
74     BtaWithContextTest::SetUp();
75     ON_CALL(controller_, LeRand).WillByDefault([](bluetooth::hci::LeRandCallback cb) {
76       cb(0x1234);
77     });
78     bluetooth::hci::testing::mock_controller_ = &controller_;
79 
80     BTA_dm_init();
81     bluetooth::legacy::testing::bta_dm_init_cb();
82 
83     for (int i = 0; i < BTA_DM_NUM_PM_TIMER; i++) {
84       for (int j = 0; j < BTA_DM_PM_MODE_TIMER_MAX; j++) {
85         bta_dm_cb.pm_timer[i].srvc_id[j] = kUnusedTimer;
86       }
87     }
88   }
TearDown()89   void TearDown() override {
90     bluetooth::legacy::testing::bta_dm_deinit_cb();
91     BtaWithContextTest::TearDown();
92     bluetooth::hci::testing::mock_controller_ = nullptr;
93   }
94   bluetooth::hci::testing::MockControllerInterface controller_;
95 };
96 
97 class BtaDmCustomAlarmTest : public BtaDmTest {
98 protected:
SetUp()99   void SetUp() override {
100     BtaDmTest::SetUp();
101     test::mock::osi_alarm::alarm_set_on_mloop.body =
102             [this](alarm_t* alarm, uint64_t /*interval_ms*/, alarm_callback_t cb, void* data) {
103               ASSERT_TRUE(alarm != nullptr);
104               this->alarm_callback = cb;
105               this->alarm_data = data;
106             };
107   }
TearDown()108   void TearDown() override {
109     test::mock::osi_alarm::alarm_set_on_mloop = {};
110     BtaDmTest::TearDown();
111   }
112   alarm_callback_t alarm_callback;
113   void* alarm_data{nullptr};
114 };
115 
TEST_F(BtaDmTest,nop)116 TEST_F(BtaDmTest, nop) {
117   bool status = true;
118   ASSERT_EQ(true, status);
119 }
120 
TEST_F(BtaDmCustomAlarmTest,disable_no_acl_links)121 TEST_F(BtaDmCustomAlarmTest, disable_no_acl_links) {
122   bta_dm_cb.disabling = true;
123 
124   bta_dm_disable();  // Waiting for all ACL connections to drain
125   ASSERT_EQ(0, get_func_call_count("btm_remove_acl"));
126   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
127 
128   // Execute timer callback
129   alarm_callback(this->alarm_data);
130   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
131   ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));
132   ASSERT_EQ(1, get_func_call_count("future_ready"));
133   ASSERT_TRUE(!bta_dm_cb.disabling);
134 }
135 
TEST_F(BtaDmCustomAlarmTest,disable_first_pass_with_acl_links)136 TEST_F(BtaDmCustomAlarmTest, disable_first_pass_with_acl_links) {
137   test::mock::stack_acl::BTM_GetNumAclLinks.body = []() { return 1; };
138   bta_dm_cb.disabling = true;
139   // ACL link is open
140   bta_dm_cb.device_list.count = 1;
141 
142   bta_dm_disable();  // Waiting for all ACL connections to drain
143   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
144   ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));
145 
146   test::mock::stack_acl::BTM_GetNumAclLinks.body = []() { return 0; };
147   // First disable pass
148   alarm_callback(this->alarm_data);
149   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
150   ASSERT_EQ(1, get_func_call_count("BTIF_dm_disable"));
151   ASSERT_TRUE(!bta_dm_cb.disabling);
152 
153   test::mock::stack_acl::BTM_GetNumAclLinks = {};
154 }
155 
TEST_F(BtaDmCustomAlarmTest,disable_second_pass_with_acl_links)156 TEST_F(BtaDmCustomAlarmTest, disable_second_pass_with_acl_links) {
157   test::mock::stack_acl::BTM_GetNumAclLinks.body = []() { return 1; };
158   bta_dm_cb.disabling = true;
159   // ACL link is open
160   bta_dm_cb.device_list.count = 1;
161 
162   bta_dm_disable();  // Waiting for all ACL connections to drain
163   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
164   ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));
165 
166   // First disable pass
167   alarm_callback(alarm_data);
168   ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
169   ASSERT_EQ(0, get_func_call_count("BTIF_dm_disable"));
170   ASSERT_EQ(1, get_func_call_count("btm_remove_acl"));
171 
172   // Second disable pass
173   alarm_callback(alarm_data);
174   ASSERT_EQ(1, get_func_call_count("BTIF_dm_disable"));
175   ASSERT_TRUE(!bta_dm_cb.disabling);
176 
177   test::mock::stack_acl::BTM_GetNumAclLinks = {};
178 }
179 
180 namespace {
181 
182 struct BTA_DM_ENCRYPT_CBACK_parms {
183   const RawAddress bd_addr;
184   tBT_TRANSPORT transport;
185   tBTA_STATUS result;
186 };
187 
188 std::queue<BTA_DM_ENCRYPT_CBACK_parms> BTA_DM_ENCRYPT_CBACK_queue;
189 
BTA_DM_ENCRYPT_CBACK(const RawAddress & bd_addr,tBT_TRANSPORT transport,tBTA_STATUS result)190 void BTA_DM_ENCRYPT_CBACK(const RawAddress& bd_addr, tBT_TRANSPORT transport, tBTA_STATUS result) {
191   BTA_DM_ENCRYPT_CBACK_queue.push({bd_addr, transport, result});
192 }
193 
194 }  // namespace
195 
196 namespace bluetooth {
197 namespace legacy {
198 namespace testing {
199 tBTA_DM_PEER_DEVICE* allocate_device_for(const RawAddress& bd_addr, tBT_TRANSPORT transport);
200 
201 void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p);
202 
203 tBT_TRANSPORT bta_dm_determine_discovery_transport(const RawAddress& remote_bd_addr);
204 
205 tBTM_STATUS bta_dm_sp_cback(tBTM_SP_EVT event, tBTM_SP_EVT_DATA* p_data);
206 
207 void BTA_dm_on_hw_on();
208 
209 }  // namespace testing
210 }  // namespace legacy
211 }  // namespace bluetooth
212 
TEST_F(BtaDmTest,bta_dm_set_encryption)213 TEST_F(BtaDmTest, bta_dm_set_encryption) {
214   const tBT_TRANSPORT transport{BT_TRANSPORT_LE};
215   const tBTM_BLE_SEC_ACT sec_act{BTM_BLE_SEC_NONE};
216 
217   // Callback not provided
218   bta_dm_set_encryption(kRawAddress, transport, nullptr, sec_act);
219 
220   // Device connection does not exist
221   bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
222 
223   // Setup a connected device
224   tBTA_DM_PEER_DEVICE* device =
225           bluetooth::legacy::testing::allocate_device_for(kRawAddress, transport);
226   ASSERT_TRUE(device != nullptr);
227   device->p_encrypt_cback = nullptr;
228 
229   // Setup a device that is busy with another encryption
230   // Fake indication that the encryption is in progress with non-null callback
231   device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
232   bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
233   ASSERT_EQ(0, get_func_call_count("BTM_SetEncryption"));
234   ASSERT_EQ(1UL, BTA_DM_ENCRYPT_CBACK_queue.size());
235   auto params = BTA_DM_ENCRYPT_CBACK_queue.front();
236   BTA_DM_ENCRYPT_CBACK_queue.pop();
237   ASSERT_EQ(BTA_BUSY, params.result);
238   device->p_encrypt_cback = nullptr;
239 
240   // Setup a device that fails encryption
241   mock_btm_client_interface.security.BTM_SetEncryption =
242           [](const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/,
243              tBTM_SEC_CALLBACK* /*p_callback*/, void* /*p_ref_data*/,
244              tBTM_BLE_SEC_ACT /*sec_act*/) -> tBTM_STATUS {
245     inc_func_call_count("BTM_SetEncryption");
246     return tBTM_STATUS::BTM_MODE_UNSUPPORTED;
247   };
248 
249   bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
250   ASSERT_EQ(1, get_func_call_count("BTM_SetEncryption"));
251   ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size());
252   device->p_encrypt_cback = nullptr;
253 
254   // Setup a device that successfully starts encryption
255   mock_btm_client_interface.security.BTM_SetEncryption =
256           [](const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/,
257              tBTM_SEC_CALLBACK* /*p_callback*/, void* /*p_ref_data*/,
258              tBTM_BLE_SEC_ACT /*sec_act*/) -> tBTM_STATUS {
259     inc_func_call_count("BTM_SetEncryption");
260     return tBTM_STATUS::BTM_CMD_STARTED;
261   };
262 
263   bta_dm_set_encryption(kRawAddress, transport, BTA_DM_ENCRYPT_CBACK, sec_act);
264   ASSERT_EQ(2, get_func_call_count("BTM_SetEncryption"));
265   ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size());
266   ASSERT_NE(nullptr, device->p_encrypt_cback);
267 
268   BTA_DM_ENCRYPT_CBACK_queue = {};
269 }
270 
271 void bta_dm_encrypt_cback(RawAddress bd_addr, tBT_TRANSPORT transport, void* /* p_ref_data */,
272                           tBTM_STATUS result);
273 
TEST_F(BtaDmTest,bta_dm_encrypt_cback)274 TEST_F(BtaDmTest, bta_dm_encrypt_cback) {
275   const tBT_TRANSPORT transport{BT_TRANSPORT_LE};
276 
277   // Setup a connected device
278   tBTA_DM_PEER_DEVICE* device =
279           bluetooth::legacy::testing::allocate_device_for(kRawAddress, transport);
280   ASSERT_TRUE(device != nullptr);
281 
282   // Encryption with no callback set
283   device->p_encrypt_cback = nullptr;
284   bta_dm_encrypt_cback(kRawAddress, transport, nullptr, tBTM_STATUS::BTM_SUCCESS);
285   ASSERT_EQ(0UL, BTA_DM_ENCRYPT_CBACK_queue.size());
286 
287   // Encryption with callback
288   device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
289   bta_dm_encrypt_cback(kRawAddress, transport, nullptr, tBTM_STATUS::BTM_SUCCESS);
290   device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
291   bta_dm_encrypt_cback(kRawAddress, transport, nullptr, tBTM_STATUS::BTM_WRONG_MODE);
292   device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
293   bta_dm_encrypt_cback(kRawAddress, transport, nullptr, tBTM_STATUS::BTM_NO_RESOURCES);
294   device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
295   bta_dm_encrypt_cback(kRawAddress, transport, nullptr, tBTM_STATUS::BTM_BUSY);
296   device->p_encrypt_cback = BTA_DM_ENCRYPT_CBACK;
297   bta_dm_encrypt_cback(kRawAddress, transport, nullptr, tBTM_STATUS::BTM_ILLEGAL_VALUE);
298 
299   ASSERT_EQ(5UL, BTA_DM_ENCRYPT_CBACK_queue.size());
300 
301   auto params_BTM_SUCCESS = BTA_DM_ENCRYPT_CBACK_queue.front();
302   BTA_DM_ENCRYPT_CBACK_queue.pop();
303   ASSERT_EQ(BTA_SUCCESS, params_BTM_SUCCESS.result);
304   auto params_BTM_WRONG_MODE = BTA_DM_ENCRYPT_CBACK_queue.front();
305   BTA_DM_ENCRYPT_CBACK_queue.pop();
306   ASSERT_EQ(BTA_WRONG_MODE, params_BTM_WRONG_MODE.result);
307   auto params_BTM_NO_RESOURCES = BTA_DM_ENCRYPT_CBACK_queue.front();
308   BTA_DM_ENCRYPT_CBACK_queue.pop();
309   ASSERT_EQ(BTA_NO_RESOURCES, params_BTM_NO_RESOURCES.result);
310   auto params_BTM_BUSY = BTA_DM_ENCRYPT_CBACK_queue.front();
311   BTA_DM_ENCRYPT_CBACK_queue.pop();
312   ASSERT_EQ(BTA_BUSY, params_BTM_BUSY.result);
313   auto params_BTM_ILLEGAL_VALUE = BTA_DM_ENCRYPT_CBACK_queue.front();
314   BTA_DM_ENCRYPT_CBACK_queue.pop();
315   ASSERT_EQ(BTA_FAILURE, params_BTM_ILLEGAL_VALUE.result);
316 }
317 
TEST_F(BtaDmTest,bta_dm_remname_cback__typical)318 TEST_F(BtaDmTest, bta_dm_remname_cback__typical) {
319   tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb();
320   search_cb.peer_bdaddr = kRawAddress;
321   search_cb.name_discover_done = false;
322 
323   tBTM_REMOTE_DEV_NAME name = {
324           .bd_addr = kRawAddress,
325           .remote_bd_name = {},
326           .btm_status = tBTM_STATUS::BTM_SUCCESS,
327           .hci_status = HCI_SUCCESS,
328   };
329   bd_name_from_char_pointer(name.remote_bd_name, kRemoteName);
330 
331   bluetooth::legacy::testing::bta_dm_remname_cback(&name);
332 
333   sync_main_handler();
334 
335   ASSERT_TRUE(bluetooth::legacy::testing::bta_dm_disc_search_cb().name_discover_done);
336 }
337 
TEST_F(BtaDmTest,bta_dm_remname_cback__wrong_address)338 TEST_F(BtaDmTest, bta_dm_remname_cback__wrong_address) {
339   tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb();
340   search_cb.p_device_search_cback = nullptr;
341   search_cb.peer_bdaddr = kRawAddress;
342   search_cb.name_discover_done = false;
343 
344   tBTM_REMOTE_DEV_NAME name = {
345           .bd_addr = kRawAddress2,
346           .remote_bd_name = {},
347           .btm_status = tBTM_STATUS::BTM_SUCCESS,
348           .hci_status = HCI_SUCCESS,
349   };
350   bd_name_from_char_pointer(name.remote_bd_name, kRemoteName);
351 
352   bluetooth::legacy::testing::bta_dm_remname_cback(&name);
353 
354   sync_main_handler();
355 }
356 
TEST_F(BtaDmTest,bta_dm_remname_cback__HCI_ERR_CONNECTION_EXISTS)357 TEST_F(BtaDmTest, bta_dm_remname_cback__HCI_ERR_CONNECTION_EXISTS) {
358   tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb();
359   search_cb.peer_bdaddr = kRawAddress;
360   search_cb.name_discover_done = false;
361 
362   tBTM_REMOTE_DEV_NAME name = {
363           .bd_addr = RawAddress::kEmpty,
364           .remote_bd_name = {},
365           .btm_status = tBTM_STATUS::BTM_SUCCESS,
366           .hci_status = HCI_ERR_CONNECTION_EXISTS,
367   };
368   bd_name_from_char_pointer(name.remote_bd_name, kRemoteName);
369 
370   bluetooth::legacy::testing::bta_dm_remname_cback(&name);
371 
372   sync_main_handler();
373 
374   ASSERT_TRUE(bluetooth::legacy::testing::bta_dm_disc_search_cb().name_discover_done);
375 }
376 
TEST_F(BtaDmTest,bta_dm_determine_discovery_transport__BR_EDR)377 TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BR_EDR) {
378   tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb();
379 
380   mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& /*remote_bda*/,
381                                                       tBT_DEVICE_TYPE* p_dev_type,
382                                                       tBLE_ADDR_TYPE* p_addr_type) {
383     *p_dev_type = BT_DEVICE_TYPE_BREDR;
384     *p_addr_type = BLE_ADDR_PUBLIC;
385   };
386 
387   ASSERT_EQ(BT_TRANSPORT_BR_EDR,
388             bluetooth::legacy::testing::bta_dm_determine_discovery_transport(kRawAddress));
389 }
390 
TEST_F(BtaDmTest,bta_dm_determine_discovery_transport__BLE__PUBLIC)391 TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__BLE__PUBLIC) {
392   tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb();
393 
394   mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& /*remote_bda*/,
395                                                       tBT_DEVICE_TYPE* p_dev_type,
396                                                       tBLE_ADDR_TYPE* p_addr_type) {
397     *p_dev_type = BT_DEVICE_TYPE_BLE;
398     *p_addr_type = BLE_ADDR_PUBLIC;
399   };
400 
401   ASSERT_EQ(BT_TRANSPORT_LE,
402             bluetooth::legacy::testing::bta_dm_determine_discovery_transport(kRawAddress));
403 }
404 
TEST_F(BtaDmTest,bta_dm_determine_discovery_transport__DUMO)405 TEST_F(BtaDmTest, bta_dm_determine_discovery_transport__DUMO) {
406   tBTA_DM_SEARCH_CB& search_cb = bluetooth::legacy::testing::bta_dm_disc_search_cb();
407 
408   mock_btm_client_interface.peer.BTM_ReadDevInfo = [](const RawAddress& /*remote_bda*/,
409                                                       tBT_DEVICE_TYPE* p_dev_type,
410                                                       tBLE_ADDR_TYPE* p_addr_type) {
411     *p_dev_type = BT_DEVICE_TYPE_DUMO;
412     *p_addr_type = BLE_ADDR_PUBLIC;
413   };
414 
415   ASSERT_EQ(BT_TRANSPORT_BR_EDR,
416             bluetooth::legacy::testing::bta_dm_determine_discovery_transport(kRawAddress));
417 }
418 
TEST_F(BtaDmTest,bta_dm_search_evt_text)419 TEST_F(BtaDmTest, bta_dm_search_evt_text) {
420   std::vector<std::pair<tBTA_DM_SEARCH_EVT, std::string>> events = {
421           std::make_pair(BTA_DM_INQ_RES_EVT, "BTA_DM_INQ_RES_EVT"),
422           std::make_pair(BTA_DM_INQ_CMPL_EVT, "BTA_DM_INQ_CMPL_EVT"),
423           std::make_pair(BTA_DM_DISC_CMPL_EVT, "BTA_DM_DISC_CMPL_EVT"),
424           std::make_pair(BTA_DM_SEARCH_CANCEL_CMPL_EVT, "BTA_DM_SEARCH_CANCEL_CMPL_EVT"),
425           std::make_pair(BTA_DM_NAME_READ_EVT, "BTA_DM_NAME_READ_EVT"),
426   };
427   for (const auto& event : events) {
428     ASSERT_STREQ(event.second.c_str(), bta_dm_search_evt_text(event.first).c_str());
429   }
430   ASSERT_STREQ(std::format("UNKNOWN[{}]", std::numeric_limits<uint8_t>::max()).c_str(),
431                bta_dm_search_evt_text(
432                        static_cast<tBTA_DM_SEARCH_EVT>(std::numeric_limits<uint8_t>::max()))
433                        .c_str());
434 }
435 
TEST_F(BtaDmTest,bta_dm_remote_name_cmpl)436 TEST_F(BtaDmTest, bta_dm_remote_name_cmpl) {
437   reset_mock_btm_client_interface();
438   mock_btm_client_interface.db.BTM_InqDbRead = [](const RawAddress& /*bd_addr*/) -> tBTM_INQ_INFO* {
439     inc_func_call_count("BTM_InqDbRead");
440     return nullptr;
441   };
442   tBTA_DM_REMOTE_NAME remote_name_msg{
443           // tBTA_DM_REMOTE_NAME
444           .bd_addr = kRawAddress,
445           .bd_name = {0},
446           .hci_status = HCI_SUCCESS,
447   };
448   bluetooth::legacy::testing::bta_dm_remote_name_cmpl(remote_name_msg);
449   ASSERT_EQ(1, get_func_call_count("BTM_InqDbRead"));
450 }
451 
TEST_F(BtaDmTest,bta_dm_disc_start__true)452 TEST_F(BtaDmTest, bta_dm_disc_start__true) { bta_dm_disc_start(true); }
TEST_F(BtaDmTest,bta_dm_disc_start__false)453 TEST_F(BtaDmTest, bta_dm_disc_start__false) { bta_dm_disc_start(false); }
454 
TEST_F(BtaDmTest,bta_dm_disc_stop)455 TEST_F(BtaDmTest, bta_dm_disc_stop) { bta_dm_disc_stop(); }
456 
TEST_F(BtaDmCustomAlarmTest,bta_dm_sniff_cback)457 TEST_F(BtaDmCustomAlarmTest, bta_dm_sniff_cback) {
458   // Setup a connected device
459   const tBT_TRANSPORT transport{BT_TRANSPORT_BR_EDR};
460   tBTA_DM_PEER_DEVICE* device =
461           bluetooth::legacy::testing::allocate_device_for(kRawAddress, transport);
462   ASSERT_TRUE(device != nullptr);
463 
464   // Trigger a sniff timer
465   bta_dm_pm_start_timer(&bta_dm_cb.pm_timer[0], bta_pm_action_to_timer_idx(BTA_DM_PM_SNIFF), 10, 1,
466                         BTA_DM_PM_SNIFF);
467   bta_dm_cb.pm_timer[0].peer_bdaddr = kRawAddress;
468   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
469 
470   // Trigger reset sniff
471   bta_dm_sniff_cback(BTA_ID_JV, 1, kRawAddress);
472   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
473   ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
474 }
475 
TEST_F(BtaDmCustomAlarmTest,sniff_offload_feature__test_sysprop)476 TEST_F(BtaDmCustomAlarmTest, sniff_offload_feature__test_sysprop) {
477   bool is_property_enabled = true;
478   test::mock::osi_properties::osi_property_get_bool.body =
479           [&](const char* /*key*/, bool /*default_value*/) -> int { return is_property_enabled; };
480 
481   // Expect not to trigger bta_dm_init_pm due to sysprop enabled
482   // and reset the value of .srvc_id.
483   is_property_enabled = true;
484   bluetooth::legacy::testing::BTA_dm_on_hw_on();
485   ASSERT_EQ(0, bta_dm_cb.pm_timer[0].srvc_id[0]);
486 
487   // Expect to trigger bta_dm_init_pm and init the value of .srvc_id to
488   // BTA_ID_MAX due to sysprop disabled.
489   is_property_enabled = false;
490   bluetooth::legacy::testing::BTA_dm_on_hw_on();
491   ASSERT_EQ((uint8_t)BTA_ID_MAX, bta_dm_cb.pm_timer[0].srvc_id[0]);
492 
493   // Shouldn't crash even there's no active timer when calling
494   // bta_dm_disable_pm.
495   bta_dm_cb.pm_timer[0].in_use = false;
496   bta_dm_cb.pm_timer[0].srvc_id[0] = kUnusedTimer;
497   bta_dm_disable_pm();
498 }
499