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