1 /*
2  * Copyright 2023 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 "btif/include/btif_dm.h"
18 
19 #include <com_android_bluetooth_flags.h>
20 #include <flag_macros.h>
21 #include <gtest/gtest.h>
22 
23 #include <memory>
24 
25 #include "bta/include/bta_api_data_types.h"
26 #include "btif/include/btif_dm.h"
27 #include "btif/include/mock_core_callbacks.h"
28 #include "main/shim/stack.h"
29 #include "module.h"
30 #include "stack/include/bt_dev_class.h"
31 #include "stack/include/btm_ble_api_types.h"
32 #include "storage/storage_module.h"
33 #include "test/fake/fake_osi.h"
34 #include "test/mock/mock_osi_properties.h"
35 
36 using bluetooth::core::testing::MockCoreInterface;
37 using ::testing::ElementsAre;
38 
39 namespace {
40 const RawAddress kRawAddress = {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
41 constexpr char kBdName[] = {'k', 'B', 'd', 'N', 'a', 'm', 'e', '\0'};
42 }  // namespace
43 
44 namespace bluetooth {
45 namespace legacy {
46 namespace testing {
47 
48 void set_interface_to_profiles(
49     bluetooth::core::CoreInterface* interfaceToProfiles);
50 
51 void bta_energy_info_cb(tBTM_BLE_TX_TIME_MS tx_time,
52                         tBTM_BLE_RX_TIME_MS rx_time,
53                         tBTM_BLE_IDLE_TIME_MS idle_time,
54                         tBTM_BLE_ENERGY_USED energy_used,
55                         tBTM_CONTRL_STATE ctrl_state, tBTA_STATUS status);
56 
57 void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status,
58                        const BD_NAME bd_name, bool during_device_search);
59 
60 }  // namespace testing
61 }  // namespace legacy
62 }  // namespace bluetooth
63 
64 namespace {
65 constexpr tBTM_BLE_TX_TIME_MS tx_time = 0x12345678;
66 constexpr tBTM_BLE_RX_TIME_MS rx_time = 0x87654321;
67 constexpr tBTM_BLE_IDLE_TIME_MS idle_time = 0x2468acd0;
68 constexpr tBTM_BLE_ENERGY_USED energy_used = 0x13579bdf;
69 }  // namespace
70 
71 class BtifDmWithMocksTest : public ::testing::Test {
72  protected:
SetUp()73   void SetUp() override { fake_osi_ = std::make_unique<test::fake::FakeOsi>(); }
74 
TearDown()75   void TearDown() override { fake_osi_.reset(); }
76 
77   std::unique_ptr<test::fake::FakeOsi> fake_osi_;
78 };
79 
80 class BtifDmTest : public BtifDmWithMocksTest {
81  protected:
SetUp()82   void SetUp() override {
83     BtifDmWithMocksTest::SetUp();
84     mock_core_interface_ = std::make_unique<MockCoreInterface>();
85     bluetooth::legacy::testing::set_interface_to_profiles(
86         mock_core_interface_.get());
87   }
88 
TearDown()89   void TearDown() override {
90     bluetooth::legacy::testing::set_interface_to_profiles(nullptr);
91     mock_core_interface_.reset();
92     BtifDmWithMocksTest::TearDown();
93   }
94 
95   std::unique_ptr<MockCoreInterface> mock_core_interface_;
96 };
97 
TEST_F(BtifDmTest,bta_energy_info_cb__with_no_uid)98 TEST_F(BtifDmTest, bta_energy_info_cb__with_no_uid) {
99   static bool invoke_energy_info_cb_entered = false;
100   bluetooth::core::testing::mock_event_callbacks.invoke_energy_info_cb =
101       [](bt_activity_energy_info /* energy_info */,
102          bt_uid_traffic_t* /* uid_data */) {
103         invoke_energy_info_cb_entered = true;
104       };
105 
106   bluetooth::legacy::testing::bta_energy_info_cb(
107       tx_time, rx_time, idle_time, energy_used, BTM_CONTRL_UNKNOWN,
108       BTA_SUCCESS);
109 
110   ASSERT_FALSE(invoke_energy_info_cb_entered);
111 }
112 
113 class BtifDmWithUidTest : public BtifDmTest {
114  protected:
SetUp()115   void SetUp() override {
116     BtifDmTest::SetUp();
117     btif_dm_init(uid_set_create());
118   }
119 
TearDown()120   void TearDown() override {
121     btif_dm_cleanup();
122     BtifDmTest::TearDown();
123   }
124 };
125 
TEST_F(BtifDmWithUidTest,bta_energy_info_cb__with_uid)126 TEST_F(BtifDmWithUidTest, bta_energy_info_cb__with_uid) {
127   static bool invoke_energy_info_cb_entered = false;
128   bluetooth::core::testing::mock_event_callbacks.invoke_energy_info_cb =
129       [](bt_activity_energy_info /* energy_info */,
130          bt_uid_traffic_t* /* uid_data */) {
131         invoke_energy_info_cb_entered = true;
132       };
133   bluetooth::legacy::testing::bta_energy_info_cb(
134       tx_time, rx_time, idle_time, energy_used, BTM_CONTRL_UNKNOWN,
135       BTA_SUCCESS);
136 
137   ASSERT_TRUE(invoke_energy_info_cb_entered);
138 }
139 
140 class BtifDmWithStackTest : public BtifDmTest {
141  protected:
SetUp()142   void SetUp() override {
143     BtifDmTest::SetUp();
144     modules_.add<bluetooth::storage::StorageModule>();
145     bluetooth::shim::Stack::GetInstance()->StartModuleStack(
146         &modules_,
147         new bluetooth::os::Thread("gd_stack_thread",
148                                   bluetooth::os::Thread::Priority::NORMAL));
149   }
150 
TearDown()151   void TearDown() override {
152     bluetooth::shim::Stack::GetInstance()->Stop();
153     BtifDmTest::TearDown();
154   }
155   bluetooth::ModuleList modules_;
156 };
157 
158 #define MY_PACKAGE com::android::bluetooth::flags
159 
TEST_F_WITH_FLAGS(BtifDmWithStackTest,btif_dm_search_services_evt__BTA_DM_NAME_READ_EVT,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (MY_PACKAGE,rnr_present_during_service_discovery)))160 TEST_F_WITH_FLAGS(BtifDmWithStackTest,
161                   btif_dm_search_services_evt__BTA_DM_NAME_READ_EVT,
162                   REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
163                       MY_PACKAGE, rnr_present_during_service_discovery))) {
164   static struct {
165     bt_status_t status;
166     RawAddress bd_addr;
167     int num_properties;
168     std::vector<bt_property_t> properties;
169   } invoke_remote_device_properties_cb{
170       .status = BT_STATUS_NOT_READY,
171       .bd_addr = RawAddress::kEmpty,
172       .num_properties = -1,
173       .properties = {},
174   };
175 
176   bluetooth::core::testing::mock_event_callbacks
177       .invoke_remote_device_properties_cb =
178       [](bt_status_t status, RawAddress bd_addr, int num_properties,
179          bt_property_t* properties) {
180         invoke_remote_device_properties_cb = {
181             .status = status,
182             .bd_addr = bd_addr,
183             .num_properties = num_properties,
184             .properties = std::vector<bt_property_t>(
185                 properties, properties + (size_t)num_properties),
186         };
187       };
188 
189   BD_NAME bd_name;
190   bd_name_from_char_pointer(bd_name, kBdName);
191 
192   bluetooth::legacy::testing::btif_on_name_read(kRawAddress, HCI_SUCCESS,
193                                                 bd_name, true);
194 
195   ASSERT_EQ(BT_STATUS_SUCCESS, invoke_remote_device_properties_cb.status);
196   ASSERT_EQ(kRawAddress, invoke_remote_device_properties_cb.bd_addr);
197   ASSERT_EQ(1, invoke_remote_device_properties_cb.num_properties);
198   ASSERT_EQ(BT_PROPERTY_BDNAME,
199             invoke_remote_device_properties_cb.properties[0].type);
200   ASSERT_EQ((int)strlen(kBdName),
201             invoke_remote_device_properties_cb.properties[0].len);
202   ASSERT_STREQ(
203       kBdName,
204       (const char*)invoke_remote_device_properties_cb.properties[0].val);
205 }
206 
TEST_F(BtifDmWithStackTest,btif_dm_get_local_class_of_device__default)207 TEST_F(BtifDmWithStackTest, btif_dm_get_local_class_of_device__default) {
208   DEV_CLASS dev_class = btif_dm_get_local_class_of_device();
209   ASSERT_EQ(dev_class, kDevClassUnclassified);
210 }
211 
212 std::string kClassOfDeviceText = "1,2,3";
213 DEV_CLASS kClassOfDevice = {1, 2, 3};
TEST_F(BtifDmWithStackTest,btif_dm_get_local_class_of_device__with_property)214 TEST_F(BtifDmWithStackTest, btif_dm_get_local_class_of_device__with_property) {
215   test::mock::osi_properties::osi_property_get.body =
216       [](const char* /* key */, char* value, const char* /* default_value */) {
217         std::copy(kClassOfDeviceText.begin(), kClassOfDeviceText.end(), value);
218         return kClassOfDeviceText.size();
219       };
220 
221   DEV_CLASS dev_class = btif_dm_get_local_class_of_device();
222   if (dev_class != kClassOfDevice) {
223     // If BAP is enabled, an extra bit gets set.
224     DEV_CLASS dev_class_with_bap = kClassOfDevice;
225     dev_class_with_bap[1] |= 0x01 << 6;
226     ASSERT_EQ(dev_class, dev_class_with_bap);
227   }
228   test::mock::osi_properties::osi_property_get = {};
229 }
230