• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstring>
27 
28 #include <base/bind.h>
29 
30 #include "bt_common.h"
31 #include "bta_ag_api.h"
32 #include "bta_ag_int.h"
33 #include "bta_api.h"
34 #include "bta_sys.h"
35 #include "btif_config.h"
36 #include "btm_api.h"
37 #include "osi/include/log.h"
38 #include "osi/include/osi.h"
39 #include "sdp_api.h"
40 #include "stack/include/btu.h"
41 #include "utl.h"
42 
43 using bluetooth::Uuid;
44 
45 /* Number of protocol elements in protocol element list. */
46 #define BTA_AG_NUM_PROTO_ELEMS 2
47 
48 /* Number of elements in service class id list. */
49 #define BTA_AG_NUM_SVC_ELEMS 2
50 
51 /* size of database for service discovery */
52 #ifndef BTA_AG_DISC_BUF_SIZE
53 #define BTA_AG_DISC_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
54 #endif
55 
56 /* declare sdp callback functions */
57 void bta_ag_sdp_cback_1(uint16_t status);
58 void bta_ag_sdp_cback_2(uint16_t status);
59 void bta_ag_sdp_cback_3(uint16_t status);
60 void bta_ag_sdp_cback_4(uint16_t status);
61 void bta_ag_sdp_cback_5(uint16_t status);
62 void bta_ag_sdp_cback_6(uint16_t status);
63 
64 /* SDP callback function table */
65 typedef tSDP_DISC_CMPL_CB* tBTA_AG_SDP_CBACK;
66 const tBTA_AG_SDP_CBACK bta_ag_sdp_cback_tbl[] = {
67     bta_ag_sdp_cback_1, bta_ag_sdp_cback_2, bta_ag_sdp_cback_3,
68     bta_ag_sdp_cback_4, bta_ag_sdp_cback_5, bta_ag_sdp_cback_6};
69 
70 /*******************************************************************************
71  *
72  * Function         bta_ag_sdp_cback
73  *
74  * Description      SDP callback function.
75  *
76  *
77  * Returns          void
78  *
79  ******************************************************************************/
bta_ag_sdp_cback(uint16_t status,uint8_t idx)80 static void bta_ag_sdp_cback(uint16_t status, uint8_t idx) {
81   APPL_TRACE_DEBUG("%s status:0x%x", __func__, status);
82   tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(idx);
83   if (p_scb) {
84     uint16_t event;
85     /* set event according to int/acp */
86     if (p_scb->role == BTA_AG_ACP) {
87       event = BTA_AG_DISC_ACP_RES_EVT;
88     } else {
89       event = BTA_AG_DISC_INT_RES_EVT;
90     }
91     tBTA_AG_DATA disc_result = {.disc_result = {.status = status}};
92     do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, idx,
93                                             event, disc_result));
94   }
95 }
96 
97 /*******************************************************************************
98  *
99  * Function         bta_ag_sdp_cback_1 to 6
100  *
101  * Description      SDP callback functions.  Since there is no way to
102  *                  distinguish scb from the callback we need separate
103  *                  callbacks for each scb.
104  *
105  *
106  * Returns          void
107  *
108  ******************************************************************************/
bta_ag_sdp_cback_1(uint16_t status)109 void bta_ag_sdp_cback_1(uint16_t status) { bta_ag_sdp_cback(status, 1); }
bta_ag_sdp_cback_2(uint16_t status)110 void bta_ag_sdp_cback_2(uint16_t status) { bta_ag_sdp_cback(status, 2); }
bta_ag_sdp_cback_3(uint16_t status)111 void bta_ag_sdp_cback_3(uint16_t status) { bta_ag_sdp_cback(status, 3); }
bta_ag_sdp_cback_4(uint16_t status)112 void bta_ag_sdp_cback_4(uint16_t status) { bta_ag_sdp_cback(status, 4); }
bta_ag_sdp_cback_5(uint16_t status)113 void bta_ag_sdp_cback_5(uint16_t status) { bta_ag_sdp_cback(status, 5); }
bta_ag_sdp_cback_6(uint16_t status)114 void bta_ag_sdp_cback_6(uint16_t status) { bta_ag_sdp_cback(status, 6); }
115 
116 /******************************************************************************
117  *
118  * Function         bta_ag_add_record
119  *
120  * Description      This function is called by a server application to add
121  *                  HSP or HFP information to an SDP record.  Prior to
122  *                  calling this function the application must call
123  *                  SDP_CreateRecord() to create an SDP record.
124  *
125  * Returns          true if function execution succeeded,
126  *                  false if function execution failed.
127  *
128  *****************************************************************************/
bta_ag_add_record(uint16_t service_uuid,const char * p_service_name,uint8_t scn,tBTA_AG_FEAT features,uint32_t sdp_handle)129 bool bta_ag_add_record(uint16_t service_uuid, const char* p_service_name,
130                        uint8_t scn, tBTA_AG_FEAT features,
131                        uint32_t sdp_handle) {
132   tSDP_PROTOCOL_ELEM proto_elem_list[BTA_AG_NUM_PROTO_ELEMS];
133   uint16_t svc_class_id_list[BTA_AG_NUM_SVC_ELEMS];
134   uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
135   uint16_t version;
136   uint16_t profile_uuid;
137   uint8_t network;
138   bool result = true;
139   bool codec_supported = false;
140   uint8_t buf[2];
141 
142   APPL_TRACE_DEBUG("%s uuid: %x", __func__, service_uuid);
143 
144   for (auto& proto_element : proto_elem_list) {
145     proto_element = {};
146   }
147 
148   /* add the protocol element sequence */
149   proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
150   proto_elem_list[0].num_params = 0;
151   proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
152   proto_elem_list[1].num_params = 1;
153   proto_elem_list[1].params[0] = scn;
154   result &=
155       SDP_AddProtocolList(sdp_handle, BTA_AG_NUM_PROTO_ELEMS, proto_elem_list);
156 
157   /* add service class id list */
158   svc_class_id_list[0] = service_uuid;
159   svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
160   result &= SDP_AddServiceClassIdList(sdp_handle, BTA_AG_NUM_SVC_ELEMS,
161                                       svc_class_id_list);
162 
163   /* add profile descriptor list */
164   if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
165     profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
166     version = BTA_HFP_VERSION;
167   } else {
168     profile_uuid = UUID_SERVCLASS_HEADSET;
169     version = HSP_VERSION_1_2;
170   }
171   result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
172 
173   /* add service name */
174   if (p_service_name != nullptr && p_service_name[0] != 0) {
175     result &= SDP_AddAttribute(
176         sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
177         (uint32_t)(strlen(p_service_name) + 1), (uint8_t*)p_service_name);
178   }
179 
180   /* add features and network */
181   if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE) {
182     network = (features & BTA_AG_FEAT_REJECT) ? 1 : 0;
183     result &= SDP_AddAttribute(sdp_handle, ATTR_ID_DATA_STORES_OR_NETWORK,
184                                UINT_DESC_TYPE, 1, &network);
185 
186     if (features & BTA_AG_FEAT_CODEC) codec_supported = true;
187 
188     features &= BTA_AG_SDP_FEAT_SPEC;
189 
190     /* Codec bit position is different in SDP and in BRSF */
191     if (codec_supported) features |= 0x0020;
192 
193     UINT16_TO_BE_FIELD(buf, features);
194     result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES,
195                                UINT_DESC_TYPE, 2, buf);
196   }
197 
198   /* add browse group list */
199   result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1,
200                                 browse_list);
201 
202   return result;
203 }
204 
205 /*******************************************************************************
206  *
207  * Function         bta_ag_create_records
208  *
209  * Description      Create SDP records for registered services.
210  *
211  *
212  * Returns          void
213  *
214  ******************************************************************************/
bta_ag_create_records(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)215 void bta_ag_create_records(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
216   int i;
217   tBTA_SERVICE_MASK services;
218 
219   services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
220   for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
221     /* if service is set in mask */
222     if (services & 1) {
223       /* add sdp record if not already registered */
224       if (bta_ag_cb.profile[i].sdp_handle == 0) {
225         bta_ag_cb.profile[i].sdp_handle = SDP_CreateRecord();
226         bta_ag_cb.profile[i].scn = BTM_AllocateSCN();
227         bta_ag_add_record(bta_ag_uuid[i], data.api_register.p_name[i],
228                           bta_ag_cb.profile[i].scn, data.api_register.features,
229                           bta_ag_cb.profile[i].sdp_handle);
230         bta_sys_add_uuid(bta_ag_uuid[i]);
231       }
232     }
233   }
234 }
235 
236 /*******************************************************************************
237  *
238  * Function         bta_ag_del_records
239  *
240  * Description      Delete SDP records for any registered services.
241  *
242  *
243  * Returns          void
244  *
245  ******************************************************************************/
bta_ag_del_records(tBTA_AG_SCB * p_scb)246 void bta_ag_del_records(tBTA_AG_SCB* p_scb) {
247   tBTA_AG_SCB* p = &bta_ag_cb.scb[0];
248   tBTA_SERVICE_MASK services;
249   tBTA_SERVICE_MASK others = 0;
250   int i;
251 
252   /* get services of all other registered servers */
253   for (i = 0; i < BTA_AG_NUM_IDX; i++, p++) {
254     if (p_scb == p) {
255       continue;
256     }
257 
258     if (p->in_use && !p->dealloc) {
259       others |= p->reg_services;
260     }
261   }
262 
263   others >>= BTA_HSP_SERVICE_ID;
264   services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
265   for (i = 0; i < BTA_AG_NUM_IDX && services != 0;
266        i++, services >>= 1, others >>= 1) {
267     /* if service registered for this scb and not registered for any other scb
268      */
269     if (((services & 1) == 1) && ((others & 1) == 0)) {
270       APPL_TRACE_DEBUG("bta_ag_del_records %d", i);
271       if (bta_ag_cb.profile[i].sdp_handle != 0) {
272         SDP_DeleteRecord(bta_ag_cb.profile[i].sdp_handle);
273         bta_ag_cb.profile[i].sdp_handle = 0;
274       }
275       BTM_FreeSCN(bta_ag_cb.profile[i].scn);
276       BTM_SecClrService(bta_ag_sec_id[i]);
277       bta_sys_remove_uuid(bta_ag_uuid[i]);
278     }
279   }
280 }
281 
282 /*******************************************************************************
283  *
284  * Function         bta_ag_sdp_find_attr
285  *
286  * Description      Process SDP discovery results to find requested attributes
287  *                  for requested service.
288  *
289  *
290  * Returns          true if results found, false otherwise.
291  *
292  ******************************************************************************/
bta_ag_sdp_find_attr(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK service)293 bool bta_ag_sdp_find_attr(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
294   tSDP_DISC_REC* p_rec = nullptr;
295   tSDP_DISC_ATTR* p_attr;
296   tSDP_PROTOCOL_ELEM pe;
297   uint16_t uuid;
298   bool result = false;
299 
300   if (service & BTA_HFP_SERVICE_MASK) {
301     uuid = UUID_SERVCLASS_HF_HANDSFREE;
302     /* If there is no cached peer version, use default one */
303     if (p_scb->peer_version == HFP_HSP_VERSION_UNKNOWN) {
304       p_scb->peer_version = HFP_VERSION_1_1; /* Default version */
305     }
306   } else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
307     uuid = UUID_SERVCLASS_HEADSET_HS;
308     p_scb->peer_version = HSP_VERSION_1_2; /* Default version */
309   } else {
310     uuid = UUID_SERVCLASS_HEADSET_HS;
311     p_scb->peer_version = HSP_VERSION_1_0;
312   }
313 
314   /* loop through all records we found */
315   while (true) {
316     /* get next record; if none found, we're done */
317     p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec);
318     if (p_rec == nullptr) {
319       if (uuid == UUID_SERVCLASS_HEADSET_HS) {
320         /* Search again in case the peer device uses the old HSP UUID */
321         uuid = UUID_SERVCLASS_HEADSET;
322         p_scb->peer_version = HSP_VERSION_1_0;
323         p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec);
324         if (p_rec == nullptr) {
325           break;
326         }
327       } else
328         break;
329     }
330 
331     /* get scn from proto desc list if initiator */
332     if (p_scb->role == BTA_AG_INT) {
333       if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
334         p_scb->peer_scn = (uint8_t)pe.params[0];
335       } else {
336         continue;
337       }
338     }
339 
340     /* get profile version (if failure, version parameter is not updated) */
341     uint16_t peer_version = HFP_HSP_VERSION_UNKNOWN;
342     if (!SDP_FindProfileVersionInRec(p_rec, uuid, &peer_version)) {
343       APPL_TRACE_WARNING("%s: Get peer_version failed, using default 0x%04x",
344                          __func__, p_scb->peer_version);
345       peer_version = p_scb->peer_version;
346     }
347 
348     if (service & BTA_HFP_SERVICE_MASK) {
349       /* Update cached peer version if the new one is different */
350       if (peer_version != p_scb->peer_version) {
351         p_scb->peer_version = peer_version;
352         if (btif_config_set_bin(
353                 p_scb->peer_addr.ToString(), HFP_VERSION_CONFIG_KEY,
354                 (const uint8_t*)&peer_version, sizeof(peer_version))) {
355           btif_config_save();
356         } else {
357           APPL_TRACE_WARNING("%s: Failed to store peer HFP version for %s",
358                              __func__, p_scb->peer_addr.ToString().c_str());
359         }
360       }
361       /* get features if HFP */
362       p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
363       if (p_attr != nullptr) {
364         /* Found attribute. Get value. */
365         /* There might be race condition between SDP and BRSF.  */
366         /* Do not update if we already received BRSF.           */
367         uint16_t sdp_features = p_attr->attr_value.v.u16;
368         bool sdp_wbs_support = sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
369         if (!p_scb->received_at_bac && sdp_wbs_support) {
370           // Workaround for misbehaving HFs (e.g. some Hyundai car kit) that:
371           // 1. Indicate WBS support in SDP and codec negotiation in BRSF
372           // 2. But do not send required AT+BAC command
373           // Will assume mSBC is enabled and try codec negotiation by default
374           p_scb->codec_updated = true;
375           p_scb->peer_codecs = BTA_AG_CODEC_CVSD & BTA_AG_CODEC_MSBC;
376           p_scb->sco_codec = UUID_CODEC_MSBC;
377         }
378         if (sdp_features != p_scb->peer_sdp_features) {
379           p_scb->peer_sdp_features = sdp_features;
380           if (btif_config_set_bin(
381                   p_scb->peer_addr.ToString(), HFP_SDP_FEATURES_CONFIG_KEY,
382                   (const uint8_t*)&sdp_features, sizeof(sdp_features))) {
383             btif_config_save();
384           } else {
385             APPL_TRACE_WARNING(
386                 "%s: Failed to store peer HFP SDP Features for %s", __func__,
387                 p_scb->peer_addr.ToString().c_str());
388           }
389         }
390         if (p_scb->peer_features == 0) {
391           p_scb->peer_features = sdp_features & HFP_SDP_BRSF_FEATURES_MASK;
392         }
393       }
394     } else {
395       /* No peer version caching for HSP, use discovered one directly */
396       p_scb->peer_version = peer_version;
397       /* get features if HSP */
398       p_attr =
399           SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL);
400       if (p_attr != nullptr) {
401         /* Remote volume control of HSP */
402         if (p_attr->attr_value.v.u8)
403           p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL;
404         else
405           p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL;
406       }
407     }
408 
409     /* found what we needed */
410     result = true;
411     break;
412   }
413   return result;
414 }
415 
416 /*******************************************************************************
417  *
418  * Function         bta_ag_do_disc
419  *
420  * Description      Do service discovery.
421  *
422  *
423  * Returns          void
424  *
425  ******************************************************************************/
bta_ag_do_disc(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK service)426 void bta_ag_do_disc(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
427   Uuid uuid_list[1];
428   uint16_t num_uuid = 1;
429   uint16_t attr_list[4];
430   uint8_t num_attr;
431 
432   /* HFP initiator; get proto list and features */
433   if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
434     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
435     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
436     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
437     attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
438     num_attr = 4;
439     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
440   }
441   /* HFP acceptor; get features */
442   else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP) {
443     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
444     attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
445     attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
446     num_attr = 3;
447     uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HF_HANDSFREE);
448   }
449   /* HSP initiator; get proto list */
450   else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT) {
451     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
452     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
453     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
454     attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
455     num_attr = 4;
456     // Although UUID_SERVCLASS_HEADSET_HS (0x1131) is to be used in HSP 1.2,
457     // some HSP 1.2 implementations, such as PTS, still use
458     // UUID_SERVCLASS_HEADSET (0x1108) to store its service record. However,
459     // most of such devices are HSP 1.0 devices.
460     if (p_scb->hsp_version >= HSP_VERSION_1_2) {
461       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
462     } else {
463       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
464     }
465   } else {
466     /* HSP acceptor; get features */
467     attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
468     attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
469     attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
470     attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
471     num_attr = 4;
472 
473     if (p_scb->hsp_version >= HSP_VERSION_1_2) {
474       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET_HS);
475     } else {
476       /* Legacy from HSP v1.0 */
477       uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_HEADSET);
478     }
479   }
480 
481   if (p_scb->p_disc_db != nullptr) {
482     android_errorWriteLog(0x534e4554, "174052148");
483     APPL_TRACE_ERROR("Discovery already in progress... returning.");
484     return;
485   }
486 
487   /* allocate buffer for sdp database */
488   p_scb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_AG_DISC_BUF_SIZE);
489   /* set up service discovery database; attr happens to be attr_list len */
490   if (SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid,
491                           uuid_list, num_attr, attr_list)) {
492     if (SDP_ServiceSearchAttributeRequest(
493             p_scb->peer_addr, p_scb->p_disc_db,
494             bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1])) {
495       return;
496     } else {
497       LOG(ERROR) << __func__ << ": failed to start SDP discovery for "
498                  << p_scb->peer_addr;
499     }
500   } else {
501     LOG(ERROR) << __func__ << ": failed to init SDP discovery database for "
502                << p_scb->peer_addr;
503   }
504   // Failure actions
505   bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
506   bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, tBTA_AG_DATA::kEmpty);
507 }
508 
509 /*******************************************************************************
510  *
511  * Function         bta_ag_free_db
512  *
513  * Description      Free discovery database.
514  *
515  *
516  * Returns          void
517  *
518  ******************************************************************************/
bta_ag_free_db(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)519 void bta_ag_free_db(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
520   osi_free_and_reset((void**)&p_scb->p_disc_db);
521 }
522