OSDN Git Service

Refactoring btif_sock_sdp.c for clarity
authorJune R. Tate-Gans <jtgans@google.com>
Thu, 11 Sep 2014 00:05:21 +0000 (17:05 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Mon, 16 Mar 2015 23:51:38 +0000 (16:51 -0700)
btif/src/btif_sock_sdp.c

index 00671a0..e8f7e27 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2009-2012 Broadcom Corporation
+ *  Copyright (C) 2014 Google, Inc.
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *
  ******************************************************************************/
 
-/************************************************************************************
- *
- *  Filename:      btif_hf.c
- *
- *  Description:   Handsfree Profile Bluetooth Interface
- *
- *
- ***********************************************************************************/
+#define LOG_TAG "BTIF_SOCK_SDP"
 
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <errno.h>
+#include <cutils/log.h>
 
-#define LOG_TAG "BTIF_SOCK_SDP"
 #include "btif_common.h"
 #include "btif_util.h"
-
 #include "bd.h"
-
 #include "bta_api.h"
-
-
 #include "bt_target.h"
 #include "gki.h"
 #include "hcimsgs.h"
 #include "../bta/pb/bta_pbs_int.h"
 #include "../include/bta_op_api.h"
 #include "bta_jv_api.h"
-#include <cutils/log.h>
-
-#define RESERVED_SCN_PBS 19
-#define RESERVED_SCN_OPS 12
-
-#define UUID_MAX_LENGTH 16
 
+// This module provides an abstraction on top of the lower-level SDP database
+// code for registration and discovery of various bluetooth sockets.
+//
+// This code also provides for on-demand registration of "pre-registered"
+// services as a backwards compatibility function to third-party applications
+// expecting a bluez stack.
 
-#define IS_UUID(u1,u2)  !memcmp(u1,u2,UUID_MAX_LENGTH)
-
-
-#define BTM_NUM_PROTO_ELEMS 2
-static int add_sdp_by_uuid(const char *name,  const uint8_t *service_uuid, UINT16 channel)
-{
-
-    UINT32 btm_sdp_handle;
-
-    tSDP_PROTOCOL_ELEM  proto_elem_list[BTM_NUM_PROTO_ELEMS];
-
-    /* register the service */
-    if ((btm_sdp_handle = SDP_CreateRecord()) != FALSE)
-    {
-        /*** Fill out the protocol element sequence for SDP ***/
-        proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-        proto_elem_list[0].num_params = 0;
-        proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
-        proto_elem_list[1].num_params = 1;
-
-        proto_elem_list[1].params[0] = channel;
-
-        if (SDP_AddProtocolList(btm_sdp_handle, BTM_NUM_PROTO_ELEMS,
-            proto_elem_list))
-        {
-            UINT8           buff[48];
-            UINT8           *p, *type_buf[1];
-            UINT8       type[1], type_len[1];
-         p = type_buf[0] = buff;
-         type[0] = UUID_DESC_TYPE;
-
-//         UINT8_TO_BE_STREAM  (p, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
-         ARRAY_TO_BE_STREAM (p, service_uuid, 16);
-            type_len[0] = 16;
-            if( SDP_AddSequence(btm_sdp_handle, (UINT16) ATTR_ID_SERVICE_CLASS_ID_LIST,
-                          1, type, type_len, type_buf) )
-//            if (SDP_AddServiceClassIdList(btm_sdp_handle, 1, &service_uuid))
-            {
-                if ((SDP_AddAttribute(btm_sdp_handle, ATTR_ID_SERVICE_NAME,
-                    TEXT_STR_DESC_TYPE, (UINT32)(strlen(name)+1),
-                    (UINT8 *)name)) )
-                {
-                    UINT16  list[1];
-
-                    /* Make the service browseable */
-                    list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
-                    if ((SDP_AddUuidSequence (btm_sdp_handle,  ATTR_ID_BROWSE_GROUP_LIST,
-                        1, list)) )
-
-                        return btm_sdp_handle;
-                }
-            }
-        }
-    }
-    else APPL_TRACE_ERROR("failed to create sdp record, service_name:%s", name);
-    return 0;
-}
+// Realm Character Set -- 0 is ASCII
+#define BTA_PBS_REALM_CHARSET 0
 
+// Specifies whether or not client's user id is required during obex
+// authentication
+#define BTA_PBS_USERID_REQ FALSE
 
-/* Realm Character Set */
-#define BTA_PBS_REALM_CHARSET   0       /* ASCII */
-
-/* Specifies whether or not client's user id is required during obex authentication */
-#define BTA_PBS_USERID_REQ      FALSE
+// TODO(jtgans): Is this really exported to anything anywhere? If so, we should
+// stuff it into the header, otherwise, WHY IS IT HERE?!
 extern const tBTA_PBS_CFG bta_pbs_cfg;
-const tBTA_PBS_CFG bta_pbs_cfg =
-{
-    BTA_PBS_REALM_CHARSET,      /* Server only */
-    BTA_PBS_USERID_REQ,         /* Server only */
-    (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),
-    BTA_PBS_REPOSIT_LOCAL,
-};
-
-static int add_pbap_sdp(const char* p_service_name, int scn)
-{
-
-    tSDP_PROTOCOL_ELEM  protoList [3];
-    UINT16              pbs_service = UUID_SERVCLASS_PBAP_PSE;
-    UINT16              browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
-    BOOLEAN             status = FALSE;
-    UINT32              sdp_handle = 0;
-    tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg;
-
-    APPL_TRACE_DEBUG("add_pbap_sdd:scn %d, service name %s", scn, p_service_name);
 
-    if ((sdp_handle = SDP_CreateRecord()) == 0)
-    {
-        APPL_TRACE_ERROR("PBS SDP: Unable to register PBS Service");
-        return sdp_handle;
-    }
-
-    /* add service class */
-    if (SDP_AddServiceClassIdList(sdp_handle, 1, &pbs_service))
-    {
-        memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
-        /* add protocol list, including RFCOMM scn */
-        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-        protoList[0].num_params = 0;
-        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
-        protoList[1].num_params = 1;
-        protoList[1].params[0] = scn;
-        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
-        protoList[2].num_params = 0;
-
-        if (SDP_AddProtocolList(sdp_handle, 3, protoList))
-        {
-            status = TRUE;  /* All mandatory fields were successful */
-
-            /* optional:  if name is not "", add a name entry */
-            if (*p_service_name != '\0')
-                SDP_AddAttribute(sdp_handle,
-                                 (UINT16)ATTR_ID_SERVICE_NAME,
-                                 (UINT8)TEXT_STR_DESC_TYPE,
-                                 (UINT32)(strlen(p_service_name) + 1),
-                                 (UINT8 *)p_service_name);
-
-            /* Add in the Bluetooth Profile Descriptor List */
-            SDP_AddProfileDescriptorList(sdp_handle,
-                                             UUID_SERVCLASS_PHONE_ACCESS,
-                                             BTA_PBS_DEFAULT_VERSION);
-
-        } /* end of setting mandatory protocol list */
-    } /* end of setting mandatory service class */
-
-    /* add supported feature and repositories */
-    if (status)
-    {
-        SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
-                  (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories);
-
-        /* Make the service browseable */
-        SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
-    }
+const tBTA_PBS_CFG bta_pbs_cfg = {
+  BTA_PBS_REALM_CHARSET,                          // realm_charset: Server only
+  BTA_PBS_USERID_REQ,                             // userid_req: Server only
+  (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),  // supported_features
+  BTA_PBS_REPOSIT_LOCAL,                          // supported_repositories
+};
 
-    if (!status)
-    {
-        SDP_DeleteRecord(sdp_handle);
-        sdp_handle = 0;
-        APPL_TRACE_ERROR("bta_pbs_sdp_register FAILED");
-    }
-    else
-    {
-        bta_sys_add_uuid(pbs_service);  /* UUID_SERVCLASS_PBAP_PSE */
-        APPL_TRACE_DEBUG("PBS:  SDP Registered (handle 0x%08x)", sdp_handle);
-    }
+// object format lookup table
+#define OBEX_PUSH_NUM_FORMATS 7
+
+static const tBTA_OP_FMT bta_ops_obj_fmt[OBEX_PUSH_NUM_FORMATS] = {
+  BTA_OP_VCARD21_FMT,
+  BTA_OP_VCARD30_FMT,
+  BTA_OP_VCAL_FMT,
+  BTA_OP_ICAL_FMT,
+  BTA_OP_VNOTE_FMT,
+  BTA_OP_VMSG_FMT,
+  BTA_OP_OTHER_FMT
+};
 
-    return sdp_handle;
-}
+// TODO(jtgans): Figure out if we actually need this define. This is ifndef
+// defined in bt_target.h, but nowhere else, so right now, unless something
+// overrides this before bt_target.h sets it, it will always be bt_target.h's
+// version.
+#ifndef BTUI_OPS_FORMATS
+#define BTUI_OPS_FORMATS (BTA_OP_VCARD21_MASK   \
+                          | BTA_OP_VCARD30_MASK \
+                          | BTA_OP_VCAL_MASK    \
+                          | BTA_OP_ICAL_MASK    \
+                          | BTA_OP_VNOTE_MASK   \
+                          | BTA_OP_VMSG_MASK    \
+                          | BTA_OP_ANY_MASK)
+#endif
 
