1 /******************************************************************************
2 *
3 * Copyright 2014 The Android Open Source Project
4 * Copyright 2003-2012 Broadcom Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 /******************************************************************************
21 *
22 * This file contains the audio gateway functions performing SDP
23 * operations.
24 *
25 ******************************************************************************/
26
27 #include <bluetooth/log.h>
28 #include <com_android_bluetooth_flags.h>
29
30 #include <cstddef>
31 #include <cstdint>
32 #include <cstring>
33
34 #include "bta/hf_client/bta_hf_client_int.h"
35 #include "bta/include/bta_hf_client_api.h"
36 #include "bta/include/bta_rfcomm_scn.h"
37 #include "bta/sys/bta_sys.h"
38 #include "bta_hfp_api.h"
39 #include "common/bind.h"
40 #include "internal_include/bt_target.h"
41 #include "osi/include/allocator.h"
42 #include "sdp_status.h"
43 #include "stack/include/bt_types.h"
44 #include "stack/include/bt_uuid16.h"
45 #include "stack/include/sdp_api.h"
46 #include "stack/include/sdpdefs.h"
47 #include "stack/sdp/sdp_discovery_db.h"
48 #include "types/bluetooth/uuid.h"
49 #include "types/raw_address.h"
50
51 using bluetooth::Uuid;
52 using namespace bluetooth::legacy::stack::sdp;
53 using namespace bluetooth;
54
55 /* Number of protocol elements in protocol element list. */
56 #define BTA_HF_CLIENT_NUM_PROTO_ELEMS 2
57
58 /* Number of elements in service class id list. */
59 #define BTA_HF_CLIENT_NUM_SVC_ELEMS 2
60
61 /*******************************************************************************
62 *
63 * Function bta_hf_client_sdp_cback
64 *
65 * Description SDP callback function.
66 *
67 *
68 * Returns void
69 *
70 ******************************************************************************/
bta_hf_client_sdp_cback(tBTA_HF_CLIENT_CB * client_cb,const RawAddress &,tSDP_STATUS status)71 static void bta_hf_client_sdp_cback(tBTA_HF_CLIENT_CB* client_cb, const RawAddress& /* bd_addr */,
72 tSDP_STATUS status) {
73 uint16_t event;
74 tBTA_HF_CLIENT_DISC_RESULT* p_buf =
75 (tBTA_HF_CLIENT_DISC_RESULT*)osi_malloc(sizeof(tBTA_HF_CLIENT_DISC_RESULT));
76
77 log::verbose("bta_hf_client_sdp_cback status:0x{:x}", status);
78
79 /* set event according to int/acp */
80 if (client_cb->role == BTA_HF_CLIENT_ACP) {
81 event = BTA_HF_CLIENT_DISC_ACP_RES_EVT;
82 } else {
83 event = BTA_HF_CLIENT_DISC_INT_RES_EVT;
84 }
85
86 p_buf->hdr.event = event;
87 p_buf->hdr.layer_specific = client_cb->handle;
88 p_buf->status = status;
89
90 bta_sys_sendmsg(p_buf);
91 }
92
93 /******************************************************************************
94 *
95 * Function bta_hf_client_add_record
96 *
97 * Description This function is called by a server application to add
98 * HFP Client information to an SDP record. Prior to
99 * calling this function the application must call
100 * get_legacy_stack_sdp_api()->handle.SDP_CreateRecord() to
101 * create an SDP record.
102 *
103 * Returns true if function execution succeeded,
104 * false if function execution failed.
105 *
106 *****************************************************************************/
bta_hf_client_add_record(const char * p_service_name,uint8_t scn,tBTA_HF_CLIENT_FEAT features,uint32_t sdp_handle)107 bool bta_hf_client_add_record(const char* p_service_name, uint8_t scn, tBTA_HF_CLIENT_FEAT features,
108 uint32_t sdp_handle) {
109 tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HF_CLIENT_NUM_PROTO_ELEMS];
110 uint16_t svc_class_id_list[BTA_HF_CLIENT_NUM_SVC_ELEMS];
111 uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
112 uint16_t version;
113 uint16_t profile_uuid;
114 bool result = true;
115 uint8_t buf[2];
116 uint16_t sdp_features = 0;
117
118 log::verbose("bta_hf_client_add_record");
119 log::info("features: {}", features);
120
121 memset(proto_elem_list, 0, BTA_HF_CLIENT_NUM_PROTO_ELEMS * sizeof(tSDP_PROTOCOL_ELEM));
122
123 /* add the protocol element sequence */
124 proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
125 proto_elem_list[0].num_params = 0;
126 proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
127 proto_elem_list[1].num_params = 1;
128 proto_elem_list[1].params[0] = scn;
129 result &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
130 sdp_handle, BTA_HF_CLIENT_NUM_PROTO_ELEMS, proto_elem_list);
131
132 /* add service class id list */
133 svc_class_id_list[0] = UUID_SERVCLASS_HF_HANDSFREE;
134 svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
135 result &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
136 sdp_handle, BTA_HF_CLIENT_NUM_SVC_ELEMS, svc_class_id_list);
137
138 /* add profile descriptor list */
139 profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
140 version = get_default_hfp_version();
141
142 result &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(sdp_handle,
143 profile_uuid, version);
144
145 /* add service name */
146 if (p_service_name != NULL && p_service_name[0] != 0) {
147 result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
148 sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
149 (uint32_t)(strlen(p_service_name) + 1), (uint8_t*)p_service_name);
150 }
151
152 /* add features */
153 if (features & BTA_HF_CLIENT_FEAT_ECNR) {
154 sdp_features |= BTA_HF_CLIENT_FEAT_ECNR;
155 }
156
157 if (features & BTA_HF_CLIENT_FEAT_3WAY) {
158 sdp_features |= BTA_HF_CLIENT_FEAT_3WAY;
159 }
160
161 if (features & BTA_HF_CLIENT_FEAT_CLI) {
162 sdp_features |= BTA_HF_CLIENT_FEAT_CLI;
163 }
164
165 if (features & BTA_HF_CLIENT_FEAT_VREC) {
166 sdp_features |= BTA_HF_CLIENT_FEAT_VREC;
167 }
168
169 if (features & BTA_HF_CLIENT_FEAT_VOL) {
170 sdp_features |= BTA_HF_CLIENT_FEAT_VOL;
171 }
172
173 /* Codec bit position is different in SDP (bit 5) and in BRSF (bit 7) */
174 if (features & BTA_HF_CLIENT_FEAT_CODEC) {
175 sdp_features |= BTA_HF_CLIENT_WBS_SUPPORT;
176 }
177
178 /* Support swb */
179 if (features & BTA_HF_CLIENT_FEAT_SWB) {
180 sdp_features |= BTA_HF_CLIENT_FEAT_SWB_SUPPORT;
181 }
182
183 UINT16_TO_BE_FIELD(buf, sdp_features);
184 result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
185 sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf);
186
187 /* add browse group list */
188 result &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
189 sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
190
191 return result;
192 }
193
194 /*******************************************************************************
195 *
196 * Function bta_hf_client_create_record
197 *
198 * Description Create SDP record for registered service.
199 *
200 *
201 * Returns void
202 *
203 ******************************************************************************/
bta_hf_client_create_record(tBTA_HF_CLIENT_CB_ARR * client_cb_arr,const char * p_service_name)204 void bta_hf_client_create_record(tBTA_HF_CLIENT_CB_ARR* client_cb_arr, const char* p_service_name) {
205 /* add sdp record if not already registered */
206 if (client_cb_arr->sdp_handle == 0) {
207 client_cb_arr->sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
208 client_cb_arr->scn = BTA_AllocateSCN();
209 bta_hf_client_add_record(p_service_name, client_cb_arr->scn, client_cb_arr->features,
210 client_cb_arr->sdp_handle);
211
212 bta_sys_add_uuid(UUID_SERVCLASS_HF_HANDSFREE);
213 }
214 }
215
216 /*******************************************************************************
217 *
218 * Function bta_hf_client_del_record
219 *
220 * Description Delete SDP record for registered service.
221 *
222 *
223 * Returns void
224 *
225 ******************************************************************************/
bta_hf_client_del_record(tBTA_HF_CLIENT_CB_ARR * client_cb)226 void bta_hf_client_del_record(tBTA_HF_CLIENT_CB_ARR* client_cb) {
227 log::verbose("");
228
229 if (client_cb->sdp_handle != 0) {
230 if (get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(client_cb->sdp_handle)) {
231 log::warn("Unable to delete SDP record handle:{}", client_cb->sdp_handle);
232 }
233 client_cb->sdp_handle = 0;
234 BTA_FreeSCN(client_cb->scn);
235 bta_sys_remove_uuid(UUID_SERVCLASS_HF_HANDSFREE);
236 }
237 }
238
239 /*******************************************************************************
240 *
241 * Function bta_hf_client_sdp_find_attr
242 *
243 * Description Process SDP discovery results to find requested attribute
244 *
245 *
246 * Returns true if results found, false otherwise.
247 *
248 ******************************************************************************/
bta_hf_client_sdp_find_attr(tBTA_HF_CLIENT_CB * client_cb)249 bool bta_hf_client_sdp_find_attr(tBTA_HF_CLIENT_CB* client_cb) {
250 tSDP_DISC_REC* p_rec = NULL;
251 tSDP_DISC_ATTR* p_attr;
252 tSDP_PROTOCOL_ELEM pe;
253 bool result = false;
254
255 client_cb->peer_version = HFP_VERSION_1_1; /* Default version */
256
257 /* loop through all records we found */
258 while (true) {
259 /* get next record; if none found, we're done */
260 p_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(client_cb->p_disc_db,
261 UUID_SERVCLASS_AG_HANDSFREE, p_rec);
262 if (p_rec == NULL) {
263 break;
264 }
265
266 /* get scn from proto desc list if initiator */
267 if (client_cb->role == BTA_HF_CLIENT_INT) {
268 if (get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
269 p_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
270 client_cb->peer_scn = (uint8_t)pe.params[0];
271 } else {
272 continue;
273 }
274 }
275
276 /* get profile version (if failure, version parameter is not updated) */
277 if (!get_legacy_stack_sdp_api()->record.SDP_FindProfileVersionInRec(
278 p_rec, UUID_SERVCLASS_HF_HANDSFREE, &client_cb->peer_version)) {
279 log::warn("Uable to find HFP profile version in SDP record peer:{}", p_rec->remote_bd_addr);
280 }
281
282 /* get features */
283 p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(p_rec,
284 ATTR_ID_SUPPORTED_FEATURES);
285 if (p_attr != NULL && SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UINT_DESC_TYPE &&
286 SDP_DISC_ATTR_LEN(p_attr->attr_len_type) >= 2) {
287 /* Found attribute. Get value. */
288 /* There might be race condition between SDP and BRSF. */
289 /* Do not update if we already received BRSF. */
290 if (client_cb->peer_features == 0) {
291 client_cb->peer_features = p_attr->attr_value.v.u16;
292
293 /* SDP and BRSF WBS bit are different, correct it if set */
294 if (client_cb->peer_features & 0x0020) {
295 client_cb->peer_features &= ~0x0020;
296 client_cb->peer_features |= BTA_HF_CLIENT_PEER_CODEC;
297 }
298
299 /* get network for ability to reject calls */
300 p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(p_rec, ATTR_ID_NETWORK);
301 if (p_attr != NULL && SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UINT_DESC_TYPE &&
302 SDP_DISC_ATTR_LEN(p_attr->attr_len_type) >= 2) {
303 if (p_attr->attr_value.v.u16 == 0x01) {
304 client_cb->peer_features |= BTA_HF_CLIENT_PEER_REJECT;
305 }
306 }
307 }
308 }
309
310 /* found what we needed */
311 result = true;
312 break;
313 }
314
315 log::verbose("peer_version=0x{:x} peer_features=0x{:x}", client_cb->peer_version,
316 client_cb->peer_features);
317
318 return result;
319 }
320
321 /*******************************************************************************
322 *
323 * Function bta_hf_client_do_disc
324 *
325 * Description Do service discovery.
326 *
327 *
328 * Returns void
329 *
330 ******************************************************************************/
bta_hf_client_do_disc(tBTA_HF_CLIENT_CB * client_cb)331 void bta_hf_client_do_disc(tBTA_HF_CLIENT_CB* client_cb) {
332 Uuid uuid_list[1];
333 uint16_t num_uuid = 1;
334 uint16_t attr_list[4];
335 uint8_t num_attr;
336 bool db_inited = false;
337
338 /* initiator; get proto list and features */
339 if (client_cb->role == BTA_HF_CLIENT_INT) {
340 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
341 attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
342 attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
343 attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
344 num_attr = 4;
345 uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
346 } else {
347 /* acceptor; get features */
348 attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
349 attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
350 attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
351 num_attr = 3;
352 uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
353 }
354
355 /* If we already have a non-null discovery database at this point, we can get
356 * into a race condition leading to UAF once this connection is closed.
357 * This should only happen with malicious modifications to a client. */
358 if (com::android::bluetooth::flags::btsec_check_valid_discovery_database() &&
359 client_cb->p_disc_db != NULL) {
360 log::error("Tried to set up a HF client with a preexisting discovery database.");
361 client_cb->p_disc_db = NULL;
362 // We manually set the state here because it's possible to call this from an
363 // OPEN state, in which case the discovery fail event will be ignored.
364 client_cb->state = 0; // BTA_HF_CLIENT_INIT_ST
365 return;
366 }
367
368 /* allocate buffer for sdp database */
369 client_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
370
371 /* set up service discovery database; attr happens to be attr_list len */
372 db_inited = get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
373 client_cb->p_disc_db, BT_DEFAULT_BUFFER_SIZE, num_uuid, uuid_list, num_attr, attr_list);
374
375 if (db_inited) {
376 /*Service discovery not initiated */
377 db_inited = get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest2(
378 client_cb->peer_addr, client_cb->p_disc_db,
379 base::BindRepeating(&bta_hf_client_sdp_cback, client_cb));
380 }
381
382 if (!db_inited) {
383 log::warn("Unable to start SDP service search request peer:{}", client_cb->peer_addr);
384 /*free discover db */
385 osi_free_and_reset((void**)&client_cb->p_disc_db);
386 /* sent failed event */
387 tBTA_HF_CLIENT_DATA msg;
388 msg.hdr.layer_specific = client_cb->handle;
389 bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, &msg);
390 }
391 }
392
393 /*******************************************************************************
394 *
395 * Function bta_hf_client_free_db
396 *
397 * Description Free discovery database.
398 *
399 *
400 * Returns void
401 *
402 ******************************************************************************/
bta_hf_client_free_db(tBTA_HF_CLIENT_DATA * p_data)403 void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA* p_data) {
404 log::assert_that(p_data != NULL, "assert failed: p_data != NULL");
405 tBTA_HF_CLIENT_CB* client_cb = bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
406 if (client_cb == NULL) {
407 log::error("cb not found for handle {}", p_data->hdr.layer_specific);
408 return;
409 }
410
411 osi_free_and_reset((void**)&client_cb->p_disc_db);
412 }
413