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