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