-/* This is horrible design - to reserve channel ID's and use them to magically link
- * a channel number to a hard coded SDP entry.
+/*
+ * This is horrible design - to reserve channel ID's and use them to magically
+ * link a channel number to a hard coded SDP entry.
+ *
  * TODO: expose a prober SDP API, to avoid hacks like this, and make it possible
- *        to set useful names for the ServiceName */
+ * to set useful names for the ServiceName
+ */
 #define BTA_MAP_MSG_TYPE_EMAIL    0x01
 #define BTA_MAP_MSG_TYPE_SMS_GSM  0x02
 #define BTA_MAP_MSG_TYPE_SMS_CDMA 0x04
 #define BTA_MAP_MSG_TYPE_MMS      0x08
 
-#define BTA_MAPS_DEFAULT_VERSION 0x0101 /* MAP 1.1 */
-typedef struct
-{
-    UINT8       mas_id;                 /* the MAS instance id */
-    const char* service_name;          /* Description of the MAS instance */
-    UINT8       supported_message_types;/* Server supported message types - SMS/MMS/EMAIL */
-} tBTA_MAPS_CFG;
-const tBTA_MAPS_CFG bta_maps_cfg_sms =
-{
-    0,                  /* Mas id 0 is for SMS/MMS */
-    "MAP SMS",
-    BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA
-};
-const tBTA_MAPS_CFG bta_maps_cfg_email =
-{
-    1,                  /* Mas id 1 is for EMAIL */
-    "MAP EMAIL",
-    BTA_MAP_MSG_TYPE_EMAIL
-};
-static int add_maps_sdp(const char* p_service_name, int scn)
-{
-
-    tSDP_PROTOCOL_ELEM  protoList [3];
-    UINT16              service = UUID_SERVCLASS_MESSAGE_ACCESS;
-    UINT16              browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
-    BOOLEAN             status = FALSE;
-    UINT32              sdp_handle = 0;
-    // TODO: To add support for EMAIL set below depending on the scn to either SMS or Email
-    const tBTA_MAPS_CFG *p_bta_maps_cfg = &bta_maps_cfg_sms;
-
-    APPL_TRACE_DEBUG("add_maps_sdd:scn %d, service name %s", scn, p_service_name);
-
-    if ((sdp_handle = SDP_CreateRecord()) == 0)
-    {
-        APPL_TRACE_ERROR("MAPS SDP: Unable to register MAPS Service");
-        return sdp_handle;
-    }
-
-    /* add service class */
-    if (SDP_AddServiceClassIdList(sdp_handle, 1, &service))
-    {
-        memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
-        /* add protocol list, including RFCOMM scn */
-        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-        protoList[0].num_params = 0;
-        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
-        protoList[1].num_params = 1;
-        protoList[1].params[0] = scn;
-        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
-        protoList[2].num_params = 0;
-
-        if (SDP_AddProtocolList(sdp_handle, 3, protoList))
-        {
-            status = TRUE;  /* All mandatory fields were successful */
-
-            /* optional:  if name is not "", add a name entry */
-            SDP_AddAttribute(sdp_handle,
-                            (UINT16)ATTR_ID_SERVICE_NAME,
-                            (UINT8)TEXT_STR_DESC_TYPE,
-                            (UINT32)(strlen(p_bta_maps_cfg->service_name) + 1),
-                            (UINT8 *)p_bta_maps_cfg->service_name);
-
-            /* Add in the Bluetooth Profile Descriptor List */
-            SDP_AddProfileDescriptorList(sdp_handle,
-                                             UUID_SERVCLASS_MAP_PROFILE,
-                                             BTA_MAPS_DEFAULT_VERSION);
-
-        } /* end of setting mandatory protocol list */
-    } /* end of setting mandatory service class */
-
-    /* add supported feature and repositories */
-    if (status)
-    {
-        SDP_AddAttribute(sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
-                  (UINT32)1, (UINT8*)&p_bta_maps_cfg->mas_id);
-        SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
-                  (UINT32)1, (UINT8*)&p_bta_maps_cfg->supported_message_types);
-
-        /* Make the service browseable */
-        SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
-    }
-
-    if (!status)
-    {
-        SDP_DeleteRecord(sdp_handle);
-        sdp_handle = 0;
-        APPL_TRACE_ERROR("bta_mass_sdp_register FAILED");
-    }
-    else
-    {
-        bta_sys_add_uuid(service);  /* UUID_SERVCLASS_MESSAGE_ACCESS */
-        APPL_TRACE_DEBUG("MAPSS:  SDP Registered (handle 0x%08x)", sdp_handle);
-    }
+#define BTA_MAP_MAS_ID_SMSMMS 0
+#define BTA_MAP_MAS_ID_EMAIL 1
 
