Home | History | Annotate | Download | only in src
      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_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 < 0 || id >= MAX_SDP_SLOTS) {
    218     android_errorWriteLog(0x534e4554, "37502513");
    219     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
    220     return handle;
    221   }
    222 
    223   {
    224     std::unique_lock<std::recursive_mutex> lock(sdp_lock);
    225     handle = sdp_slots[id].sdp_handle;
    226     sdp_slots[id].sdp_handle = 0;
    227     if (sdp_slots[id].state != SDP_RECORD_FREE) {
    228       /* safe a copy of the pointer, and free after unlock() */
    229       record = sdp_slots[id].record_data;
    230     }
    231     sdp_slots[id].state = SDP_RECORD_FREE;
    232   }
    233 
    234   if (record != NULL) {
    235     osi_free(record);
    236   } else {
    237     // Record have already been freed
    238     handle = -1;
    239   }
    240   return handle;
    241 }
    242 
    243 /***
    244  * Use this to get a reference to a SDP slot AND change the state to
    245  * SDP_RECORD_CREATE_INITIATED.
    246  */
    247 static const sdp_slot_t* start_create_sdp(int id) {
    248   if (id >= MAX_SDP_SLOTS) {
    249     APPL_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id);
    250     return NULL;
    251   }
    252 
    253   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
    254   if (sdp_slots[id].state != SDP_RECORD_ALLOCED) {
    255     /* The record have been removed before this event occurred - e.g. deinit */
    256     APPL_TRACE_ERROR(
    257         "%s() failed - state for id %d is "
    258         "sdp_slots[id].state = %d expected %d",
    259         __func__, id, sdp_slots[id].state, SDP_RECORD_ALLOCED);
    260     return NULL;
    261   }
    262 
    263   return &(sdp_slots[id]);
    264 }
    265 
    266 static void set_sdp_handle(int id, int handle) {
    267   std::unique_lock<std::recursive_mutex> lock(sdp_lock);
    268   sdp_slots[id].sdp_handle = handle;
    269   BTIF_TRACE_DEBUG("%s() id=%d to handle=0x%08x", __func__, id, handle);
    270 }
    271 
    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 
    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 
    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       //        break; not yet supported
    342       default:
    343         BTIF_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
    344         break;
    345     }
    346     if (handle != -1) {
    347       set_sdp_handle(id, handle);
    348     }
    349   }
    350 }
    351 
    352 void on_remove_record_event(int handle) {
    353   BTIF_TRACE_DEBUG("Sdp Server %s", __func__);
    354 
    355   // User data carries the actual SDP handle, not the ID.
    356   if (handle != -1 && handle != 0) {
    357     bool result;
    358     result = SDP_DeleteRecord(handle);
    359     if (!result) {
    360       BTIF_TRACE_ERROR("  Unable to remove handle 0x%08x", handle);
    361     }
    362   }
    363 }
    364 
    365 /****
    366  * Below the actual functions accessing BTA context data - hence only call from
    367  * BTA context!
    368  */
    369 
    370 /* Create a MAP MAS SDP record based on information stored in a
    371  * bluetooth_sdp_mas_record */
    372 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) {
    373   tSDP_PROTOCOL_ELEM protoList[3];
    374   uint16_t service = UUID_SERVCLASS_MESSAGE_ACCESS;
    375   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
    376   bool status = true;
    377   uint32_t sdp_handle = 0;
    378   uint8_t temp[4];
    379   uint8_t* p_temp = temp;
    380 
    381   APPL_TRACE_DEBUG(
    382       "%s(): MASID = 0x%02x, scn 0x%02x, psm = 0x%04x\n  service name %s",
    383       __func__, rec->mas_instance_id, rec->hdr.rfcomm_channel_number,
    384       rec->hdr.l2cap_psm, rec->hdr.service_name);
    385 
    386   APPL_TRACE_DEBUG("  msg_types: 0x%02x, feature_bits: 0x%08x",
    387                    rec->supported_message_types, rec->supported_features);
    388 
    389   sdp_handle = SDP_CreateRecord();
    390   if (sdp_handle == 0) {
    391     APPL_TRACE_ERROR("%s() - Unable to register MAPS Service", __func__);
    392     return sdp_handle;
    393   }
    394 
    395   /* add service class */
    396   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
    397   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
    398 
    399   /* add protocol list, including RFCOMM scn */
    400   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
    401   protoList[0].num_params = 0;
    402   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
    403   protoList[1].num_params = 1;
    404   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
    405   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
    406   protoList[2].num_params = 0;
    407   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
    408 
    409   /* Add a name entry */
    410   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
    411                              (uint8_t)TEXT_STR_DESC_TYPE,
    412                              (uint32_t)(rec->hdr.service_name_length + 1),
    413                              (uint8_t*)rec->hdr.service_name);
    414 
    415   /* Add in the Bluetooth Profile Descriptor List */
    416   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_MAP_PROFILE,
    417                                          rec->hdr.profile_version);
    418 
    419   /* Add MAS instance ID */
    420   status &=
    421       SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
    422                        (uint32_t)1, (uint8_t*)&rec->mas_instance_id);
    423 
    424   /* Add supported message types */
    425   status &=
    426       SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
    427                        (uint32_t)1, (uint8_t*)&rec->supported_message_types);
    428 
    429   /* Add supported feature */
    430   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
    431   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
    432                              UINT_DESC_TYPE, (uint32_t)4, temp);
    433 
    434   /* Add the L2CAP PSM if present */
    435   if (rec->hdr.l2cap_psm != -1) {
    436     p_temp = temp;  // The macro modifies p_temp, hence rewind.
    437     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
    438     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
    439                                UINT_DESC_TYPE, (uint32_t)2, temp);
    440   }
    441 
    442   /* Make the service browseable */
    443   status &=
    444       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
    445 
    446   if (!status) {
    447     SDP_DeleteRecord(sdp_handle);
    448     sdp_handle = 0;
    449     APPL_TRACE_ERROR("%s() FAILED", __func__);
    450   } else {
    451     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
    452     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
    453                      sdp_handle);
    454   }
    455   return sdp_handle;
    456 }
    457 
    458 /* Create a MAP MNS SDP record based on information stored in a
    459  * bluetooth_sdp_mns_record */
    460 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) {
    461   tSDP_PROTOCOL_ELEM protoList[3];
    462   uint16_t service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
    463   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
    464   bool status = true;
    465   uint32_t sdp_handle = 0;
    466   uint8_t temp[4];
    467   uint8_t* p_temp = temp;
    468 
    469   APPL_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n  service name %s",
    470                    __func__, rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm,
    471                    rec->hdr.service_name);
    472 
    473   APPL_TRACE_DEBUG("  feature_bits: 0x%08x", rec->supported_features);
    474 
    475   sdp_handle = SDP_CreateRecord();
    476   if (sdp_handle == 0) {
    477     APPL_TRACE_ERROR("%s(): Unable to register MAP Notification Service",
    478                      __func__);
    479     return sdp_handle;
    480   }
    481 
    482   /* add service class */
    483   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
    484   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
    485 
    486   /* add protocol list, including RFCOMM scn */
    487   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
    488   protoList[0].num_params = 0;
    489   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
    490   protoList[1].num_params = 1;
    491   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
    492   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
    493   protoList[2].num_params = 0;
    494   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
    495 
    496   /* Add a name entry */
    497   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
    498                              (uint8_t)TEXT_STR_DESC_TYPE,
    499                              (uint32_t)(rec->hdr.service_name_length + 1),
    500                              (uint8_t*)rec->hdr.service_name);
    501 
    502   /* Add in the Bluetooth Profile Descriptor List */
    503   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_MAP_PROFILE,
    504                                          rec->hdr.profile_version);
    505 
    506   /* Add supported feature */
    507   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
    508   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_MAP_SUPPORTED_FEATURES,
    509                              UINT_DESC_TYPE, (uint32_t)4, temp);
    510 
    511   /* Add the L2CAP PSM if present */
    512   if (rec->hdr.l2cap_psm != -1) {
    513     p_temp = temp;  // The macro modifies p_temp, hence rewind.
    514     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
    515     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
    516                                UINT_DESC_TYPE, (uint32_t)2, temp);
    517   }
    518 
    519   /* Make the service browseable */
    520   status &=
    521       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
    522 
    523   if (!status) {
    524     SDP_DeleteRecord(sdp_handle);
    525     sdp_handle = 0;
    526     APPL_TRACE_ERROR("%s() FAILED", __func__);
    527   } else {
    528     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
    529     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
    530                      sdp_handle);
    531   }
    532   return sdp_handle;
    533 }
    534 
    535 /* Create a PBAP Server SDP record based on information stored in a
    536  * bluetooth_sdp_pse_record */
    537 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) {
    538   tSDP_PROTOCOL_ELEM protoList[3];
    539   uint16_t service = UUID_SERVCLASS_PBAP_PSE;
    540   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
    541   bool status = true;
    542   uint32_t sdp_handle = 0;
    543   uint8_t temp[4];
    544   uint8_t* p_temp = temp;
    545 
    546   APPL_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n  service name %s",
    547                    __func__, rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm,
    548                    rec->hdr.service_name);
    549 
    550   APPL_TRACE_DEBUG("  supported_repositories: 0x%08x, feature_bits: 0x%08x",
    551                    rec->supported_repositories, rec->supported_features);
    552 
    553   sdp_handle = SDP_CreateRecord();
    554   if (sdp_handle == 0) {
    555     APPL_TRACE_ERROR("%s(): Unable to register PBAP Server Service", __func__);
    556     return sdp_handle;
    557   }
    558 
    559   /* add service class */
    560   status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
    561   memset(protoList, 0, 3 * sizeof(tSDP_PROTOCOL_ELEM));
    562 
    563   /* add protocol list, including RFCOMM scn */
    564   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
    565   protoList[0].num_params = 0;
    566   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
    567   protoList[1].num_params = 1;
    568   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
    569   protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
    570   protoList[2].num_params = 0;
    571   status &= SDP_AddProtocolList(sdp_handle, 3, protoList);
    572 
    573   /* Add a name entry */
    574   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
    575                              (uint8_t)TEXT_STR_DESC_TYPE,
    576                              (uint32_t)(rec->hdr.service_name_length + 1),
    577                              (uint8_t*)rec->hdr.service_name);
    578 
    579   /* Add in the Bluetooth Profile Descriptor List */
    580   status &= SDP_AddProfileDescriptorList(
    581       sdp_handle, UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version);
    582 
    583   /* Add supported repositories 1 byte */
    584   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES,
    585                              UINT_DESC_TYPE, (uint32_t)1,
    586                              (uint8_t*)&rec->supported_repositories);
    587 
    588   /* Add supported feature 4 bytes*/
    589   UINT32_TO_BE_STREAM(p_temp, rec->supported_features);
    590   status &= SDP_AddAttribute(sdp_handle, ATTR_ID_PBAP_SUPPORTED_FEATURES,
    591                              UINT_DESC_TYPE, (uint32_t)4, temp);
    592 
    593   /* Add the L2CAP PSM if present */
    594   if (rec->hdr.l2cap_psm != -1) {
    595     p_temp = temp;  // The macro modifies p_temp, hence rewind.
    596     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
    597     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
    598                                UINT_DESC_TYPE, (uint32_t)2, temp);
    599   }
    600 
    601   /* Make the service browseable */
    602   status &=
    603       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
    604 
    605   if (!status) {
    606     SDP_DeleteRecord(sdp_handle);
    607     sdp_handle = 0;
    608     APPL_TRACE_ERROR("%s() FAILED", __func__);
    609   } else {
    610     bta_sys_add_uuid(service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
    611     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
    612                      sdp_handle);
    613   }
    614   return sdp_handle;
    615 }
    616 
    617 /* Create a OPP Server SDP record based on information stored in a
    618  * bluetooth_sdp_ops_record */
    619 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) {
    620   tSDP_PROTOCOL_ELEM protoList[3];
    621   uint16_t service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
    622   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
    623   uint8_t type_len[rec->supported_formats_list_len];
    624   uint8_t desc_type[rec->supported_formats_list_len];
    625   uint8_t* type_value[rec->supported_formats_list_len];
    626   bool status = true;
    627   uint32_t sdp_handle = 0;
    628   uint8_t temp[4];
    629   uint8_t* p_temp = temp;
    630   tBTA_UTL_COD cod;
    631   int i, j;
    632 
    633   APPL_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n  service name %s",
    634                    __func__, rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm,
    635                    rec->hdr.service_name);
    636 
    637   APPL_TRACE_DEBUG("  supported formats count: %d",
    638                    rec->supported_formats_list_len);
    639 
    640   sdp_handle = SDP_CreateRecord();
    641   if (sdp_handle == 0) {
    642     APPL_TRACE_ERROR("%s(): Unable to register Object Push Server Service",
    643                      __func__);
    644     return sdp_handle;
    645   }
    646 
    647   /* add service class */
    648   status &= 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 &= SDP_AddProtocolList(sdp_handle, 3, protoList);
    660 
    661   /* Add a name entry */
    662   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
    663                              (uint8_t)TEXT_STR_DESC_TYPE,
    664                              (uint32_t)(rec->hdr.service_name_length + 1),
    665                              (uint8_t*)rec->hdr.service_name);
    666 
    667   /* Add in the Bluetooth Profile Descriptor List */
    668   status &= SDP_AddProfileDescriptorList(
    669       sdp_handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH, rec->hdr.profile_version);
    670 
    671   /* add sequence for supported types */
    672   for (i = 0, j = 0; i < rec->supported_formats_list_len; i++) {
    673     type_value[j] = (uint8_t*)&rec->supported_formats_list[i];
    674     desc_type[j] = UINT_DESC_TYPE;
    675     type_len[j++] = 1;
    676   }
    677 
    678   status &=
    679       SDP_AddSequence(sdp_handle, (uint16_t)ATTR_ID_SUPPORTED_FORMATS_LIST,
    680                       (uint8_t)rec->supported_formats_list_len, desc_type,
    681                       type_len, type_value);
    682 
    683   /* Add the L2CAP PSM if present */
    684   if (rec->hdr.l2cap_psm != -1) {
    685     p_temp = temp;  // The macro modifies p_temp, hence rewind.
    686     UINT16_TO_BE_STREAM(p_temp, rec->hdr.l2cap_psm);
    687     status &= SDP_AddAttribute(sdp_handle, ATTR_ID_GOEP_L2CAP_PSM,
    688                                UINT_DESC_TYPE, (uint32_t)2, temp);
    689   }
    690 
    691   /* Make the service browseable */
    692   status &=
    693       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
    694 
    695   if (!status) {
    696     SDP_DeleteRecord(sdp_handle);
    697     sdp_handle = 0;
    698     APPL_TRACE_ERROR("%s() FAILED", __func__);
    699   } else {
    700     /* set class of device */
    701     cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
    702     utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
    703 
    704     bta_sys_add_uuid(service); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
    705     APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
    706                      sdp_handle);
    707   }
    708   return sdp_handle;
    709 }
    710 
    711 // Create a Sim Access Profile SDP record based on information stored in a
    712 // bluetooth_sdp_sap_record.
    713 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) {
    714   tSDP_PROTOCOL_ELEM protoList[2];
    715   uint16_t services[2];
    716   uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
    717   bool status = true;
    718   uint32_t sdp_handle = 0;
    719 
    720   APPL_TRACE_DEBUG("%s(): scn 0x%02x, service name %s", __func__,
    721                    rec->hdr.rfcomm_channel_number, rec->hdr.service_name);
    722 
    723   sdp_handle = SDP_CreateRecord();
    724   if (sdp_handle == 0) {
    725     APPL_TRACE_ERROR("%s(): Unable to register SAPS Service", __func__);
    726     return sdp_handle;
    727   }
    728 
    729   services[0] = UUID_SERVCLASS_SAP;
    730   services[1] = UUID_SERVCLASS_GENERIC_TELEPHONY;
    731 
    732   // add service class
    733   status &= SDP_AddServiceClassIdList(sdp_handle, 2, services);
    734   memset(protoList, 0, 2 * sizeof(tSDP_PROTOCOL_ELEM));
    735 
    736   // add protocol list, including RFCOMM scn
    737   protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
    738   protoList[0].num_params = 0;
    739   protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
    740   protoList[1].num_params = 1;
    741   protoList[1].params[0] = rec->hdr.rfcomm_channel_number;
    742   status &= SDP_AddProtocolList(sdp_handle, 2, protoList);
    743 
    744   // Add a name entry
    745   status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
    746                              (uint8_t)TEXT_STR_DESC_TYPE,
    747                              (uint32_t)(rec->hdr.service_name_length + 1),
    748                              (uint8_t*)rec->hdr.service_name);
    749 
    750   // Add in the Bluetooth Profile Descriptor List
    751   status &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_SAP,
    752                                          rec->hdr.profile_version);
    753 
    754   // Make the service browseable
    755   status &=
    756       SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
    757 
    758   if (!status) {
    759     SDP_DeleteRecord(sdp_handle);
    760     sdp_handle = 0;
    761     APPL_TRACE_ERROR("%s(): FAILED deleting record", __func__);
    762   } else {
    763     bta_sys_add_uuid(UUID_SERVCLASS_SAP);
    764     APPL_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__,
    765                      sdp_handle);
    766   }
    767   return sdp_handle;
    768 }
    769