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