1 /*
2 * Copyright 2020 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 #define LOG_TAG "bt_headless_sdp"
18
19 #include "test/headless/sdp/sdp.h"
20
21 #include <future>
22
23 #include "bta/dm/bta_dm_int.h"
24 #include "bta/include/bta_api.h"
25 #include "stack/include/sdp_api.h"
26 #include "test/headless/get_options.h"
27 #include "test/headless/headless.h"
28 #include "test/headless/sdp/sdp_db.h"
29 #include "types/bluetooth/uuid.h"
30 #include "types/raw_address.h"
31
32 using namespace bluetooth::legacy::stack::sdp;
33 using namespace bluetooth::test::headless;
34
bta_jv_start_discovery_callback(std::promise<tSDP_STATUS> * promise,const RawAddress &,tSDP_STATUS result)35 static void bta_jv_start_discovery_callback(std::promise<tSDP_STATUS>* promise,
36 const RawAddress& /* bd_addr */, tSDP_STATUS result) {
37 promise->set_value(result);
38 }
39
40 namespace {
41
42 constexpr size_t kMaxDiscoveryRecords = 1024;
43
sdp_query_uuid(unsigned int num_loops,const RawAddress & raw_address,const bluetooth::Uuid & uuid)44 int sdp_query_uuid([[maybe_unused]] unsigned int num_loops,
45 [[maybe_unused]] const RawAddress& raw_address,
46 [[maybe_unused]] const bluetooth::Uuid& uuid) {
47 SdpDb sdp_discovery_db(kMaxDiscoveryRecords);
48
49 if (!get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(sdp_discovery_db.RawPointer(),
50 sdp_discovery_db.Length(),
51 1, // num_uuid,
52 &uuid, 0, nullptr)) {
53 LOG_CONSOLE("Unable to initialize sdp discovery");
54 return -1;
55 }
56 LOG_CONSOLE("Initialized sdp discovery database");
57
58 std::promise<tSDP_STATUS> promise;
59 auto future = promise.get_future();
60
61 sdp_discovery_db.Print(stdout);
62
63 if (!get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest2(
64 raw_address, sdp_discovery_db.RawPointer(),
65 base::BindRepeating(bta_jv_start_discovery_callback, &promise))) {
66 fprintf(stdout, "%s Failed to start search attribute request\n", __func__);
67 return -2;
68 }
69 LOG_CONSOLE("Started service search for uuid:%s", uuid.ToString().c_str());
70
71 const tSDP_STATUS result = future.get();
72 if (result != tSDP_STATUS::SDP_SUCCESS) {
73 fprintf(stdout, "Failed search discovery result:%s\n", sdp_status_text(result).c_str());
74 return static_cast<int>(result);
75 }
76
77 LOG_CONSOLE("Found records peer:%s uuid:%s", raw_address.ToString().c_str(),
78 uuid.ToString().c_str());
79 for (unsigned i = 0; i < BTA_MAX_SERVICE_ID; i++) {
80 uint16_t uuid_as16Bit = bta_service_id_to_uuid_lkup_tbl[i];
81 tSDP_DISC_REC* rec = SDP_FindServiceInDb(sdp_discovery_db.RawPointer(), uuid_as16Bit, nullptr);
82 if (rec != nullptr) {
83 LOG_CONSOLE(" uuid:0x%x", uuid_as16Bit);
84 }
85 }
86
87 return 0;
88 }
89
90 } // namespace
91
Run()92 int bluetooth::test::headless::Sdp::Run() {
93 if (options_.loop_ < 1) {
94 printf("This test requires at least a single loop\n");
95 options_.Usage();
96 return -1;
97 }
98 if (options_.device_.size() != 1) {
99 printf("This test requires a single device specified\n");
100 options_.Usage();
101 return -1;
102 }
103 if (options_.uuid_.size() != 1) {
104 printf("This test requires a single uuid specified\n");
105 options_.Usage();
106 return -1;
107 }
108
109 return RunOnHeadlessStack<int>([this]() {
110 return sdp_query_uuid(options_.loop_, options_.device_.front(), options_.uuid_.front());
111 });
112 }
113