-    return sdp_handle;
-}
+// MAP 1.1
+#define BTA_MAP_DEFAULT_VERSION 0x0101
 
+typedef struct {
+  UINT8 mas_id;                  // the MAS instance id
+  const char *service_name;      // Description of the MAS instance
+  UINT8 supported_message_types; // Server supported message types - SMS/MMS/EMAIL
+} tBTA_MAP_CFG;
 
-/* object format lookup table */
-static const tBTA_OP_FMT bta_ops_obj_fmt[] =
-{
-    BTA_OP_VCARD21_FMT,
-    BTA_OP_VCARD30_FMT,
-    BTA_OP_VCAL_FMT,
-    BTA_OP_ICAL_FMT,
-    BTA_OP_VNOTE_FMT,
-    BTA_OP_VMSG_FMT,
-    BTA_OP_OTHER_FMT
+const tBTA_MAP_CFG bta_map_cfg_sms = {
+  BTA_MAP_MAS_ID_SMSMMS,
+  "MAP SMS",
+  BTA_MAP_MSG_TYPE_SMS_GSM | BTA_MAP_MSG_TYPE_SMS_CDMA
 };
 
-#define BTA_OPS_NUM_FMTS        7
-#define BTA_OPS_PROTOCOL_COUNT  3
-
-#ifndef BTUI_OPS_FORMATS
-#define BTUI_OPS_FORMATS            (BTA_OP_VCARD21_MASK | BTA_OP_VCARD30_MASK | \
-                                         BTA_OP_VCAL_MASK | BTA_OP_ICAL_MASK | \
-                                         BTA_OP_VNOTE_MASK | BTA_OP_VMSG_MASK | \
-                                         BTA_OP_ANY_MASK )
-#endif
+#define RESERVED_SCN_PBS 19
+#define RESERVED_SCN_OPS 12
 
