1 /*
2  * Copyright 2022 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 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <stdlib.h>
20 
21 #include <cstddef>
22 
23 #include "osi/include/allocator.h"
24 #include "stack/include/bt_uuid16.h"
25 #include "stack/include/sdpdefs.h"
26 #include "stack/sdp/internal/sdp_api.h"
27 #include "stack/sdp/sdpint.h"
28 #include "test/fake/fake_osi.h"
29 #include "test/mock/mock_osi_allocator.h"
30 #include "test/mock/mock_stack_l2cap_api.h"
31 
32 #ifndef BT_DEFAULT_BUFFER_SIZE
33 #define BT_DEFAULT_BUFFER_SIZE (4096 + 16)
34 #endif
35 
36 namespace {
37 
38 static int L2CA_ConnectReqWithSecurity_cid = 0x42;
39 static RawAddress addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
40 static tSDP_DISCOVERY_DB* sdp_db = nullptr;
41 
42 class StackSdpWithMocksTest : public ::testing::Test {
43  protected:
SetUp()44   void SetUp() override {
45     fake_osi_ = std::make_unique<test::fake::FakeOsi>();
46 
47     test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity.body =
48         [](uint16_t /* psm */, const RawAddress& /* p_bd_addr */,
49            uint16_t /* sec_level */) {
50           return ++L2CA_ConnectReqWithSecurity_cid;
51         };
52     test::mock::stack_l2cap_api::L2CA_DataWrite.body = [](uint16_t /* cid */,
53                                                           BT_HDR* p_data) {
54       osi_free_and_reset((void**)&p_data);
55       return 0;
56     };
57     test::mock::stack_l2cap_api::L2CA_DisconnectReq.body =
58         [](uint16_t /* cid */) { return true; };
59     test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity.body =
60         [](uint16_t psm, const tL2CAP_APPL_INFO& /* p_cb_info */,
61            bool /* enable_snoop */, tL2CAP_ERTM_INFO* /* p_ertm_info */,
62            uint16_t /* my_mtu */, uint16_t /* required_remote_mtu */,
63            uint16_t /* sec_level */) { return psm; };
64   }
65 
TearDown()66   void TearDown() override {
67     test::mock::stack_l2cap_api::L2CA_ConnectReqWithSecurity = {};
68     test::mock::stack_l2cap_api::L2CA_RegisterWithSecurity = {};
69     test::mock::stack_l2cap_api::L2CA_DataWrite = {};
70     test::mock::stack_l2cap_api::L2CA_DisconnectReq = {};
71 
72     fake_osi_.reset();
73   }
74 
75   std::unique_ptr<test::fake::FakeOsi> fake_osi_;
76 };
77 
78 class StackSdpInitTest : public StackSdpWithMocksTest {
79  protected:
SetUp()80   void SetUp() override {
81     StackSdpWithMocksTest::SetUp();
82     sdp_init();
83     sdp_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
84   }
85 
TearDown()86   void TearDown() override {
87     osi_free(sdp_db);
88     sdp_free();
89     StackSdpWithMocksTest::TearDown();
90   }
91 };
92 
93 }  // namespace
94 
TEST_F(StackSdpInitTest,nop)95 TEST_F(StackSdpInitTest, nop) {}
96 
TEST_F(StackSdpInitTest,sdp_service_search_request)97 TEST_F(StackSdpInitTest, sdp_service_search_request) {
98   ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
99   int cid = L2CA_ConnectReqWithSecurity_cid;
100   tCONN_CB* p_ccb = sdpu_find_ccb_by_cid(cid);
101   ASSERT_NE(p_ccb, nullptr);
102   ASSERT_EQ(p_ccb->con_state, SDP_STATE_CONN_SETUP);
103 
104   tL2CAP_CFG_INFO cfg;
105   sdp_cb.reg_info.pL2CA_ConfigCfm_Cb(p_ccb->connection_id, 0, &cfg);
106 
107   ASSERT_EQ(p_ccb->con_state, SDP_STATE_CONNECTED);
108 
109   sdp_disconnect(p_ccb, SDP_SUCCESS);
110   sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb(p_ccb->connection_id, 0);
111 
112   ASSERT_EQ(p_ccb->con_state, SDP_STATE_IDLE);
113 }
114 
find_ccb(uint16_t cid,uint8_t state)115 tCONN_CB* find_ccb(uint16_t cid, uint8_t state) {
116   uint16_t xx;
117   tCONN_CB* p_ccb;
118 
119   // Look through each connection control block
120   for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
121     if ((p_ccb->con_state == state) && (p_ccb->connection_id == cid)) {
122       return p_ccb;
123     }
124   }
125   return nullptr;  // not found
126 }
127 
TEST_F(StackSdpInitTest,sdp_service_search_request_queuing)128 TEST_F(StackSdpInitTest, sdp_service_search_request_queuing) {
129   ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
130   const int cid = L2CA_ConnectReqWithSecurity_cid;
131   tCONN_CB* p_ccb1 = find_ccb(cid, SDP_STATE_CONN_SETUP);
132   ASSERT_NE(p_ccb1, nullptr);
133   ASSERT_EQ(p_ccb1->con_state, SDP_STATE_CONN_SETUP);
134 
135   ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
136   tCONN_CB* p_ccb2 = find_ccb(cid, SDP_STATE_CONN_PEND);
137   ASSERT_NE(p_ccb2, nullptr);
138   ASSERT_NE(p_ccb2, p_ccb1);
139   ASSERT_EQ(p_ccb2->con_state, SDP_STATE_CONN_PEND);
140 
141   tL2CAP_CFG_INFO cfg;
142   sdp_cb.reg_info.pL2CA_ConfigCfm_Cb(p_ccb1->connection_id, 0, &cfg);
143 
144   ASSERT_EQ(p_ccb1->con_state, SDP_STATE_CONNECTED);
145   ASSERT_EQ(p_ccb2->con_state, SDP_STATE_CONN_PEND);
146 
147   p_ccb1->disconnect_reason = SDP_SUCCESS;
148   sdp_disconnect(p_ccb1, SDP_SUCCESS);
149 
150   ASSERT_EQ(p_ccb1->con_state, SDP_STATE_IDLE);
151   ASSERT_EQ(p_ccb2->con_state, SDP_STATE_CONNECTED);
152 
153   sdp_disconnect(p_ccb2, SDP_SUCCESS);
154   sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb(p_ccb2->connection_id, 0);
155 
156   ASSERT_EQ(p_ccb1->con_state, SDP_STATE_IDLE);
157   ASSERT_EQ(p_ccb2->con_state, SDP_STATE_IDLE);
158 }
159 
sdp_callback(const RawAddress &,tSDP_RESULT result)160 void sdp_callback(const RawAddress& /* bd_addr */, tSDP_RESULT result) {
161   if (result == SDP_SUCCESS) {
162     ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, nullptr));
163   }
164 }
165 
TEST_F(StackSdpInitTest,sdp_service_search_request_queuing_race_condition)166 TEST_F(StackSdpInitTest, sdp_service_search_request_queuing_race_condition) {
167   // start first request
168   ASSERT_TRUE(SDP_ServiceSearchRequest(addr, sdp_db, sdp_callback));
169   const int cid1 = L2CA_ConnectReqWithSecurity_cid;
170   tCONN_CB* p_ccb1 = find_ccb(cid1, SDP_STATE_CONN_SETUP);
171   ASSERT_NE(p_ccb1, nullptr);
172   ASSERT_EQ(p_ccb1->con_state, SDP_STATE_CONN_SETUP);
173 
174   tL2CAP_CFG_INFO cfg;
175   sdp_cb.reg_info.pL2CA_ConfigCfm_Cb(p_ccb1->connection_id, 0, &cfg);
176 
177   ASSERT_EQ(p_ccb1->con_state, SDP_STATE_CONNECTED);
178 
179   sdp_disconnect(p_ccb1, SDP_SUCCESS);
180   sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb(p_ccb1->connection_id, 0);
181 
182   const int cid2 = L2CA_ConnectReqWithSecurity_cid;
183   ASSERT_NE(cid1, cid2);  // The callback a queued a new request
184   tCONN_CB* p_ccb2 = find_ccb(cid2, SDP_STATE_CONN_SETUP);
185   ASSERT_NE(p_ccb2, nullptr);
186   // If race condition, this will be stuck in PEND
187   ASSERT_EQ(p_ccb2->con_state, SDP_STATE_CONN_SETUP);
188 
189   sdp_disconnect(p_ccb2, SDP_SUCCESS);
190 }
191 
TEST_F(StackSdpInitTest,sdp_disc_wait_text)192 TEST_F(StackSdpInitTest, sdp_disc_wait_text) {
193   std::vector<std::pair<tSDP_DISC_WAIT, std::string>> states = {
194       std::make_pair(SDP_DISC_WAIT_CONN, "SDP_DISC_WAIT_CONN"),
195       std::make_pair(SDP_DISC_WAIT_HANDLES, "SDP_DISC_WAIT_HANDLES"),
196       std::make_pair(SDP_DISC_WAIT_ATTR, "SDP_DISC_WAIT_ATTR"),
197       std::make_pair(SDP_DISC_WAIT_SEARCH_ATTR, "SDP_DISC_WAIT_SEARCH_ATTR"),
198       std::make_pair(SDP_DISC_WAIT_CANCEL, "SDP_DISC_WAIT_CANCEL"),
199   };
200   for (const auto& state : states) {
201     ASSERT_STREQ(state.second.c_str(), sdp_disc_wait_text(state.first).c_str());
202   }
203   auto unknown =
204       base::StringPrintf("UNKNOWN[%d]", std::numeric_limits<uint8_t>::max());
205   ASSERT_STREQ(unknown.c_str(),
206                sdp_disc_wait_text(static_cast<tSDP_DISC_WAIT>(
207                                       std::numeric_limits<uint8_t>::max()))
208                    .c_str());
209 }
210 
TEST_F(StackSdpInitTest,sdp_state_text)211 TEST_F(StackSdpInitTest, sdp_state_text) {
212   std::vector<std::pair<tSDP_STATE, std::string>> states = {
213       std::make_pair(SDP_STATE_IDLE, "SDP_STATE_IDLE"),
214       std::make_pair(SDP_STATE_CONN_SETUP, "SDP_STATE_CONN_SETUP"),
215       std::make_pair(SDP_STATE_CFG_SETUP, "SDP_STATE_CFG_SETUP"),
216       std::make_pair(SDP_STATE_CONNECTED, "SDP_STATE_CONNECTED"),
217       std::make_pair(SDP_STATE_CONN_PEND, "SDP_STATE_CONN_PEND"),
218   };
219   for (const auto& state : states) {
220     ASSERT_STREQ(state.second.c_str(), sdp_state_text(state.first).c_str());
221   }
222   auto unknown = base::StringPrintf("UNKNOWN[%hhu]",
223                                     std::numeric_limits<std::uint8_t>::max());
224   ASSERT_STREQ(unknown.c_str(),
225                sdp_state_text(static_cast<tSDP_STATE>(
226                                   std::numeric_limits<std::uint8_t>::max()))
227                    .c_str());
228 }
229 
TEST_F(StackSdpInitTest,sdp_flags_text)230 TEST_F(StackSdpInitTest, sdp_flags_text) {
231   std::vector<std::pair<tSDP_DISC_WAIT, std::string>> flags = {
232       std::make_pair(SDP_FLAGS_IS_ORIG, "SDP_FLAGS_IS_ORIG"),
233       std::make_pair(SDP_FLAGS_HIS_CFG_DONE, "SDP_FLAGS_HIS_CFG_DONE"),
234       std::make_pair(SDP_FLAGS_MY_CFG_DONE, "SDP_FLAGS_MY_CFG_DONE"),
235   };
236   for (const auto& flag : flags) {
237     ASSERT_STREQ(flag.second.c_str(), sdp_flags_text(flag.first).c_str());
238   }
239   auto unknown =
240       base::StringPrintf("UNKNOWN[%hhu]", std::numeric_limits<uint8_t>::max());
241   ASSERT_STREQ(unknown.c_str(),
242                sdp_flags_text(static_cast<tSDP_DISC_WAIT>(
243                                   std::numeric_limits<uint8_t>::max()))
244                    .c_str());
245 }
246 
TEST_F(StackSdpInitTest,sdp_status_text)247 TEST_F(StackSdpInitTest, sdp_status_text) {
248   std::vector<std::pair<tSDP_STATUS, std::string>> status = {
249       std::make_pair(SDP_SUCCESS, "SDP_SUCCESS"),
250       std::make_pair(SDP_INVALID_VERSION, "SDP_INVALID_VERSION"),
251       std::make_pair(SDP_INVALID_SERV_REC_HDL, "SDP_INVALID_SERV_REC_HDL"),
252       std::make_pair(SDP_INVALID_REQ_SYNTAX, "SDP_INVALID_REQ_SYNTAX"),
253       std::make_pair(SDP_INVALID_PDU_SIZE, "SDP_INVALID_PDU_SIZE"),
254       std::make_pair(SDP_INVALID_CONT_STATE, "SDP_INVALID_CONT_STATE"),
255       std::make_pair(SDP_NO_RESOURCES, "SDP_NO_RESOURCES"),
256       std::make_pair(SDP_DI_REG_FAILED, "SDP_DI_REG_FAILED"),
257       std::make_pair(SDP_DI_DISC_FAILED, "SDP_DI_DISC_FAILED"),
258       std::make_pair(SDP_NO_DI_RECORD_FOUND, "SDP_NO_DI_RECORD_FOUND"),
259       std::make_pair(SDP_ERR_ATTR_NOT_PRESENT, "SDP_ERR_ATTR_NOT_PRESENT"),
260       std::make_pair(SDP_ILLEGAL_PARAMETER, "SDP_ILLEGAL_PARAMETER"),
261       std::make_pair(HID_SDP_NO_SERV_UUID, "HID_SDP_NO_SERV_UUID"),
262       std::make_pair(HID_SDP_MANDATORY_MISSING, "HID_SDP_MANDATORY_MISSING"),
263       std::make_pair(SDP_NO_RECS_MATCH, "SDP_NO_RECS_MATCH"),
264       std::make_pair(SDP_CONN_FAILED, "SDP_CONN_FAILED"),
265       std::make_pair(SDP_CFG_FAILED, "SDP_CFG_FAILED"),
266       std::make_pair(SDP_GENERIC_ERROR, "SDP_GENERIC_ERROR"),
267       std::make_pair(SDP_DB_FULL, "SDP_DB_FULL"),
268       std::make_pair(SDP_CANCEL, "SDP_CANCEL"),
269   };
270   for (const auto& stat : status) {
271     ASSERT_STREQ(stat.second.c_str(), sdp_status_text(stat.first).c_str());
272   }
273   auto unknown =
274       base::StringPrintf("UNKNOWN[%hu]", std::numeric_limits<uint16_t>::max());
275   ASSERT_STREQ(unknown.c_str(),
276                sdp_status_text(static_cast<tSDP_STATUS>(
277                                    std::numeric_limits<uint16_t>::max()))
278                    .c_str());
279 }
280 
281 static tSDP_DISCOVERY_DB db{};
282 static tSDP_DISC_REC rec{};
283 static tSDP_DISC_ATTR uuid_desc_attr{};
284 static tSDP_DISC_ATTR client_exe_url_attr{};
285 static tSDP_DISC_ATTR service_desc_attr{};
286 static tSDP_DISC_ATTR doc_url_desc_attr{};
287 static tSDP_DISC_ATTR spec_id_attr{};
288 static tSDP_DISC_ATTR vendor_id_attr{};
289 static tSDP_DISC_ATTR vendor_id_src_attr{};
290 static tSDP_DISC_ATTR prod_id_attr{};
291 static tSDP_DISC_ATTR prod_version_attr{};
292 static tSDP_DISC_ATTR primary_rec_attr{};
293 
294 class SDP_GetDiRecord_Tests : public ::testing::Test {
295 protected:
296 
SetUp()297   void SetUp() override {
298     db.p_first_rec = &rec;
299     rec.p_first_attr = &uuid_desc_attr;
300 
301     uuid_desc_attr.attr_id = ATTR_ID_SERVICE_ID;
302     uuid_desc_attr.p_next_attr = &client_exe_url_attr;
303 
304     client_exe_url_attr.attr_id = ATTR_ID_CLIENT_EXE_URL;
305     client_exe_url_attr.p_next_attr = &service_desc_attr;
306 
307     service_desc_attr.attr_id = ATTR_ID_SERVICE_DESCRIPTION;
308     service_desc_attr.p_next_attr = &doc_url_desc_attr;
309 
310     doc_url_desc_attr.attr_id = ATTR_ID_DOCUMENTATION_URL;
311     doc_url_desc_attr.p_next_attr = &spec_id_attr;
312 
313     spec_id_attr.attr_id = ATTR_ID_SPECIFICATION_ID;
314     spec_id_attr.p_next_attr = &vendor_id_attr;
315 
316     vendor_id_attr.attr_id = ATTR_ID_VENDOR_ID;
317     vendor_id_attr.p_next_attr = &vendor_id_src_attr;
318 
319     vendor_id_src_attr.attr_id = ATTR_ID_VENDOR_ID_SOURCE;
320     vendor_id_src_attr.p_next_attr = &prod_id_attr;
321 
322     prod_id_attr.attr_id = ATTR_ID_PRODUCT_ID;
323     prod_id_attr.p_next_attr = &prod_version_attr;
324 
325     prod_version_attr.attr_id = ATTR_ID_PRODUCT_VERSION;
326     prod_version_attr.p_next_attr = &primary_rec_attr;
327 
328     primary_rec_attr.attr_id = ATTR_ID_PRIMARY_RECORD;
329     primary_rec_attr.p_next_attr = nullptr;
330   }
331 
TearDown()332   void TearDown() override {
333     db = {};
334     rec = {};
335     uuid_desc_attr = {};
336     client_exe_url_attr = {};
337     service_desc_attr = {};
338     doc_url_desc_attr = {};
339     spec_id_attr = {};
340     vendor_id_attr = {};
341     vendor_id_src_attr = {};
342     prod_id_attr = {};
343     prod_version_attr = {};
344     primary_rec_attr = {};
345   }
346 };
347 
348 // regression test for b/297831980 and others
TEST_F(SDP_GetDiRecord_Tests,SDP_GetDiRecord_Regression_test0)349 TEST_F(SDP_GetDiRecord_Tests, SDP_GetDiRecord_Regression_test0) {
350   // tune the type/len and value of each attribute in
351   // each test
352   uuid_desc_attr.attr_len_type = (UUID_DESC_TYPE<<12) | 2;
353   uuid_desc_attr.attr_value.v.u16 = UUID_SERVCLASS_PNP_INFORMATION;
354 
355   // use a 2-byte string so that it can be
356   // saved in tSDP_DISC_ATVAL
357   const char *const text = "AB";
358   int len = strlen(text);
359   client_exe_url_attr.attr_len_type = (URL_DESC_TYPE<<12) | len;
360   memcpy(client_exe_url_attr.attr_value.v.array, text, len);
361 
362   // make this attr not found by id
363   service_desc_attr.attr_id = ATTR_ID_SERVICE_DESCRIPTION + 1;
364   service_desc_attr.attr_len_type = (TEXT_STR_DESC_TYPE<<12) | len;
365   memcpy(service_desc_attr.attr_value.v.array, text, len);
366 
367   // make a wrong type
368   doc_url_desc_attr.attr_len_type =(TEXT_STR_DESC_TYPE<<12) | len;
369   memcpy(doc_url_desc_attr.attr_value.v.array, text, len);
370 
371   // setup unexpected sizes for the following attrs
372   spec_id_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
373   spec_id_attr.attr_value.v.u16 = 0x1111;
374 
375   vendor_id_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
376   vendor_id_attr.attr_value.v.u16 = 0x2222;
377 
378   vendor_id_src_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
379   vendor_id_src_attr.attr_value.v.u16 = 0x3333;
380 
381   prod_id_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
382   prod_id_attr.attr_value.v.u16 = 0x4444;
383 
384   prod_version_attr.attr_len_type = (UINT_DESC_TYPE << 12) | 1;
385   prod_version_attr.attr_value.v.u16 = 0x5555;
386 
387   // setup wrong size for primary_rec_attr
388   primary_rec_attr.attr_len_type = (BOOLEAN_DESC_TYPE << 12) | 0;
389   primary_rec_attr.attr_value.v.u8 = 0x66;
390 
391   tSDP_DI_GET_RECORD device_info{};
392 
393   SDP_GetDiRecord(1, &device_info, &db);
394 
395   ASSERT_STREQ(text, device_info.rec.client_executable_url);
396 
397   // service description could not be found
398   ASSERT_EQ(strlen(device_info.rec.service_description), (size_t) 0);
399 
400   // with a wrong attr type, the attr value won't be accepted
401   ASSERT_EQ(strlen(device_info.rec.documentation_url), (size_t) 0);
402 
403   // none of the following values got setup
404   ASSERT_EQ(device_info.spec_id, 0);
405   ASSERT_EQ(device_info.rec.vendor, 0);
406   ASSERT_EQ(device_info.rec.vendor_id_source, 0);
407   ASSERT_EQ(device_info.rec.product, 0);
408   ASSERT_EQ(device_info.rec.version, 0);
409   ASSERT_FALSE(device_info.rec.primary_record);
410 }
411