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 <pthread.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include <mutex>
36 
37 #include <hardware/bluetooth.h>
38 #include <hardware/bt_sdp.h>
39 
40 #include "bta_sdp_api.h"
41 #include "bta_sys.h"
42 #include "btif_common.h"
43 #include "btif_sock_util.h"
44 #include "btif_util.h"
45 #include "osi/include/allocator.h"
46 #include "utl.h"
47 
48 // Protects the sdp_slots array from concurrent access.
49 static std::recursive_mutex sdp_lock;
50 
51 /**
52  * The need for a state variable have been reduced to two states.
53  * The remaining state control is handled by program flow
54  */
55 typedef enum {
56   SDP_RECORD_FREE = 0,
57   SDP_RECORD_ALLOCED,
58 } sdp_state_t;
59 
60 typedef struct {
61   sdp_state_t state;
62   int sdp_handle;
63   bluetooth_sdp_record* record_data;
64 } sdp_slot_t;
65 
66 #define MAX_SDP_SLOTS 128
67 static sdp_slot_t sdp_slots[MAX_SDP_SLOTS];
68 
69 /*****************************************************************************
70  * LOCAL Functions
71  *****************************************************************************/
72 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec);
73 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec);
74 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec);
75 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec);
76 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec);
77 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec);
78 bt_status_t remove_sdp_record(int record_id);
79 static int free_sdp_slot(int id);
80 
81 /******************************************************************************
82  * WARNING: Functions below are not called in BTU context.
83  * Introduced to make it possible to create SDP records from JAVA with both a
84  * RFCOMM channel and a L2CAP PSM.
85  * Overall architecture:
86  *  1) JAVA calls createRecord() which returns a pseudo ID which at a later
87  *     point will be linked to a specific SDP handle.
88  *  2) createRecord() requests the BTU task(thread) to call a callback in SDP
89  *     which creates the actual record, and updates the ID<->SDPHandle map
90  *     based on the ID beeing passed to BTA as user_data.
91  *****************************************************************************/
92 
init_sdp_slots()93 static void init_sdp_slots() {
94   int i;
95   memset(sdp_slots, 0, sizeof(sdp_slot_t) * MAX_SDP_SLOTS);
96   /* if SDP_RECORD_FREE is zero - no need to set the value */
97   if (SDP_RECORD_FREE != 0) {
98     for (i = 0; i < MAX_SDP_SLOTS; i++) {
99       sdp_slots[i].state = SDP_RECORD_FREE;
100     }
101   }
102 }
103 
sdp_server_init()104 bt_status_t sdp_server_init() {
105   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
106   init_sdp_slots();
107   return BT_STATUS_SUCCESS;
108 }
109 
sdp_server_cleanup()110 void sdp_server_cleanup() {
111   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
112   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
113   int i;
114   for (i = 0; i < MAX_SDP_SLOTS; i++) {
115     /*remove_sdp_record(i); we cannot send messages to the other threads, since
116     * they might
117     *                       have been shut down already. Just do local cleanup.
118     */
119     free_sdp_slot(i);
120   }
121 }
122 
get_sdp_records_size(bluetooth_sdp_record * in_record,int count)123 int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) {
124   bluetooth_sdp_record* record = in_record;
125   int records_size = 0;
126   int i;
127   for (i = 0; i < count; i++) {
128     record = &in_record[i];
129     records_size += sizeof(bluetooth_sdp_record);
130     records_size += record->hdr.service_name_length;
131     if (record->hdr.service_name_length > 0) {
132       records_size++; /* + '\0' termination of string */
133     }
134     records_size += record->hdr.user1_ptr_len;
135     records_size += record->hdr.user2_ptr_len;
136   }
137   return records_size;
138 }
139 
140 /* Deep copy all content of in_records into out_records.
141  * out_records must point to a chunk of memory large enough to contain all
142  * the data. Use getSdpRecordsSize() to calculate the needed size. */
copy_sdp_records(bluetooth_sdp_record * in_records,bluetooth_sdp_record * out_records,int count)143 void copy_sdp_records(bluetooth_sdp_record* in_records,
144                       bluetooth_sdp_record* out_records, int count) {
145   int i;
146   bluetooth_sdp_record* in_record;
147   bluetooth_sdp_record* out_record;
148   char* free_ptr =
149       (char*)(&out_records[count]); /* set pointer to after the last entry */
150 
151   for (i = 0; i < count; i++) {
152     in_record = &in_records[i];
153     out_record = &out_records[i];
154     *out_record = *in_record;
155 
156     if (in_record->hdr.service_name == NULL ||
157         in_record->hdr.service_name_length == 0) {
158       out_record->hdr.service_name = NULL;
159       out_record->hdr.service_name_length = 0;
160     } else {
161       out_record->hdr.service_name = free_ptr;  // Update service_name pointer
162       // Copy string
163       memcpy(free_ptr, in_record->hdr.service_name,
164              in_record->hdr.service_name_length);
165       free_ptr += in_record->hdr.service_name_length;
166       *(free_ptr) = '\0';  // Set '\0' termination of string
167       free_ptr++;
168     }
169     if (in_record->hdr.user1_ptr != NULL) {
170       out_record->hdr.user1_ptr = (uint8_t*)free_ptr;  // Update pointer
171       memcpy(free_ptr, in_record->hdr.user1_ptr,
172              in_record->hdr.user1_ptr_len);  // Copy content
173       free_ptr += in_record->hdr.user1_ptr_len;
174     }
175     if (in_record->hdr.user2_ptr != NULL) {
176       out_record->hdr.user2_ptr = (uint8_t*)free_ptr;  // Update pointer
177       memcpy(free_ptr, in_record->hdr.user2_ptr,
178              in_record->hdr.user2_ptr_len);  // Copy content
179       free_ptr += in_record->hdr.user2_ptr_len;
180     }
181   }
182   return;
183 }
184 
185 /* Reserve a slot in sdp_slots, copy data and set a reference to the copy.
186  * The record_data will contain both the record and any data pointed to by
187  * the record.
188  * Currently this covers:
189  *   service_name string,
190  *   user1_ptr and
191  *   user2_ptr. */
alloc_sdp_slot(bluetooth_sdp_record * in_record)192 static int alloc_sdp_slot(bluetooth_sdp_record* in_record) {
193   int record_size = get_sdp_records_size(in_record, 1);
194   /* We are optimists here, and preallocate the record.
195    * This is to reduce the time we hold the sdp_lock. */
196   bluetooth_sdp_record* record = (bluetooth_sdp_record*)osi_malloc(record_size);
197 
198   copy_sdp_records(in_record, record, 1);
199   {
200     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
201     for (int i = 0; i < MAX_SDP_SLOTS; i++) {
202       if (sdp_slots[i].state == SDP_RECORD_FREE) {
203         sdp_slots[i].state = SDP_RECORD_ALLOCED;
204         sdp_slots[i].record_data = record;
205         return i;
206       }
207     }
208   }
209   APPL_TRACE_ERROR("%s() failed - no more free slots!", __func__);
210   /* Rearly the optimist is too optimistic, and cleanup is needed...*/
211   osi_free(record);
212   return -1;
213 }
214 
free_sdp_slot(int id)215 static int free_sdp_slot(int id) {
216   int handle = -1;
217   bluetooth_sdp_record* record = NULL;
218   if (id < 0 || id >= MAX_SDP_SLOTS) {
219     android_errorWriteLog(0x534e4554, "37502513");
220     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
221     return handle;
222   }
223 
224   {
225     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
226     handle = sdp_slots[id].sdp_handle;
227     sdp_slots[id].sdp_handle = 0;
228     if (sdp_slots[id].state != SDP_RECORD_FREE) {
229       /* safe a copy of the pointer, and free after unlock() */
230       record = sdp_slots[id].record_data;
231     }
232     sdp_slots[id].state = SDP_RECORD_FREE;
233   }
234 
235   if (record != NULL) {
236     osi_free(record);
237   } else {
238     // Record have already been freed
239     handle = -1;
240   }
241   return handle;
242 }
243 
244 /***
245  * Use this to get a reference to a SDP slot AND change the state to
246  * SDP_RECORD_CREATE_INITIATED.
247  */
start_create_sdp(int id)248 static const sdp_slot_t* start_create_sdp(int id) {
249   if (id >= MAX_SDP_SLOTS) {
250     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
251     return NULL;
252   }
253 
254   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
255   if (sdp_slots[id].state != SDP_RECORD_ALLOCED) {
256     /* The record have been removed before this event occurred - e.g. deinit */
257     APPL_TRACE_ERROR(
258         "%s() failed - state for id %d is "
259         "sdp_slots[id].state = %d expected %d",
260         __func__, id, sdp_slots[id].state, SDP_RECORD_ALLOCED);
261     return NULL;
262   }
263 
264   return &(sdp_slots[id]);
265 }
266 
set_sdp_handle(int id,int handle)267 static void set_sdp_handle(int id, int handle) {
268   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
269   sdp_slots[id].sdp_handle = handle;
270 }
271 
create_sdp_record(bluetooth_sdp_record * record,int * record_handle)272 bt_status_t create_sdp_record(bluetooth_sdp_record* record,
273                               int* record_handle) {
274   int handle;
275 
276   handle = alloc_sdp_slot(record);
277   BTIF_TRACE_DEBUG("%s() handle = 0x%08x", __func__, handle);
278 
279   if (handle < 0) return BT_STATUS_FAIL;
280 
281   BTA_SdpCreateRecordByUser(INT_TO_PTR(handle));
282 
283   *record_handle = handle;
284 
285   return BT_STATUS_SUCCESS;
286 }
287 
remove_sdp_record(int record_id)288 bt_status_t remove_sdp_record(int record_id) {
289   int handle;
290 
291   /* Get the Record handle, and free the slot */
292   handle = free_sdp_slot(record_id);
293   BTIF_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x", __func__, record_id,
294                    handle);
295 
296   /* Pass the actual record handle */
297   if (handle > 0) {
298     BTA_SdpRemoveRecordByUser(INT_TO_PTR(handle));
299     return BT_STATUS_SUCCESS;
300   }
301   BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created",
302                    __func__);
303   return BT_STATUS_FAIL;
304 }
305 
306 /******************************************************************************
307  * CALLBACK FUNCTIONS
308  * Called in BTA context to create/remove SDP records.
309  ******************************************************************************/
310 
on_create_record_event(int id)311 void on_create_record_event(int id) {
312   /*
313    * 1) Fetch the record pointer, and change its state?
314    * 2) switch on the type to create the correct record
315    * 3) Update state on completion
316    * 4) What to do at fail?
317    * */
318   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
319   const sdp_slot_t* sdp_slot = start_create_sdp(id);
320   /* In the case we are shutting down, sdp_slot is NULL */
321   if (sdp_slot != NULL) {
322     bluetooth_sdp_record* record = sdp_slot->record_data;
323     int handle = -1;
324     switch (record->hdr.type) {
325       case SDP_TYPE_MAP_MAS:
326         handle = add_maps_sdp(&record->mas);
327         break;
328       case SDP_TYPE_MAP_MNS:
329         handle = add_mapc_sdp(&record->mns);
330         break;
331       case SDP_TYPE_PBAP_PSE:
332         handle = add_pbaps_sdp(&record->pse);
333         break;
334       case SDP_TYPE_OPP_SERVER:
335         handle = add_opps_sdp(&record->ops);
336         break;
337       case SDP_TYPE_SAP_SERVER:
338         handle = add_saps_sdp(&record->sap);
339         break;
340       case SDP_TYPE_PBAP_PCE:
341         handle = add_pbapc_sdp(&record->pce);
342         break;
343       default:
344         BTIF_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
345         break;
346     }
347     if (handle != -1) {
348       set_sdp_handle(id, handle);
349     }
350   }
351 }
352 
on_remove_record_event(int handle)353 void on_remove_record_event(int handle) {
354   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
355 
356   // User data carries the actual SDP handle, not the ID.
357   if (handle != -1 && handle != 0) {
358     bool result;
359     result = SDP_DeleteRecord(handle);
360     if (!result) {
361       BTIF_TRACE_ERROR("  Unable to remove handle 0x%08x", handle);
362     }
363   }
364 }
365 
366 /****
367  * Below the actual functions accessing BTA context data - hence only call from
368  * BTA context!
369  */
370 
371 /* Create a MAP MAS SDP record based on information stored in a
372  * bluetooth_sdp_mas_record */
add_maps_sdp(const bluetooth_sdp_mas_record * rec)373 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) {
374   tSDP_PROTOCOL_ELEM protoList[3];
375   uint16_t service = UUID_SERVCLASS_MESSAGE_ACCESS;
376   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
377   bool status = true;
378   uint32_t sdp_handle = 0;
379   uint8_t temp[4];
380   uint8_t* p_temp = temp;
381 
382   sdp_handle = SDP_CreateRecord();
383   if (sdp_handle == 0) {
384     LOG_ERROR("Unable to register MAPS Service");
385     return sdp_handle;
386   }
387 
388   /* add service class */
389   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
390   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
391 
392   /* add protocol list, including RFCOMM scn */
393   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
394   protoList[0].num_params = 0;
395   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
396   protoList[1].num_params = 1;
397   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
398   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
399   protoList[2].num_params = 0;
400   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
401 
402   /* Add a name entry */
403   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
404                              (uint8_t)TEXT_STR_DESC_TYPE,
405                              (uint32_t)(rec->hdr.service_name_length + 1),
406                              (uint8_t*)rec->hdr.service_name);
407 
408   /* Add in the Bluetooth Profile Descriptor List */
409   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_MAP_PROFILE,
410                                          rec->hdr.profile_version);
411 
412   /* Add MAS instance ID */
413   status &=
414       SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
415                        (uint32_t)1, (uint8_t*)&rec->mas_instance_id);
416 
417   /* Add supported message types */
418   status &=
419       SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
420                        (uint32_t)1, (uint8_t*)&rec->supported_message_types);
421 
422   /* Add supported feature */
423   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
424   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
425                              UINT_DESC_TYPE, (uint32_t)4, temp);
426 
427   /* Add the L2CAP PSM if present */
428   if (rec->hdr.l2cap_psm != -1) {
429     p_temp = temp;  // The macro modifies p_temp, hence rewind.
430     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
431     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
432                                UINT_DESC_TYPE, (uint32_t)2, temp);
433   }
434 
435   /* Make the service browseable */
436   status &=
437       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
438 
439   if (!status) {
440     SDP_DeleteRecord(sdp_handle);
441     sdp_handle = 0;
442     APPL_TRACE_ERROR("%s() FAILED", __func__);
443   } else {
444     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
445     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
446                      sdp_handle);
447   }
448   return sdp_handle;
449 }
450 
451 /* Create a MAP MNS SDP record based on information stored in a
452  * bluetooth_sdp_mns_record */
add_mapc_sdp(const bluetooth_sdp_mns_record * rec)453 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) {
454   tSDP_PROTOCOL_ELEM protoList[3];
455   uint16_t service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
456   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
457   bool status = true;
458   uint32_t sdp_handle = 0;
459   uint8_t temp[4];
460   uint8_t* p_temp = temp;
461 
462   sdp_handle = SDP_CreateRecord();
463   if (sdp_handle == 0) {
464     LOG_ERROR("Unable to register MAP Notification Service");
465     return sdp_handle;
466   }
467 
468   /* add service class */
469   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
470   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
471 
472   /* add protocol list, including RFCOMM scn */
473   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
474   protoList[0].num_params = 0;
475   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
476   protoList[1].num_params = 1;
477   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
478   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
479   protoList[2].num_params = 0;
480   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
481 
482   /* Add a name entry */
483   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
484                              (uint8_t)TEXT_STR_DESC_TYPE,
485                              (uint32_t)(rec->hdr.service_name_length + 1),
486                              (uint8_t*)rec->hdr.service_name);
487 
488   /* Add in the Bluetooth Profile Descriptor List */
489   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_MAP_PROFILE,
490                                          rec->hdr.profile_version);
491 
492   /* Add supported feature */
493   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
494   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
495                              UINT_DESC_TYPE, (uint32_t)4, 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 &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
502                                UINT_DESC_TYPE, (uint32_t)2, temp);
503   }
504 
505   /* Make the service browseable */
506   status &=
507       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
508 
509   if (!status) {
510     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 PBAP Client SDP record based on information stored in a
522  * bluetooth_sdp_pce_record */
add_pbapc_sdp(const bluetooth_sdp_pce_record * rec)523 static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec) {
524   uint16_t service = UUID_SERVCLASS_PBAP_PCE;
525   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
526   bool status = true;
527   uint32_t sdp_handle = 0;
528 
529   sdp_handle = SDP_CreateRecord();
530   if (sdp_handle == 0) {
531     LOG_ERROR("Unable to register PBAP Client Service");
532     return sdp_handle;
533   }
534 
535   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
536 
537   /* Add a name entry */
538   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
539                              (uint8_t)TEXT_STR_DESC_TYPE,
540                              (uint32_t)(rec->hdr.service_name_length + 1),
541                              (uint8_t*)rec->hdr.service_name);
542 
543   /* Add in the Bluetooth Profile Descriptor List */
544   status &= SDP_AddProfileDescriptorList(
545       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
546 
547   /* Make the service browseable */
548   status &=
549       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
550 
551   if (!status) {
552     SDP_DeleteRecord(sdp_handle);
553     sdp_handle = 0;
554     APPL_TRACE_ERROR("%s() FAILED", __func__);
555     return sdp_handle;
556   }
557   bta_sys_add_uuid(service); /* UUID_SERVCLASS_PBAP_PCE */
558   APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
559                    sdp_handle);
560   return sdp_handle;
561 }
562 
563 /* Create a PBAP Server SDP record based on information stored in a
564  * bluetooth_sdp_pse_record */
add_pbaps_sdp(const bluetooth_sdp_pse_record * rec)565 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) {
566   tSDP_PROTOCOL_ELEM protoList[3];
567   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
568   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
569   bool status = true;
570   uint32_t sdp_handle = 0;
571   uint8_t temp[4];
572   uint8_t* p_temp = temp;
573 
574   sdp_handle = SDP_CreateRecord();
575   if (sdp_handle == 0) {
576     LOG_ERROR("Unable to register PBAP Server Service");
577     return sdp_handle;
578   }
579 
580   /* add service class */
581   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
582   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
583 
584   /* add protocol list, including RFCOMM scn */
585   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
586   protoList[0].num_params = 0;
587   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
588   protoList[1].num_params = 1;
589   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
590   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
591   protoList[2].num_params = 0;
592   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
593 
594   /* Add a name entry */
595   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
596                              (uint8_t)TEXT_STR_DESC_TYPE,
597                              (uint32_t)(rec->hdr.service_name_length + 1),
598                              (uint8_t*)rec->hdr.service_name);
599 
600   /* Add in the Bluetooth Profile Descriptor List */
601   status &= SDP_AddProfileDescriptorList(
602       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
603 
604   /* Add supported repositories 1 byte */
605   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES,
606                              UINT_DESC_TYPE, (uint32_t)1,
607                              (uint8_t*)&rec->supported_repositories);
608 
609   /* Add supported feature 4 bytes*/
610   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
611   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES,
612                              UINT_DESC_TYPE, (uint32_t)4, temp);
613 
614   /* Add the L2CAP PSM if present */
615   if (rec->hdr.l2cap_psm != -1) {
616     p_temp = temp;  // The macro modifies p_temp, hence rewind.
617     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
618     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
619                                UINT_DESC_TYPE, (uint32_t)2, temp);
620   }
621 
622   /* Make the service browseable */
623   status &=
624       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
625 
626   if (!status) {
627     SDP_DeleteRecord(sdp_handle);
628     sdp_handle = 0;
629     APPL_TRACE_ERROR("%s() FAILED", __func__);
630   } else {
631     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
632     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
633                      sdp_handle);
634   }
635   return sdp_handle;
636 }
637 
638 /* Create a OPP Server SDP record based on information stored in a
639  * bluetooth_sdp_ops_record */
add_opps_sdp(const bluetooth_sdp_ops_record * rec)640 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) {
641   tSDP_PROTOCOL_ELEM protoList[3];
642   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
643   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
644   uint8_t type_len[rec->supported_formats_list_len];
645   uint8_t desc_type[rec->supported_formats_list_len];
646   uint8_t* type_value[rec->supported_formats_list_len];
647   bool status = true;
648   uint32_t sdp_handle = 0;
649   uint8_t temp[4];
650   uint8_t* p_temp = temp;
651   tBTA_UTL_COD cod;
652   int i, j;
653 
654   sdp_handle = SDP_CreateRecord();
655   if (sdp_handle == 0) {
656     LOG_ERROR("Unable to register Object Push Server Service");
657     return sdp_handle;
658   }
659 
660   /* add service class */
661   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
662   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
663 
664   /* add protocol list, including RFCOMM scn */
665   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
666   protoList[0].num_params = 0;
667   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
668   protoList[1].num_params = 1;
669   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
670   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
671   protoList[2].num_params = 0;
672   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
673 
674   /* Add a name entry */
675   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
676                              (uint8_t)TEXT_STR_DESC_TYPE,
677                              (uint32_t)(rec->hdr.service_name_length + 1),
678                              (uint8_t*)rec->hdr.service_name);
679 
680   /* Add in the Bluetooth Profile Descriptor List */
681   status &= SDP_AddProfileDescriptorList(
682       sdp_handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, rec->hdr.profile_version);
683 
684   /* add sequence for supported types */
685   for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) {
686     type_value[j] = (uint8_t*)&rec->supported_formats_list[i];
687     desc_type[j] = UINT_DESC_TYPE;
688     type_len[j++] = 1;
689   }
690 
691   status &=
692       SDP_AddSequence(sdp_handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
693                       (uint8_t)rec->supported_formats_list_len, desc_type,
694                       type_len, type_value);
695 
696   /* Add the L2CAP PSM if present */
697   if (rec->hdr.l2cap_psm != -1) {
698     p_temp = temp;  // The macro modifies p_temp, hence rewind.
699     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
700     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
701                                UINT_DESC_TYPE, (uint32_t)2, temp);
702   }
703 
704   /* Make the service browseable */
705   status &=
706       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
707 
708   if (!status) {
709     SDP_DeleteRecord(sdp_handle);
710     sdp_handle = 0;
711     APPL_TRACE_ERROR("%s() FAILED", __func__);
712   } else {
713     /* set class of device */
714     cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
715     utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
716 
717     bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
718     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
719                      sdp_handle);
720   }
721   return sdp_handle;
722 }
723 
724 // Create a Sim Access Profile SDP record based on information stored in a
725 // bluetooth_sdp_sap_record.
add_saps_sdp(const bluetooth_sdp_sap_record * rec)726 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) {
727   tSDP_PROTOCOL_ELEM protoList[2];
728   uint16_t services[2];
729   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
730   bool status = true;
731   uint32_t sdp_handle = 0;
732 
733   sdp_handle = SDP_CreateRecord();
734   if (sdp_handle == 0) {
735     LOG_ERROR("Unable to register SAPS Service");
736     return sdp_handle;
737   }
738 
739   services[0] = UUID_SERVCLASS_SAP;
740   services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY;
741 
742   // add service class
743   status &= SDP_AddServiceClassIdList(sdp_handle, 2, services);
744   memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM));
745 
746   // add protocol list, including RFCOMM scn
747   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
748   protoList[0].num_params = 0;
749   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
750   protoList[1].num_params = 1;
751   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
752   status &= SDP_AddProtocolList(sdp_handle, 2, protoList);
753 
754   // Add a name entry
755   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
756                              (uint8_t)TEXT_STR_DESC_TYPE,
757                              (uint32_t)(rec->hdr.service_name_length + 1),
758                              (uint8_t*)rec->hdr.service_name);
759 
760   // Add in the Bluetooth Profile Descriptor List
761   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_SAP,
762                                          rec->hdr.profile_version);
763 
764   // Make the service browseable
765   status &=
766       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
767 
768   if (!status) {
769     SDP_DeleteRecord(sdp_handle);
770     sdp_handle = 0;
771     APPL_TRACE_ERROR("%s(): FAILED deleting record", __func__);
772   } else {
773     bta_sys_add_uuid(UUID_SERVCLASS_SAP);
774     APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
775                      sdp_handle);
776   }
777   return sdp_handle;
778 }
779