-static int add_ops_sdp(const char *p_service_name,int scn)
-{
-
-
-    tSDP_PROTOCOL_ELEM  protoList [BTA_OPS_PROTOCOL_COUNT];
-    UINT16      servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
-    int         i, j;
-    tBTA_UTL_COD cod;
-    UINT8       desc_type[BTA_OPS_NUM_FMTS];
-    UINT8       type_len[BTA_OPS_NUM_FMTS];
-    UINT8       *type_value[BTA_OPS_NUM_FMTS];
-    UINT16      browse;
-    UINT32 sdp_handle;
-    tBTA_OP_FMT_MASK    formats = BTUI_OPS_FORMATS;
-
-    APPL_TRACE_DEBUG("scn %d, service name %s", scn, p_service_name);
-
-    sdp_handle = SDP_CreateRecord();
-
-    /* add service class */
-    if (SDP_AddServiceClassIdList(sdp_handle, 1, &servclass))
-    {
-        /* add protocol list, including RFCOMM scn */
-        protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-        protoList[0].num_params = 0;
-        protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
-        protoList[1].num_params = 1;
-        protoList[1].params[0] = scn;
-        protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
-        protoList[2].num_params = 0;
-
-        if (SDP_AddProtocolList(sdp_handle, BTA_OPS_PROTOCOL_COUNT, protoList))
-        {
-            SDP_AddAttribute(sdp_handle,
-               (UINT16)ATTR_ID_SERVICE_NAME,
-                (UINT8)TEXT_STR_DESC_TYPE,
-                (UINT32)(strlen(p_service_name) + 1),
-                (UINT8 *)p_service_name);
-
-            SDP_AddProfileDescriptorList(sdp_handle,
-                UUID_SERVCLASS_OBEX_OBJECT_PUSH,
-                0x0100);
-        }
-    }
+#define UUID_MAX_LENGTH 16
+#define UUID_MATCHES(u1, u2) !memcmp(u1, u2, UUID_MAX_LENGTH)
+
+// Adds a protocol list and service name (if provided) to an SDP record given by
+// |sdp_handle|, and marks it as browseable. This is a shortcut for defining a
+// set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. If
+// |with_obex| is |TRUE|, then an additional OBEX protocol UUID will be included
+// at the end of the protocol list.
+//
+// Returns TRUE if successful, otherwise FALSE.
+static BOOLEAN create_base_record(const UINT32 sdp_handle, const char *name,
+                                  const UINT16 channel, const BOOLEAN with_obex) {
+  APPL_TRACE_DEBUG("create_base_record: scn: %d, name: %s, with_obex: %d",
+                   channel, name, with_obex);
+
+  // Setup the protocol list and add it.
+  tSDP_PROTOCOL_ELEM proto_list[SDP_MAX_LIST_ELEMS];
+  int num_proto_elements = with_obex ? 3 : 2;
+
+  memset(proto_list, 0, num_proto_elements * sizeof(tSDP_PROTOCOL_ELEM));
+
+  proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+  proto_list[0].num_params = 0;
+  proto_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
+  proto_list[1].num_params = 1;
+  proto_list[1].params[0] = channel;
+
+  if (with_obex == TRUE) {
+    proto_list[2].protocol_uuid = UUID_PROTOCOL_OBEX;
+    proto_list[2].num_params = 0;
+  }
+
+  char *stage = "protocol_list";
+  if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list))
+    goto error;
+
+  // Add the name to the SDP record.
+  if (name[0] != '\0') {
+    stage = "service_name";
+    if (!SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
+                          TEXT_STR_DESC_TYPE, (UINT32)(strlen(name) + 1),
+                          (UINT8 *)name))
+      goto error;
+  }
+
+  // Mark the service as browseable.
+  UINT16 list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+  stage = "browseable";
+  if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list))
+    goto error;
+
+  APPL_TRACE_DEBUG("create_base_record: successfully created base service "
+                   "record, handle: 0x%08x, scn: %d, name: %s, with_obex: %d",
+                   sdp_handle, channel, name, with_obex);
+  return TRUE;
+
+error:
+  APPL_TRACE_ERROR("create_base_record: failed to create base service "
+                   "record, stage: %s, scn: %d, name: %s, with_obex: %d",
+                   stage, channel, name, with_obex);
+  return FALSE;
+}
 
