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