1 /******************************************************************************
2  *
3  *  Copyright 2003-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains the audio gateway functions performing SDP
22  *  operations.
23  *
24  ******************************************************************************/
25 
26 #include <base/functional/bind.h>
27 #include <base/location.h>
28 #include <bluetooth/log.h>
29 
30 #include "bta/ag/bta_ag_int.h"
31 #include "bta/include/bta_hfp_api.h"
32 #include "bta/include/bta_rfcomm_scn.h"
33 #include "btif/include/btif_config.h"
34 #include "common/init_flags.h"
35 #include "device/include/interop.h"
36 #include "device/include/interop_config.h"
37 #include "internal_include/bt_target.h"
38 #include "os/logging/log_adapter.h"
39 #include "osi/include/allocator.h"
40 #include "stack/btm/btm_sco_hfp_hal.h"
41 #include "stack/include/bt_types.h"
42 #include "stack/include/bt_uuid16.h"
43 #include "stack/include/main_thread.h"
44 #include "stack/include/sdp_api.h"
45 #include "storage/config_keys.h"
46 #include "types/bluetooth/uuid.h"
47 
48 using namespace bluetooth::legacy::stack::sdp;
49 using namespace bluetooth;
50 using bluetooth::Uuid;
51 
52 /* Number of protocol elements in protocol element list. */
53 #define BTA_AG_NUM_PROTO_ELEMS 2
54 
55 /* Number of elements in service class id list. */
56 #define BTA_AG_NUM_SVC_ELEMS 2
57 
58 /* size of database for service discovery */
59 #ifndef BTA_AG_DISC_BUF_SIZE
60 #define BTA_AG_DISC_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
61 #endif
62 
63 /* declare sdp callback functions */
64 void bta_ag_sdp_cback_1(const RawAddress& bd_addr, tSDP_RESULT);
65 void bta_ag_sdp_cback_2(const RawAddress& bd_addr, tSDP_RESULT);
66 void bta_ag_sdp_cback_3(const RawAddress& bd_addr, tSDP_RESULT);
67 void bta_ag_sdp_cback_4(const RawAddress& bd_addr, tSDP_RESULT);
68 void bta_ag_sdp_cback_5(const RawAddress& bd_addr, tSDP_RESULT);
69 void bta_ag_sdp_cback_6(const RawAddress& bd_addr, tSDP_RESULT);
70 
71 /* SDP callback function table */
72 typedef tSDP_DISC_CMPL_CB* tBTA_AG_SDP_CBACK;
73 const tBTA_AG_SDP_CBACK bta_ag_sdp_cback_tbl[] = {
74     bta_ag_sdp_cback_1, bta_ag_sdp_cback_2, bta_ag_sdp_cback_3,
75     bta_ag_sdp_cback_4, bta_ag_sdp_cback_5, bta_ag_sdp_cback_6};
76 
77 /*******************************************************************************
78  *
79  * Function         bta_ag_sdp_cback
80  *
81  * Description      SDP callback function.
82  *
83  *
84  * Returns          void
85  *
86  ******************************************************************************/
bta_ag_sdp_cback(uint16_t status,uint8_t idx)87 static void bta_ag_sdp_cback(uint16_t status, uint8_t idx) {
88   log::verbose("status:0x{:x}", status);
89   tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(idx);
90   if (p_scb) {
91     uint16_t event;
92     /* set event according to int/acp */
93     if (p_scb->role == BTA_AG_ACP) {
94       event = BTA_AG_DISC_ACP_RES_EVT;
95     } else {
96       event = BTA_AG_DISC_INT_RES_EVT;
97     }
98     tBTA_AG_DATA disc_result = {.disc_result = {.status = status}};
99     do_in_main_thread(FROM_HERE, base::BindOnce(&bta_ag_sm_execute_by_handle,
100                                                 idx, event, disc_result));
101   }
102 }
103 
104 /*******************************************************************************
105  *
106  * Function         bta_ag_sdp_cback_1 to 6
107  *
108  * Description      SDP callback functions.  Since there is no way to
109  *                  distinguish scb from the callback we need separate
110  *                  callbacks for each scb.
111  *
112  *
113  * Returns          void
114  *
115  ******************************************************************************/
bta_ag_sdp_cback_1(const RawAddress &,tSDP_STATUS status)116 void bta_ag_sdp_cback_1(const RawAddress& /* bd_addr */, tSDP_STATUS status) {
117   bta_ag_sdp_cback(status, 1);
118 }
bta_ag_sdp_cback_2(const RawAddress &,tSDP_STATUS status)119 void bta_ag_sdp_cback_2(const RawAddress& /* bd_addr */, tSDP_STATUS status) {
120   bta_ag_sdp_cback(status, 2);
121 }
bta_ag_sdp_cback_3(const RawAddress &,tSDP_STATUS status)122 void bta_ag_sdp_cback_3(const RawAddress& /* bd_addr */, tSDP_STATUS status) {
123   bta_ag_sdp_cback(status, 3);
124 }
bta_ag_sdp_cback_4(const RawAddress &,tSDP_STATUS status)125 void bta_ag_sdp_cback_4(const RawAddress& /* bd_addr */, tSDP_STATUS status) {
126   bta_ag_sdp_cback(status, 4);
127 }
bta_ag_sdp_cback_5(const RawAddress &,tSDP_STATUS status)128 void bta_ag_sdp_cback_5(const RawAddress& /* bd_addr */, tSDP_STATUS status) {
129   bta_ag_sdp_cback(status, 5);
130 }
bta_ag_sdp_cback_6(const RawAddress &,tSDP_STATUS status)131 void bta_ag_sdp_cback_6(const RawAddress& /* bd_addr */, tSDP_STATUS status) {
132   bta_ag_sdp_cback(status, 6);
133 }
134 
135 /******************************************************************************
136  *
137  * Function         bta_ag_add_record
138  *
139  * Description      This function is called by a server application to add
140  *                  HSP or HFP information to an SDP record.  Prior to
141  *                  calling this function the application must call
142  *                  SDP_CreateRecord() to create an SDP record.
143  *
144  * Returns          true if function execution succeeded,
145  *                  false if function execution failed.
146  *
147  *****************************************************************************/
bta_ag_add_record(uint16_t service_uuid,const char * p_service_name,uint8_t scn,tBTA_AG_FEAT features,uint32_t sdp_handle)148 bool bta_ag_add_record(uint16_t service_uuid, const char* p_service_name,
149                        uint8_t scn, tBTA_AG_FEAT features,
150                        uint32_t sdp_handle) {
151   tSDP_PROTOCOL_ELEM proto_elem_list[BTA_AG_NUM_PROTO_ELEMS];
152   uint16_t svc_class_id_list[BTA_AG_NUM_SVC_ELEMS];
153   uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
154   uint16_t version;
155   uint16_t profile_uuid;
156   uint8_t network;
157   bool result = true;
158   bool codec_supported = false;
159   uint8_t buf[2];
160 
161   log::verbose("uuid: {:x}", service_uuid);
162   log::info("features: {}", features);
163 
164   for (auto& proto_element : proto_elem_list) {
165     proto_element = {};
166   }
167 
168   /* add the protocol element sequence */
169   proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
170   proto_elem_list[0].num_params = 0;
171   proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
172   proto_elem_list[1].num_params = 1;
173   proto_elem_list[1].params[0] = scn;
174   result &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
175       sdp_handle, BTA_AG_NUM_PROTO_ELEMS, proto_elem_list);
176 
177   /* add service class id list */
178   svc_class_id_list[0] = service_uuid;
179   svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
180   result &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
181       sdp_handle, BTA_AG_NUM_SVC_ELEMS, svc_class_id_list);
182 
183   /* add profile descriptor list */
184   if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
185     profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
186     if (bluetooth::common::init_flags::hfp_dynamic_version_is_enabled()) {
187       version = HFP_VERSION_1_6;
188     } else {
189       version = get_default_hfp_version();
190     }
191   } else {
192     profile_uuid = UUID_SERVCLASS_HEADSET;
193     version = HSP_VERSION_1_2;
194   }
195   result &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
196       sdp_handle, profile_uuid, version);
197 
198   /* add service name */
199   if (p_service_name != nullptr && p_service_name[0] != 0) {
200     result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
201         sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
202         (uint32_t)(strlen(p_service_name) + 1), (uint8_t*)p_service_name);
203   }
204 
205   /* add features and network */
206   if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
207     network = (features & BTA_AG_FEAT_REJECT) ? 1 : 0;
208     result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
209         sdp_handle, ATTR_ID_DATA_STORES_OR_NETWORK, UINT_DESC_TYPE, 1,
210         &network);
211 
212     if (features & BTA_AG_FEAT_CODEC) codec_supported = true;
213 
214     features &= BTA_AG_SDP_FEAT_SPEC;
215 
216     /* Codec bit position is different in SDP and in BRSF */
217     if (codec_supported) features |= BTA_AG_FEAT_WBS_SUPPORT;
218     // check property for SWB support
219     if (hfp_hal_interface::get_swb_supported()) {
220       features |= BTA_AG_FEAT_SWB_SUPPORT;
221     }
222 
223     UINT16_TO_BE_FIELD(buf, features);
224     result &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
225         sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf);
226   }
227 
228   /* add browse group list */
229   result &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
230       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
231 
232   return result;
233 }
234 
235 /*******************************************************************************
236  *
237  * Function         bta_ag_create_records
238  *
239  * Description      Create SDP records for registered services.
240  *
241  *
242  * Returns          void
243  *
244  ******************************************************************************/
bta_ag_create_records(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)245 void bta_ag_create_records(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
246   int i;
247   tBTA_SERVICE_MASK services;
248 
249   services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
250   for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
251     /* if service is set in mask */
252     if (services & 1) {
253       /* add sdp record if not already registered */
254       if (bta_ag_cb.profile[i].sdp_handle == 0) {
255         bta_ag_cb.profile[i].sdp_handle =
256             get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
257         bta_ag_cb.profile[i].scn = BTA_AllocateSCN();
258         bta_ag_add_record(bta_ag_uuid[i], data.api_register.p_name[i],
259                           bta_ag_cb.profile[i].scn, data.api_register.features,
260                           bta_ag_cb.profile[i].sdp_handle);
261         bta_sys_add_uuid(bta_ag_uuid[i]);
262       }
263     }
264   }
265 }
266 
267 /*******************************************************************************
268  *
269  * Function         bta_ag_del_records
270  *
271  * Description      Delete SDP records for any registered services.
272  *
273  *
274  * Returns          void
275  *
276  ******************************************************************************/
bta_ag_del_records(tBTA_AG_SCB * p_scb)277 void bta_ag_del_records(tBTA_AG_SCB* p_scb) {
278   tBTA_AG_SCB* p = &bta_ag_cb.scb[0];
279   tBTA_SERVICE_MASK services;
280   tBTA_SERVICE_MASK others = 0;
281   int i;
282 
283   /* get services of all other registered servers */
284   for (i = 0; i < BTA_AG_NUM_IDX; i++, p++) {
285     if (p_scb == p) {
286       continue;
287     }
288 
289     if (p->in_use && !p->dealloc) {
290       others |= p->reg_services;
291     }
292   }
293 
294   others >>= BTA_HSP_SERVICE_ID;
295   services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
296   for (i = 0; i < BTA_AG_NUM_IDX && services != 0;
297        i++, services >>= 1, others >>= 1) {
298     /* if service registered for this scb and not registered for any other scb
299      */
300     if (((services & 1) == 1) && ((others & 1) == 0)) {
301       log::verbose("bta_ag_del_records {}", i);
302       if (bta_ag_cb.profile[i].sdp_handle != 0) {
303         if (!get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(
304                 bta_ag_cb.profile[i].sdp_handle)) {
305           log::warn("Unable to delete record sdp_handle:{}",
306                     bta_ag_cb.profile[i].sdp_handle);
307         }
308         bta_ag_cb.profile[i].sdp_handle = 0;
309       }
310       BTA_FreeSCN(bta_ag_cb.profile[i].scn);
311       bta_sys_remove_uuid(bta_ag_uuid[i]);
312     }
313   }
314 }
315 
316 /*******************************************************************************
317  *
318  * Function         bta_ag_sdp_find_attr
319  *
320  * Description      Process SDP discovery results to find requested attributes
321  *                  for requested service.
322  *
323  *
324  * Returns          true if results found, false otherwise.
325  *
326  ******************************************************************************/
bta_ag_sdp_find_attr(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK service)327 bool bta_ag_sdp_find_attr(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
328   tSDP_DISC_REC* p_rec = nullptr;
329   tSDP_DISC_ATTR* p_attr;
330   tSDP_PROTOCOL_ELEM pe;
331   uint16_t uuid;
332   bool result = false;
333 
334   if (service & BTA_HFP_SERVICE_MASK) {
335     uuid = UUID_SERVCLASS_HF_HANDSFREE;
336     /* If there is no cached peer version, use default one */
337     if (p_scb->peer_version == HFP_HSP_VERSION_UNKNOWN) {
338       p_scb->peer_version = HFP_VERSION_1_1; /* Default version */
339     }
340   } else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
341     uuid = UUID_SERVCLASS_HEADSET_HS;
342     p_scb->peer_version = HSP_VERSION_1_2; /* Default version */
343   } else {
344     uuid = UUID_SERVCLASS_HEADSET_HS;
345     p_scb->peer_version = HSP_VERSION_1_0;
346   }
347 
348   /* loop through all records we found */
349   while (true) {
350     /* get next record; if none found, we're done */
351     p_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(p_scb->p_disc_db,
352                                                                uuid, p_rec);
353     if (p_rec == nullptr) {
354       if (uuid == UUID_SERVCLASS_HEADSET_HS) {
355         /* Search again in case the peer device uses the old HSP UUID */
356         uuid = UUID_SERVCLASS_HEADSET;
357         p_scb->peer_version = HSP_VERSION_1_0;
358         p_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceInDb(
359             p_scb->p_disc_db, uuid, p_rec);
360         if (p_rec == nullptr) {
361           break;
362         }
363       } else
364         break;
365     }
366 
367     /* get scn from proto desc list if initiator */
368     if (p_scb->role == BTA_AG_INT) {
369       if (get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
370               p_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
371         p_scb->peer_scn = (uint8_t)pe.params[0];
372       } else {
373         continue;
374       }
375     }
376 
377     /* get profile version (if failure, version parameter is not updated) */
378     uint16_t peer_version = HFP_HSP_VERSION_UNKNOWN;
379     if (!get_legacy_stack_sdp_api()->record.SDP_FindProfileVersionInRec(
380             p_rec, uuid, &peer_version)) {
381       log::warn("Get peer_version failed, using default 0x{:04x}",
382                 p_scb->peer_version);
383       peer_version = p_scb->peer_version;
384     }
385 
386     if (service & BTA_HFP_SERVICE_MASK) {
387       /* Update cached peer version if the new one is different */
388       if (peer_version != p_scb->peer_version) {
389         p_scb->peer_version = peer_version;
390         if (btif_config_set_bin(
391                 p_scb->peer_addr.ToString(), BTIF_STORAGE_KEY_HFP_VERSION,
392                 (const uint8_t*)&peer_version, sizeof(peer_version))) {
393         } else {
394           log::warn("Failed to store peer HFP version for {}",
395                     p_scb->peer_addr);
396         }
397       }
398       /* get features if HFP */
399       p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(
400           p_rec, ATTR_ID_SUPPORTED_FEATURES);
401       if (p_attr != nullptr &&
402           SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UINT_DESC_TYPE &&
403           SDP_DISC_ATTR_LEN(p_attr->attr_len_type) >= 2) {
404         /* Found attribute. Get value. */
405         /* There might be race condition between SDP and BRSF.  */
406         /* Do not update if we already received BRSF.           */
407         uint16_t sdp_features = p_attr->attr_value.v.u16;
408         bool sdp_wbs_support = sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
409         if (!p_scb->received_at_bac && sdp_wbs_support) {
410           // Workaround for misbehaving HFs (e.g. some Hyundai car kit) that:
411           // 1. Indicate WBS support in SDP and codec negotiation in BRSF
412           // 2. But do not send required AT+BAC command
413           // Will assume mSBC is enabled and try codec negotiation by default
414           p_scb->codec_updated = true;
415           p_scb->peer_codecs = BTM_SCO_CODEC_CVSD | BTM_SCO_CODEC_MSBC;
416           p_scb->sco_codec = UUID_CODEC_MSBC;
417         }
418         if (sdp_features != p_scb->peer_sdp_features) {
419           p_scb->peer_sdp_features = sdp_features;
420           if (btif_config_set_bin(p_scb->peer_addr.ToString(),
421                                   BTIF_STORAGE_KEY_HFP_SDP_FEATURES,
422                                   (const uint8_t*)&sdp_features,
423                                   sizeof(sdp_features))) {
424           } else {
425             log::warn("Failed to store peer HFP SDP Features for {}",
426                       p_scb->peer_addr);
427           }
428         }
429         if (p_scb->peer_features == 0) {
430           p_scb->peer_features = sdp_features & HFP_SDP_BRSF_FEATURES_MASK;
431         }
432         /* Remote supports 1.7, store it in HFP 1.7 BL file */
433         if (bluetooth::common::init_flags::hfp_dynamic_version_is_enabled()) {
434           if (p_scb->peer_version >= HFP_VERSION_1_9) {
435             interop_database_add_addr(INTEROP_HFP_1_9_ALLOWLIST,
436                                       &p_scb->peer_addr, 3);
437           } else if (p_scb->peer_version >= HFP_VERSION_1_7) {
438             interop_database_add_addr(INTEROP_HFP_1_7_ALLOWLIST,
439                                       &p_scb->peer_addr, 3);
440           }
441         }
442       }
443     } else {
444       /* No peer version caching for HSP, use discovered one directly */
445       p_scb->peer_version = peer_version;
446       /* get features if HSP */
447       p_attr = get_legacy_stack_sdp_api()->record.SDP_FindAttributeInRec(
448           p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL);
449       if (p_attr != nullptr &&
450             SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == BOOLEAN_DESC_TYPE &&
451             SDP_DISC_ATTR_LEN(p_attr->attr_len_type) >= 1) {
452         /* Remote volume control of HSP */
453         if (p_attr->attr_value.v.u8)
454           p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL;
455         else
456           p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL;
457       }
458     }
459 
460     /* found what we needed */
461     result = true;
462     break;
463   }
464   return result;
465 }
466 
467 /*******************************************************************************
468  *
469  * Function         bta_ag_do_disc
470  *
471  * Description      Do service discovery.
472  *
473  *
474  * Returns          void
475  *
476  ******************************************************************************/
bta_ag_do_disc(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK service)477 void bta_ag_do_disc(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
478   Uuid uuid_list[1];
479   uint16_t num_uuid = 1;
480   uint16_t attr_list[4];
481   uint8_t num_attr;
482 
483   /* HFP initiator; get proto list and features */
484   if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
485     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
486     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
487     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
488     attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
489     num_attr = 4;
490     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
491   }
492   /* HFP acceptor; get features */
493   else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP) {
494     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
495     attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
496     attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
497     num_attr = 3;
498     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
499   }
500   /* HSP initiator; get proto list */
501   else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
502     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
503     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
504     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
505     attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
506     num_attr = 4;
507     // Although UUID_SERVCLASS_HEADSET_HS (0x1131) is to be used in HSP 1.2,
508     // some HSP 1.2 implementations, such as PTS, still use
509     // UUID_SERVCLASS_HEADSET (0x1108) to store its service record. However,
510     // most of such devices are HSP 1.0 devices.
511     if (p_scb->hsp_version >= HSP_VERSION_1_2) {
512       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
513     } else {
514       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
515     }
516   } else {
517     /* HSP acceptor; get features */
518     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
519     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
520     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
521     attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
522     num_attr = 4;
523 
524     if (p_scb->hsp_version >= HSP_VERSION_1_2) {
525       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
526     } else {
527       /* Legacy from HSP v1.0 */
528       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
529     }
530   }
531 
532   if (p_scb->p_disc_db != nullptr) {
533     log::error("Discovery already in progress... returning.");
534     return;
535   }
536 
537   /* allocate buffer for sdp database */
538   p_scb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_AG_DISC_BUF_SIZE);
539   /* set up service discovery database; attr happens to be attr_list len */
540   if (get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
541           p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid, uuid_list, num_attr,
542           attr_list)) {
543     if (get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest(
544             p_scb->peer_addr, p_scb->p_disc_db,
545             bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1])) {
546       return;
547     } else {
548       log::error("failed to start SDP discovery for {}", p_scb->peer_addr);
549     }
550   } else {
551     log::error("failed to init SDP discovery database for {}",
552                p_scb->peer_addr);
553   }
554   // Failure actions
555   bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
556   bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, tBTA_AG_DATA::kEmpty);
557 }
558 
559 /*******************************************************************************
560  *
561  * Function         bta_ag_free_db
562  *
563  * Description      Free discovery database.
564  *
565  *
566  * Returns          void
567  *
568  ******************************************************************************/
bta_ag_free_db(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)569 void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
570   osi_free_and_reset((void**)&p_scb->p_disc_db);
571 }
572