1 /*
2 * Copyright 2024 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 <bluetooth/log.h>
18 #include <com_android_bluetooth_flags.h>
19 #include <flag_macros.h>
20 #include <gtest/gtest.h>
21 #include <stdlib.h>
22
23 #include <cstdint>
24
25 #include "gd/os/rand.h"
26 #include "os/log.h"
27 #include "osi/include/allocator.h"
28 #include "stack/include/bt_hdr.h"
29 #include "stack/include/bt_uuid16.h"
30 #include "stack/include/sdp_api.h"
31 #include "stack/sdp/sdp_discovery_db.h"
32 #include "stack/sdp/sdpint.h"
33 #include "stack/test/sdp/sdp_packet00.h"
34 #include "test/common/mock_functions.h"
35 #include "test/fake/fake_osi.h"
36 #include "test/mock/mock_osi_allocator.h"
37 #include "test/mock/mock_stack_l2cap_api.h"
38
39 constexpr uint32_t kBtDefaultBufferSize =
40 static_cast<uint32_t>(BT_DEFAULT_BUFFER_SIZE);
41
42 #define TEST_BT com::android::bluetooth::flags
43
44 using bluetooth::legacy::stack::sdp::get_legacy_stack_sdp_api;
45
46 namespace {
47
48 const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
49 constexpr size_t kSdpDbSize = BTA_DM_SDP_DB_SIZE * 16;
50 constexpr size_t kSdpPacketStartOffset = 9;
51 int L2CA_ConnectReqWithSecurity_cid = 0x42;
52
53 class StackSdpParserWithMocksTest : public ::testing::Test {
54 protected:
SetUp()55 void SetUp() override {
56 reset_mock_function_count_map();
57 fake_osi_ = std::make_unique<test::fake::FakeOsi>();
58 test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity.body =
59 [](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
60 uint16_t /* sec_level */) {
61 return ++L2CA_ConnectReqWithSecurity_cid;
62 };
63 test::mock::stack_l2cap_api::L2CA_DataWrite.body = [](uint16_t /* cid */,
64 BT_HDR* p_data) {
65 osi_free_and_reset((void**)&p_data);
66 return 0;
67 };
68 test::mock::stack_l2cap_api::L2CA_DisconnectReq.body =
69 [](uint16_t /* cid */) { return true; };
70 test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity.body =
71 [](uint16_t psm, const tL2CAP_APPL_INFO& /* p_cb_info */,
72 bool /* enable_snoop */, tL2CAP_ERTM_INFO* /* p_ertm_info */,
73 uint16_t /* my_mtu */, uint16_t /* required_remote_mtu */,
74 uint16_t /* sec_level */) { return psm; };
75 }
76
TearDown()77 void TearDown() override {
78 test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity = {};
79 test::mock::stack_l2cap_api::L2CA_DisconnectReq = {};
80 test::mock::stack_l2cap_api::L2CA_DataWrite = {};
81 test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity = {};
82 fake_osi_.reset();
83 }
84
85 std::unique_ptr<test::fake::FakeOsi> fake_osi_;
86 };
87
88 class StackSdpParserInitTest : public StackSdpParserWithMocksTest {
89 protected:
SetUp()90 void SetUp() override {
91 StackSdpParserWithMocksTest::SetUp();
92 sdp_init();
93 p_db_ = (tSDP_DISCOVERY_DB*)osi_malloc(kSdpDbSize);
94 }
95
TearDown()96 void TearDown() override {
97 osi_free(p_db_);
98 p_db_ = nullptr;
99 sdp_free();
100 StackSdpParserWithMocksTest::TearDown();
101 }
102
103 tSDP_DISCOVERY_DB* p_db_{nullptr};
104 };
105
106 } // namespace
107
TEST_F(StackSdpParserInitTest,SDP_InitDiscoveryDb)108 TEST_F(StackSdpParserInitTest, SDP_InitDiscoveryDb) {
109 bluetooth::Uuid uuid;
110 const bool success = get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
111 p_db_, kBtDefaultBufferSize, 1, &uuid, 0, nullptr);
112 ASSERT_TRUE(success);
113
114 ASSERT_TRUE(get_legacy_stack_sdp_api()->service.SDP_ServiceSearchRequest(
115 kRawAddress, p_db_,
116 [](const RawAddress& /* bd_addr */, tSDP_RESULT /* result */) {}));
117 }
118
119 class StackSdpAsClientParseTest : public StackSdpParserInitTest {
120 protected:
SetUp()121 void SetUp() override {
122 StackSdpParserInitTest::SetUp();
123 ASSERT_TRUE(get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
124 p_db_, kSdpDbSize, 1, p_uuid_list, 0, nullptr));
125 ASSERT_TRUE(get_legacy_stack_sdp_api()->service.SDP_ServiceSearchRequest(
126 kRawAddress, p_db_,
127 [](const RawAddress& /* bd_addr */, tSDP_RESULT /* result */) {}));
128
129 // Fast forward to to accept SDP responses as originator
130 p_ccb_ = sdpu_find_ccb_by_db(p_db_);
131 ASSERT_NE(nullptr, p_ccb_);
132 p_ccb_->disc_state = SDP_DISC_WAIT_SEARCH_ATTR;
133 p_ccb_->con_state = SDP_STATE_CONNECTED;
134 p_ccb_->con_flags = SDP_FLAGS_IS_ORIG;
135 }
136
TearDown()137 void TearDown() override {
138 sdpu_release_ccb(*p_ccb_);
139 StackSdpParserInitTest::TearDown();
140 }
141
142 tCONN_CB* p_ccb_{nullptr};
143 const bluetooth::Uuid p_uuid_list[1]{
144 bluetooth::Uuid::From128BitBE(
145 bluetooth::os::GenerateRandom<bluetooth::Uuid::kNumBytes128>()),
146 };
147
parse_sdp_responses(const bluetooth::testing::raw_packet_t * pkts,size_t num_pkts)148 void parse_sdp_responses(const bluetooth::testing::raw_packet_t* pkts,
149 size_t num_pkts) {
150 for (size_t i = 0; i < num_pkts; i++) {
151 const bluetooth::testing::raw_packet_t* pkt = &pkts[i];
152 char* data = (char*)osi_malloc(pkt->len + sizeof(BT_HDR));
153 BT_HDR* bt_hdr = (BT_HDR*)data;
154 *bt_hdr = {
155 .event = 0,
156 .len = (uint16_t)pkt->len,
157 .offset = 0,
158 .layer_specific = 0,
159 };
160 uint8_t* payload = (uint8_t*)(bt_hdr + 1);
161 memcpy(payload, (const void*)(pkt->data + kSdpPacketStartOffset),
162 pkt->len - kSdpPacketStartOffset);
163 sdp_disc_server_rsp(p_ccb_, bt_hdr);
164 osi_free(data);
165 bluetooth::log::info("i:{} L2CA_DisconnectReq:{}", i,
166 get_func_call_count("L2CA_DisconnectReq"));
167 }
168 }
169 };
170
TEST_F(StackSdpAsClientParseTest,nop)171 TEST_F(StackSdpAsClientParseTest, nop) {}
172
TEST_F_WITH_FLAGS(StackSdpAsClientParseTest,sdp_disc_server_rsp_packets00,REQUIRES_FLAGS_DISABLED (ACONFIG_FLAG (TEST_BT,stack_sdp_detect_nil_property_type)))173 TEST_F_WITH_FLAGS(StackSdpAsClientParseTest, sdp_disc_server_rsp_packets00,
174 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(
175 TEST_BT, stack_sdp_detect_nil_property_type))) {
176 parse_sdp_responses(bluetooth::testing::stack::sdp::packets00::rx_pkts,
177 bluetooth::testing::stack::sdp::packets00::kNumRxPkts);
178
179 ASSERT_EQ(1U, sdp_get_num_records(*p_db_));
180
181 tSDP_DISC_REC* p_sdp_rec = p_db_->p_first_rec;
182 ASSERT_NE(nullptr, p_sdp_rec);
183 ASSERT_EQ(6U, sdp_get_num_attributes(*p_sdp_rec));
184
185 // Service Record Handle
186 ASSERT_EQ(0x00010009U,
187 get_legacy_stack_sdp_api()
188 ->record
189 .SDP_FindAttributeInRec(p_sdp_rec, ATTR_ID_SERVICE_RECORD_HDL)
190 ->attr_value.v.u32);
191
192 // Service Class ID List
193 p_sdp_rec = p_db_->p_first_rec;
194 p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb_128bit(
195 p_db_, p_sdp_rec);
196 // ASSERT_NE(nullptr, p_sdp_rec);
197 auto uuid_list = std::vector<bluetooth::Uuid>(1);
198 p_sdp_rec = p_db_->p_first_rec;
199 ASSERT_EQ(true,
200 get_legacy_stack_sdp_api()->record.SDP_FindServiceUUIDInRec_128bit(
201 p_sdp_rec, &uuid_list[0]));
202 ASSERT_EQ(1U, uuid_list.size());
203 ASSERT_STREQ("4de17a00-52cb-11e6-bdf4-0800200c9a66",
204 uuid_list.front().ToString().c_str());
205
206 // Service Record State
207 ASSERT_EQ(0x008f5162U,
208 get_legacy_stack_sdp_api()
209 ->record
210 .SDP_FindAttributeInRec(p_sdp_rec, ATTR_ID_SERVICE_RECORD_STATE)
211 ->attr_value.v.u32);
212
213 // Protocol Descriptor List
214 tSDP_PROTOCOL_ELEM pe;
215 ASSERT_EQ(true,
216 get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
217 p_sdp_rec, UUID_PROTOCOL_L2CAP, &pe));
218 ASSERT_EQ(UUID_PROTOCOL_L2CAP, pe.protocol_uuid);
219 ASSERT_EQ(0U, pe.num_params);
220
221 ASSERT_EQ(true,
222 get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
223 p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe));
224 ASSERT_EQ(UUID_PROTOCOL_RFCOMM, pe.protocol_uuid);
225 ASSERT_EQ(1U, pe.num_params);
226 ASSERT_EQ(UUID_PROTOCOL_RFCOMM, pe.params[0]);
227
228 // Browse Group List
229 ASSERT_NE(nullptr, get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(
230 p_sdp_rec, ATTR_ID_BROWSE_GROUP_LIST));
231
232 // Bluetooth Profile List
233 ASSERT_NE(nullptr, get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(
234 p_sdp_rec, ATTR_ID_BT_PROFILE_DESC_LIST));
235
236 // Service Name
237 ASSERT_EQ(
238 nullptr,
239 (const char*)get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(
240 p_sdp_rec, ATTR_ID_SERVICE_NAME));
241 }
242
TEST_F_WITH_FLAGS(StackSdpAsClientParseTest,sdp_disc_server_rsp_packets00b,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,stack_sdp_detect_nil_property_type)))243 TEST_F_WITH_FLAGS(StackSdpAsClientParseTest, sdp_disc_server_rsp_packets00b,
244 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
245 TEST_BT, stack_sdp_detect_nil_property_type))) {
246 parse_sdp_responses(bluetooth::testing::stack::sdp::packets00::rx_pkts,
247 bluetooth::testing::stack::sdp::packets00::kNumRxPkts);
248
249 ASSERT_EQ(1U, sdp_get_num_records(*p_db_));
250
251 tSDP_DISC_REC* p_sdp_rec = p_db_->p_first_rec;
252 ASSERT_NE(nullptr, p_sdp_rec);
253 ASSERT_EQ(7U, sdp_get_num_attributes(*p_sdp_rec));
254 }
255