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 <gtest/gtest.h>
18 
19 #include <memory>
20 
21 #include "bta/jv/bta_jv_int.h"
22 #include "bta_jv_api.h"
23 #include "osi/include/allocator.h"
24 #include "stack/include/sdp_status.h"
25 #include "test/common/mock_functions.h"
26 #include "test/fake/fake_osi.h"
27 #include "test/mock/mock_stack_sdp_legacy_api.h"
28 #include "types/bluetooth/uuid.h"
29 #include "types/raw_address.h"
30 
31 namespace {
32 const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
33 const RawAddress kRawAddress2 =
34     RawAddress({0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc});
35 const bluetooth::Uuid kUuid = bluetooth::Uuid::From16Bit(0x1234);
36 const bluetooth::Uuid kUuid2 = bluetooth::Uuid::From16Bit(0x789a);
37 
38 constexpr uint32_t kSlotId = 0x1234568;
39 constexpr uint8_t kScn = 123;
40 
41 }  // namespace
42 
43 namespace bluetooth::legacy::testing {
44 
45 void bta_jv_start_discovery_cback(uint32_t rfcomm_slot_id,
46                                   const RawAddress& bd_addr,
47                                   tSDP_RESULT result);
48 
49 }  // namespace bluetooth::legacy::testing
50 
51 class FakeSdp {
52  public:
FakeSdp()53   FakeSdp() {
54     test::mock::stack_sdp_legacy::api_ = {
55         .service = {
56             .SDP_InitDiscoveryDb = [](tSDP_DISCOVERY_DB*, uint32_t, uint16_t,
57                                       const bluetooth::Uuid*, uint16_t,
58                                       const uint16_t*) -> bool { return true; },
59             .SDP_CancelServiceSearch = nullptr,
60             .SDP_ServiceSearchRequest = nullptr,
61             .SDP_ServiceSearchAttributeRequest = nullptr,
62             .SDP_ServiceSearchAttributeRequest2 =
63                 [](const RawAddress& /* p_bd_addr */,
64                    tSDP_DISCOVERY_DB* /* p_db */,
65                    base::RepeatingCallback<
66                        tSDP_DISC_CMPL_CB> /* complete_callback */) {
67                   return true;
68                 },
69         },
70         .db =
71             {
72                 .SDP_FindServiceInDb = nullptr,
73                 .SDP_FindServiceUUIDInDb =
74                     [](const tSDP_DISCOVERY_DB* /* p_db */,
75                        const bluetooth::Uuid& /* uuid */,
76                        tSDP_DISC_REC* /* p_start_rec */) -> tSDP_DISC_REC* {
77                   return nullptr;
78                 },
79                 .SDP_FindServiceInDb_128bit = nullptr,
80             },
81         .record =
82             {
83                 .SDP_FindAttributeInRec = nullptr,
84                 .SDP_FindServiceUUIDInRec_128bit = nullptr,
85                 .SDP_FindProtocolListElemInRec =
86                     [](const tSDP_DISC_REC* /* p_rec */,
87                        uint16_t /* layer_uuid */,
88                        tSDP_PROTOCOL_ELEM* /* p_elem */) -> bool {
89                   return false;
90                 },
91                 .SDP_FindProfileVersionInRec = nullptr,
92                 .SDP_FindServiceUUIDInRec = nullptr,
93             },
94         .handle =
95             {
96                 .SDP_CreateRecord = nullptr,
97                 .SDP_DeleteRecord = nullptr,
98                 .SDP_AddAttribute = nullptr,
99                 .SDP_AddSequence = nullptr,
100                 .SDP_AddUuidSequence = nullptr,
101                 .SDP_AddProtocolList = nullptr,
102                 .SDP_AddAdditionProtoLists = nullptr,
103                 .SDP_AddProfileDescriptorList = nullptr,
104                 .SDP_AddLanguageBaseAttrIDList = nullptr,
105                 .SDP_AddServiceClassIdList = nullptr,
106             },
107         .device_id =
108             {
109                 .SDP_SetLocalDiRecord = nullptr,
110                 .SDP_DiDiscover = nullptr,
111                 .SDP_GetNumDiRecords = nullptr,
112                 .SDP_GetDiRecord = nullptr,
113             },
114     };
115   }
116 
~FakeSdp()117   ~FakeSdp() { test::mock::stack_sdp_legacy::api_ = {}; }
118 };
119 
120 class BtaJvMockAndFakeTest : public ::testing::Test {
121  protected:
SetUp()122   void SetUp() override {
123     reset_mock_function_count_map();
124     fake_osi_ = std::make_unique<test::fake::FakeOsi>();
125     fake_sdp_ = std::make_unique<FakeSdp>();
126   }
127 
TearDown()128   void TearDown() override {}
129 
130   std::unique_ptr<test::fake::FakeOsi> fake_osi_;
131   std::unique_ptr<FakeSdp> fake_sdp_;
132 };
133 
134 class BtaJvTest : public BtaJvMockAndFakeTest {
135  protected:
SetUp()136   void SetUp() override {
137     BtaJvMockAndFakeTest::SetUp();
138     bta_jv_cb.sdp_cb = {};
139   }
140 
TearDown()141   void TearDown() override {
142     bta_jv_cb.sdp_cb = {};
143     BtaJvMockAndFakeTest::TearDown();
144   }
145 };
146 
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__no_callback)147 TEST_F(BtaJvTest, bta_jv_start_discovery_cback__no_callback) {
148   bta_jv_enable(nullptr);
149   bluetooth::legacy::testing::bta_jv_start_discovery_cback(
150       0x12345678, kRawAddress, SDP_SUCCESS);
151 }
152 
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__with_callback_success_no_record)153 TEST_F(BtaJvTest,
154        bta_jv_start_discovery_cback__with_callback_success_no_record) {
155   // Ensure that there was an sdp active
156   bta_jv_cb.sdp_cb = {
157       .sdp_active = true,
158       .bd_addr = kRawAddress,
159       .uuid = kUuid,
160   };
161   bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
162     switch (event) {
163       case BTA_JV_DISCOVERY_COMP_EVT:
164         ASSERT_EQ(p_data->disc_comp.status, tBTA_JV_STATUS::FAILURE);
165         ASSERT_EQ(kSlotId, id);
166         break;
167 
168       case BTA_JV_ENABLE_EVT:
169         ASSERT_EQ(p_data->disc_comp.status, tBTA_JV_STATUS::SUCCESS);
170         ASSERT_EQ(0U, id);
171         break;
172 
173       default:
174         FAIL();
175     }
176   });
177   bluetooth::legacy::testing::bta_jv_start_discovery_cback(kSlotId, kRawAddress,
178                                                            SDP_SUCCESS);
179 }
180 
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__with_callback_success_with_record)181 TEST_F(BtaJvTest,
182        bta_jv_start_discovery_cback__with_callback_success_with_record) {
183   static tSDP_DISC_REC sdp_disc_rec = {
184       .p_first_attr = nullptr,
185       .p_next_rec = nullptr,
186       .time_read = 1,
187       .remote_bd_addr = RawAddress::kAny,
188   };
189 
190   test::mock::stack_sdp_legacy::api_.db.SDP_FindServiceUUIDInDb =
191       [](const tSDP_DISCOVERY_DB* /* p_db */, const bluetooth::Uuid& /* uuid */,
192          tSDP_DISC_REC* /* p_start_rec */) -> tSDP_DISC_REC* {
193     return &sdp_disc_rec;
194   };
195 
196   test::mock::stack_sdp_legacy::api_.record.SDP_FindProtocolListElemInRec =
197       [](const tSDP_DISC_REC* /* p_rec */, uint16_t /* layer_uuid */,
198          tSDP_PROTOCOL_ELEM* p_elem) -> bool {
199     p_elem->params[0] = (uint16_t)kScn;
200     return true;
201   };
202 
203   // Ensure that there was an sdp active
204   bta_jv_cb.sdp_cb = {
205       .sdp_active = true,
206       .bd_addr = kRawAddress,
207       .uuid = kUuid,
208   };
209   bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
210     switch (event) {
211       case BTA_JV_DISCOVERY_COMP_EVT:
212         ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
213         ASSERT_EQ(kScn, p_data->disc_comp.scn);
214         ASSERT_EQ(kSlotId, id);
215         break;
216 
217       case BTA_JV_ENABLE_EVT:
218         ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
219         ASSERT_EQ(0U, id);
220         break;
221 
222       default:
223         FAIL();
224     }
225   });
226   bluetooth::legacy::testing::bta_jv_start_discovery_cback(kSlotId, kRawAddress,
227                                                            SDP_SUCCESS);
228 }
229 
TEST_F(BtaJvTest,bta_jv_start_discovery_cback__with_callback_failure)230 TEST_F(BtaJvTest, bta_jv_start_discovery_cback__with_callback_failure) {
231   tSDP_RESULT result = SDP_CONN_FAILED;
232 
233   // Ensure that there was an sdp active
234   bta_jv_cb.sdp_cb = {
235       .sdp_active = true,
236       .bd_addr = kRawAddress,
237       .uuid = kUuid,
238   };
239   bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
240     switch (event) {
241       case BTA_JV_DISCOVERY_COMP_EVT:
242         ASSERT_EQ(tBTA_JV_STATUS::FAILURE, p_data->disc_comp.status);
243         ASSERT_EQ(kSlotId, id);
244         break;
245 
246       case BTA_JV_ENABLE_EVT:
247         ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
248         ASSERT_EQ(0U, id);
249         break;
250 
251       default:
252         FAIL();
253     }
254   });
255   bluetooth::legacy::testing::bta_jv_start_discovery_cback(kSlotId, kRawAddress,
256                                                            result);
257 }
258 
TEST_F(BtaJvTest,bta_jv_start_discovery__idle)259 TEST_F(BtaJvTest, bta_jv_start_discovery__idle) {
260   bluetooth::Uuid uuid_list[1] = {
261       kUuid,
262   };
263   uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));
264 
265   bta_jv_start_discovery(kRawAddress, num_uuid, uuid_list, kSlotId);
266 
267   ASSERT_EQ(true, bta_jv_cb.sdp_cb.sdp_active);
268   ASSERT_EQ(kRawAddress, bta_jv_cb.sdp_cb.bd_addr);
269   ASSERT_EQ(kUuid, bta_jv_cb.sdp_cb.uuid);
270 }
271 
TEST_F(BtaJvTest,bta_jv_start_discovery__idle_failed_to_start)272 TEST_F(BtaJvTest, bta_jv_start_discovery__idle_failed_to_start) {
273   bluetooth::Uuid uuid_list[1] = {
274       kUuid,
275   };
276   uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));
277 
278   test::mock::stack_sdp_legacy::api_.service
279       .SDP_ServiceSearchAttributeRequest2 =
280       [](const RawAddress& /* p_bd_addr */, tSDP_DISCOVERY_DB* /* p_db */,
281          base::RepeatingCallback<tSDP_DISC_CMPL_CB> /* complete_callback */) {
282         return false;
283       };
284 
285   bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
286     switch (event) {
287       case BTA_JV_DISCOVERY_COMP_EVT:
288         ASSERT_EQ(tBTA_JV_STATUS::FAILURE, p_data->disc_comp.status);
289         ASSERT_EQ(kSlotId, id);
290         break;
291 
292       case BTA_JV_ENABLE_EVT:
293         ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
294         ASSERT_EQ(0U, id);
295         break;
296 
297       default:
298         FAIL();
299     }
300   });
301   bta_jv_start_discovery(kRawAddress2, num_uuid, uuid_list, kSlotId);
302 
303   ASSERT_EQ(false, bta_jv_cb.sdp_cb.sdp_active);
304   ASSERT_EQ(RawAddress::kEmpty, bta_jv_cb.sdp_cb.bd_addr);
305   ASSERT_EQ(bluetooth::Uuid::kEmpty, bta_jv_cb.sdp_cb.uuid);
306 }
307 
TEST_F(BtaJvTest,bta_jv_start_discovery__already_active)308 TEST_F(BtaJvTest, bta_jv_start_discovery__already_active) {
309   bta_jv_cb.sdp_cb = {
310       .sdp_active = true,
311       .bd_addr = kRawAddress,
312       .uuid = kUuid,
313   };
314 
315   bluetooth::Uuid uuid_list[1] = {
316       kUuid2,
317   };
318   uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));
319 
320   bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
321     switch (event) {
322       case BTA_JV_DISCOVERY_COMP_EVT:
323         ASSERT_EQ(tBTA_JV_STATUS::BUSY, p_data->disc_comp.status);
324         ASSERT_EQ(kSlotId, id);
325         break;
326 
327       case BTA_JV_ENABLE_EVT:
328         ASSERT_EQ(tBTA_JV_STATUS::SUCCESS, p_data->disc_comp.status);
329         ASSERT_EQ(0U, id);
330         break;
331 
332       default:
333         FAIL();
334     }
335   });
336   bta_jv_start_discovery(kRawAddress2, num_uuid, uuid_list, kSlotId);
337 
338   ASSERT_EQ(true, bta_jv_cb.sdp_cb.sdp_active);
339   ASSERT_EQ(kRawAddress, bta_jv_cb.sdp_cb.bd_addr);
340   ASSERT_EQ(kUuid, bta_jv_cb.sdp_cb.uuid);
341 }
342