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