-    /* Make the service browseable */
-    browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
-    SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
-
-    /* add sequence for supported types */
-    for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++)
-    {
-        if ((formats >> i) & 1)
-        {
-            type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i];
-            desc_type[j] = UINT_DESC_TYPE;
-            type_len[j++] = 1;
-        }
-    }
+// Registers a service with the given |name|, |uuid|, and |channel| in the SDP
+// database as a generic L2CAP RFCOMM protocol, storing its |uuid| as a service
+// class sequence.
+static int add_sdp_by_uuid(const char *name,  const uint8_t *uuid,
+                           const UINT16 channel) {
+  APPL_TRACE_DEBUG("add_sdp_by_uuid: scn: %d, service_name: %s", channel, name);
+
+  UINT32 handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_sdp_by_uuid: failed to create sdp record, "
+                     "scn: %d, service_name: %s", channel, name);
+    return 0;
+  }
+
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
+    goto error;
+
+  // Convert the |uuid| into a big-endian representation and add it as a
+  // sequence.
+  UINT8 type = UUID_DESC_TYPE;
+  UINT8 type_len = UUID_MAX_LENGTH;
+  UINT8 type_buf[48];
+
+  // Do the conversion to big-endian -- tmp is only used to iterate through the
+  // UUID array in the macro and serves no other purpose as the conversion
+  // macros are not hygenic.
+  {
+    UINT8 *tmp = type_buf;
+    ARRAY_TO_BE_STREAM(tmp, uuid, UUID_MAX_LENGTH);
+  }
+
+  stage = "service_class_sequence";
+  if (!SDP_AddSequence(handle, (UINT16)ATTR_ID_SERVICE_CLASS_ID_LIST,
+                       1, &type, &type_len, (UINT8**)&type_buf))
+    goto error;
+
+
+  APPL_TRACE_DEBUG("add_sdp_by_uuid: service registered successfully, "
+                   "service_name: %s, handle: 0x%08x", name, handle);
+  return handle;
+
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_sdp_by_uuid: failed to register service "
+                   "stage: %s, service_name: %s", stage, name);
+  return 0;
+}
 
-    SDP_AddSequence(sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
-        (UINT8) j, desc_type, type_len, type_value);
+// Registers a service with the given |name| and |channel| in the SDP
+// database as a PBAP protocol.
+static int add_pbap_sdp(const char *name, const int channel) {
+  APPL_TRACE_DEBUG("add_pbap_sdp: scn %d, service_name %s", channel, name);
 
-    /* set class of device */
-    cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
-    utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+  UINT32 handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_pbap_sdp: failed to create sdp record, "
+                     "service_name: %s", name);
+    return 0;
+  }
+
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
+    goto error;
+
+  // Add service class
+  UINT16 service = UUID_SERVCLASS_PBAP_PSE;
+  stage = "service_class";
+  if (!SDP_AddServiceClassIdList(handle, 1, &service))
+    goto error;
+
+  // Add in the phone access descriptor
+  stage = "profile_descriptor_list";
+  if (!SDP_AddProfileDescriptorList(handle,
+                                    UUID_SERVCLASS_PHONE_ACCESS,
+                                    BTA_PBS_DEFAULT_VERSION))
+    goto error;
+
+  // Set up our supported repositories
+  stage = "supported_repositories";
+  if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
+                        1, (UINT8*)&bta_pbs_cfg.supported_repositories))
+    goto error;
+
+  // Notify the system that we've got a new service class UUID.
+  bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PSE);
+  APPL_TRACE_DEBUG("add_pbap_sdp: service registered successfully, "
+                   "service_name: %s, handle: 0x%08x", name, handle);
+
+  return handle;
+
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_pbap_sdp: failed to register PBAP service, stage: %s, "
+                   "service_name: %s", stage, name);
+  return 0;
+}
 
