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::legacy::testing {
45 void set_interface_to_profiles(bluetooth::core::CoreInterface* interfaceToProfiles);
46 } // namespace bluetooth::legacy::testing
47
48 namespace {
49 constexpr tBTM_BLE_TX_TIME_MS tx_time = 0x12345678;
50 constexpr tBTM_BLE_RX_TIME_MS rx_time = 0x87654321;
51 constexpr tBTM_BLE_IDLE_TIME_MS idle_time = 0x2468acd0;
52 constexpr tBTM_BLE_ENERGY_USED energy_used = 0x13579bdf;
53 } // namespace
54
55 class BtifDmWithMocksTest : public ::testing::Test {
56 protected:
SetUp()57 void SetUp() override { fake_osi_ = std::make_unique<test::fake::FakeOsi>(); }
58
TearDown()59 void TearDown() override { fake_osi_.reset(); }
60
61 std::unique_ptr<test::fake::FakeOsi> fake_osi_;
62 };
63
64 class BtifDmTest : public BtifDmWithMocksTest {
65 protected:
SetUp()66 void SetUp() override {
67 BtifDmWithMocksTest::SetUp();
68 mock_core_interface_ = std::make_unique<MockCoreInterface>();
69 bluetooth::legacy::testing::set_interface_to_profiles(mock_core_interface_.get());
70 }
71
TearDown()72 void TearDown() override {
73 bluetooth::legacy::testing::set_interface_to_profiles(nullptr);
74 mock_core_interface_.reset();
75 BtifDmWithMocksTest::TearDown();
76 }
77
78 std::unique_ptr<MockCoreInterface> mock_core_interface_;
79 };
80
TEST_F(BtifDmTest,bta_energy_info_cb__with_no_uid)81 TEST_F(BtifDmTest, bta_energy_info_cb__with_no_uid) {
82 static bool invoke_energy_info_cb_entered = false;
83 bluetooth::core::testing::mock_event_callbacks.invoke_energy_info_cb =
84 [](bt_activity_energy_info /* energy_info */, bt_uid_traffic_t* /* uid_data */) {
85 invoke_energy_info_cb_entered = true;
86 };
87
88 bluetooth::legacy::testing::bta_energy_info_cb(tx_time, rx_time, idle_time, energy_used,
89 BTM_CONTRL_UNKNOWN, BTA_SUCCESS);
90
91 ASSERT_FALSE(invoke_energy_info_cb_entered);
92 }
93
94 class BtifDmWithUidTest : public BtifDmTest {
95 protected:
SetUp()96 void SetUp() override {
97 BtifDmTest::SetUp();
98 btif_dm_init(uid_set_create());
99 }
100
TearDown()101 void TearDown() override {
102 btif_dm_cleanup();
103 BtifDmTest::TearDown();
104 }
105 };
106
TEST_F(BtifDmWithUidTest,bta_energy_info_cb__with_uid)107 TEST_F(BtifDmWithUidTest, bta_energy_info_cb__with_uid) {
108 static bool invoke_energy_info_cb_entered = false;
109 bluetooth::core::testing::mock_event_callbacks.invoke_energy_info_cb =
110 [](bt_activity_energy_info /* energy_info */, bt_uid_traffic_t* /* uid_data */) {
111 invoke_energy_info_cb_entered = true;
112 };
113 bluetooth::legacy::testing::bta_energy_info_cb(tx_time, rx_time, idle_time, energy_used,
114 BTM_CONTRL_UNKNOWN, BTA_SUCCESS);
115
116 ASSERT_TRUE(invoke_energy_info_cb_entered);
117 }
118
119 class BtifDmWithStackTest : public BtifDmTest {
120 protected:
SetUp()121 void SetUp() override {
122 BtifDmTest::SetUp();
123 modules_.add<bluetooth::storage::StorageModule>();
124 bluetooth::shim::Stack::GetInstance()->StartModuleStack(
125 &modules_,
126 new bluetooth::os::Thread("gd_stack_thread", bluetooth::os::Thread::Priority::NORMAL));
127 }
128
TearDown()129 void TearDown() override {
130 bluetooth::shim::Stack::GetInstance()->Stop();
131 BtifDmTest::TearDown();
132 }
133 bluetooth::ModuleList modules_;
134 };
135
TEST_F_WITH_FLAGS(BtifDmWithStackTest,btif_dm_search_services_evt__BTA_DM_NAME_READ_EVT)136 TEST_F_WITH_FLAGS(BtifDmWithStackTest, btif_dm_search_services_evt__BTA_DM_NAME_READ_EVT) {
137 static struct {
138 bt_status_t status;
139 RawAddress bd_addr;
140 int num_properties;
141 std::vector<bt_property_t> properties;
142 } invoke_remote_device_properties_cb{
143 .status = BT_STATUS_NOT_READY,
144 .bd_addr = RawAddress::kEmpty,
145 .num_properties = -1,
146 .properties = {},
147 };
148
149 bluetooth::core::testing::mock_event_callbacks.invoke_remote_device_properties_cb =
150 [](bt_status_t status, RawAddress bd_addr, int num_properties,
151 bt_property_t* properties) {
152 invoke_remote_device_properties_cb = {
153 .status = status,
154 .bd_addr = bd_addr,
155 .num_properties = num_properties,
156 .properties = std::vector<bt_property_t>(properties,
157 properties + (size_t)num_properties),
158 };
159 };
160
161 BD_NAME bd_name;
162 bd_name_from_char_pointer(bd_name, kBdName);
163
164 bluetooth::legacy::testing::btif_on_name_read(kRawAddress, HCI_SUCCESS, bd_name, true);
165
166 ASSERT_EQ(BT_STATUS_SUCCESS, invoke_remote_device_properties_cb.status);
167 ASSERT_EQ(kRawAddress, invoke_remote_device_properties_cb.bd_addr);
168 ASSERT_EQ(1, invoke_remote_device_properties_cb.num_properties);
169 ASSERT_EQ(BT_PROPERTY_BDNAME, invoke_remote_device_properties_cb.properties[0].type);
170 ASSERT_EQ((int)strlen(kBdName), invoke_remote_device_properties_cb.properties[0].len);
171 ASSERT_STREQ(kBdName, (const char*)invoke_remote_device_properties_cb.properties[0].val);
172 }
173
TEST_F(BtifDmWithStackTest,btif_dm_get_local_class_of_device__default)174 TEST_F(BtifDmWithStackTest, btif_dm_get_local_class_of_device__default) {
175 DEV_CLASS dev_class = btif_dm_get_local_class_of_device();
176 ASSERT_EQ(dev_class, kDevClassUnclassified);
177 }
178
179 std::string kClassOfDeviceText = "1,2,3";
180 DEV_CLASS kClassOfDevice = {1, 2, 3};
TEST_F(BtifDmWithStackTest,btif_dm_get_local_class_of_device__with_property)181 TEST_F(BtifDmWithStackTest, btif_dm_get_local_class_of_device__with_property) {
182 test::mock::osi_properties::osi_property_get.body = [](const char* /* key */, char* value,
183 const char* /* default_value */) {
184 std::copy(kClassOfDeviceText.begin(), kClassOfDeviceText.end(), value);
185 return kClassOfDeviceText.size();
186 };
187
188 DEV_CLASS dev_class = btif_dm_get_local_class_of_device();
189 if (dev_class != kClassOfDevice) {
190 // If BAP is enabled, an extra bit gets set.
191 DEV_CLASS dev_class_with_bap = kClassOfDevice;
192 dev_class_with_bap[1] |= 0x01 << 6;
193 ASSERT_EQ(dev_class, dev_class_with_bap);
194 }
195 test::mock::osi_properties::osi_property_get = {};
196 }
197