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