-    bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
+// Registers a service with the given |name| and |channel| in the SDP database
+// as a MAP protocol.
+static int add_maps_sdp(const char *name, const int channel) {
+  APPL_TRACE_DEBUG("add_maps_sdp: scn %d, service_name %s", channel,
+                   name);
 
-    return sdp_handle;
+  UINT32 handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_maps_sdp: failed to create sdp record, "
+                     "service_name: %s", name);
+    return 0;
+  }
+
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
+    goto error;
+
+  // add service class
+  UINT16 service = UUID_SERVCLASS_MESSAGE_ACCESS;
+  stage = "service_class";
+  if (!SDP_AddServiceClassIdList(handle, 1, &service))
+    goto error;
+
+  // TODO: To add support for EMAIL set below depending on the scn to either
+  // SMS or Email
+  const tBTA_MAP_CFG *bta_map_cfg = &bta_map_cfg_sms;
+
+  // Add in the Bluetooth Profile Descriptor List
+  stage = "profile_descriptor_list";
+  if (!SDP_AddProfileDescriptorList(handle,
+                                    UUID_SERVCLASS_MAP_PROFILE,
+                                    BTA_MAP_DEFAULT_VERSION))
+    goto error;
+
+  stage = "mas_instance_id";
+  if (!SDP_AddAttribute(handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
+                        (UINT32)1, (UINT8*)(&bta_map_cfg->mas_id)))
+    goto error;
+
+  stage = "support_message_types";
+  if (!SDP_AddAttribute(handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
+                        (UINT32)1,
+                        (UINT8*)(&bta_map_cfg->supported_message_types)))
+    goto error;
+
+  // Notify the system that we've got a new service class UUID.
+  bta_sys_add_uuid(service);  // UUID_SERVCLASS_MESSAGE_ACCESS
+  APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, "
+                   "service_name: %s, handle 0x%08x)", name, handle);
+
+  return handle;
+
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_maps_sdp: failed to register MAP service, stage: %s, "
+                   "service_name: %s", stage, name);
+  return 0;
 }
-#define SPP_NUM_PROTO_ELEMS 2
-static int add_spp_sdp(const char *service_name, int scn)
-{
-    UINT16 serviceclassid = UUID_SERVCLASS_SERIAL_PORT;
-    tSDP_PROTOCOL_ELEM  proto_elem_list[SPP_NUM_PROTO_ELEMS];
-    int              sdp_handle;
-
-    APPL_TRACE_DEBUG("scn %d, service name %s", scn, service_name);
-
-    /* register the service */
-    if ((sdp_handle = SDP_CreateRecord()) != FALSE)
-    {
-        /*** Fill out the protocol element sequence for SDP ***/
-        proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-        proto_elem_list[0].num_params = 0;
-        proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
-        proto_elem_list[1].num_params = 1;
-
-        proto_elem_list[1].params[0] = scn;
-
-        if (SDP_AddProtocolList(sdp_handle, SPP_NUM_PROTO_ELEMS, proto_elem_list))
-        {
-            if (SDP_AddServiceClassIdList(sdp_handle, 1, &serviceclassid))
-            {
-                if ((SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME,
-                                TEXT_STR_DESC_TYPE, (UINT32)(strlen(service_name)+1),
-                                (UINT8 *)service_name)))
-                {
-                    UINT16  list[1];
-                    /* Make the service browseable */
-                    list[0] = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
-                    SDP_AddUuidSequence (sdp_handle,  ATTR_ID_BROWSE_GROUP_LIST,
-                                    1, list);
-                }
-            }
-        }
+
+// Registers a service with the given |name| and |channel| as an OBEX Push
+// protocol.
+static int add_ops_sdp(const char *name, const int channel) {
+  APPL_TRACE_DEBUG("add_ops_sdp: scn %d, service_name %s", channel, name);
+
+  UINT32 handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_ops_sdp: failed to create sdp record, "
+                     "service_name: %s", name);
+    return 0;
+  }
+
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, TRUE /* with_obex */))
+    goto error;
+
+  // Add service class.
+  stage = "service_class";
+  UINT16 service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+  if (!SDP_AddServiceClassIdList(handle, 1, &service))
+    goto error;
+
+  // Add the OBEX push profile descriptor.
+  stage = "profile_descriptor_list";
+  if (!SDP_AddProfileDescriptorList(handle, UUID_SERVCLASS_OBEX_OBJECT_PUSH,
+                                    0x0100))
+    goto error;
+
+  // Add sequence for supported types.
+  UINT8 desc_type[OBEX_PUSH_NUM_FORMATS];
+  UINT8 type_len[OBEX_PUSH_NUM_FORMATS];
+  UINT8 *type_value[OBEX_PUSH_NUM_FORMATS];
+  UINT8 j = 0;
+
+  for (int i = 0; i < OBEX_PUSH_NUM_FORMATS; i++) {
+    if ((BTUI_OPS_FORMATS >> i) & 1) {
+      type_value[j] = (UINT8*)(&bta_ops_obj_fmt[i]);
+      desc_type[j] = UINT_DESC_TYPE;
+      type_len[j++] = 1;
     }
-    return sdp_handle;
+  }
+
+  stage = "supported_types";
+  if (!SDP_AddSequence(handle, (UINT16)ATTR_ID_SUPPORTED_FORMATS_LIST,
+                       j, desc_type, type_len, type_value))
+    goto error;
+
+  // Set class of device.
+  tBTA_UTL_COD cod;
+  cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+  stage = "class_of_device";
+  if (!utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS))
+    goto error;
+
+  // Notify the system that we've got a new service class UUID.
+  bta_sys_add_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
+  APPL_TRACE_DEBUG("ad_maps_sdp: service registered successfully, "
+                   "service_name: %s, handle 0x%08x)", name, handle);
+
+  return handle;
+
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_ops_sdp: failed to register OPS service, "
+                   "stage: %s, service_name: %s", stage, name);
+  return 0;
 }
 
