• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright 2014 Samsung System LSI
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  *  Filename:      btif_sdp_server.cc
22  *  Description:   SDP server Bluetooth Interface to create and remove SDP
23  *                 records.
24  *                 To be used in combination with the RFCOMM/L2CAP(LE) sockets.
25  *
26  *
27  ******************************************************************************/
28 
29 #define LOG_TAG "bt_btif_sdp_server"
30 
31 #include <hardware/bluetooth.h>
32 #include <hardware/bt_sdp.h>
33 #include <pthread.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include <mutex>
38 
39 #include "bta_sdp_api.h"
40 #include "bta_sys.h"
41 #include "btif_common.h"
42 #include "btif_sock_sdp.h"
43 #include "btif_sock_util.h"
44 #include "btif_util.h"
45 #include "osi/include/allocator.h"
46 #include "stack/include/sdp_api.h"
47 #include "stack/sdp/sdpint.h"
48 #include "types/bluetooth/uuid.h"
49 #include "utl.h"
50 
51 using namespace bluetooth::legacy::stack::sdp;
52 
53 // Protects the sdp_slots array from concurrent access.
54 static std::recursive_mutex sdp_lock;
55 
56 /**
57  * The need for a state variable have been reduced to two states.
58  * The remaining state control is handled by program flow
59  */
60 typedef enum {
61   SDP_RECORD_FREE = 0,
62   SDP_RECORD_ALLOCED,
63 } sdp_state_t;
64 
65 typedef struct {
66   sdp_state_t state;
67   int sdp_handle;
68   bluetooth_sdp_record* record_data;
69 } sdp_slot_t;
70 
71 #define MAX_SDP_SLOTS 128
72 static sdp_slot_t sdp_slots[MAX_SDP_SLOTS];
73 
74 /*****************************************************************************
75  * LOCAL Functions
76  *****************************************************************************/
77 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec);
78 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec);
79 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec);
80 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec);
81 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec);
82 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec);
83 static int add_mps_sdp(const bluetooth_sdp_mps_record* rec);
84 bt_status_t remove_sdp_record(int record_id);
85 static int free_sdp_slot(int id);
86 
87 /******************************************************************************
88  * WARNING: Functions below are not called in BTU context.
89  * Introduced to make it possible to create SDP records from JAVA with both a
90  * RFCOMM channel and a L2CAP PSM.
91  * Overall architecture:
92  *  1) JAVA calls createRecord() which returns a pseudo ID which at a later
93  *     point will be linked to a specific SDP handle.
94  *  2) createRecord() requests the BTU task(thread) to call a callback in SDP
95  *     which creates the actual record, and updates the ID<->SDPHandle map
96  *     based on the ID beeing passed to BTA as user_data.
97  *****************************************************************************/
98 
init_sdp_slots()99 static void init_sdp_slots() {
100   int i;
101   memset(sdp_slots, 0, sizeof(sdp_slot_t) * MAX_SDP_SLOTS);
102   /* if SDP_RECORD_FREE is zero - no need to set the value */
103   if (SDP_RECORD_FREE != 0) {
104     for (i = 0; i < MAX_SDP_SLOTS; i++) {
105       sdp_slots[i].state = SDP_RECORD_FREE;
106     }
107   }
108 }
109 
sdp_server_init()110 bt_status_t sdp_server_init() {
111   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
112   init_sdp_slots();
113   return BT_STATUS_SUCCESS;
114 }
115 
sdp_server_cleanup()116 void sdp_server_cleanup() {
117   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
118   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
119   int i;
120   for (i = 0; i < MAX_SDP_SLOTS; i++) {
121     /*remove_sdp_record(i); we cannot send messages to the other threads, since
122     * they might
123     *                       have been shut down already. Just do local cleanup.
124     */
125     free_sdp_slot(i);
126   }
127 }
128 
get_sdp_records_size(bluetooth_sdp_record * in_record,int count)129 int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) {
130   bluetooth_sdp_record* record = in_record;
131   int records_size = 0;
132   int i;
133   for (i = 0; i < count; i++) {
134     record = &in_record[i];
135     records_size += sizeof(bluetooth_sdp_record);
136     records_size += record->hdr.service_name_length;
137     if (record->hdr.service_name_length > 0) {
138       records_size++; /* + '\0' termination of string */
139     }
140     records_size += record->hdr.user1_ptr_len;
141     records_size += record->hdr.user2_ptr_len;
142   }
143   return records_size;
144 }
145 
146 /* Deep copy all content of in_records into out_records.
147  * out_records must point to a chunk of memory large enough to contain all
148  * the data. Use getSdpRecordsSize() to calculate the needed size. */
copy_sdp_records(bluetooth_sdp_record * in_records,bluetooth_sdp_record * out_records,int count)149 void copy_sdp_records(bluetooth_sdp_record* in_records,
150                       bluetooth_sdp_record* out_records, int count) {
151   int i;
152   bluetooth_sdp_record* in_record;
153   bluetooth_sdp_record* out_record;
154   char* free_ptr =
155       (char*)(&out_records[count]); /* set pointer to after the last entry */
156 
157   for (i = 0; i < count; i++) {
158     in_record = &in_records[i];
159     out_record = &out_records[i];
160     *out_record = *in_record;
161 
162     if (in_record->hdr.service_name == NULL ||
163         in_record->hdr.service_name_length == 0) {
164       out_record->hdr.service_name = NULL;
165       out_record->hdr.service_name_length = 0;
166     } else {
167       out_record->hdr.service_name = free_ptr;  // Update service_name pointer
168       // Copy string
169       memcpy(free_ptr, in_record->hdr.service_name,
170              in_record->hdr.service_name_length);
171       free_ptr += in_record->hdr.service_name_length;
172       *(free_ptr) = '\0';  // Set '\0' termination of string
173       free_ptr++;
174     }
175     if (in_record->hdr.user1_ptr != NULL) {
176       out_record->hdr.user1_ptr = (uint8_t*)free_ptr;  // Update pointer
177       memcpy(free_ptr, in_record->hdr.user1_ptr,
178              in_record->hdr.user1_ptr_len);  // Copy content
179       free_ptr += in_record->hdr.user1_ptr_len;
180     }
181     if (in_record->hdr.user2_ptr != NULL) {
182       out_record->hdr.user2_ptr = (uint8_t*)free_ptr;  // Update pointer
183       memcpy(free_ptr, in_record->hdr.user2_ptr,
184              in_record->hdr.user2_ptr_len);  // Copy content
185       free_ptr += in_record->hdr.user2_ptr_len;
186     }
187   }
188   return;
189 }
190 
191 /* Reserve a slot in sdp_slots, copy data and set a reference to the copy.
192  * The record_data will contain both the record and any data pointed to by
193  * the record.
194  * Currently this covers:
195  *   service_name string,
196  *   user1_ptr and
197  *   user2_ptr. */
alloc_sdp_slot(bluetooth_sdp_record * in_record)198 static int alloc_sdp_slot(bluetooth_sdp_record* in_record) {
199   int record_size = get_sdp_records_size(in_record, 1);
200   /* We are optimists here, and preallocate the record.
201    * This is to reduce the time we hold the sdp_lock. */
202   bluetooth_sdp_record* record = (bluetooth_sdp_record*)osi_malloc(record_size);
203 
204   copy_sdp_records(in_record, record, 1);
205   {
206     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
207     for (int i = 0; i < MAX_SDP_SLOTS; i++) {
208       if (sdp_slots[i].state == SDP_RECORD_FREE) {
209         sdp_slots[i].state = SDP_RECORD_ALLOCED;
210         sdp_slots[i].record_data = record;
211         return i;
212       }
213     }
214   }
215   APPL_TRACE_ERROR("%s() failed - no more free slots!", __func__);
216   /* Rearly the optimist is too optimistic, and cleanup is needed...*/
217   osi_free(record);
218   return -1;
219 }
220 
free_sdp_slot(int id)221 static int free_sdp_slot(int id) {
222   int handle = -1;
223   bluetooth_sdp_record* record = NULL;
224   if (id < 0 || id >= MAX_SDP_SLOTS) {
225     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
226     return handle;
227   }
228 
229   {
230     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
231     handle = sdp_slots[id].sdp_handle;
232     sdp_slots[id].sdp_handle = 0;
233     if (sdp_slots[id].state != SDP_RECORD_FREE) {
234       /* safe a copy of the pointer, and free after unlock() */
235       record = sdp_slots[id].record_data;
236     }
237     sdp_slots[id].state = SDP_RECORD_FREE;
238   }
239 
240   if (record != NULL) {
241     osi_free(record);
242   } else {
243     // Record have already been freed
244     handle = -1;
245   }
246   return handle;
247 }
248 
249 /***
250  * Use this to get a reference to a SDP slot AND change the state to
251  * SDP_RECORD_CREATE_INITIATED.
252  */
start_create_sdp(int id)253 static const sdp_slot_t* start_create_sdp(int id) {
254   if (id >= MAX_SDP_SLOTS) {
255     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
256     return NULL;
257   }
258 
259   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
260   if (sdp_slots[id].state != SDP_RECORD_ALLOCED) {
261     /* The record have been removed before this event occurred - e.g. deinit */
262     APPL_TRACE_ERROR(
263         "%s() failed - state for id %d is "
264         "sdp_slots[id].state = %d expected %d",
265         __func__, id, sdp_slots[id].state, SDP_RECORD_ALLOCED);
266     return NULL;
267   }
268 
269   return &(sdp_slots[id]);
270 }
271 
set_sdp_handle(int id,int handle)272 static void set_sdp_handle(int id, int handle) {
273   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
274   sdp_slots[id].sdp_handle = handle;
275 }
276 
create_sdp_record(bluetooth_sdp_record * record,int * record_handle)277 bt_status_t create_sdp_record(bluetooth_sdp_record* record,
278                               int* record_handle) {
279   int handle;
280 
281   handle = alloc_sdp_slot(record);
282   BTIF_TRACE_DEBUG("%s() handle = 0x%08x", __func__, handle);
283 
284   if (handle < 0) return BT_STATUS_FAIL;
285 
286   BTA_SdpCreateRecordByUser(INT_TO_PTR(handle));
287 
288   *record_handle = handle;
289 
290   return BT_STATUS_SUCCESS;
291 }
292 
remove_sdp_record(int record_id)293 bt_status_t remove_sdp_record(int record_id) {
294   int handle;
295 
296   if (record_id >= MAX_SDP_SLOTS) {
297     return BT_STATUS_PARM_INVALID;
298   }
299 
300   bluetooth_sdp_record* record;
301   bluetooth_sdp_types sdp_type = SDP_TYPE_RAW;
302   {
303     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
304     record = sdp_slots[record_id].record_data;
305     if (record != NULL) {
306       sdp_type = record->hdr.type;
307     }
308   }
309   tBTA_SERVICE_ID service_id = -1;
310   switch (sdp_type) {
311     case SDP_TYPE_MAP_MAS:
312       service_id = BTA_MAP_SERVICE_ID;
313       break;
314     case SDP_TYPE_MAP_MNS:
315       service_id = BTA_MN_SERVICE_ID;
316       break;
317     case SDP_TYPE_PBAP_PSE:
318       service_id = BTA_PBAP_SERVICE_ID;
319       break;
320     case SDP_TYPE_PBAP_PCE:
321       service_id = BTA_PCE_SERVICE_ID;
322       break;
323     default:
324       /* other enumeration values were not enabled in {@link on_create_record_event} */
325       break;
326   }
327   if (service_id > 0) {
328     // {@link btif_disable_service} sets the mask {@link btif_enabled_services}.
329     btif_disable_service(service_id);
330   }
331 
332   /* Get the Record handle, and free the slot */
333   handle = free_sdp_slot(record_id);
334   BTIF_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x", __func__, record_id,
335                    handle);
336 
337   /* Pass the actual record handle */
338   if (handle > 0) {
339     BTA_SdpRemoveRecordByUser(INT_TO_PTR(handle));
340     return BT_STATUS_SUCCESS;
341   }
342   BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created",
343                    __func__);
344   return BT_STATUS_FAIL;
345 }
346 
347 /******************************************************************************
348  * CALLBACK FUNCTIONS
349  * Called in BTA context to create/remove SDP records.
350  ******************************************************************************/
351 
on_create_record_event(int id)352 void on_create_record_event(int id) {
353   /*
354    * 1) Fetch the record pointer, and change its state?
355    * 2) switch on the type to create the correct record
356    * 3) Update state on completion
357    * 4) What to do at fail?
358    * */
359   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
360   const sdp_slot_t* sdp_slot = start_create_sdp(id);
361   tBTA_SERVICE_ID service_id = -1;
362   bluetooth_sdp_record* record;
363   /* In the case we are shutting down, sdp_slot is NULL */
364   if (sdp_slot != nullptr && (record = sdp_slot->record_data) != nullptr) {
365     int handle = -1;
366     switch (record->hdr.type) {
367       case SDP_TYPE_MAP_MAS:
368         handle = add_maps_sdp(&record->mas);
369         service_id = BTA_MAP_SERVICE_ID;
370         break;
371       case SDP_TYPE_MAP_MNS:
372         handle = add_mapc_sdp(&record->mns);
373         service_id = BTA_MN_SERVICE_ID;
374         break;
375       case SDP_TYPE_PBAP_PSE:
376         handle = add_pbaps_sdp(&record->pse);
377         service_id = BTA_PBAP_SERVICE_ID;
378         break;
379       case SDP_TYPE_OPP_SERVER:
380         handle = add_opps_sdp(&record->ops);
381         break;
382       case SDP_TYPE_SAP_SERVER:
383         handle = add_saps_sdp(&record->sap);
384         break;
385       case SDP_TYPE_PBAP_PCE:
386         handle = add_pbapc_sdp(&record->pce);
387         service_id = BTA_PCE_SERVICE_ID;
388         break;
389       case SDP_TYPE_MPS:
390         handle = add_mps_sdp(&record->mps);
391         break;
392       case SDP_TYPE_RAW:
393         if (record->hdr.rfcomm_channel_number > 0) {
394           handle = add_rfc_sdp_rec(record->hdr.service_name, record->hdr.uuid,
395                                    record->hdr.rfcomm_channel_number);
396         }
397         break;
398       default:
399         BTIF_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
400         break;
401     }
402     if (handle != -1) {
403       set_sdp_handle(id, handle);
404       if (service_id > 0) {
405         /**
406          * {@link btif_enable_service} calls {@link btif_dm_enable_service}, which calls {@link
407          * btif_in_execute_service_request}.
408          *     - {@link btif_enable_service} sets the mask {@link btif_enabled_services}.
409          *     - {@link btif_dm_enable_service} invokes the java callback to return uuids based
410          *       on the enabled services mask.
411          *     - {@link btif_in_execute_service_request} gates the java callback in {@link
412          *       btif_dm_enable_service}.
413          */
414         btif_enable_service(service_id);
415       }
416     }
417   }
418 }
419 
on_remove_record_event(int handle)420 void on_remove_record_event(int handle) {
421   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
422 
423   // User data carries the actual SDP handle, not the ID.
424   if (handle != -1 && handle != 0) {
425     bool result;
426     result = get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(handle);
427     if (!result) {
428       BTIF_TRACE_ERROR("  Unable to remove handle 0x%08x", handle);
429     }
430   }
431 }
432 
433 /****
434  * Below the actual functions accessing BTA context data - hence only call from
435  * BTA context!
436  */
437 
438 /* Create a MAP MAS SDP record based on information stored in a
439  * bluetooth_sdp_mas_record */
add_maps_sdp(const bluetooth_sdp_mas_record * rec)440 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) {
441   tSDP_PROTOCOL_ELEM protoList[3];
442   uint16_t service = UUID_SERVCLASS_MESSAGE_ACCESS;
443   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
444   bool status = true;
445   uint32_t sdp_handle = 0;
446   uint8_t temp[4];
447   uint8_t* p_temp = temp;
448 
449   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
450   if (sdp_handle == 0) {
451     LOG_ERROR("Unable to register MAPS Service");
452     return sdp_handle;
453   }
454 
455   /* add service class */
456   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
457       sdp_handle, 1, &service);
458   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
459 
460   /* add protocol list, including RFCOMM scn */
461   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
462   protoList[0].num_params = 0;
463   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
464   protoList[1].num_params = 1;
465   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
466   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
467   protoList[2].num_params = 0;
468   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
469       sdp_handle, 3, protoList);
470 
471   /* Add a name entry */
472   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
473       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
474       (uint32_t)(rec->hdr.service_name_length + 1),
475       (uint8_t*)rec->hdr.service_name);
476 
477   /* Add in the Bluetooth Profile Descriptor List */
478   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
479       sdp_handle, UUID_SERVCLASS_MAP_PROFILE, rec->hdr.profile_version);
480 
481   /* Add MAS instance ID */
482   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
483       sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE, (uint32_t)1,
484       (uint8_t*)&rec->mas_instance_id);
485 
486   /* Add supported message types */
487   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
488       sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE, (uint32_t)1,
489       (uint8_t*)&rec->supported_message_types);
490 
491   /* Add supported feature */
492   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
493   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
494       sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, UINT_DESC_TYPE, (uint32_t)4,
495       temp);
496 
497   /* Add the L2CAP PSM if present */
498   if (rec->hdr.l2cap_psm != -1) {
499     p_temp = temp;  // The macro modifies p_temp, hence rewind.
500     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
501     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
502         sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
503   }
504 
505   /* Make the service browseable */
506   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
507       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
508 
509   if (!status) {
510     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
511     sdp_handle = 0;
512     APPL_TRACE_ERROR("%s() FAILED", __func__);
513   } else {
514     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
515     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
516                      sdp_handle);
517   }
518   return sdp_handle;
519 }
520 
521 /* Create a MAP MNS SDP record based on information stored in a
522  * bluetooth_sdp_mns_record */
add_mapc_sdp(const bluetooth_sdp_mns_record * rec)523 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) {
524   tSDP_PROTOCOL_ELEM protoList[3];
525   uint16_t service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
526   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
527   bool status = true;
528   uint32_t sdp_handle = 0;
529   uint8_t temp[4];
530   uint8_t* p_temp = temp;
531 
532   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
533   if (sdp_handle == 0) {
534     LOG_ERROR("Unable to register MAP Notification Service");
535     return sdp_handle;
536   }
537 
538   /* add service class */
539   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
540       sdp_handle, 1, &service);
541   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
542 
543   /* add protocol list, including RFCOMM scn */
544   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
545   protoList[0].num_params = 0;
546   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
547   protoList[1].num_params = 1;
548   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
549   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
550   protoList[2].num_params = 0;
551   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
552       sdp_handle, 3, protoList);
553 
554   /* Add a name entry */
555   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
556       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
557       (uint32_t)(rec->hdr.service_name_length + 1),
558       (uint8_t*)rec->hdr.service_name);
559 
560   /* Add in the Bluetooth Profile Descriptor List */
561   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
562       sdp_handle, UUID_SERVCLASS_MAP_PROFILE, rec->hdr.profile_version);
563 
564   /* Add supported feature */
565   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
566   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
567       sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES, UINT_DESC_TYPE, (uint32_t)4,
568       temp);
569 
570   /* Add the L2CAP PSM if present */
571   if (rec->hdr.l2cap_psm != -1) {
572     p_temp = temp;  // The macro modifies p_temp, hence rewind.
573     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
574     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
575         sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
576   }
577 
578   /* Make the service browseable */
579   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
580       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
581 
582   if (!status) {
583     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
584     sdp_handle = 0;
585     APPL_TRACE_ERROR("%s() FAILED", __func__);
586   } else {
587     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
588     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
589                      sdp_handle);
590   }
591   return sdp_handle;
592 }
593 
594 /* Create a PBAP Client SDP record based on information stored in a
595  * bluetooth_sdp_pce_record */
add_pbapc_sdp(const bluetooth_sdp_pce_record * rec)596 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec) {
597   uint16_t service = UUID_SERVCLASS_PBAP_PCE;
598   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
599   bool status = true;
600   uint32_t sdp_handle = 0;
601 
602   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
603   if (sdp_handle == 0) {
604     LOG_ERROR("Unable to register PBAP Client Service");
605     return sdp_handle;
606   }
607 
608   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
609       sdp_handle, 1, &service);
610 
611   /* Add a name entry */
612   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
613       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
614       (uint32_t)(rec->hdr.service_name_length + 1),
615       (uint8_t*)rec->hdr.service_name);
616 
617   /* Add in the Bluetooth Profile Descriptor List */
618   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
619       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
620 
621   /* Make the service browseable */
622   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
623       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
624 
625   if (!status) {
626     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
627     sdp_handle = 0;
628     APPL_TRACE_ERROR("%s() FAILED", __func__);
629     return sdp_handle;
630   }
631   bta_sys_add_uuid(service); /* UUID_SERVCLASS_PBAP_PCE */
632   APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
633                    sdp_handle);
634   return sdp_handle;
635 }
636 
637 /* Create a PBAP Server SDP record based on information stored in a
638  * bluetooth_sdp_pse_record */
add_pbaps_sdp(const bluetooth_sdp_pse_record * rec)639 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) {
640   tSDP_PROTOCOL_ELEM protoList[3];
641   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
642   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
643   bool status = true;
644   uint32_t sdp_handle = 0;
645   uint8_t temp[4];
646   uint8_t* p_temp = temp;
647 
648   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
649   if (sdp_handle == 0) {
650     LOG_ERROR("Unable to register PBAP Server Service");
651     return sdp_handle;
652   }
653 
654   /* add service class */
655   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
656       sdp_handle, 1, &service);
657   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
658 
659   /* add protocol list, including RFCOMM scn */
660   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
661   protoList[0].num_params = 0;
662   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
663   protoList[1].num_params = 1;
664   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
665   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
666   protoList[2].num_params = 0;
667   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
668       sdp_handle, 3, protoList);
669 
670   /* Add a name entry */
671   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
672       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
673       (uint32_t)(rec->hdr.service_name_length + 1),
674       (uint8_t*)rec->hdr.service_name);
675   if (bluetooth::common::init_flags::
676           pbap_pse_dynamic_version_upgrade_is_enabled()) {
677     /*
678     PBAP 1.1.1  repositories bits
679     Bit 0 = Local Phonebook
680     Bit 1 = SIM card
681     Bit 2~7 reserved for future use */
682     uint8_t supported_repositories_1_1_mask = 0x03;
683     uint8_t supported_repositories_1_1 =
684         ((uint8_t)rec->supported_repositories) &
685         supported_repositories_1_1_mask;
686     status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
687         sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, 0x0101);
688 
689     /* Add supported repositories 1 byte */
690     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
691         sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (uint32_t)1,
692         (uint8_t*)&supported_repositories_1_1);
693     APPL_TRACE_DEBUG(" supported_repositories_1_1: 0x%x",
694                      supported_repositories_1_1);
695     sdp_save_local_pse_record_attributes(
696         rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm,
697         rec->hdr.profile_version, rec->supported_features,
698         rec->supported_repositories);
699   } else {
700     /* Add in the Bluetooth Profile Descriptor List */
701     status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
702         sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
703 
704     /* Add supported repositories 1 byte */
705     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
706         sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (uint32_t)1,
707         (uint8_t*)&rec->supported_repositories);
708     /* Add supported feature 4 bytes*/
709     UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
710     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
711         sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES, UINT_DESC_TYPE,
712         (uint32_t)4, temp);
713 
714     /* Add the L2CAP PSM if present */
715     if (rec->hdr.l2cap_psm != -1) {
716       p_temp = temp;  // The macro modifies p_temp, hence rewind.
717       UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
718       status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
719           sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2,
720           temp);
721     }
722 #if 0
723   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
724       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
725       (uint32_t)(rec->hdr.service_name_length + 1),
726       (uint8_t*)rec->hdr.service_name);
727 
728   /* Add in the Bluetooth Profile Descriptor List */
729   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
730       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
731 
732   /* Add supported repositories 1 byte */
733   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
734       sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (uint32_t)1,
735       (uint8_t*)&rec->supported_repositories);
736 
737   /* Add supported feature 4 bytes*/
738   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
739   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
740       sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES, UINT_DESC_TYPE, (uint32_t)4,
741       temp);
742 
743   /* Add the L2CAP PSM if present */
744   if (rec->hdr.l2cap_psm != -1) {
745     p_temp = temp;  // The macro modifies p_temp, hence rewind.
746     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
747     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
748         sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
749 #endif
750   }
751 
752   /* Make the service browseable */
753   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
754       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
755 
756   if (!status) {
757     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
758     sdp_handle = 0;
759     APPL_TRACE_ERROR("%s() FAILED", __func__);
760   } else {
761     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
762     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
763                      sdp_handle);
764   }
765   return sdp_handle;
766 }
767 
768 /* Create a OPP Server SDP record based on information stored in a
769  * bluetooth_sdp_ops_record */
770 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) {
771   tSDP_PROTOCOL_ELEM protoList[3];
772   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
773   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
774   uint8_t type_len[rec->supported_formats_list_len];
775   uint8_t desc_type[rec->supported_formats_list_len];
776   uint8_t* type_value[rec->supported_formats_list_len];
777   bool status = true;
778   uint32_t sdp_handle = 0;
779   uint8_t temp[4];
780   uint8_t* p_temp = temp;
781   tBTA_UTL_COD cod;
782   int i, j;
783 
784   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
785   if (sdp_handle == 0) {
786     LOG_ERROR("Unable to register Object Push Server Service");
787     return sdp_handle;
788   }
789 
790   /* add service class */
791   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
792       sdp_handle, 1, &service);
793   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
794 
795   /* add protocol list, including RFCOMM scn */
796   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
797   protoList[0].num_params = 0;
798   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
799   protoList[1].num_params = 1;
800   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
801   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
802   protoList[2].num_params = 0;
803   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
804       sdp_handle, 3, protoList);
805 
806   /* Add a name entry */
807   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
808       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
809       (uint32_t)(rec->hdr.service_name_length + 1),
810       (uint8_t*)rec->hdr.service_name);
811 
812   /* Add in the Bluetooth Profile Descriptor List */
813   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
814       sdp_handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, rec->hdr.profile_version);
815 
816   /* add sequence for supported types */
817   for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) {
818     type_value[j] = (uint8_t*)&rec->supported_formats_list[i];
819     desc_type[j] = UINT_DESC_TYPE;
820     type_len[j++] = 1;
821   }
822 
823   status &= get_legacy_stack_sdp_api()->handle.SDP_AddSequence(
824       sdp_handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
825       (uint8_t)rec->supported_formats_list_len, desc_type, type_len,
826       type_value);
827 
828   /* Add the L2CAP PSM if present */
829   if (rec->hdr.l2cap_psm != -1) {
830     p_temp = temp;  // The macro modifies p_temp, hence rewind.
831     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
832     status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
833         sdp_handle, ATTR_ID_GOEP_L2CAP_PSM, UINT_DESC_TYPE, (uint32_t)2, temp);
834   }
835 
836   /* Make the service browseable */
837   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
838       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
839 
840   if (!status) {
841     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
842     sdp_handle = 0;
843     APPL_TRACE_ERROR("%s() FAILED", __func__);
844   } else {
845     /* set class of device */
846     cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
847     utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
848 
849     bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
850     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
851                      sdp_handle);
852   }
853   return sdp_handle;
854 }
855 
856 // Create a Sim Access Profile SDP record based on information stored in a
857 // bluetooth_sdp_sap_record.
858 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) {
859   tSDP_PROTOCOL_ELEM protoList[2];
860   uint16_t services[2];
861   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
862   bool status = true;
863   uint32_t sdp_handle = 0;
864 
865   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
866   if (sdp_handle == 0) {
867     LOG_ERROR("Unable to register SAPS Service");
868     return sdp_handle;
869   }
870 
871   services[0] = UUID_SERVCLASS_SAP;
872   services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY;
873 
874   // add service class
875   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
876       sdp_handle, 2, services);
877   memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM));
878 
879   // add protocol list, including RFCOMM scn
880   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
881   protoList[0].num_params = 0;
882   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
883   protoList[1].num_params = 1;
884   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
885   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProtocolList(
886       sdp_handle, 2, protoList);
887 
888   // Add a name entry
889   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
890       sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME, (uint8_t)TEXT_STR_DESC_TYPE,
891       (uint32_t)(rec->hdr.service_name_length + 1),
892       (uint8_t*)rec->hdr.service_name);
893 
894   // Add in the Bluetooth Profile Descriptor List
895   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
896       sdp_handle, UUID_SERVCLASS_SAP, rec->hdr.profile_version);
897 
898   // Make the service browseable
899   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
900       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
901 
902   if (!status) {
903     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
904     sdp_handle = 0;
905     APPL_TRACE_ERROR("%s(): FAILED deleting record", __func__);
906   } else {
907     bta_sys_add_uuid(UUID_SERVCLASS_SAP);
908     APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
909                      sdp_handle);
910   }
911   return sdp_handle;
912 }
913 
914 /* Create a Multi-Profile Specification SDP record based on information stored
915  * in a bluetooth_sdp_mps_record */
916 static int add_mps_sdp(const bluetooth_sdp_mps_record* rec) {
917   uint16_t service = UUID_SERVCLASS_MPS_SC;
918   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
919   bool status = true;
920   uint32_t sdp_handle = 0;
921 
922   sdp_handle = get_legacy_stack_sdp_api()->handle.SDP_CreateRecord();
923   if (sdp_handle == 0) {
924     LOG_ERROR("Unable to register MPS record");
925     return sdp_handle;
926   }
927 
928   status &= get_legacy_stack_sdp_api()->handle.SDP_AddServiceClassIdList(
929       sdp_handle, 1, &service);
930 
931   /* Add in the Bluetooth Profile Descriptor List */
932   status &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList(
933       sdp_handle, UUID_SERVCLASS_MPS_PROFILE, rec->hdr.profile_version);
934 
935   /* Add supported scenarios MPSD */
936   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
937       sdp_handle, ATTR_ID_MPS_SUPPORTED_SCENARIOS_MPSD, UINT_DESC_TYPE,
938       (uint32_t)8, (uint8_t*)&rec->supported_scenarios_mpsd);
939   /* Add supported scenarios MPMD */
940   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
941       sdp_handle, ATTR_ID_MPS_SUPPORTED_SCENARIOS_MPMD, UINT_DESC_TYPE,
942       (uint32_t)8, (uint8_t*)&rec->supported_scenarios_mpmd);
943   /* Add supported dependencies */
944   status &= get_legacy_stack_sdp_api()->handle.SDP_AddAttribute(
945       sdp_handle, ATTR_ID_MPS_SUPPORTED_DEPENDENCIES, UINT_DESC_TYPE,
946       (uint32_t)2, (uint8_t*)&rec->supported_dependencies);
947 
948   /* Make the service browseable */
949   status &= get_legacy_stack_sdp_api()->handle.SDP_AddUuidSequence(
950       sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
951 
952   if (!status) {
953     get_legacy_stack_sdp_api()->handle.SDP_DeleteRecord(sdp_handle);
954     sdp_handle = 0;
955     APPL_TRACE_ERROR("%s() FAILED", __func__);
956     return sdp_handle;
957   }
958   bta_sys_add_uuid(service); /* UUID_SERVCLASS_MPS_SC */
959   APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
960                    sdp_handle);
961   return sdp_handle;
962 }
963