+// Registers a service with the given |name| and |channel| as a serial port
+// profile protocol.
+static int add_spp_sdp(const char *name, const int channel) {
+  APPL_TRACE_DEBUG("add_spp_sdp: scn %d, service_name %s", channel, name);
 
-static int add_rfc_sdp_by_uuid(const char* name, const uint8_t* uuid, int scn)
-{
-    int handle = 0;
+  int handle = SDP_CreateRecord();
+  if (handle == 0) {
+    APPL_TRACE_ERROR("add_spp_sdp: failed to create sdp record, "
+                     "service_name: %s", name);
+    return 0;
+  }
 
-    APPL_TRACE_DEBUG("name:%s, scn:%d", name, scn);
+  // Create the base SDP record.
+  char *stage = "create_base_record";
+  if (!create_base_record(handle, name, channel, FALSE /* with_obex */))
+    goto error;
 
-    /*
-        Bluetooth Socket API relies on having preregistered bluez sdp records for HSAG, HFAG, OPP & PBAP
-        that are mapped to rc chan 10, 11,12 & 19. Today HSAG and HFAG is routed to BRCM AG and are not
-        using BT socket API so for now we will need to support OPP and PBAP to enable 3rd party developer
-        apps running on BRCM Android.
+  UINT16 service = UUID_SERVCLASS_SERIAL_PORT;
+  stage = "service_class";
+  if (!SDP_AddServiceClassIdList(handle, 1, &service))
+    goto error;
 
-        To do this we will check the UUID for the requested service and mimic the SDP records of bluez
-        upon reception.  See functions add_opush() and add_pbap() in sdptool.c for actual records
-    */
+  APPL_TRACE_DEBUG("add_spp_sdp: service registered successfully, "
+                   "service_name: %s, handle 0x%08x)", name, handle);
 
-    /* special handling for preregistered bluez services (OPP, PBAP) that we need to mimic */
+  return handle;
 
-    int final_scn = get_reserved_rfc_channel(uuid);
-    if (final_scn == -1)
-    {
-        final_scn=scn;
-    }
-    if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
-    {
-        handle = add_ops_sdp(name,final_scn);
-    }
-    else if (IS_UUID(UUID_PBAP_PSE,uuid))
-    {
-        handle = add_pbap_sdp(name, final_scn); //PBAP Server is always 19
-    }
-    else if (IS_UUID(UUID_MAPS_MAS,uuid))
-    {
-        handle = add_maps_sdp(name, final_scn); //MAP Server is always 19
-    }
-    else if (IS_UUID(UUID_SPP, uuid))
-    {
-        handle = add_spp_sdp(name, final_scn);
-    }
-    else
-    {
-        handle = add_sdp_by_uuid(name, uuid, final_scn);
-    }
-    return handle;
+error:
+  SDP_DeleteRecord(handle);
+  APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, "
+                   "stage: %s, service_name: %s", stage, name);
+  return 0;
 }
 
-BOOLEAN is_reserved_rfc_channel(int scn)
-{
-    switch(scn)
-    {
-        case RESERVED_SCN_PBS:
-        case RESERVED_SCN_OPS:
-            return TRUE;
-    }
-    return FALSE;
+// Adds an RFCOMM SDP record for a service with the given |name|, |uuid|, and
+// |channel|. This function attempts to identify the type of the service based
+// upon its |uuid|, and will override the |channel| with a reserved channel
+// number if the |uuid| matches one of the preregistered bluez SDP records.
+static int add_rfc_sdp_by_uuid(const char *name, const uint8_t *uuid,
+                               const int channel) {
+  APPL_TRACE_DEBUG("add_rfc_sdp_by_uuid: service_name: %s, channel: %d", name,
+                   channel);
+
+  /*
+   * Bluetooth Socket API relies on having preregistered bluez sdp records for
+   * HSAG, HFAG, OPP & PBAP that are mapped to rc chan 10, 11,12 & 19. Today
+   * HSAG and HFAG is routed to BRCM AG and are not using BT socket API so for
+   * now we will need to support OPP and PBAP to enable 3rd party developer apps
+   * running on BRCM Android.
+   *
+   * To do this we will check the UUID for the requested service and mimic the
+   * SDP records of bluez upon reception.  See functions add_opush() and
+   * add_pbap() in sdptool.c for actual records.
+   */
+
+  int final_channel = get_reserved_rfc_channel(uuid);
+
+  if (final_channel == -1) {
+    final_channel = channel;
+  }
+
+  int handle = 0;
+
+  if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
+    handle = add_ops_sdp(name, final_channel);
+  } else if (UUID_MATCHES(UUID_PBAP_PSE,uuid)) {
+    // PBAP Server is always channel 19
+    handle = add_pbap_sdp(name, final_channel);
+  } else if (UUID_MATCHES(UUID_SPP, uuid)) {
+    handle = add_spp_sdp(name, final_channel);
+  } else if (UUID_MATCHES(UUID_MAPS_MAS,uuid)) {
+    // MAP Server is always channel 19
+    handle = add_maps_sdp(name, final_channel);
+  } else {
+    handle = add_sdp_by_uuid(name, uuid, final_channel);
+  }
+
+  return handle;
 }
 
+BOOLEAN is_reserved_rfc_channel(const int channel) {
+  switch(channel) {
+    case RESERVED_SCN_PBS:
+    case RESERVED_SCN_OPS:
+      return TRUE;
+  }
 
-int get_reserved_rfc_channel (const uint8_t* uuid)
-{
-    if (IS_UUID(UUID_PBAP_PSE,uuid))
-    {
-      return RESERVED_SCN_PBS;
-    }
-    else if (IS_UUID(UUID_OBEX_OBJECT_PUSH,uuid))
-    {
-      return RESERVED_SCN_OPS;
-    }
-    return -1;
+  return FALSE;
 }
 
-int add_rfc_sdp_rec(const char* name, const uint8_t* uuid, int scn)
-{
-    int sdp_handle = 0;
-    if(is_uuid_empty(uuid))
-    {
-        switch(scn)
-        {
-            case RESERVED_SCN_PBS: // PBAP Reserved port
-                uuid = UUID_PBAP_PSE;
-                break;
-             case RESERVED_SCN_OPS:
-                uuid = UUID_OBEX_OBJECT_PUSH;
-                break;
-            default:
-                uuid = UUID_SPP;
-                break;
-        }
-    }
-    sdp_handle = add_rfc_sdp_by_uuid(name, uuid, scn);
-    return sdp_handle;
+int get_reserved_rfc_channel(const uint8_t *uuid) {
+  if (UUID_MATCHES(UUID_PBAP_PSE, uuid)) {
+    return RESERVED_SCN_PBS;
+  } else if (UUID_MATCHES(UUID_OBEX_OBJECT_PUSH, uuid)) {
+    return RESERVED_SCN_OPS;
+  }
+
+  return -1;
 }
 
-void del_rfc_sdp_rec(int handle)
-{
-    APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle);
-    if(handle != -1 && handle != 0)
-        BTA_JvDeleteRecord( handle );
+// Adds an SDP record to the SDP database using the given |name|, |uuid|, and
+// |channel|. Note that if the |uuid| is empty, the |uuid| will be set based
+// upon the |channel| passed in.
+int add_rfc_sdp_rec(const char *name, const uint8_t *uuid, const int channel) {
+  if (is_uuid_empty(uuid)) {
+    switch(channel) {
+      case RESERVED_SCN_PBS: // PBAP Reserved port
+        uuid = UUID_PBAP_PSE;
+        break;
+
+      case RESERVED_SCN_OPS:
+        uuid = UUID_OBEX_OBJECT_PUSH;
+        break;
+
+      default:
+        uuid = UUID_SPP;
+        break;
+    }
+  }
+
+  return add_rfc_sdp_by_uuid(name, uuid, channel);
 }
 
+// Deletes an SDP record with the given |handle|.
+void del_rfc_sdp_rec(int handle) {
+  APPL_TRACE_DEBUG("del_rfc_sdp_rec: handle:0x%x", handle);
+
+  if ((handle != -1) && (handle != 0))
+    BTA_JvDeleteRecord(handle);
+}