GATT Server refactoring (4/4)

Right now in order to add gatt service, we need to add it piece by
piece - each characteristic and descriptor separately. This causes lots
of concurrency errors in higher layers. Instead accept whole service
definition and start whole service at once.

Also, use handles to identify GATT server attributes. It's already done
on clinet side.

Bug: 27999121
Change-Id: I42c796809423d116fe6755ef8b1c40da270427a5
diff --git a/bta/gatt/bta_gatts_act.cc b/bta/gatt/bta_gatts_act.cc
index 8ad94df..3ca572c 100644
--- a/bta/gatt/bta_gatts_act.cc
+++ b/bta/gatt/bta_gatts_act.cc
@@ -316,176 +316,7 @@
         APPL_TRACE_ERROR("application not registered.");
     }
 }
-/*******************************************************************************
-**
-** Function         bta_gatts_create_srvc
-**
-** Description      action function to create a service.
-**
-** Returns          none.
-**
-*******************************************************************************/
-void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
-{
-    uint8_t               rcb_idx;
-    tBTA_GATTS          cb_data;
-    uint8_t               srvc_idx;
-    uint16_t              service_id = 0;
 
-    cb_data.create.status = BTA_GATT_ERROR;
-
-    rcb_idx = bta_gatts_find_app_rcb_idx_by_app_if(p_cb, p_msg->api_create_svc.server_if);
-
-    APPL_TRACE_ERROR("create service rcb_idx = %d", rcb_idx);
-
-    if (rcb_idx != BTA_GATTS_INVALID_APP)
-    {
-        if ((srvc_idx = bta_gatts_alloc_srvc_cb(p_cb, rcb_idx)) != BTA_GATTS_INVALID_APP)
-        {
-            /* create the service now */
-            service_id = GATTS_CreateService (p_cb->rcb[rcb_idx].gatt_if,
-                                              &p_msg->api_create_svc.service_uuid,
-                                              p_msg->api_create_svc.inst,
-                                              p_msg->api_create_svc.num_handle,
-                                              p_msg->api_create_svc.is_pri);
-
-            if (service_id != 0)
-            {
-                memcpy(&p_cb->srvc_cb[srvc_idx].service_uuid,
-                    &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
-                p_cb->srvc_cb[srvc_idx].service_id   = service_id;
-                p_cb->srvc_cb[srvc_idx].inst_num     = p_msg->api_create_svc.inst;
-                p_cb->srvc_cb[srvc_idx].idx          = srvc_idx;
-
-                cb_data.create.status      = BTA_GATT_OK;
-                cb_data.create.service_id  = service_id;
-                cb_data.create.is_primary  = p_msg->api_create_svc.is_pri;
-                cb_data.create.server_if   = p_cb->rcb[rcb_idx].gatt_if;
-            }
-            else
-            {
-                cb_data.status  = BTA_GATT_ERROR;
-                memset(&p_cb->srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
-                APPL_TRACE_ERROR("service creation failed.");
-            }
-            memcpy(&cb_data.create.uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
-            cb_data.create.svc_instance= p_msg->api_create_svc.inst;
-        }
-        if (p_cb->rcb[rcb_idx].p_cback)
-            (* p_cb->rcb[rcb_idx].p_cback)(BTA_GATTS_CREATE_EVT, &cb_data);
-    }
-    else /* application not registered */
-    {
-        APPL_TRACE_ERROR("Application not registered");
-    }
-}
-/*******************************************************************************
-**
-** Function         bta_gatts_add_include_srvc
-**
-** Description      action function to add an included service.
-**
-** Returns          none.
-**
-*******************************************************************************/
-void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb,tBTA_GATTS_DATA * p_msg)
-{
-    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
-    uint16_t          attr_id = 0;
-    tBTA_GATTS      cb_data;
-
-    attr_id = GATTS_AddIncludeService(p_msg->api_add_incl_srvc.hdr.layer_specific,
-                                      p_msg->api_add_incl_srvc.included_service_id);
-
-    cb_data.add_result.server_if = p_rcb->gatt_if;
-    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
-    cb_data.add_result.attr_id = attr_id;
-
-    if (attr_id)
-    {
-        cb_data.add_result.status = BTA_GATT_OK;
-    }
-    else
-    {
-        cb_data.add_result.status = BTA_GATT_ERROR;
-    }
-
-    if (p_rcb->p_cback)
-        (*p_rcb->p_cback)(BTA_GATTS_ADD_INCL_SRVC_EVT, &cb_data);
-}
-/*******************************************************************************
-**
-** Function         bta_gatts_add_char
-**
-** Description      action function to add characteristic.
-**
-** Returns          none.
-**
-*******************************************************************************/
-void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
-{
-    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
-    uint16_t          attr_id = 0;
-    tBTA_GATTS      cb_data;
-
-    attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific,
-                                      &p_msg->api_add_char.char_uuid,
-                                      p_msg->api_add_char.perm,
-                                      p_msg->api_add_char.property);
-    cb_data.add_result.server_if = p_rcb->gatt_if;
-    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
-    cb_data.add_result.attr_id = attr_id;
-    memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char.char_uuid, sizeof(tBT_UUID));
-
-    if (attr_id)
-    {
-        cb_data.add_result.status = BTA_GATT_OK;
-    }
-    else
-    {
-        cb_data.add_result.status = BTA_GATT_ERROR;
-    }
-
-    if (p_rcb->p_cback)
-        (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
-}
-/*******************************************************************************
-**
-** Function         bta_gatts_add_char_descr
-**
-** Description      action function to add characteristic descriptor.
-**
-** Returns          none.
-**
-*******************************************************************************/
-void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
-{
-    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
-    uint16_t          attr_id = 0;
-    tBTA_GATTS      cb_data;
-
-    attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific,
-                                       p_msg->api_add_char_descr.perm,
-                                       &p_msg->api_add_char_descr.descr_uuid);
-
-    cb_data.add_result.server_if = p_rcb->gatt_if;
-    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
-    cb_data.add_result.attr_id = attr_id;
-    memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char_descr.descr_uuid, sizeof(tBT_UUID));
-
-    if (attr_id)
-    {
-        cb_data.add_result.status = BTA_GATT_OK;
-    }
-    else
-    {
-        cb_data.add_result.status = BTA_GATT_ERROR;
-    }
-
-    if (p_rcb->p_cback)
-        (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data);
-
-}
 /*******************************************************************************
 **
 ** Function         bta_gatts_delete_service
@@ -501,11 +332,11 @@
     tBTA_GATTS      cb_data;
 
     cb_data.srvc_oper.server_if = p_rcb->gatt_if;
-    cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    // cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
 
     if (GATTS_DeleteService(p_rcb->gatt_if,
                             &p_srvc_cb->service_uuid,
-                            p_srvc_cb->inst_num))
+                            p_srvc_cb->service_id))
     {
         cb_data.srvc_oper.status = BTA_GATT_OK;
         memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
@@ -519,39 +350,7 @@
         (*p_rcb->p_cback)(BTA_GATTS_DELELTE_EVT, &cb_data);
 
 }
-/*******************************************************************************
-**
-** Function         bta_gatts_start_service
-**
-** Description      action function to start a service.
-**
-** Returns          none.
-**
-*******************************************************************************/
-void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
-{
-    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
-    tBTA_GATTS      cb_data;
 
-    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
-    cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
-
-    if (GATTS_StartService(p_rcb->gatt_if,
-                           p_srvc_cb->service_id,
-                           p_msg->api_start.transport) ==  GATT_SUCCESS)
-    {
-        APPL_TRACE_DEBUG("bta_gatts_start_service service_id= %d", p_srvc_cb->service_id);
-        cb_data.srvc_oper.status = BTA_GATT_OK;
-    }
-    else
-    {
-        cb_data.srvc_oper.status = BTA_GATT_ERROR;
-    }
-
-    if (p_rcb->p_cback)
-        (*p_rcb->p_cback)(BTA_GATTS_START_EVT, &cb_data);
-
-}
 /*******************************************************************************
 **
 ** Function         bta_gatts_stop_service
@@ -850,8 +649,8 @@
     {
         p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
 
-        APPL_TRACE_DEBUG ("bta_gatts_send_request_cback conn_id=%d trans_id=%d req_type=%d",
-                            conn_id, trans_id, req_type);
+        APPL_TRACE_DEBUG("%s: conn_id=%d trans_id=%d req_type=%d",
+                         __func__, conn_id, trans_id, req_type);
 
         if (p_rcb && p_rcb->p_cback)
         {
diff --git a/bta/gatt/bta_gatts_api.cc b/bta/gatt/bta_gatts_api.cc
index a6c5a14..64bb05f 100644
--- a/bta/gatt/bta_gatts_api.cc
+++ b/bta/gatt/bta_gatts_api.cc
@@ -32,6 +32,8 @@
 #include "bta_gatt_api.h"
 #include "bta_gatts_int.h"
 
+void btif_to_bta_uuid(tBT_UUID *p_dest, const bt_uuid_t *p_src);
+
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
@@ -123,127 +125,47 @@
 
 /*******************************************************************************
 **
-** Function         BTA_GATTS_CreateService
+** Function         BTA_GATTS_AddService
 **
-** Description      Create a service. When service creation is done, a callback
-**                  event BTA_GATTS_CREATE_SRVC_EVT is called to report status
-**                  and service ID to the profile. The service ID obtained in
-**                  the callback function needs to be used when adding included
-**                  service and characteristics/descriptors into the service.
+** Description      Add the given |service| and all included elements to the
+**                  GATT database. a |BTA_GATTS_ADD_SRVC_EVT| is triggered to
+**                  report the status and attribute handles.
 **
-** Parameters       app_id: Profile ID this service is belonged to.
-**                  p_service_uuid: service UUID.
-**                  inst: instance ID number of this service.
-**                  num_handle: numble of handle requessted for this service.
-**                  is_primary: is this service a primary one or not.
+** Parameters       server_if: server interface.
+**                  service: pointer vector describing service.
 **
-** Returns          void
+** Returns          Returns |BTA_GATT_OK| on success or |BTA_GATT_ERROR| if the
+**                  service cannot be added.
 **
 *******************************************************************************/
-void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid, uint8_t inst,
-                             uint16_t num_handle, bool is_primary)
+extern uint16_t BTA_GATTS_AddService(tBTA_GATTS_IF server_if, vector<btgatt_db_element_t> &service)
 {
-    tBTA_GATTS_API_CREATE_SRVC *p_buf =
-        (tBTA_GATTS_API_CREATE_SRVC *)osi_malloc(sizeof(tBTA_GATTS_API_CREATE_SRVC));
+    uint8_t rcb_idx = bta_gatts_find_app_rcb_idx_by_app_if(&bta_gatts_cb, server_if);
 
-    p_buf->hdr.event = BTA_GATTS_API_CREATE_SRVC_EVT;
-    p_buf->server_if = server_if;
-    p_buf->inst = inst;
-    memcpy(&p_buf->service_uuid, p_service_uuid, sizeof(tBT_UUID));
-    p_buf->num_handle = num_handle;
-    p_buf->is_pri = is_primary;
+    APPL_TRACE_ERROR("%s: rcb_idx = %d", __func__, rcb_idx);
 
-    bta_sys_sendmsg(p_buf);
-}
-/*******************************************************************************
-**
-** Function         BTA_GATTS_AddIncludeService
-**
-** Description      This function is called to add an included service. After included
-**                  service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
-**                  is reported the included service ID.
-**
-** Parameters       service_id: service ID to which this included service is to
-**                              be added.
-**                  included_service_id: the service ID to be included.
-**
-** Returns          void
-**
-*******************************************************************************/
-void BTA_GATTS_AddIncludeService(uint16_t service_id, uint16_t included_service_id)
-{
-    tBTA_GATTS_API_ADD_INCL_SRVC *p_buf =
-        (tBTA_GATTS_API_ADD_INCL_SRVC *)osi_malloc(sizeof(tBTA_GATTS_API_ADD_INCL_SRVC));
+    if (rcb_idx == BTA_GATTS_INVALID_APP)
+        return BTA_GATT_ERROR;
 
-    p_buf->hdr.event = BTA_GATTS_API_ADD_INCL_SRVC_EVT;
-    p_buf->hdr.layer_specific = service_id;
-    p_buf->included_service_id = included_service_id;
+    uint8_t srvc_idx = bta_gatts_alloc_srvc_cb(&bta_gatts_cb, rcb_idx);
+    if (srvc_idx == BTA_GATTS_INVALID_APP)
+        return BTA_GATT_ERROR;
 
-    bta_sys_sendmsg(p_buf);
-}
+    uint16_t status = GATTS_AddService(server_if, service.data(), service.size());
 
-/*******************************************************************************
-**
-** Function         BTA_GATTS_AddCharacteristic
-**
-** Description      This function is called to add a characteristic into a service.
-**
-** Parameters       service_id: service ID to which this included service is to
-**                              be added.
-**                  p_char_uuid : Characteristic UUID.
-**                  perm      : Characteristic value declaration attribute permission.
-**                  property  : Characteristic Properties
-**
-** Returns          None
-**
-*******************************************************************************/
-void BTA_GATTS_AddCharacteristic (uint16_t service_id,  tBT_UUID  *p_char_uuid,
-                                  tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property)
-{
-    tBTA_GATTS_API_ADD_CHAR *p_buf =
-        (tBTA_GATTS_API_ADD_CHAR *)osi_calloc(sizeof(tBTA_GATTS_API_ADD_CHAR));
+    if (status == GATT_SERVICE_STARTED) {
+        btif_to_bta_uuid(&bta_gatts_cb.srvc_cb[srvc_idx].service_uuid, &service[0].uuid);
 
-    p_buf->hdr.event = BTA_GATTS_API_ADD_CHAR_EVT;
-    p_buf->hdr.layer_specific = service_id;
-    p_buf->perm = perm;
-    p_buf->property = property;
+        // service_id is equal to service start handle
+        bta_gatts_cb.srvc_cb[srvc_idx].service_id   = service[0].attribute_handle;
+        bta_gatts_cb.srvc_cb[srvc_idx].idx          = srvc_idx;
 
-    if (p_char_uuid)
-        memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
-
-    bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
-**
-** Function         BTA_GATTS_AddCharDescriptor
-**
-** Description      This function is called to add characteristic descriptor. When
-**                  it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
-**                  to report the status and an ID number for this descriptor.
-**
-** Parameters       service_id: service ID to which this charatceristic descriptor is to
-**                              be added.
-**                  perm: descriptor access permission.
-**                  p_descr_uuid: descriptor UUID.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-void BTA_GATTS_AddCharDescriptor (uint16_t service_id,
-                                  tBTA_GATT_PERM perm,
-                                  tBT_UUID  * p_descr_uuid)
-{
-    tBTA_GATTS_API_ADD_DESCR *p_buf =
-        (tBTA_GATTS_API_ADD_DESCR *)osi_calloc(sizeof(tBTA_GATTS_API_ADD_DESCR));
-
-    p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
-    p_buf->hdr.layer_specific = service_id;
-    p_buf->perm = perm;
-    if (p_descr_uuid)
-        memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
-
-    bta_sys_sendmsg(p_buf);
+        return BTA_GATT_OK;
+    }else {
+        memset(&bta_gatts_cb.srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
+        APPL_TRACE_ERROR("%s: service creation failed.", __func__);
+        return BTA_GATT_ERROR;
+    }
 }
 
 /*******************************************************************************
@@ -270,30 +192,6 @@
 
 /*******************************************************************************
 **
-** Function         BTA_GATTS_StartService
-**
-** Description      This function is called to start a service.
-**
-** Parameters       service_id: the service ID to be started.
-**                  sup_transport: supported trasnport.
-**
-** Returns          None.
-**
-*******************************************************************************/
-void BTA_GATTS_StartService(uint16_t service_id, tBTA_GATT_TRANSPORT sup_transport)
-{
-    tBTA_GATTS_API_START *p_buf =
-        (tBTA_GATTS_API_START *)osi_malloc(sizeof(tBTA_GATTS_API_START));
-
-    p_buf->hdr.event = BTA_GATTS_API_START_SRVC_EVT;
-    p_buf->hdr.layer_specific = service_id;
-    p_buf->transport = sup_transport;
-
-    bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
-**
 ** Function         BTA_GATTS_StopService
 **
 ** Description      This function is called to stop a service.
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
index 69bda1f..b92383a 100644
--- a/bta/gatt/bta_gatts_int.h
+++ b/bta/gatt/bta_gatts_int.h
@@ -39,14 +39,9 @@
     BTA_GATTS_API_REG_EVT  = BTA_SYS_EVT_START(BTA_ID_GATTS),
     BTA_GATTS_INT_START_IF_EVT,
     BTA_GATTS_API_DEREG_EVT,
-    BTA_GATTS_API_CREATE_SRVC_EVT,
     BTA_GATTS_API_INDICATION_EVT,
 
-    BTA_GATTS_API_ADD_INCL_SRVC_EVT,
-    BTA_GATTS_API_ADD_CHAR_EVT,
-    BTA_GATTS_API_ADD_DESCR_EVT,
     BTA_GATTS_API_DEL_SRVC_EVT,
-    BTA_GATTS_API_START_SRVC_EVT,
     BTA_GATTS_API_STOP_SRVC_EVT,
     BTA_GATTS_API_RSP_EVT,
     BTA_GATTS_API_OPEN_EVT,
@@ -83,35 +78,9 @@
 {
     BT_HDR                  hdr;
     tBTA_GATTS_IF           server_if;
-    tBT_UUID                service_uuid;
-    uint16_t                  num_handle;
-    uint8_t                   inst;
-    bool                 is_pri;
-
-} tBTA_GATTS_API_CREATE_SRVC;
-
-typedef struct
-{
-    BT_HDR                  hdr;
-    tBT_UUID                char_uuid;
-    tBTA_GATT_PERM          perm;
-    tBTA_GATT_CHAR_PROP     property;
-
-}tBTA_GATTS_API_ADD_CHAR;
-
-typedef struct
-{
-    BT_HDR                  hdr;
-    uint16_t                  included_service_id;
-
-}tBTA_GATTS_API_ADD_INCL_SRVC;
-
-typedef struct
-{
-    BT_HDR                      hdr;
-    tBT_UUID                    descr_uuid;
-    tBTA_GATT_PERM              perm;
-}tBTA_GATTS_API_ADD_DESCR;
+    btgatt_db_element_t    *service;
+    UINT16                  count;
+} tBTA_GATTS_API_ADD_SERVICE;
 
 typedef struct
 {
@@ -162,11 +131,7 @@
     BT_HDR                          hdr;
     tBTA_GATTS_API_REG              api_reg;
     tBTA_GATTS_API_DEREG            api_dereg;
-    tBTA_GATTS_API_CREATE_SRVC      api_create_svc;
-    tBTA_GATTS_API_ADD_INCL_SRVC    api_add_incl_srvc;
-    tBTA_GATTS_API_ADD_CHAR         api_add_char;
-    tBTA_GATTS_API_ADD_DESCR        api_add_char_descr;
-    tBTA_GATTS_API_START            api_start;
+    tBTA_GATTS_API_ADD_SERVICE      api_add_service;
     tBTA_GATTS_API_INDICATION       api_indicate;
     tBTA_GATTS_API_RSP              api_rsp;
     tBTA_GATTS_API_OPEN             api_open;
@@ -190,12 +155,10 @@
 typedef struct
 {
     tBT_UUID    service_uuid;   /* service UUID */
-    uint16_t      service_id;     /* service handle */
-    uint8_t       inst_num;       /* instance ID */
+    uint16_t      service_id;     /* service start handle */
     uint8_t       rcb_idx;
     uint8_t       idx;            /* self index of serviec CB */
     bool     in_use;
-
 }tBTA_GATTS_SRVC_CB;
 
 
@@ -226,12 +189,7 @@
 extern void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
 extern void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
 extern void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
-extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
-extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
-extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
-extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
 extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
-extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
 extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
 
 extern void bta_gatts_send_rsp(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
diff --git a/bta/gatt/bta_gatts_main.cc b/bta/gatt/bta_gatts_main.cc
index 5656ecc..9f78cae 100644
--- a/bta/gatt/bta_gatts_main.cc
+++ b/bta/gatt/bta_gatts_main.cc
@@ -31,20 +31,6 @@
 #include "bta_gatts_int.h"
 #include "bt_common.h"
 
-/* type for service building action functions */
-typedef void (*tBTA_GATTS_SRVC_ACT)(tBTA_GATTS_SRVC_CB *p_rcb, tBTA_GATTS_DATA *p_data);
-
-/* service building action function list */
-const tBTA_GATTS_SRVC_ACT bta_gatts_srvc_build_act[] =
-{
-    bta_gatts_add_include_srvc,
-    bta_gatts_add_char,
-    bta_gatts_add_char_descr,
-    bta_gatts_delete_service,
-    bta_gatts_start_service,
-    bta_gatts_stop_service,
-};
-
 /* GATTS control block */
 tBTA_GATTS_CB  bta_gatts_cb;
 
@@ -61,7 +47,6 @@
 bool bta_gatts_hdl_event(BT_HDR *p_msg)
 {
     tBTA_GATTS_CB *p_cb = &bta_gatts_cb;
-    tBTA_GATTS_SRVC_CB *p_srvc_cb = NULL;
 
     switch (p_msg->event)
     {
@@ -81,10 +66,6 @@
             bta_gatts_deregister(p_cb, (tBTA_GATTS_DATA *) p_msg);
             break;
 
-        case BTA_GATTS_API_CREATE_SRVC_EVT:
-            bta_gatts_create_srvc(p_cb, (tBTA_GATTS_DATA *) p_msg);
-            break;
-
         case BTA_GATTS_API_INDICATION_EVT:
             bta_gatts_indicate_handle(p_cb,(tBTA_GATTS_DATA *) p_msg);
             break;
@@ -110,25 +91,31 @@
             break;
 
 
-        case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
-        case BTA_GATTS_API_ADD_CHAR_EVT:
-        case BTA_GATTS_API_ADD_DESCR_EVT:
         case BTA_GATTS_API_DEL_SRVC_EVT:
-        case BTA_GATTS_API_START_SRVC_EVT:
-        case BTA_GATTS_API_STOP_SRVC_EVT:
-
-            p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
-                                ((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
+        {
+            tBTA_GATTS_SRVC_CB *p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
+                                ((tBTA_GATTS_DATA *)p_msg)->api_add_service.hdr.layer_specific);
 
             if (p_srvc_cb != NULL)
-            {
-                bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
-            }
+                bta_gatts_delete_service(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
             else
-            {
-                APPL_TRACE_ERROR("service not created");
-            }
+                APPL_TRACE_ERROR("%s: can't delete service - no srvc_cb found", __func__);
+
             break;
+        }
+
+        case BTA_GATTS_API_STOP_SRVC_EVT:
+        {
+            tBTA_GATTS_SRVC_CB *p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
+                                ((tBTA_GATTS_DATA *)p_msg)->api_add_service.hdr.layer_specific);
+
+            if (p_srvc_cb != NULL)
+                bta_gatts_stop_service(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
+            else
+                APPL_TRACE_ERROR("%s: can't stop service - no srvc_cb found", __func__);
+
+            break;
+        }
 
         default:
             break;
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 2ef8ebf..f1b688c 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -353,18 +353,15 @@
 /* GATT Server Data Structure */
 /* Server callback function events */
 #define BTA_GATTS_REG_EVT                               0
-#define BTA_GATTS_READ_EVT                              GATTS_REQ_TYPE_READ         /* 1 */
-#define BTA_GATTS_WRITE_EVT                             GATTS_REQ_TYPE_WRITE        /* 2 */
-#define BTA_GATTS_EXEC_WRITE_EVT                        GATTS_REQ_TYPE_WRITE_EXEC   /* 3 */
-#define BTA_GATTS_MTU_EVT                               GATTS_REQ_TYPE_MTU          /* 4 */
-#define BTA_GATTS_CONF_EVT                              GATTS_REQ_TYPE_CONF         /* 5 */
-#define BTA_GATTS_DEREG_EVT                             6
-#define BTA_GATTS_CREATE_EVT                            7
-#define BTA_GATTS_ADD_INCL_SRVC_EVT                     8
-#define BTA_GATTS_ADD_CHAR_EVT                          9
-#define BTA_GATTS_ADD_CHAR_DESCR_EVT                    10
+#define BTA_GATTS_READ_CHARACTERISTIC_EVT               GATTS_REQ_TYPE_READ_CHARACTERISTIC     /* 1 */
+#define BTA_GATTS_READ_DESCRIPTOR_EVT                   GATTS_REQ_TYPE_READ_DESCRIPTOR         /* 2 */
+#define BTA_GATTS_WRITE_CHARACTERISTIC_EVT              GATTS_REQ_TYPE_WRITE_CHARACTERISTIC    /* 3 */
+#define BTA_GATTS_WRITE_DESCRIPTOR_EVT                  GATTS_REQ_TYPE_WRITE_DESCRIPTOR        /* 4 */
+#define BTA_GATTS_EXEC_WRITE_EVT                        GATTS_REQ_TYPE_WRITE_EXEC   /* 5 */
+#define BTA_GATTS_MTU_EVT                               GATTS_REQ_TYPE_MTU          /* 6 */
+#define BTA_GATTS_CONF_EVT                              GATTS_REQ_TYPE_CONF         /* 7 */
+#define BTA_GATTS_DEREG_EVT                             8
 #define BTA_GATTS_DELELTE_EVT                           11
-#define BTA_GATTS_START_EVT                             12
 #define BTA_GATTS_STOP_EVT                              13
 #define BTA_GATTS_CONNECT_EVT                           14
 #define BTA_GATTS_DISCONNECT_EVT                        15
@@ -486,16 +483,7 @@
 typedef struct
 {
     tBTA_GATTS_IF       server_if;
-    uint16_t              service_id;
-    uint16_t              attr_id;
-    tBTA_GATT_STATUS    status;
-    tBT_UUID            char_uuid;
-}tBTA_GATTS_ADD_RESULT;
-
-typedef struct
-{
-    tBTA_GATTS_IF       server_if;
-    uint16_t              service_id;
+    UINT16              service_id;
     tBTA_GATT_STATUS    status;
 }tBTA_GATTS_SRVC_OPER;
 
@@ -528,9 +516,6 @@
     tBTA_GATTS_CREATE       create;
     tBTA_GATTS_SRVC_OPER    srvc_oper;
     tBTA_GATT_STATUS        status;      /* BTA_GATTS_LISTEN_EVT */
-    tBTA_GATTS_ADD_RESULT   add_result;  /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
-                                           add char : BTA_GATTS_ADD_CHAR_EVT
-                                           add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
     tBTA_GATTS_REQ          req_data;
     tBTA_GATTS_CONN         conn;       /* BTA_GATTS_CONN_EVT */
     tBTA_GATTS_CONGEST      congest;    /* BTA_GATTS_CONGEST_EVT callback data */
@@ -1048,81 +1033,20 @@
 
 /*******************************************************************************
 **
-** Function         BTA_GATTS_CreateService
+** Function         BTA_GATTS_AddService
 **
-** Description      Create a service. When service creation is done, a callback
-**                  event BTA_GATTS_CREATE_SRVC_EVT is called to report status
-**                  and service ID to the profile. The service ID obtained in
-**                  the callback function needs to be used when adding included
-**                  service and characteristics/descriptors into the service.
+** Description      Add the given |service| and all included elements to the
+**                  GATT database. a |BTA_GATTS_ADD_SRVC_EVT| is triggered to
+**                  report the status and attribute handles.
 **
 ** Parameters       server_if: server interface.
-**                  p_service_uuid: service UUID.
-**                  inst: instance ID number of this service.
-**                  num_handle: numble of handle requessted for this service.
-**                  is_primary: is this service a primary one or not.
+**                  service: pointer to vector describing service.
 **
-** Returns          void
+** Returns          Returns |BTA_GATT_OK| on success or |BTA_GATT_ERROR| if the
+**                  service cannot be added.
 **
 *******************************************************************************/
-extern void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid,
-                                    uint8_t inst, uint16_t num_handle, bool is_primary);
-
-/*******************************************************************************
-**
-** Function         BTA_GATTS_AddIncludeService
-**
-** Description      This function is called to add an included service. After included
-**                  service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
-**                  is reported the included service ID.
-**
-** Parameters       service_id: service ID to which this included service is to
-**                              be added.
-**                  included_service_id: the service ID to be included.
-**
-** Returns          void
-**
-*******************************************************************************/
-extern void BTA_GATTS_AddIncludeService(uint16_t service_id, uint16_t included_service_id);
-
-/*******************************************************************************
-**
-** Function         BTA_GATTS_AddCharacteristic
-**
-** Description      This function is called to add a characteristic into a service.
-**
-** Parameters       service_id: service ID to which this included service is to
-**                              be added.
-**                  p_char_uuid : Characteristic UUID.
-**                  perm      : Characteristic value declaration attribute permission.
-**                  property  : Characteristic Properties
-**
-** Returns          None
-**
-*******************************************************************************/
-extern void BTA_GATTS_AddCharacteristic (uint16_t service_id,  tBT_UUID   *p_char_uuid,
-                                         tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property);
-
-/*******************************************************************************
-**
-** Function         BTA_GATTS_AddCharDescriptor
-**
-** Description      This function is called to add characteristic descriptor. When
-**                  it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
-**                  to report the status and an ID number for this descriptor.
-**
-** Parameters       service_id: service ID to which this charatceristic descriptor is to
-**                              be added.
-**                  perm: descriptor access permission.
-**                  p_descr_uuid: descriptor UUID.
-**                  p_descr_params: descriptor value if it's read only descriptor.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-extern void BTA_GATTS_AddCharDescriptor (uint16_t service_id,
-                                         tBTA_GATT_PERM perm,
-                                         tBT_UUID  * p_descr_uuid);
+extern uint16_t BTA_GATTS_AddService(tBTA_GATTS_IF server_if, vector<btgatt_db_element_t> &service);
 
 /*******************************************************************************
 **
@@ -1140,20 +1064,6 @@
 
 /*******************************************************************************
 **
-** Function         BTA_GATTS_StartService
-**
-** Description      This function is called to start a service.
-**
-** Parameters       service_id: the service ID to be started.
-**                  sup_transport: supported trasnport.
-**
-** Returns          None.
-**
-*******************************************************************************/
-extern void  BTA_GATTS_StartService(uint16_t service_id, tBTA_GATT_TRANSPORT sup_transport);
-
-/*******************************************************************************
-**
 ** Function         BTA_GATTS_StopService
 **
 ** Description      This function is called to stop a service.
diff --git a/btcore/include/uuid.h b/btcore/include/uuid.h
index 40607cf..ab997e3 100644
--- a/btcore/include/uuid.h
+++ b/btcore/include/uuid.h
@@ -73,3 +73,5 @@
 // |uuid|, |uuid16| and |uuid32| must not be NULL.
 bool uuid_128_to_16(const bt_uuid_t *uuid, uint16_t *uuid16);
 bool uuid_128_to_32(const bt_uuid_t *uuid, uint32_t *uuid32);
+
+void uuid_128_from_16(bt_uuid_t *uuid, uint16_t uuid16);
diff --git a/btcore/src/uuid.c b/btcore/src/uuid.c
index a860147..4213ec3 100644
--- a/btcore/src/uuid.c
+++ b/btcore/src/uuid.c
@@ -125,6 +125,15 @@
   return true;
 }
 
+void uuid_128_from_16(bt_uuid_t *uuid, uint16_t uuid16) {
+  assert(uuid != NULL);
+
+  memcpy(uuid, &base_uuid, sizeof(bt_uuid_t));
+
+  uuid->uu[2] = (uint8_t)((0xFF00 & uuid16)>>8);
+  uuid->uu[3] = (uint8_t)(0x00FF & uuid16);
+}
+
 void uuid_to_string(const bt_uuid_t *uuid, uuid_string_t *uuid_string) {
   assert(uuid != NULL);
   assert(uuid_string != NULL);
diff --git a/btcore/test/uuid_test.cc b/btcore/test/uuid_test.cc
index 7b3e788..deef64c 100644
--- a/btcore/test/uuid_test.cc
+++ b/btcore/test/uuid_test.cc
@@ -138,6 +138,31 @@
   EXPECT_EQ((uint32_t)0, uuid32);
 }
 
+TEST_F(UuidTest, uuid_128_from_16) {
+  bt_uuid_t *uuid = NULL;
+  uint16_t uuid16 = 0x1234;
+
+  uuid = uuid_new(UUID_ONES);
+  uuid_128_from_16(uuid, uuid16);
+  EXPECT_EQ(0x00, uuid->uu[0]);
+  EXPECT_EQ(0x00, uuid->uu[1]);
+  EXPECT_EQ(0x12, uuid->uu[2]);
+  EXPECT_EQ(0x34, uuid->uu[3]);
+  EXPECT_EQ(0x00, uuid->uu[4]);
+  EXPECT_EQ(0x00, uuid->uu[5]);
+  EXPECT_EQ(0x10, uuid->uu[6]);
+  EXPECT_EQ(0x00, uuid->uu[7]);
+  EXPECT_EQ(0x80, uuid->uu[8]);
+  EXPECT_EQ(0x00, uuid->uu[9]);
+  EXPECT_EQ(0x00, uuid->uu[10]);
+  EXPECT_EQ(0x80, uuid->uu[11]);
+  EXPECT_EQ(0x5f, uuid->uu[12]);
+  EXPECT_EQ(0x9b, uuid->uu[13]);
+  EXPECT_EQ(0x34, uuid->uu[14]);
+  EXPECT_EQ(0xfb, uuid->uu[15]);
+  uuid_free(uuid);
+}
+
 TEST_F(UuidTest, uuid_to_string) {
   bt_uuid_t *uuid = NULL;
 
diff --git a/btif/src/btif_gatt_server.cc b/btif/src/btif_gatt_server.cc
index c51fa3e..bb067d5 100644
--- a/btif/src/btif_gatt_server.cc
+++ b/btif/src/btif_gatt_server.cc
@@ -92,8 +92,10 @@
     // Allocate buffer for request data if necessary
     switch (event)
     {
-        case BTA_GATTS_READ_EVT:
-        case BTA_GATTS_WRITE_EVT:
+        case BTA_GATTS_READ_CHARACTERISTIC_EVT:
+        case BTA_GATTS_READ_DESCRIPTOR_EVT:
+        case BTA_GATTS_WRITE_CHARACTERISTIC_EVT:
+        case BTA_GATTS_WRITE_DESCRIPTOR_EVT:
         case BTA_GATTS_EXEC_WRITE_EVT:
         case BTA_GATTS_MTU_EVT:
             p_dest_data->req_data.p_data = (tBTA_GATTS_REQ_DATA *)osi_malloc(sizeof(tBTA_GATTS_REQ_DATA));
@@ -110,8 +112,10 @@
 {
     switch (event)
     {
-        case BTA_GATTS_READ_EVT:
-        case BTA_GATTS_WRITE_EVT:
+        case BTA_GATTS_READ_CHARACTERISTIC_EVT:
+        case BTA_GATTS_READ_DESCRIPTOR_EVT:
+        case BTA_GATTS_WRITE_CHARACTERISTIC_EVT:
+        case BTA_GATTS_WRITE_DESCRIPTOR_EVT:
         case BTA_GATTS_EXEC_WRITE_EVT:
         case BTA_GATTS_MTU_EVT:
             if (p_data != NULL)
@@ -167,63 +171,6 @@
             break;
         }
 
-        case BTA_GATTS_CREATE_EVT:
-        {
-            btgatt_srvc_id_t srvc_id;
-            srvc_id.is_primary = p_data->create.is_primary;
-            srvc_id.id.inst_id = p_data->create.svc_instance;
-            bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
-
-            HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
-                      p_data->create.status, p_data->create.server_if, &srvc_id,
-                      p_data->create.service_id
-            );
-        }
-        break;
-
-        case BTA_GATTS_ADD_INCL_SRVC_EVT:
-            HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
-                      p_data->add_result.status,
-                      p_data->add_result.server_if,
-                      p_data->add_result.service_id,
-                      p_data->add_result.attr_id);
-            break;
-
-        case BTA_GATTS_ADD_CHAR_EVT:
-        {
-            bt_uuid_t uuid;
-            bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
-
-            HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
-                      p_data->add_result.status,
-                      p_data->add_result.server_if,
-                      &uuid,
-                      p_data->add_result.service_id,
-                      p_data->add_result.attr_id);
-            break;
-        }
-
-        case BTA_GATTS_ADD_CHAR_DESCR_EVT:
-        {
-            bt_uuid_t uuid;
-            bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
-
-            HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
-                      p_data->add_result.status,
-                      p_data->add_result.server_if,
-                      &uuid,
-                      p_data->add_result.service_id,
-                      p_data->add_result.attr_id);
-            break;
-        }
-
-        case BTA_GATTS_START_EVT:
-            HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
-                      p_data->srvc_oper.status,
-                      p_data->srvc_oper.server_if,
-                      p_data->srvc_oper.service_id);
-            break;
-
         case BTA_GATTS_STOP_EVT:
             HAL_CBACK(bt_gatt_callbacks, server->service_stopped_cb,
                       p_data->srvc_oper.status,
@@ -238,12 +185,12 @@
                       p_data->srvc_oper.service_id);
             break;
 
-        case BTA_GATTS_READ_EVT:
+        case BTA_GATTS_READ_CHARACTERISTIC_EVT:
         {
             bt_bdaddr_t bda;
             bdcpy(bda.address, p_data->req_data.remote_bda);
 
-            HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
+            HAL_CBACK(bt_gatt_callbacks, server->request_read_characteristic_cb,
                       p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
                       p_data->req_data.p_data->read_req.handle,
                       p_data->req_data.p_data->read_req.offset,
@@ -251,13 +198,38 @@
             break;
         }
 
-        case BTA_GATTS_WRITE_EVT:
+        case BTA_GATTS_READ_DESCRIPTOR_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->req_data.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, server->request_read_descriptor_cb,
+                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+                      p_data->req_data.p_data->read_req.handle,
+                      p_data->req_data.p_data->read_req.offset,
+                      p_data->req_data.p_data->read_req.is_long);
+            break;
+        }
+
+        case BTA_GATTS_WRITE_CHARACTERISTIC_EVT:
         {
             bt_bdaddr_t bda;
             bdcpy(bda.address, p_data->req_data.remote_bda);
             const auto &req = p_data->req_data.p_data->write_req;
             vector<uint8_t> value(req.value, req.value + req.len);
-            HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
+            HAL_CBACK(bt_gatt_callbacks, server->request_write_characteristic_cb,
+                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+                      req.handle, req.offset, req.need_rsp, req.is_prep, value);
+            break;
+        }
+
+        case BTA_GATTS_WRITE_DESCRIPTOR_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->req_data.remote_bda);
+            const auto &req = p_data->req_data.p_data->write_req;
+            vector<uint8_t> value(req.value, req.value + req.len);
+            HAL_CBACK(bt_gatt_callbacks, server->request_write_descriptor_cb,
                       p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
                       req.handle, req.offset, req.need_rsp, req.is_prep, value);
             break;
@@ -408,54 +380,15 @@
       Bind(&btif_gatts_close_impl, server_if, base::Owned(address), conn_id));
 }
 
+static void add_service_impl(int server_if, vector<btgatt_db_element_t> service) {
+  int status = BTA_GATTS_AddService(server_if, service);
+  HAL_CBACK(bt_gatt_callbacks, server->service_added_cb, status, server_if, std::move(service));
+}
+
 static bt_status_t btif_gatts_add_service(int server_if,
-                                          btgatt_srvc_id_t *srvc_id,
-                                          int num_handles) {
+                                          vector<btgatt_db_element_t> service) {
   CHECK_BTGATT_INIT();
-  tBT_UUID *bt_uuid = new tBT_UUID;
-  btif_to_bta_uuid(bt_uuid, &srvc_id->id.uuid);
-
-  return do_in_jni_thread(
-      Bind(base::IgnoreResult(&BTA_GATTS_CreateService), server_if,
-           base::Owned(bt_uuid), (uint8_t)srvc_id->id.inst_id,
-           (uint16_t)num_handles, (bool)srvc_id->is_primary));
-}
-
-static bt_status_t btif_gatts_add_included_service(int server_if,
-                                                   int service_handle,
-                                                   int included_handle) {
-  CHECK_BTGATT_INIT();
-  return do_in_jni_thread(Bind(&BTA_GATTS_AddIncludeService, service_handle, included_handle));
-}
-
-static bt_status_t btif_gatts_add_characteristic(int server_if,
-                                                 int service_handle,
-                                                 bt_uuid_t *uuid,
-                                                 int properties,
-                                                 int permissions) {
-  CHECK_BTGATT_INIT();
-  tBT_UUID *bt_uuid = new tBT_UUID;
-  btif_to_bta_uuid(bt_uuid, uuid);
-
-  return do_in_jni_thread(Bind(&BTA_GATTS_AddCharacteristic, service_handle,
-                               base::Owned(bt_uuid), permissions, properties));
-}
-
-static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle,
-                                             bt_uuid_t *uuid, int permissions) {
-  CHECK_BTGATT_INIT();
-  tBT_UUID *bt_uuid = new tBT_UUID;
-  btif_to_bta_uuid(bt_uuid, uuid);
-
-  return do_in_jni_thread(Bind(&BTA_GATTS_AddCharDescriptor, service_handle,
-                               permissions, base::Owned(bt_uuid)));
-}
-
-static bt_status_t btif_gatts_start_service(int server_if, int service_handle,
-                                            int transport) {
-  CHECK_BTGATT_INIT();
-  return do_in_jni_thread(
-      Bind(&BTA_GATTS_StartService, service_handle, transport));
+  return do_in_jni_thread(Bind(&add_service_impl, server_if, std::move(service)));
 }
 
 static bt_status_t btif_gatts_stop_service(int server_if, int service_handle)
@@ -510,10 +443,6 @@
     btif_gatts_open,
     btif_gatts_close,
     btif_gatts_add_service,
-    btif_gatts_add_included_service,
-    btif_gatts_add_characteristic,
-    btif_gatts_add_descriptor,
-    btif_gatts_start_service,
     btif_gatts_stop_service,
     btif_gatts_delete_service,
     btif_gatts_send_indication,
diff --git a/service/Android.mk b/service/Android.mk
index 6ac02a6..84ae3f8 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -42,7 +42,6 @@
 	common/bluetooth/adapter_state.cc \
 	common/bluetooth/advertise_data.cc \
 	common/bluetooth/advertise_settings.cc \
-	common/bluetooth/gatt_identifier.cc \
 	common/bluetooth/descriptor.cc \
 	common/bluetooth/characteristic.cc \
 	common/bluetooth/scan_filter.cc \
@@ -64,7 +63,6 @@
 	common/android/bluetooth/IBluetoothLowEnergyCallback.aidl \
 	common/android/bluetooth/advertise_data.cc \
 	common/android/bluetooth/advertise_settings.cc \
-	common/android/bluetooth/gatt_identifier.cc \
 	common/android/bluetooth/bluetooth_gatt_characteristic.cc \
 	common/android/bluetooth/bluetooth_gatt_descriptor.cc \
 	common/android/bluetooth/bluetooth_gatt_included_service.cc \
@@ -84,7 +82,6 @@
 	gatt_client.cc \
 	gatt_server.cc \
 	gatt_server_old.cc \
-	hal/gatt_helpers.cc \
 	hal/bluetooth_gatt_interface.cc \
 	hal/bluetooth_interface.cc \
 	ipc/ipc_handler.cc \
@@ -122,7 +119,6 @@
 	test/advertise_data_unittest.cc \
 	test/fake_hal_util.cc \
 	test/gatt_client_unittest.cc \
-	test/gatt_identifier_unittest.cc \
 	test/gatt_server_unittest.cc \
 	test/low_energy_client_unittest.cc \
 	test/settings_unittest.cc \
diff --git a/service/BUILD.gn b/service/BUILD.gn
index f82246b..c61372a 100644
--- a/service/BUILD.gn
+++ b/service/BUILD.gn
@@ -30,7 +30,6 @@
     "common/bluetooth/scan_filter.cc",
     "common/bluetooth/scan_result.cc",
     "common/bluetooth/scan_settings.cc",
-    "common/bluetooth/gatt_identifier.cc",
     "common/bluetooth/advertise_settings.cc",
     "common/bluetooth/util/atomic_string.cc",
     "common/bluetooth/util/address_helper.cc",
@@ -38,7 +37,6 @@
     "hal/bluetooth_gatt_interface.cc",
     "hal/fake_bluetooth_gatt_interface.cc",
     "hal/fake_bluetooth_interface.cc",
-    "hal/gatt_helpers.cc",
     "ipc/ipc_handler.cc",
     "ipc/linux_ipc_host.cc",
     "ipc/ipc_manager.cc",
diff --git a/service/common/android/bluetooth/GattIdentifier.aidl b/service/common/android/bluetooth/GattIdentifier.aidl
deleted file mode 100644
index e61ca77..0000000
--- a/service/common/android/bluetooth/GattIdentifier.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-parcelable GattIdentifier cpp_header "android/bluetooth/gatt_identifier.h";
diff --git a/service/common/android/bluetooth/IBluetoothGattServer.aidl b/service/common/android/bluetooth/IBluetoothGattServer.aidl
index 1f11486..634ea3d 100644
--- a/service/common/android/bluetooth/IBluetoothGattServer.aidl
+++ b/service/common/android/bluetooth/IBluetoothGattServer.aidl
@@ -16,9 +16,8 @@
 
 package android.bluetooth;
 
+import android.bluetooth.BluetoothGattService;
 import android.bluetooth.IBluetoothGattServerCallback;
-
-import android.bluetooth.GattIdentifier;
 import android.bluetooth.UUID;
 
 interface IBluetoothGattServer {
@@ -27,17 +26,7 @@
   void UnregisterServer(int server_id);
   void UnregisterAll();
 
-  boolean BeginServiceDeclaration(
-      int server_id, boolean is_primary, in UUID uuid,
-      out GattIdentifier id);
-  boolean AddCharacteristic(
-      int server_id, in UUID uuid,
-      int properties, int permissions,
-      out GattIdentifier id);
-  boolean AddDescriptor(
-      int server_id, in UUID uuid, int permissions,
-      out GattIdentifier id);
-  boolean EndServiceDeclaration(int server_id);
+  boolean AddService(int server_id, in BluetoothGattService service);
 
   boolean SendResponse(
       int server_id,
@@ -49,7 +38,7 @@
   boolean SendNotification(
       int server_id,
       String device_address,
-      in GattIdentifier characteristic_id,
+      int handle,
       boolean confirm,
       in byte[] value);
 }
\ No newline at end of file
diff --git a/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl b/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl
index 49ba789..167c81f 100644
--- a/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothGattServerCallback.aidl
@@ -16,28 +16,26 @@
 
 package android.bluetooth;
 
-import android.bluetooth.GattIdentifier;
+import android.bluetooth.BluetoothGattService;
 
 oneway interface IBluetoothGattServerCallback {
   void OnServerRegistered(int status, int server_id);
 
-  void OnServiceAdded(int status, in GattIdentifier service_id);
+  void OnServiceAdded(int status, in BluetoothGattService service);
 
   void OnCharacteristicReadRequest(String device_address,
-    int request_id, int offset, boolean is_long,
-    in GattIdentifier characteristic_id);
+    int request_id, int offset, boolean is_long, int handle);
 
   void OnDescriptorReadRequest(String device_address,
-    int request_id, int offset, boolean is_long,
-    in GattIdentifier descriptor_id);
+    int request_id, int offset, boolean is_long, int handle);
 
   void OnCharacteristicWriteRequest(String device_address,
     int request_id, int offset, boolean is_prepare_write, boolean need_response,
-    in byte[] value, in GattIdentifier characteristic_id);
+    in byte[] value, int handle);
 
   void OnDescriptorWriteRequest(String device_address,
     int request_id, int offset, boolean is_prepare_write, boolean need_response,
-    in byte[] value, in GattIdentifier descriptor_id);
+    in byte[] value, int handle);
 
   void OnExecuteWriteRequest(String device_address,
     int request_id, boolean is_execute);
diff --git a/service/common/android/bluetooth/gatt_identifier.cc b/service/common/android/bluetooth/gatt_identifier.cc
deleted file mode 100644
index fa61db9..0000000
--- a/service/common/android/bluetooth/gatt_identifier.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-//  Copyright (C) 2015 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#include "service/common/android/bluetooth/gatt_identifier.h"
-#include "service/common/android/bluetooth/uuid.h"
-
-#include <utils/String16.h>
-#include <utils/String8.h>
-
-using android::OK;
-using android::String8;
-using android::String16;
-
-namespace android {
-namespace bluetooth {
-
-status_t GattIdentifier::writeToParcel(Parcel* parcel) const {
-  status_t status =
-      parcel->writeString16(String16(String8(device_address_.c_str())));
-  if (status != OK) return status;
-
-  status = parcel->writeBool(is_primary_);
-  if (status != OK) return status;
-
-  parcel->writeParcelable((UUID)service_uuid_);
-  parcel->writeParcelable((UUID)char_uuid_);
-  parcel->writeParcelable((UUID)desc_uuid_);
-
-  status = parcel->writeInt32(service_instance_id_);
-  if (status != OK) return status;
-
-  status = parcel->writeInt32(char_instance_id_);
-  if (status != OK) return status;
-
-  status = parcel->writeInt32(desc_instance_id_);
-  return status;
-}
-
-status_t GattIdentifier::readFromParcel(const Parcel* parcel) {
-  String16 addr;
-  status_t status = parcel->readString16(&addr);
-  if (status != OK) return status;
-
-  device_address_ = std::string(String8(addr).string());
-
-  status = parcel->readBool(&is_primary_);
-  if (status != OK) return status;
-
-  UUID uuid;
-  status = parcel->readParcelable(&uuid);
-  if (status != OK) return status;
-  service_uuid_ = uuid;
-
-  status = parcel->readParcelable(&uuid);
-  if (status != OK) return status;
-  char_uuid_ = uuid;
-
-  status = parcel->readParcelable(&uuid);
-  if (status != OK) return status;
-  desc_uuid_ = uuid;
-
-  status = parcel->readInt32(&service_instance_id_);
-  if (status != OK) return status;
-
-  status = parcel->readInt32(&char_instance_id_);
-  if (status != OK) return status;
-
-  status = parcel->readInt32(&desc_instance_id_);
-  return status;
-}
-
-}  // namespace bluetooth
-}  // namespace android
diff --git a/service/common/android/bluetooth/gatt_identifier.h b/service/common/android/bluetooth/gatt_identifier.h
deleted file mode 100644
index d6de5f4..0000000
--- a/service/common/android/bluetooth/gatt_identifier.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-//  Copyright (C) 2016 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#pragma once
-
-#include "bluetooth/gatt_identifier.h"
-
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-
-using android::Parcel;
-using android::Parcelable;
-using android::status_t;
-
-namespace android {
-namespace bluetooth {
-
-class GattIdentifier : public Parcelable, public ::bluetooth::GattIdentifier {
- public:
-  GattIdentifier() = default;
-  // NOLINT, implicit converter
-  GattIdentifier(const ::bluetooth::GattIdentifier& gatt_identifier)  // NOLINT
-      : ::bluetooth::GattIdentifier(gatt_identifier){};
-  ~GattIdentifier() = default;
-
-  // Write |this| parcelable to the given |parcel|.  Keep in mind that
-  // implementations of writeToParcel must be manually kept in sync
-  // with readFromParcel and the Java equivalent versions of these methods.
-  //
-  // Returns android::OK on success and an appropriate error otherwise.
-  status_t writeToParcel(Parcel* parcel) const override;
-
-  // Read data from the given |parcel| into |this|.  After readFromParcel
-  // completes, |this| should have equivalent state to the object that
-  // wrote itself to the parcel.
-  //
-  // Returns android::OK on success and an appropriate error otherwise.
-  status_t readFromParcel(const Parcel* parcel) override;
-};
-}  // namespace bluetooth
-}  // namespace android
diff --git a/service/common/bluetooth/gatt_identifier.cc b/service/common/bluetooth/gatt_identifier.cc
deleted file mode 100644
index 312a6c4..0000000
--- a/service/common/bluetooth/gatt_identifier.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-//
-//  Copyright (C) 2015 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#include "service/common/bluetooth/gatt_identifier.h"
-
-#include "service/common/bluetooth/util/address_helper.h"
-
-namespace bluetooth {
-
-namespace {
-
-const int kInvalidInstanceId = -1;
-
-}  // namespace
-
-// static
-std::unique_ptr<GattIdentifier> GattIdentifier::CreateServiceId(
-    const std::string& device_address,
-    int id, const UUID& uuid,
-    bool is_primary) {
-  if (id < 0 ||
-      (!device_address.empty() && !util::IsAddressValid(device_address)))
-    return nullptr;
-
-  std::unique_ptr<GattIdentifier> gatt_id(new GattIdentifier());
-
-  gatt_id->device_address_ = device_address;
-  gatt_id->service_uuid_ = uuid;
-  gatt_id->service_instance_id_ = id;
-  gatt_id->is_primary_ = is_primary;
-
-  return gatt_id;
-}
-
-// static
-std::unique_ptr<GattIdentifier> GattIdentifier::CreateCharacteristicId(
-    int id, const UUID& uuid,
-    const GattIdentifier& service_id) {
-  if (!service_id.IsService())
-    return nullptr;
-
-  std::unique_ptr<GattIdentifier> gatt_id(new GattIdentifier(service_id));
-
-  gatt_id->char_uuid_ = uuid;
-  gatt_id->char_instance_id_ = id;
-
-  return gatt_id;
-}
-
-// static
-std::unique_ptr<GattIdentifier> GattIdentifier::CreateDescriptorId(
-    int id, const UUID& uuid,
-    const GattIdentifier& char_id) {
-  if (!char_id.IsCharacteristic())
-    return nullptr;
-
-  std::unique_ptr<GattIdentifier> gatt_id(new GattIdentifier(char_id));
-
-  gatt_id->desc_uuid_ = uuid;
-  gatt_id->desc_instance_id_ = id;
-
-  return gatt_id;
-}
-
-// Copy constructor and assignment operator.
-GattIdentifier::GattIdentifier()
-  : is_primary_(false),
-    service_instance_id_(kInvalidInstanceId),
-    char_instance_id_(kInvalidInstanceId),
-    desc_instance_id_(kInvalidInstanceId) {
-}
-
-GattIdentifier::GattIdentifier(const GattIdentifier& other) {
-  device_address_ = other.device_address_;
-  is_primary_ = other.is_primary_;
-  service_uuid_ = other.service_uuid_;
-  char_uuid_ = other.char_uuid_;
-  desc_uuid_ = other.desc_uuid_;
-  service_instance_id_ = other.service_instance_id_;
-  service_instance_id_ = other.service_instance_id_;
-  char_instance_id_ = other.char_instance_id_;
-  desc_instance_id_ = other.desc_instance_id_;
-}
-
-GattIdentifier::GattIdentifier(
-    const std::string& device_address,
-    bool is_primary,
-    const UUID& service_uuid,
-    const UUID& characteristic_uuid,
-    const UUID& descriptor_uuid,
-    int service_instance_id,
-    int characteristic_instance_id,
-    int descriptor_instance_id)
-    : device_address_(device_address),
-      is_primary_(is_primary),
-      service_uuid_(service_uuid),
-      char_uuid_(characteristic_uuid),
-      desc_uuid_(descriptor_uuid),
-      service_instance_id_(service_instance_id),
-      char_instance_id_(characteristic_instance_id),
-      desc_instance_id_(descriptor_instance_id) {
-}
-
-GattIdentifier& GattIdentifier::operator=(const GattIdentifier& other) {
-  if (*this == other)
-    return *this;
-
-  device_address_ = other.device_address_;
-  is_primary_ = other.is_primary_;
-  service_uuid_ = other.service_uuid_;
-  char_uuid_ = other.char_uuid_;
-  desc_uuid_ = other.desc_uuid_;
-  service_instance_id_ = other.service_instance_id_;
-  char_instance_id_ = other.char_instance_id_;
-  desc_instance_id_ = other.desc_instance_id_;
-
-  return *this;
-}
-
-bool GattIdentifier::Equals(const GattIdentifier& other) const {
-  return (device_address_ == other.device_address_ &&
-      is_primary_ == other.is_primary_ &&
-      service_uuid_ == other.service_uuid_ &&
-      char_uuid_ == other.char_uuid_ &&
-      desc_uuid_ == other.desc_uuid_ &&
-      service_instance_id_ == other.service_instance_id_ &&
-      char_instance_id_ == other.char_instance_id_ &&
-      desc_instance_id_ == other.desc_instance_id_);
-}
-
-bool GattIdentifier::operator==(const GattIdentifier& rhs) const {
-  return Equals(rhs);
-}
-
-bool GattIdentifier::operator!=(const GattIdentifier& rhs) const {
-  return !Equals(rhs);
-}
-
-bool GattIdentifier::IsService() const {
-  return (service_instance_id_ != kInvalidInstanceId &&
-          char_instance_id_ == kInvalidInstanceId &&
-          desc_instance_id_ == kInvalidInstanceId);
-}
-
-bool GattIdentifier::IsCharacteristic() const {
-  return (service_instance_id_ != kInvalidInstanceId &&
-          char_instance_id_ != kInvalidInstanceId &&
-          desc_instance_id_ == kInvalidInstanceId);
-}
-
-bool GattIdentifier::IsDescriptor() const {
-  return (service_instance_id_ != kInvalidInstanceId &&
-          char_instance_id_ != kInvalidInstanceId &&
-          desc_instance_id_ != kInvalidInstanceId);
-}
-
-std::unique_ptr<GattIdentifier> GattIdentifier::GetOwningServiceId() const {
-  if (IsService())
-    return nullptr;
-
-  return CreateServiceId(
-      device_address_, service_instance_id_, service_uuid_, is_primary_);
-}
-
-std::unique_ptr<GattIdentifier>
-GattIdentifier::GetOwningCharacteristicId() const {
-  if (!IsDescriptor())
-    return nullptr;
-
-  std::unique_ptr<GattIdentifier> service_id = GetOwningServiceId();
-
-  return CreateCharacteristicId(char_instance_id_, char_uuid_, *service_id);
-}
-
-}  // namespace bluetooth
diff --git a/service/common/bluetooth/gatt_identifier.h b/service/common/bluetooth/gatt_identifier.h
deleted file mode 100644
index 685455c..0000000
--- a/service/common/bluetooth/gatt_identifier.h
+++ /dev/null
@@ -1,144 +0,0 @@
-//
-//  Copyright (C) 2015 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#pragma once
-
-#include <memory>
-#include <string>
-
-#include <bluetooth/uuid.h>
-
-namespace bluetooth {
-
-// Used to uniquely identify a GATT object/attribute
-// (service/characteristic/descriptor/include entry) after it has been
-// registered with the stack. Each registered object will be assigned a GATT
-// identifier that the callers may use in future callbacks.
-//
-// For local services, the uniqueness of each identifier is guaranteed only
-// within the registered GATT server that they exist in.
-class GattIdentifier {
- public:
-  // Static initialization methods. These return NULL if invalid parameters are
-  // given.
-  static std::unique_ptr<GattIdentifier> CreateServiceId(
-      const std::string& device_address,
-      int id,
-      const UUID& uuid,
-      bool is_primary);
-  static std::unique_ptr<GattIdentifier> CreateCharacteristicId(
-      int id, const UUID& uuid,
-      const GattIdentifier& service_id);
-  static std::unique_ptr<GattIdentifier> CreateDescriptorId(
-      int id, const UUID& uuid,
-      const GattIdentifier& characteristic_id);
-
-  // Constructors and assignment operator.
-  GattIdentifier();
-  GattIdentifier(
-      const std::string& device_address,
-      bool is_primary,
-      const UUID& service_uuid,
-      const UUID& characteristic_uuid,
-      const UUID& descriptor_uuid,
-      int service_instance_id,
-      int characteristic_instance_id,
-      int descriptor_instance_id);
-  ~GattIdentifier() = default;
-  GattIdentifier(const GattIdentifier& other);
-  GattIdentifier& operator=(const GattIdentifier& other);
-
-
-  // Comparison function and operator.
-  bool Equals(const GattIdentifier& other) const;
-  bool operator==(const GattIdentifier& rhs) const;
-  bool operator!=(const GattIdentifier& rhs) const;
-
-  // Functions to verify the type of attribute represented by this identifier.
-  bool IsService() const;
-  bool IsCharacteristic() const;
-  bool IsDescriptor() const;
-
-  // For characteristics and descriptors, this returns the identifier of the
-  // owning service. For services, this returns NULL.
-  std::unique_ptr<GattIdentifier> GetOwningServiceId() const;
-
-  // For descriptors, this returns the identifier of the owning characteristic.
-  // For services and characteristics, this returns NULL.
-  std::unique_ptr<GattIdentifier> GetOwningCharacteristicId() const;
-
-  // Getters for internal fields.
-  const std::string& device_address() const { return device_address_; }
-  bool is_primary() const { return is_primary_; }
-  const UUID& service_uuid() const { return service_uuid_; }
-  const UUID& characteristic_uuid() const { return char_uuid_; }
-  const UUID& descriptor_uuid() const { return desc_uuid_; }
-  int service_instance_id() const { return service_instance_id_; }
-  int characteristic_instance_id() const { return char_instance_id_; }
-  int descriptor_instance_id() const { return desc_instance_id_; }
-
- protected:
-  friend struct std::hash<bluetooth::GattIdentifier>;
-
-  // NOTE: Don't forget to update the std::hash specialization below if you
-  // update any of the instance variables in this class.
-
-  // The BD_ADDR of the device associated with the attribute.
-  std::string device_address_;
-
-  // An instance ID value of -1 means that it is unitialized. For example, a
-  // service ID would have -1 for characteristic and descriptor instance IDs.
-  bool is_primary_;
-  UUID service_uuid_;
-  UUID char_uuid_;
-  UUID desc_uuid_;
-  int service_instance_id_;
-  int char_instance_id_;
-  int desc_instance_id_;
-};
-
-}  // namespace bluetooth
-
-// Custom std::hash specialization so that bluetooth::GattIdentifier can be used
-// as a key in std::unordered_map.
-namespace std {
-
-template<>
-struct hash<bluetooth::GattIdentifier> {
-  std::size_t operator()(const bluetooth::GattIdentifier& key) const {
-    std::size_t seed = 0;
-
-    hash_combine(seed, key.device_address_);
-    hash_combine(seed, key.is_primary_);
-    hash_combine(seed, key.service_uuid_);
-    hash_combine(seed, key.char_uuid_);
-    hash_combine(seed, key.desc_uuid_);
-    hash_combine(seed, key.service_instance_id_);
-    hash_combine(seed, key.char_instance_id_);
-    hash_combine(seed, key.desc_instance_id_);
-
-    return seed;
-  }
-
- private:
-  template<typename T>
-  inline void hash_combine(std::size_t& seed, const T& v) const {
-    std::hash<T> hasher;
-    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-  }
-};
-
-}  // namespace std
diff --git a/service/doc/IBluetoothGattServer.txt b/service/doc/IBluetoothGattServer.txt
index 8ead69b..0efecab 100644
--- a/service/doc/IBluetoothGattServer.txt
+++ b/service/doc/IBluetoothGattServer.txt
@@ -39,51 +39,12 @@
   void unregisterAll();
 
   /**
-   * Begins a new GATT service declaration. This will execute synchronously and
-   * create a new service range. This can be followed by calls to populate the
-   * service range with attributes. The started service won't be published and
-   * made discoverable to remote devices until a successful call to
-   * endServiceDeclaration.
-   *
-   * The created service will be assigned a unique identifier that can be used
-   * by the caller to distinguish between different services. This will be
-   * returned in |out_id| in case of success. Returns false in case of failure,
-   * e.g. a service declaration is already in progress.
-   */
-  boolean beginServiceDeclaration(in int server_if, in boolean is_primary,
-                                  in ParcelUuid uuid,
-                                  out GattIdentifier out_id);
-
-  /**
-   * Adds a characteristic entry to a previously started service declaration.
-   * Returns false in case of failure, e.g. if no service declaration was
-   * started. Returns the uniquely assigned characteristic identifier in
-   * |out_id| in the case of success.
-   */
-  boolean addCharacteristic(in int server_if, in ParcelUuid uuid,
-                            in int properties, in int permissions,
-                            out GattIdentifier out_id);
-
-  /**
-   * Adds a characteristic descriptor entry to a previously started service
-   * declaration. Returns false in case of failure, e.g. if no service
-   * declaration was started or if the declaration does not contain a
-   * characteristic that can own this descriptor. Returns the uniquely assigned
-   * descriptor identifier in |out_id| in the case of success.
-   */
-  boolean addDescriptor(in int server_if, in ParcelUuid uuid,
-                        in int permissions,
-                        out GattIdentifier out_id);
-
-  /**
-   * Ends a previously started service declaration and asynchronously publishes
-   * the service in the underlying attribute database. Returns false in case of
-   * an asynchronous failure, e.g. if no service declaration was started or
-   * there is a pending call to endServiceDeclaration. Otherwise returns true
-   * and reports the result of the operation asynchronously in
+   * Adds new GATT service. This will execute synchronously, and result in
    * IBluetoothGattServerCallback.onServiceAdded.
+   *
+   * Returns true on success, false otherwise.
    */
-  boolean endServiceDeclaration(in int server_if);
+  boolean AddService(int server_id, in BluetoothGattService service);
 
   /**
    * Sends a response to a currently pending read or write request. The request
@@ -101,7 +62,7 @@
 
   /**
    * Sends a handle-value notification or indication to the device with the
-   * given address for the characteristic with the given identifier. |confirm|
+   * given address for the characteristic with the given handle. |confirm|
    * should be set to true, if a handle-value indication should be sent, which
    * will remain pending until the remote device sends a handle-value
    * confirmation. Returns false if a call to this method is pending. Otherwise
@@ -109,6 +70,6 @@
    * IBluetoothGattServerCallback.onNotificationSent.
    */
   boolean sendNotification(in int server_if, in String device_address,
-                           in GattIdentifier characteristic_id,
+                           in int handle,
                            in boolean confirm, in byte[] value);
 }
diff --git a/service/doc/IBluetoothGattServerCallback.txt b/service/doc/IBluetoothGattServerCallback.txt
index fd4b86a..3744ff1 100644
--- a/service/doc/IBluetoothGattServerCallback.txt
+++ b/service/doc/IBluetoothGattServerCallback.txt
@@ -29,17 +29,17 @@
   void onServerRegistered(in int status, in int server_if);
 
   /**
-   * Called to report the result of a call to
-   * IBluetoothGattServer.endServiceDeclaration. A |status| of 0 denotes
-   * success, which means that the GATT service has been published and is
-   * discoverable. |service_id| belongs to the service that was registered.
+   * Called to report the result of a call to IBluetoothGattServer.AddService.
+   * A |status| of 0 denotes success, which means that the GATT service has
+   * been published and is discoverable. In this case handles of added service,
+   * it's characteristics and descriptors are filled.
    */
-  void onServiceAdded(in int status, in GattIdentifier service_id);
+  void onServiceAdded(in int status, in BluetoothGattServer service_id);
 
   /**
    * Called when there is an incoming read request from the remote device with
-   * address |device_address| for the characteristic with identifier
-   * |characteristic_id|. |offset| is the index of the characteristic value that
+   * address |device_address| for the characteristic with handle |handle|.
+   * |offset| is the index of the characteristic value that
    * the remote device wants to read from. If |is_long| is true, then this
    * request is part of a Long Read procedure. An implementation should handle
    * this request by calling IBluetoothGattServer.sendResponse with the given
@@ -52,12 +52,12 @@
    */
   void onCharacteristicReadRequest(in String device_address, in int request_id,
                                    in int offset, in boolean is_long,
-                                   in GattIdentifier characteristic_id);
+                                   in int handle);
 
   /**
    * Called when there is an incoming read request from the remote device with
-   * address |device_address| for the descriptor with identifier
-   * |descriptor_id|. |offset| is the index of the descriptor value that
+   * address |device_address| for the descriptor with handle |handle|.
+   * |offset| is the index of the descriptor value that
    * the remote device wants to read from. If |is_long| is true, then this
    * request is part of a Long Read procedure. An implementation should handle
    * this request by calling IBluetoothGattServer.sendResponse with the given
@@ -70,12 +70,12 @@
    */
   void onDescriptorReadRequest(in String device_address, in int request_id,
                                in int offset, in boolean is_long,
-                               in GattIdentifier descriptor_id);
+                               in int handle);
 
   /**
    * Called when there is an incoming write request from the remote device with
-   * address |device_address| for the characteristic with identifier
-   * |characteristic_id| with the value |value|. An implementation should handle
+   * address |device_address| for the characteristic with handle |handle|
+   * with the value |value|. An implementation should handle
    * this request by calling IBluetoothGattServer.sendResponse with the given
    * |request_id|. |offset| is the index of the characteristic value that the
    * remote device wants to write to, so the value should be written starting at
@@ -90,12 +90,12 @@
   void onCharacteristicWriteRequest(in String device_address, in int request_id,
                                     in int offset, in boolean is_prepare_write,
                                     in boolean need_response, in byte[] value,
-                                    in GattIdentifier characteristic_id);
+                                    in int handle);
 
   /**
    * Called when there is an incoming write request from the remote device with
-   * address |device_address| for the descriptor with identifier
-   * |descriptor_id| with the value |value|. An implementation should handle
+   * address |device_address| for the descriptor with handle |handle|
+   * with the value |value|. An implementation should handle
    * this request by calling IBluetoothGattServer.sendResponse with the given
    * |request_id|. |offset| is the index of the descriptor value that the
    * remote device wants to write to, so the value should be written starting at
@@ -110,7 +110,7 @@
   void onDescriptorWriteRequest(in String device_address, in int request_id,
                                 in int offset, in boolean is_prepare_write,
                                 in boolean need_response, in byte[] value,
-                                in GattIdentifier descriptor_id);
+                                in int handle);
 
   /**
    * Called when there is an incoming execute-write request to commit or abort
diff --git a/service/example/heart_rate/heart_rate_server.cc b/service/example/heart_rate/heart_rate_server.cc
index 3bfd409..b05b219 100644
--- a/service/example/heart_rate/heart_rate_server.cc
+++ b/service/example/heart_rate/heart_rate_server.cc
@@ -32,6 +32,7 @@
 using android::String16;
 
 using android::bluetooth::IBluetoothLowEnergy;
+using android::bluetooth::BluetoothGattService;
 
 namespace heart_rate {
 
@@ -181,7 +182,7 @@
 
     bool status;
     gatt_->SendNotification(server_if_, String16(String8(iter.first.c_str())),
-                            hr_measurement_id_, false, value, &status);
+                            hr_measurement_handle_, false, value, &status);
     if (status) pending_notification_map_[iter.first] = true;
   }
 
@@ -243,87 +244,35 @@
   server_if_ = server_if;
 
   LOG(INFO) << "Heart Rate server registered - server_if: " << server_if_;
-  LOG(INFO) << "Populating attributes";
 
-  bool op_status;
-  // Start service declaration.
-  android::bluetooth::GattIdentifier gatt_id;
-  gatt_->BeginServiceDeclaration(server_if_, true, kHRServiceUUID, &gatt_id,
-                                 &op_status);
-  if (!op_status) {
-    LOG(ERROR) << "Failed to begin service declaration";
+  bluetooth::Service hrService(0, true, kHRServiceUUID, {
+    {0, kHRMeasurementUUID, bluetooth::kCharacteristicPropertyNotify, 0,
+      { {0, kCCCDescriptorUUID, (bluetooth::kAttributePermissionRead | bluetooth::kAttributePermissionWrite)}} },
+    {0, kBodySensorLocationUUID, bluetooth::kCharacteristicPropertyRead, bluetooth::kAttributePermissionRead, {}},
+    {0, kHRControlPointUUID, bluetooth::kCharacteristicPropertyWrite, bluetooth::kAttributePermissionWrite, {}}
+    }, {});
+
+  bool op_status = true;
+
+  Status stat = gatt_->AddService(server_if_, (BluetoothGattService)hrService, &op_status);
+  if (!stat.isOk()) {
+    LOG(ERROR) << "Failed to add service, status is: " /*<< stat*/;
     pending_run_cb_(false);
     return Status::ok();
   }
 
-  hr_service_id_ = gatt_id;
-
-  // Add Heart Rate Measurement characteristic.
-  gatt_->AddCharacteristic(server_if_, kHRMeasurementUUID,
-                           bluetooth::kCharacteristicPropertyNotify, 0,
-                           &gatt_id, &op_status);
   if (!op_status) {
-    LOG(ERROR) << "Failed to add heart rate measurement characteristic";
+    LOG(ERROR) << "Failed to add service";
     pending_run_cb_(false);
     return Status::ok();
   }
 
-  hr_measurement_id_ = gatt_id;
-
-  // Add Client Characteristic Configuration descriptor for the Heart Rate
-  // Measurement characteristic.
-  gatt_->AddDescriptor(server_if_, kCCCDescriptorUUID,
-                       bluetooth::kAttributePermissionRead |
-                           bluetooth::kAttributePermissionWrite,
-                       &gatt_id, &op_status);
-  if (!op_status) {
-    LOG(ERROR) << "Failed to add CCC descriptor";
-    pending_run_cb_(false);
-    return Status::ok();
-  }
-
-  hr_measurement_cccd_id_ = gatt_id;
-
-  // Add Body Sensor Location characteristic.
-  gatt_->AddCharacteristic(server_if_, kBodySensorLocationUUID,
-                           bluetooth::kCharacteristicPropertyRead,
-                           bluetooth::kAttributePermissionRead, &gatt_id,
-                           &op_status);
-  if (!op_status) {
-    LOG(ERROR) << "Failed to add body sensor location characteristic";
-    pending_run_cb_(false);
-    return Status::ok();
-  }
-
-  body_sensor_loc_id_ = gatt_id;
-
-  // Add Heart Rate Control Point characteristic.
-  gatt_->AddCharacteristic(
-      server_if_, kHRControlPointUUID, bluetooth::kCharacteristicPropertyWrite,
-      bluetooth::kAttributePermissionWrite, &gatt_id, &op_status);
-  if (!op_status) {
-    LOG(ERROR) << "Failed to add heart rate control point characteristic";
-    pending_run_cb_(false);
-    return Status::ok();
-  }
-
-  hr_control_point_id_ = gatt_id;
-
-  // End service declaration. We will be notified whether or not this succeeded
-  // via the OnServiceAdded callback.
-  gatt_->EndServiceDeclaration(server_if_, &op_status);
-  if (!op_status) {
-    LOG(ERROR) << "Failed to end service declaration";
-    pending_run_cb_(false);
-    return Status::ok();
-  }
-
-  LOG(INFO) << "Initiated EndServiceDeclaration request";
+  LOG(INFO) << "Initiated AddService request";
   return Status::ok();
 }
 
 Status HeartRateServer::OnServiceAdded(
-    int status, const android::bluetooth::GattIdentifier& service_id) {
+    int status, const android::bluetooth::BluetoothGattService& service) {
   std::lock_guard<std::mutex> lock(mutex_);
 
   if (status != bluetooth::BLE_STATUS_SUCCESS) {
@@ -332,14 +281,12 @@
     return Status::ok();
   }
 
-  if (service_id != hr_service_id_) {
-    LOG(ERROR) << "Received callback for the wrong service ID";
-    pending_run_cb_(false);
-    return Status::ok();
-  }
-
-  // EndServiceDeclaration succeeded! Our Heart Rate service is now discoverable
-  // over GATT connections.
+  hr_service_handle_ = service.handle();
+  hr_measurement_handle_ = service.characteristics()[0].handle();
+  hr_measurement_cccd_handle_ =
+      service.characteristics()[0].descriptors()[0].handle();
+  body_sensor_loc_handle_ = service.characteristics()[1].handle();
+  hr_control_point_handle_ = service.characteristics()[2].handle();
 
   LOG(INFO) << "Heart Rate service added";
   pending_run_cb_(true);
@@ -356,13 +303,13 @@
 
 Status HeartRateServer::OnCharacteristicReadRequest(
     const String16& device_address, int request_id, int offset,
-    bool /* is_long */,
-    const android::bluetooth::GattIdentifier& characteristic_id) {
+    bool /* is_long */, int handle) {
+
   std::lock_guard<std::mutex> lock(mutex_);
 
   // This is where we handle an incoming characteristic read. Only the body
   // sensor location characteristic is readable.
-  CHECK(characteristic_id == body_sensor_loc_id_);
+  CHECK(handle == body_sensor_loc_handle_);
 
   std::vector<uint8_t> value;
   bluetooth::GATTError error = bluetooth::GATT_ERROR_NONE;
@@ -379,13 +326,12 @@
 
 Status HeartRateServer::OnDescriptorReadRequest(
     const String16& device_address, int request_id, int offset,
-    bool /* is_long */,
-    const android::bluetooth::GattIdentifier& descriptor_id) {
+    bool /* is_long */, int handle) {
   std::lock_guard<std::mutex> lock(mutex_);
 
   // This is where we handle an incoming characteristic descriptor read. There
   // is only one descriptor.
-  if (descriptor_id != hr_measurement_cccd_id_) {
+  if (handle != hr_measurement_cccd_handle_) {
     std::vector<uint8_t> value;
     bool status;
     gatt_->SendResponse(server_if_, device_address, request_id,
@@ -414,8 +360,7 @@
 Status HeartRateServer::OnCharacteristicWriteRequest(
     const String16& device_address, int request_id, int offset,
     bool is_prepare_write, bool need_response,
-    const std::vector<uint8_t>& value,
-    const android::bluetooth::GattIdentifier& characteristic_id) {
+    const std::vector<uint8_t>& value, int handle) {
   std::lock_guard<std::mutex> lock(mutex_);
 
   std::vector<uint8_t> dummy;
@@ -432,7 +377,7 @@
   }
 
   // Heart Rate Control point is the only writable characteristic.
-  CHECK(characteristic_id == hr_control_point_id_);
+  CHECK(handle == hr_control_point_handle_);
 
   // Writes to the Heart Rate Control Point characteristic must contain a single
   // byte with the value 0x01.
@@ -458,8 +403,7 @@
 Status HeartRateServer::OnDescriptorWriteRequest(
     const String16& device_address, int request_id, int offset,
     bool is_prepare_write, bool need_response,
-    const std::vector<uint8_t>& value,
-    const android::bluetooth::GattIdentifier& descriptor_id) {
+    const std::vector<uint8_t>& value, int handle) {
   std::lock_guard<std::mutex> lock(mutex_);
 
   std::vector<uint8_t> dummy;
@@ -476,7 +420,7 @@
   }
 
   // CCC is the only descriptor we have.
-  CHECK(descriptor_id == hr_measurement_cccd_id_);
+  CHECK(handle == hr_measurement_cccd_handle_);
 
   // CCC must contain 2 bytes for a 16-bit value in little-endian. The only
   // allowed values here are 0x0000 and 0x0001.
diff --git a/service/example/heart_rate/heart_rate_server.h b/service/example/heart_rate/heart_rate_server.h
index d8d9f9c..b247653 100644
--- a/service/example/heart_rate/heart_rate_server.h
+++ b/service/example/heart_rate/heart_rate_server.h
@@ -25,7 +25,6 @@
 
 #include <android/bluetooth/BnBluetoothGattServerCallback.h>
 #include <android/bluetooth/IBluetooth.h>
-#include <bluetooth/gatt_identifier.h>
 
 using android::binder::Status;
 using android::String16;
@@ -57,23 +56,21 @@
   // ipc::binder::IBluetoothGattServerCallback override:
   Status OnServerRegistered(int status, int server_id) override;
   Status OnServiceAdded(
-      int status, const android::bluetooth::GattIdentifier& service_id) override;
+      int status, const android::bluetooth::BluetoothGattService& service) override;
   Status OnCharacteristicReadRequest(
       const String16& device_address, int request_id, int offset, bool is_long,
-      const android::bluetooth::GattIdentifier& characteristic_id) override;
+      int handle) override;
   Status OnDescriptorReadRequest(
       const String16& device_address, int request_id, int offset, bool is_long,
-      const android::bluetooth::GattIdentifier& descriptor_id) override;
+      int handle) override;
   Status OnCharacteristicWriteRequest(
       const String16& device_address, int request_id, int offset,
       bool is_prepare_write, bool need_response,
-      const std::vector<uint8_t>& value,
-      const android::bluetooth::GattIdentifier& characteristic_id) override;
+      const std::vector<uint8_t>& value, int handle) override;
   Status OnDescriptorWriteRequest(
       const String16& device_address, int request_id, int offset,
       bool is_prepare_write, bool need_response,
-      const std::vector<uint8_t>& value,
-      const android::bluetooth::GattIdentifier& descriptor_id) override;
+      const std::vector<uint8_t>& value, int handle) override;
   Status OnExecuteWriteRequest(const String16& device_address, int request_id,
                                bool is_execute) override;
   Status OnNotificationSent(const String16& device_address,
@@ -112,13 +109,13 @@
   // The Energy Expended value we use in our notifications.
   uint16_t energy_expended_;
 
-  // The unique IDs that refer to each of the Heart Rate Service GATT objects.
+  // Handles that refer to Heart Rate Service GATT objects.
   // These returned to us from the Bluetooth daemon as we populate the database.
-  bluetooth::GattIdentifier hr_service_id_;
-  bluetooth::GattIdentifier hr_measurement_id_;
-  bluetooth::GattIdentifier hr_measurement_cccd_id_;
-  bluetooth::GattIdentifier body_sensor_loc_id_;
-  bluetooth::GattIdentifier hr_control_point_id_;
+  uint16_t hr_service_handle_;
+  uint16_t hr_measurement_handle_;
+  uint16_t hr_measurement_cccd_handle_;
+  uint16_t body_sensor_loc_handle_;
+  uint16_t hr_control_point_handle_;
 
   // The daemon itself doesn't maintain a Client Characteristic Configuration
   // mapping, so we do it ourselves here.
diff --git a/service/gatt_server.cc b/service/gatt_server.cc
index b0441a6..9a76f66 100644
--- a/service/gatt_server.cc
+++ b/service/gatt_server.cc
@@ -17,7 +17,6 @@
 #include "service/gatt_server.h"
 
 #include "service/common/bluetooth/util/address_helper.h"
-#include "service/hal/gatt_helpers.h"
 #include "service/logging_helpers.h"
 
 using std::lock_guard;
@@ -73,97 +72,8 @@
   return server_id_;
 }
 
-std::unique_ptr<GattIdentifier> GattServer::BeginServiceDeclaration(
-    const UUID& uuid, bool is_primary) {
-  VLOG(1) << __func__ << " server_id: " << server_id_
-          << " - UUID: " << uuid.ToString()
-          << ", is_primary: " << is_primary;
-  lock_guard<mutex> lock(mutex_);
-
-  if (pending_decl_) {
-    LOG(ERROR) << "Already began service declaration";
-    return nullptr;
-  }
-
-  CHECK(!pending_id_);
-  CHECK(!pending_decl_);
-  CHECK(!pending_end_decl_cb_);
-
-  auto service_id = GetIdForService(uuid, is_primary);
-  CHECK(service_id);
-
-  // Pass 0 for permissions and properties as this is a service decl.
-  AttributeEntry entry(
-      *service_id, kCharacteristicPropertyNone, kAttributePermissionNone);
-
-  pending_decl_.reset(new ServiceDeclaration());
-  pending_decl_->num_handles++;  // 1 handle for the service decl. attribute
-  pending_decl_->service_id = *service_id;
-  pending_decl_->attributes.push_back(entry);
-
-  return service_id;
-}
-
-std::unique_ptr<GattIdentifier> GattServer::AddCharacteristic(
-      const UUID& uuid, int properties, int permissions) {
-  VLOG(1) << __func__ << " server_id: " << server_id_
-          << " - UUID: " << uuid.ToString()
-          << ", properties: " << properties
-          << ", permissions: " << permissions;
-  lock_guard<mutex> lock(mutex_);
-
-  if (!pending_decl_) {
-    LOG(ERROR) << "Service declaration not begun";
-    return nullptr;
-  }
-
-  if (pending_end_decl_cb_) {
-    LOG(ERROR) << "EndServiceDeclaration in progress, cannot modify service";
-    return nullptr;
-  }
-
-  auto char_id = GetIdForCharacteristic(uuid);
-  CHECK(char_id);
-  AttributeEntry entry(*char_id, properties, permissions);
-
-  // 2 handles for the characteristic declaration and the value attributes.
-  pending_decl_->num_handles += 2;
-  pending_decl_->attributes.push_back(entry);
-
-  return char_id;
-}
-
-std::unique_ptr<GattIdentifier> GattServer::AddDescriptor(
-    const UUID& uuid, int permissions) {
-  VLOG(1) << __func__ << " server_id: " << server_id_
-          << " - UUID: " << uuid.ToString()
-          << ", permissions: " << permissions;
-  lock_guard<mutex> lock(mutex_);
-
-  if (!pending_decl_) {
-    LOG(ERROR) << "Service declaration not begun";
-    return nullptr;
-  }
-
-  if (pending_end_decl_cb_) {
-    LOG(ERROR) << "EndServiceDeclaration in progress, cannot modify service";
-    return nullptr;
-  }
-
-  auto desc_id = GetIdForDescriptor(uuid);
-  if (!desc_id)
-    return nullptr;
-
-  AttributeEntry entry(*desc_id, kCharacteristicPropertyNone, permissions);
-
-  // 1 handle for the descriptor attribute.
-  pending_decl_->num_handles += 1;
-  pending_decl_->attributes.push_back(entry);
-
-  return desc_id;
-}
-
-bool GattServer::EndServiceDeclaration(const ResultCallback& callback) {
+bool GattServer::AddService(
+    const bluetooth::Service& service, const ResultCallback& callback) {
   VLOG(1) << __func__ << " server_id: " << server_id_;
   lock_guard<mutex> lock(mutex_);
 
@@ -172,129 +82,41 @@
     return false;
   }
 
-  if (!pending_decl_) {
-    LOG(ERROR) << "Service declaration not begun";
-    return false;
+  std::vector<btgatt_db_element_t> svc;
+
+  svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE : BTGATT_DB_SECONDARY_SERVICE),
+           .uuid = service.uuid().GetBlueDroid()});
+
+  for (const auto &  characteristic : service.characteristics()) {
+    svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
+             .uuid = characteristic.uuid().GetBlueDroid(),
+             .properties = characteristic.properties(),
+             .permissions = characteristic.permissions()
+           });
+    for (const auto &  descriptor : characteristic.descriptors())
+      svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
+               .uuid = descriptor.uuid().GetBlueDroid(),
+               .permissions = descriptor.permissions()
+             });
   }
 
-  if (pending_end_decl_cb_) {
-    LOG(ERROR) << "EndServiceDeclaration already in progress";
-    return false;
-  }
+  for (const auto &  incl_svc : service.included_services())
+    svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
+             .attribute_handle = incl_svc.handle() });
 
-  CHECK(!pending_id_);
-
-  // There has to be at least one entry here for the service declaration
-  // attribute.
-  CHECK(pending_decl_->num_handles > 0);
-  CHECK(!pending_decl_->attributes.empty());
-
-  std::unique_ptr<GattIdentifier> service_id = PopNextId();
-  CHECK(service_id->IsService());
-  CHECK(*service_id == pending_decl_->service_id);
-
-  btgatt_srvc_id_t hal_id;
-  hal::GetHALServiceId(*service_id, &hal_id);
+  pending_end_decl_cb_ = callback;
 
   bt_status_t status = hal::BluetoothGattInterface::Get()->
-      GetServerHALInterface()->add_service(
-          server_id_, &hal_id, pending_decl_->num_handles);
+      GetServerHALInterface()->add_service(server_id_, svc);
   if (status != BT_STATUS_SUCCESS) {
     LOG(ERROR) << "Failed to initiate call to populate GATT service";
     CleanUpPendingData();
     return false;
   }
 
-  pending_id_ = std::move(service_id);
-  pending_end_decl_cb_ = callback;
-
   return true;
 }
 
-std::unique_ptr<GattIdentifier> GattServer::GetIdForService(
-    const UUID& uuid, bool is_primary) {
-  // Calculate the instance ID for this service by searching through the handle
-  // map to see how many occurrences of the same service UUID we find.
-  int inst_id = 0;
-  for (const auto& iter : id_to_handle_map_) {
-    const GattIdentifier* gatt_id = &iter.first;
-
-    if (!gatt_id->IsService())
-      continue;
-
-    if (gatt_id->service_uuid() == uuid)
-      ++inst_id;
-  }
-
-  // Pass empty string for the address as this is a local service.
-  return GattIdentifier::CreateServiceId("", inst_id, uuid, is_primary);
-}
-
-std::unique_ptr<GattIdentifier> GattServer::GetIdForCharacteristic(
-    const UUID& uuid) {
-  CHECK(pending_decl_);
-
-  // Calculate the instance ID for this characteristic by searching through the
-  // pending entries.
-  int inst_id = 0;
-  for (const auto& entry : pending_decl_->attributes) {
-    const GattIdentifier& gatt_id = entry.id;
-
-    if (!gatt_id.IsCharacteristic())
-      continue;
-
-    if (gatt_id.characteristic_uuid() == uuid)
-      ++inst_id;
-  }
-
-  CHECK(pending_decl_->service_id.IsService());
-
-  return GattIdentifier::CreateCharacteristicId(
-      inst_id, uuid, pending_decl_->service_id);
-}
-
-std::unique_ptr<GattIdentifier> GattServer::GetIdForDescriptor(
-    const UUID& uuid) {
-  CHECK(pending_decl_);
-
-  // Calculate the instance ID for this descriptor by searching through the
-  // pending entries. We iterate in reverse until we find a characteristic
-  // entry.
-  CHECK(!pending_decl_->attributes.empty());
-  int inst_id = 0;
-  bool char_found = false;
-  GattIdentifier char_id;
-  for (auto iter = pending_decl_->attributes.end() - 1;
-       iter != pending_decl_->attributes.begin();  // Begin is always a service
-       --iter) {
-    const GattIdentifier& gatt_id = iter->id;
-
-    if (gatt_id.IsCharacteristic()) {
-      // Found the owning characteristic.
-      char_found = true;
-      char_id = gatt_id;
-      break;
-    }
-
-    if (!gatt_id.IsDescriptor()) {
-      // A descriptor must be preceded by a descriptor or a characteristic.
-      LOG(ERROR) << "Descriptors must come directly after a characteristic or "
-                 << "another descriptor.";
-      return nullptr;
-    }
-
-    if (gatt_id.descriptor_uuid() == uuid)
-      ++inst_id;
-  }
-
-  if (!char_found) {
-    LOG(ERROR) << "No characteristic found to add the descriptor to.";
-    return nullptr;
-  }
-
-  return GattIdentifier::CreateDescriptorId(inst_id, uuid, char_id);
-}
-
 bool GattServer::SendResponse(
     const std::string& device_address, int request_id,
     GATTError error, int offset,
@@ -368,7 +190,7 @@
 
 bool GattServer::SendNotification(
     const std::string& device_address,
-    const GattIdentifier& characteristic_id,
+    const uint16_t handle,
     bool confirm,
     const std::vector<uint8_t>& value,
     const GattCallback& callback) {
@@ -391,13 +213,6 @@
     return false;
   }
 
-  // Make sure that |characteristic_id| matches a valid attribute handle.
-  auto handle_iter = id_to_handle_map_.find(characteristic_id);
-  if (handle_iter == id_to_handle_map_.end()) {
-    LOG(ERROR) << "Unknown characteristic";
-    return false;
-  }
-
   std::shared_ptr<PendingIndication> pending_ind(
       new PendingIndication(callback));
 
@@ -418,7 +233,7 @@
     bt_status_t status = hal::BluetoothGattInterface::Get()->
         GetServerHALInterface()->send_indication(
             server_id_,
-            handle_iter->second,
+            handle,
             conn->conn_id,
             confirm,
             value);
@@ -502,130 +317,35 @@
 void GattServer::ServiceAddedCallback(
     hal::BluetoothGattInterface* gatt_iface,
     int status, int server_id,
-    const btgatt_srvc_id_t& srvc_id,
-    int service_handle) {
+    vector<btgatt_db_element_t> svc) {
   lock_guard<mutex> lock(mutex_);
 
   if (server_id != server_id_)
     return;
 
-  // Construct a GATT identifier.
-  auto gatt_id = hal::GetServiceIdFromHAL(srvc_id);
-  CHECK(pending_id_);
-  CHECK(*gatt_id == *pending_id_);
-  CHECK(*gatt_id == pending_decl_->service_id);
-  CHECK(pending_id_->IsService());
-
   VLOG(1) << __func__ << " - status: " << status
           << " server_id: " << server_id
-          << " handle: " << service_handle
-          << " UUID: " << gatt_id->service_uuid().ToString();
+          << " first handle: " << svc[0].attribute_handle
+          << " service UUID: " << UUID(svc[0].uuid).ToString()
+          << " count: " << svc.size();
 
-  if (status != BT_STATUS_SUCCESS) {
-    NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), *gatt_id);
-    return;
+  Service service(svc[0].attribute_handle, true, UUID(svc[0].uuid), {}, {});
+
+  for (size_t i=1; i<svc.size(); i++) {
+    const btgatt_db_element_t &curr = svc[i];
+    VLOG(1) << " - processing item no: " << i << " handle: " << curr.attribute_handle;
+    if (curr.type == BTGATT_DB_CHARACTERISTIC) {
+      service.characteristics().push_back({curr.attribute_handle, UUID(curr.uuid), curr.properties, curr.permissions, {}});
+    } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
+      service.characteristics().back().descriptors().push_back({curr.attribute_handle, UUID(curr.uuid), curr.permissions});
+    } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
+    }
   }
 
-  // Add this to the handle map.
-  pending_handle_map_[*gatt_id] = service_handle;
-  CHECK(-1 == pending_decl_->service_handle);
-  pending_decl_->service_handle = service_handle;
+  pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
 
-  HandleNextEntry(gatt_iface);
-}
+  CleanUpPendingData();
 
-void GattServer::CharacteristicAddedCallback(
-    hal::BluetoothGattInterface* gatt_iface,
-    int status, int server_id,
-    const bt_uuid_t& uuid,
-    int service_handle,
-    int char_handle) {
-  lock_guard<mutex> lock(mutex_);
-
-  if (server_id != server_id_)
-    return;
-
-  CHECK(pending_decl_);
-  CHECK(pending_decl_->service_handle == service_handle);
-  CHECK(pending_id_);
-  CHECK(pending_id_->IsCharacteristic());
-  CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
-
-  VLOG(1) << __func__ << " - status: " << status
-          << " server_id: " << server_id
-          << " service_handle: " << service_handle
-          << " char_handle: " << char_handle;
-
-  if (status != BT_STATUS_SUCCESS) {
-    NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
-                                  pending_decl_->service_id);
-    return;
-  }
-
-  // Add this to the handle map and continue.
-  pending_handle_map_[*pending_id_] = char_handle;
-  HandleNextEntry(gatt_iface);
-}
-
-void GattServer::DescriptorAddedCallback(
-    hal::BluetoothGattInterface* gatt_iface,
-    int status, int server_id,
-    const bt_uuid_t& uuid,
-    int service_handle,
-    int desc_handle) {
-  lock_guard<mutex> lock(mutex_);
-
-  if (server_id != server_id_)
-    return;
-
-  CHECK(pending_decl_);
-  CHECK(pending_decl_->service_handle == service_handle);
-  CHECK(pending_id_);
-  CHECK(pending_id_->IsDescriptor());
-  CHECK(pending_id_->descriptor_uuid() == UUID(uuid));
-
-  VLOG(1) << __func__ << " - status: " << status
-          << " server_id: " << server_id
-          << " service_handle: " << service_handle
-          << " desc_handle: " << desc_handle;
-
-  if (status != BT_STATUS_SUCCESS) {
-    NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
-                                  pending_decl_->service_id);
-    return;
-  }
-
-  // Add this to the handle map and contiue.
-  pending_handle_map_[*pending_id_] = desc_handle;
-  HandleNextEntry(gatt_iface);
-}
-
-void GattServer::ServiceStartedCallback(
-    hal::BluetoothGattInterface* gatt_iface,
-    int status, int server_id,
-    int service_handle) {
-  lock_guard<mutex> lock(mutex_);
-
-  if (server_id != server_id_)
-    return;
-
-  CHECK(pending_id_);
-  CHECK(pending_decl_);
-  CHECK(pending_decl_->service_handle == service_handle);
-
-  VLOG(1) << __func__ << " - server_id: " << server_id
-          << " handle: " << service_handle;
-
-  // If we failed to start the service, remove it from the database and ignore
-  // the result.
-  if (status != BT_STATUS_SUCCESS) {
-    gatt_iface->GetServerHALInterface()->delete_service(
-        server_id_, service_handle);
-  }
-
-  // Complete the operation.
-  NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
-                                pending_decl_->service_id);
 }
 
 void GattServer::ServiceStoppedCallback(
@@ -636,7 +356,7 @@
   // TODO(armansito): Support stopping a service.
 }
 
-void GattServer::RequestReadCallback(
+void GattServer::RequestReadCharacteristicCallback(
     hal::BluetoothGattInterface* /* gatt_iface */,
     int conn_id, int trans_id,
     const bt_bdaddr_t& bda,
@@ -657,13 +377,43 @@
           << " attribute_handle: " << attribute_handle << " offset: " << offset
           << " is_long: " << is_long;
 
-  // Make sure that the handle is valid.
-  auto iter = handle_to_id_map_.find(attribute_handle);
-  if (iter == handle_to_id_map_.end()) {
-    LOG(ERROR) << "Request received for unknown handle: " << attribute_handle;
+  conn->request_id_to_handle[trans_id] = attribute_handle;
+
+  // If there is no delegate then there is nobody to handle request. The request
+  // will eventually timeout and we should get a connection update that
+  // terminates the connection.
+  if (!delegate_) {
+    // TODO(armansito): Require a delegate at server registration so that this
+    // is never possible.
+    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
+                 << "will time out.";
     return;
   }
 
+  delegate_->OnCharacteristicReadRequest(
+      this, device_address, trans_id, offset, is_long, attribute_handle);
+}
+void GattServer::RequestReadDescriptorCallback(
+    hal::BluetoothGattInterface* /* gatt_iface */,
+    int conn_id, int trans_id,
+    const bt_bdaddr_t& bda,
+    int attribute_handle, int offset,
+    bool is_long) {
+  lock_guard<mutex> lock(mutex_);
+
+  // Check to see if we know about this connection. Otherwise ignore the
+  // request.
+  auto conn = GetConnection(conn_id, bda, trans_id);
+  if (!conn)
+    return;
+
+  std::string device_address = BtAddrString(&bda);
+
+  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
+          << " BD_ADDR: " << device_address
+          << " attribute_handle: " << attribute_handle << " offset: " << offset
+          << " is_long: " << is_long;
+
   conn->request_id_to_handle[trans_id] = attribute_handle;
 
   // If there is no delegate then there is nobody to handle request. The request
@@ -677,21 +427,11 @@
     return;
   }
 
-  if (iter->second.IsCharacteristic()) {
-    delegate_->OnCharacteristicReadRequest(
-        this, device_address, trans_id, offset, is_long, iter->second);
-  } else if (iter->second.IsDescriptor()) {
-    delegate_->OnDescriptorReadRequest(
-        this, device_address, trans_id, offset, is_long, iter->second);
-  } else {
-    // Our API only delegates to applications those read requests for
-    // characteristic value and descriptor attributes. Everything else should be
-    // handled by the stack.
-    LOG(WARNING) << "Read request received for unsupported attribute";
-  }
+  delegate_->OnDescriptorReadRequest(
+      this, device_address, trans_id, offset, is_long, attribute_handle);
 }
 
-void GattServer::RequestWriteCallback(
+void GattServer::RequestWriteCharacteristicCallback(
     hal::BluetoothGattInterface* /* gatt_iface */,
     int conn_id, int trans_id,
     const bt_bdaddr_t& bda,
@@ -714,13 +454,51 @@
           << " length: " << value.size() << " need_rsp: " << need_rsp
           << " is_prep: " << is_prep;
 
-  // Make sure that the handle is valid.
-  auto iter = handle_to_id_map_.find(attr_handle);
-  if (iter == handle_to_id_map_.end()) {
-    LOG(ERROR) << "Request received for unknown handle: " << attr_handle;
+  // Store the request ID only if this is not a write-without-response. If
+  // another request occurs after this with the same request ID, then we'll
+  // simply process it normally, though that shouldn't ever happen.
+  if (need_rsp)
+    conn->request_id_to_handle[trans_id] = attr_handle;
+
+  // If there is no delegate then there is nobody to handle request. The request
+  // will eventually timeout and we should get a connection update that
+  // terminates the connection.
+  if (!delegate_) {
+    // TODO(armansito): Require a delegate at server registration so that this
+    // is never possible.
+    LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
+                 << "will time out.";
     return;
   }
 
+  delegate_->OnCharacteristicWriteRequest(
+      this, device_address, trans_id, offset, is_prep, need_rsp,
+      std::move(value), attr_handle);
+}
+
+void GattServer::RequestWriteDescriptorCallback(
+    hal::BluetoothGattInterface* /* gatt_iface */,
+    int conn_id, int trans_id,
+    const bt_bdaddr_t& bda,
+    int attr_handle, int offset,
+    bool need_rsp, bool is_prep,
+    vector<uint8_t> value) {
+  lock_guard<mutex> lock(mutex_);
+
+  // Check to see if we know about this connection. Otherwise ignore the
+  // request.
+  auto conn = GetConnection(conn_id, bda, trans_id);
+  if (!conn)
+    return;
+
+  std::string device_address = BtAddrString(&bda);
+
+  VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
+          << " BD_ADDR: " << device_address
+          << " attr_handle: " << attr_handle << " offset: " << offset
+          << " length: " << value.size() << " need_rsp: " << need_rsp
+          << " is_prep: " << is_prep;
+
   // Store the request ID only if this is not a write-without-response. If
   // another request occurs after this with the same request ID, then we'll
   // simply process it normally, though that shouldn't ever happen.
@@ -738,20 +516,9 @@
     return;
   }
 
-  if (iter->second.IsCharacteristic()) {
-    delegate_->OnCharacteristicWriteRequest(
-        this, device_address, trans_id, offset, is_prep, need_rsp,
-        std::move(value), iter->second);
-  } else if (iter->second.IsDescriptor()) {
-    delegate_->OnDescriptorWriteRequest(
-        this, device_address, trans_id, offset, is_prep, need_rsp,
-        std::move(value), iter->second);
-  } else {
-    // Our API only delegates to applications those read requests for
-    // characteristic value and descriptor attributes. Everything else should be
-    // handled by the stack.
-    LOG(WARNING) << "Write request received for unsupported attribute";
-  }
+  delegate_->OnDescriptorWriteRequest(
+      this, device_address, trans_id, offset, is_prep, need_rsp,
+      std::move(value), attr_handle);
 }
 
 void GattServer::RequestExecWriteCallback(
@@ -815,93 +582,8 @@
   }
 }
 
-void GattServer::NotifyEndCallbackAndClearData(
-    BLEStatus status, const GattIdentifier& id) {
-  VLOG(1) << __func__ << " status: " << status;
-  CHECK(pending_end_decl_cb_);
-
-  if (status == BLE_STATUS_SUCCESS) {
-    id_to_handle_map_.insert(pending_handle_map_.begin(),
-                             pending_handle_map_.end());
-    for (auto& iter : pending_handle_map_)
-      handle_to_id_map_[iter.second] = iter.first;
-  }
-
-  pending_end_decl_cb_(status, id);
-
-  CleanUpPendingData();
-}
-
 void GattServer::CleanUpPendingData() {
-  pending_id_ = nullptr;
-  pending_decl_ = nullptr;
   pending_end_decl_cb_ = ResultCallback();
-  pending_handle_map_.clear();
-}
-
-void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
-  CHECK(pending_decl_);
-  CHECK(gatt_iface);
-
-  auto next_entry = PopNextEntry();
-  if (!next_entry) {
-    // No more entries. Call start_service to finish up.
-    bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
-        server_id_,
-        pending_decl_->service_handle,
-        TRANSPORT_BREDR | TRANSPORT_LE);
-
-    // Terminate the procedure in the case of an error.
-    if (status != BT_STATUS_SUCCESS) {
-      NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
-                                    pending_decl_->service_id);
-    }
-
-    return;
-  }
-
-  if (next_entry->id.IsCharacteristic()) {
-    bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
-    bt_status_t status = gatt_iface->GetServerHALInterface()->
-        add_characteristic(
-            server_id_,
-            pending_decl_->service_handle,
-            &char_uuid,
-            next_entry->char_properties,
-            next_entry->permissions);
-
-    // Terminate the procedure in the case of an error.
-    if (status != BT_STATUS_SUCCESS) {
-      NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
-                                    pending_decl_->service_id);
-      return;
-    }
-
-    pending_id_.reset(new GattIdentifier(next_entry->id));
-    return;
-  }
-
-  if (next_entry->id.IsDescriptor()) {
-    bt_uuid_t desc_uuid = next_entry->id.descriptor_uuid().GetBlueDroid();
-    bt_status_t status = gatt_iface->GetServerHALInterface()->
-        add_descriptor(
-            server_id_,
-            pending_decl_->service_handle,
-            &desc_uuid,
-            next_entry->permissions);
-
-    // Terminate the procedure in the case of an error.
-    if (status != BT_STATUS_SUCCESS) {
-      NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
-                                    pending_decl_->service_id);
-      return;
-    }
-
-    pending_id_.reset(new GattIdentifier(next_entry->id));
-    return;
-  }
-
-  NOTREACHED() << "Unexpected entry type";
 }
 
 std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
@@ -929,28 +611,6 @@
   return conn;
 }
 
-std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
-  CHECK(pending_decl_);
-
-  if (pending_decl_->attributes.empty())
-    return nullptr;
-
-  const auto& next = pending_decl_->attributes.front();
-  std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
-
-  pending_decl_->attributes.pop_front();
-
-  return entry;
-}
-
-std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
-  auto entry = PopNextEntry();
-  if (!entry)
-    return nullptr;
-
-  return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
-}
-
 // GattServerFactory implementation
 // ========================================================
 
diff --git a/service/gatt_server.h b/service/gatt_server.h
index 30df9e6..aa0be81 100644
--- a/service/gatt_server.h
+++ b/service/gatt_server.h
@@ -26,7 +26,7 @@
 #include <base/macros.h>
 
 #include "service/bluetooth_instance.h"
-#include "service/common/bluetooth/gatt_identifier.h"
+#include "service/common/bluetooth/service.h"
 #include "service/common/bluetooth/uuid.h"
 #include "service/hal/bluetooth_gatt_interface.h"
 
@@ -52,8 +52,7 @@
     virtual void OnCharacteristicReadRequest(
         GattServer* gatt_server,
         const std::string& device_address,
-        int request_id, int offset, bool is_long,
-        const bluetooth::GattIdentifier& characteristic_id) = 0;
+        int request_id, int offset, bool is_long, uint16_t handle) = 0;
 
     // Called when there is an incoming read request for the descriptor with
     // ID |descriptor_id| from a remote device with address |device_address|.
@@ -62,8 +61,7 @@
     virtual void OnDescriptorReadRequest(
         GattServer* gatt_server,
         const std::string& device_address,
-        int request_id, int offset, bool is_long,
-        const bluetooth::GattIdentifier& descriptor_id) = 0;
+        int request_id, int offset, bool is_long, uint16_t handle) = 0;
 
     // Called when there is an incoming write request for the characteristic
     // with ID |characteristic_id| from a remote device with address
@@ -78,8 +76,7 @@
         GattServer* gatt_server,
         const std::string& device_address,
         int request_id, int offset, bool is_prepare_write, bool need_response,
-        const std::vector<uint8_t>& value,
-        const bluetooth::GattIdentifier& characteristic_id) = 0;
+        const std::vector<uint8_t>& value, uint16_t handle) = 0;
 
     // Called when there is an incoming write request for the descriptor
     // with ID |descriptor_id| from a remote device with address
@@ -94,8 +91,7 @@
         GattServer* gatt_server,
         const std::string& device_address,
         int request_id, int offset, bool is_prepare_write, bool need_response,
-        const std::vector<uint8_t>& value,
-        const bluetooth::GattIdentifier& descriptor_id) = 0;
+        const std::vector<uint8_t>& value, uint16_t handle) = 0;
 
     // Called when there is an incoming "Execute Write Request". If |is_execute|
     // is true, then the Delegate should commit all previously prepared writes.
@@ -129,46 +125,20 @@
   // Callback type used to report the status of an asynchronous GATT server
   // operation.
   using ResultCallback =
-      std::function<void(BLEStatus status, const GattIdentifier& id)>;
+      std::function<void(BLEStatus status, const Service& id)>;
   using GattCallback = std::function<void(GATTError error)>;
 
-  // Starts a new GATT service declaration for the service with the given
-  // parameters. In the case of an error, for example If a service declaration
-  // is already in progress, then this method returns a NULL pointer. Otherwise,
-  // this returns an identifier that uniquely identifies the added service.
-  //
-  // TODO(armansito): In the framework code, the "min_handles" parameter is
-  // annotated to be used for "conformance testing only". I don't fully see the
-  // point of this and suggest getting rid of this parameter entirely. For now
-  // this code doesn't declare or use it.
-  std::unique_ptr<GattIdentifier> BeginServiceDeclaration(
-      const UUID& uuid, bool is_primary);
-
-  // Inserts a new characteristic definition into a previously begun service
-  // declaration. Returns the assigned identifier for the characteristic, or
-  // nullptr if a service declaration wasn't begun or a call to
-  // EndServiceDeclaration is still in progress.
-  std::unique_ptr<GattIdentifier> AddCharacteristic(
-      const UUID& uuid, int properties, int permissions);
-
-  // Inserts a new descriptor definition into a previous begun service
-  // declaration. Returns the assigned identifier for the descriptor, or
-  // nullptr if a service declaration wasn't begun, a call to
-  // EndServiceDeclaration is still in progress, or a characteristic definition
-  // doesn't properly precede this definition.
-  std::unique_ptr<GattIdentifier> AddDescriptor(
-      const UUID& uuid, int permissions);
-
-  // Ends a previously started service declaration. This method immediately
-  // returns false if a service declaration hasn't been started. Otherwise,
-  // |callback| will be called asynchronously with the result of the operation.
+  // Add service declaration. This method immediately
+  // returns false if a service hasn't been started. Otherwise, |callback| will
+  // be called asynchronously with the result of the operation.
   //
   // TODO(armansito): It is unclear to me what it means for this function to
   // fail. What is the state that we're in? Is the service declaration over so
   // we can add other services to this server instance? Do we need to clean up
   // all the entries or does the upper-layer need to remove the service? Or are
   // we in a stuck-state where the service declaration hasn't ended?
-  bool EndServiceDeclaration(const ResultCallback& callback);
+  bool AddService(const bluetooth::Service&, const ResultCallback& callback);
+
 
   // Sends a response for a pending notification. |request_id| and
   // |device_address| should match those that were received through one of the
@@ -181,7 +151,7 @@
                     const std::vector<uint8_t>& value);
 
   // Sends an ATT Handle-Value Notification to the device with BD_ADDR
-  // |device_address| for the characteristic with ID |characteristic_id| and
+  // |device_address| for the characteristic with handle |handle| and
   // value |value|. If |confirm| is true, then an ATT Handle-Value Indication
   // will be sent instead, which requires the remote to confirm receipt. Returns
   // false if there was an immediate error in initiating the notification
@@ -192,37 +162,13 @@
   // sends a ATT Handle-Value Confirmation packet. Otherwise, it will be run as
   // soon as the notification has been sent out.
   bool SendNotification(const std::string& device_address,
-                        const GattIdentifier& characteristic_id,
+                        const uint16_t handle,
                         bool confirm, const std::vector<uint8_t>& value,
                         const GattCallback& callback);
 
  private:
   friend class GattServerFactory;
 
-  // Internal representation of an attribute entry as part of a service
-  // declaration.
-  struct AttributeEntry {
-    AttributeEntry(const GattIdentifier& id,
-                   int char_properties,
-                   int permissions)
-        : id(id), char_properties(char_properties), permissions(permissions) {}
-
-    GattIdentifier id;
-    int char_properties;
-    int permissions;
-  };
-
-  // Internal representation of a GATT service declaration before it has been
-  // sent to the stack.
-  struct ServiceDeclaration {
-    ServiceDeclaration() : num_handles(0), service_handle(-1) {}
-
-    size_t num_handles;
-    GattIdentifier service_id;
-    int service_handle;
-    std::deque<AttributeEntry> attributes;
-  };
-
   // Used for the internal remote connection tracking. Keeps track of the
   // request ID and the device address for the connection. If |request_id| is -1
   // then no ATT read/write request is currently pending.
@@ -251,13 +197,6 @@
   // obtained from the factory.
   GattServer(const UUID& uuid, int server_id);
 
-  // Returns a GattIdentifier for the attribute with the given UUID within the
-  // current pending service declaration.
-  std::unique_ptr<GattIdentifier> GetIdForService(const UUID& uuid,
-                                                  bool is_primary);
-  std::unique_ptr<GattIdentifier> GetIdForCharacteristic(const UUID& uuid);
-  std::unique_ptr<GattIdentifier> GetIdForDescriptor(const UUID& uuid);
-
   // hal::BluetoothGattInterface::ServerObserver overrides:
   void ConnectionCallback(
       hal::BluetoothGattInterface* gatt_iface,
@@ -266,36 +205,32 @@
       const bt_bdaddr_t& bda) override;
   void ServiceAddedCallback(
       hal::BluetoothGattInterface* gatt_iface,
-      int status, int server_id,
-      const btgatt_srvc_id_t& srvc_id,
-      int service_handle) override;
-  void CharacteristicAddedCallback(
-      hal::BluetoothGattInterface* gatt_iface,
-      int status, int server_id,
-      const bt_uuid_t& uuid,
-      int service_handle,
-      int char_handle) override;
-  void DescriptorAddedCallback(
-      hal::BluetoothGattInterface* gatt_iface,
-      int status, int server_id,
-      const bt_uuid_t& uuid,
-      int service_handle,
-      int desc_handle) override;
-  void ServiceStartedCallback(
-      hal::BluetoothGattInterface* gatt_iface,
-      int status, int server_id,
-      int service_handle) override;
+      int status, int server_if,
+      vector<btgatt_db_element_t>) override;
   void ServiceStoppedCallback(
       hal::BluetoothGattInterface* gatt_iface,
       int status, int server_id,
       int service_handle) override;
-  void RequestReadCallback(
+  void RequestReadCharacteristicCallback(
       hal::BluetoothGattInterface* gatt_iface,
       int conn_id, int trans_id,
       const bt_bdaddr_t& bda,
       int attribute_handle, int offset,
       bool is_long) override;
-  void RequestWriteCallback(
+  void RequestReadDescriptorCallback(
+      hal::BluetoothGattInterface* gatt_iface,
+      int conn_id, int trans_id,
+      const bt_bdaddr_t& bda,
+      int attribute_handle, int offset,
+      bool is_long) override;
+  void RequestWriteCharacteristicCallback(
+      hal::BluetoothGattInterface* gatt_iface,
+      int conn_id, int trans_id,
+      const bt_bdaddr_t& bda,
+      int attr_handle, int offset,
+      bool need_rsp, bool is_prep,
+      vector<uint8_t> value) override;
+  void RequestWriteDescriptorCallback(
       hal::BluetoothGattInterface* gatt_iface,
       int conn_id, int trans_id,
       const bt_bdaddr_t& bda,
@@ -311,8 +246,6 @@
       int conn_id, int status) override;
 
   // Helper function that notifies and clears the pending callback.
-  void NotifyEndCallbackAndClearData(BLEStatus status,
-                                     const GattIdentifier& id);
   void CleanUpPendingData();
 
   // Handles the next attribute entry in the pending service declaration.
@@ -323,25 +256,13 @@
   std::shared_ptr<Connection> GetConnection(int conn_id, const bt_bdaddr_t& bda,
                                             int request_id);
 
-  // Pops the next GATT ID or entry from the pending service declaration's
-  // attribute list.
-  std::unique_ptr<AttributeEntry> PopNextEntry();
-  std::unique_ptr<GattIdentifier> PopNextId();
-
   // See getters for documentation.
   UUID app_identifier_;
   int server_id_;
 
   // Mutex that synchronizes access to the entries below.
   std::mutex mutex_;
-  std::unique_ptr<GattIdentifier> pending_id_;
-  std::unique_ptr<ServiceDeclaration> pending_decl_;
   ResultCallback pending_end_decl_cb_;
-  std::unordered_map<GattIdentifier, int> pending_handle_map_;
-
-  // Mapping of handles and GATT identifiers for started services.
-  std::unordered_map<GattIdentifier, int> id_to_handle_map_;
-  std::unordered_map<int, GattIdentifier> handle_to_id_map_;
 
   // GATT connection mappings from stack-provided "conn_id" IDs and remote
   // device addresses to Connection structures. The conn_id map is one-to-one
diff --git a/service/gatt_server_old.cc b/service/gatt_server_old.cc
index 7a66af9..9f196a8 100644
--- a/service/gatt_server_old.cc
+++ b/service/gatt_server_old.cc
@@ -31,6 +31,7 @@
 #include <set>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <vector>
 
 #include <hardware/bluetooth.h>
@@ -47,8 +48,8 @@
 namespace {
 
 const size_t kMaxGattAttributeSize = 512;
-// TODO(icoolidge): Difficult to generalize without knowing how many attributes.
-const int kNumBlueDroidHandles = 60;
+std::vector<btgatt_db_element_t> pending_svc_decl;
+std::unordered_set<int> blob_index;
 
 // TODO(icoolidge): Support multiple instances
 // TODO(armansito): Remove this variable. No point of having this if
@@ -97,8 +98,8 @@
   int Initialize();
   bt_status_t AddCharacteristic(
       const UUID& uuid,
-      int properties,
-      int permissions);
+      uint8_t properties,
+      uint16_t permissions);
 
   // This maps API attribute UUIDs to BlueDroid handles.
   std::map<UUID, int> uuid_to_attribute;
@@ -116,7 +117,6 @@
   int server_if;
   int client_if;
   int service_handle;
-  btgatt_srvc_id_t service_id;
   std::set<int> connections;
 
   std::mutex lock;
@@ -135,27 +135,70 @@
            server_if, app_uuid);
 
   g_internal->server_if = server_if;
-
-  btgatt_srvc_id_t service_id;
-  service_id.id.uuid = *app_uuid;
-  service_id.id.inst_id = 0;
-  service_id.is_primary = true;
-
-  g_internal->gatt->server->add_service(
-      server_if, &service_id, kNumBlueDroidHandles);
+  pending_svc_decl.push_back({.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = *app_uuid});
 }
 
-void ServiceAddedCallback(int status, int server_if, btgatt_srvc_id_t *srvc_id,
-                          int srvc_handle) {
-  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d gatt_srvc_id:%u srvc_handle:%d",
-           __func__, status, server_if, srvc_id->id.inst_id, srvc_handle);
+void ServiceAddedCallback(int status, int server_if, vector<btgatt_db_element_t> service) {
+  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d count:%zu svc_handle:%d",
+           __func__, status, server_if, service.size(), service[0].attribute_handle);
 
   std::lock_guard<std::mutex> lock(g_internal->lock);
   g_internal->server_if = server_if;
-  g_internal->service_handle = srvc_handle;
-  g_internal->service_id = *srvc_id;
-  // This finishes the Initialize call.
-  g_internal->api_synchronize.notify_one();
+
+  g_internal->service_handle = service[0].attribute_handle;
+
+  uint16_t prev_char_handle = 0;
+  uint16_t prev_char_properties = 0;
+  for (size_t i = 1; i<service.size(); i++) {
+    const btgatt_db_element_t &el = service[i];
+    if (el.type == BTGATT_DB_CHARACTERISTIC) {
+      LOG_INFO(LOG_TAG, "%s: descr_handle:%d", __func__, el.attribute_handle);
+    } else if (el.type == BTGATT_DB_CHARACTERISTIC) {
+      bluetooth::UUID id(el.uuid);
+      uint16_t char_handle = el.attribute_handle;
+
+      LOG_INFO(LOG_TAG, "%s: char_handle:%d", __func__, char_handle);
+
+      g_internal->uuid_to_attribute[id] = char_handle;
+      g_internal->characteristics[char_handle].uuid = id;
+      g_internal->characteristics[char_handle].blob_section = 0;
+
+      // If the added characteristic is blob
+      if (blob_index.find(i) != blob_index.end()) {
+        // Finally, associate the control attribute with the value attribute.
+        // Also, initialize the control attribute to a readable zero.
+        const uint16_t control_attribute = char_handle;
+        const uint16_t blob_attribute = prev_char_handle;
+        g_internal->controlled_blobs[control_attribute] = blob_attribute;
+        g_internal->characteristics[blob_attribute].notify =
+            prev_char_properties & bluetooth::gatt::kPropertyNotify;
+
+        bluetooth::gatt::Characteristic &ctrl =
+            g_internal->characteristics[control_attribute];
+        ctrl.next_blob.clear();
+        ctrl.next_blob.push_back(0);
+        ctrl.next_blob_pending = true;
+        ctrl.blob_section = 0;
+        ctrl.notify = false;
+      }
+      prev_char_handle = char_handle;
+      prev_char_properties = el.properties;
+    }
+  }
+
+  pending_svc_decl.clear();
+  blob_index.clear();
+
+  // The UUID provided here is unimportant, and is only used to satisfy
+  // BlueDroid.
+  // It must be different than any other registered UUID.
+  bt_uuid_t client_id = service[0].uuid;
+  ++client_id.uu[15];
+
+  bt_status_t btstat = g_internal->gatt->client->register_client(&client_id);
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: Failed to register client", __func__);
+  }
 }
 
 void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
@@ -294,48 +337,6 @@
   }
 }
 
-void CharacteristicAddedCallback(int status, int server_if, bt_uuid_t *uuid,
-                                 int srvc_handle, int char_handle) {
-  LOG_INFO(LOG_TAG,
-      "%s: status:%d server_if:%d service_handle:%d char_handle:%d", __func__,
-      status, server_if, srvc_handle, char_handle);
-
-  bluetooth::UUID id(*uuid);
-
-  std::lock_guard<std::mutex> lock(g_internal->lock);
-
-  g_internal->uuid_to_attribute[id] = char_handle;
-  g_internal->characteristics[char_handle].uuid = id;
-  g_internal->characteristics[char_handle].blob_section = 0;
-
-  // This terminates an AddCharacteristic.
-  g_internal->api_synchronize.notify_one();
-}
-
-void DescriptorAddedCallback(int status, int server_if, bt_uuid_t *uuid,
-                             int srvc_handle, int descr_handle) {
-  LOG_INFO(LOG_TAG,
-      "%s: status:%d server_if:%d service_handle:%d uuid[0]:%u "
-      "descr_handle:%d",
-      __func__, status, server_if, srvc_handle, uuid->uu[0], descr_handle);
-}
-
-void ServiceStartedCallback(int status, int server_if, int srvc_handle) {
-  LOG_INFO(LOG_TAG, "%s: status:%d server_if:%d srvc_handle:%d", __func__,
-      status, server_if, srvc_handle);
-
-  // The UUID provided here is unimportant, and is only used to satisfy
-  // BlueDroid.
-  // It must be different than any other registered UUID.
-  bt_uuid_t client_id = g_internal->service_id.id.uuid;
-  ++client_id.uu[15];
-
-  bt_status_t btstat = g_internal->gatt->client->register_client(&client_id);
-  if (btstat != BT_STATUS_SUCCESS) {
-    LOG_ERROR(LOG_TAG, "%s: Failed to register client", __func__);
-  }
-}
-
 void RegisterClientCallback(int status, int client_if, bt_uuid_t *app_uuid) {
   LOG_INFO(LOG_TAG, "%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
       client_if, app_uuid->uu[0]);
@@ -415,13 +416,11 @@
     RegisterServerCallback,
     ConnectionCallback,
     ServiceAddedCallback,
-    nullptr, /* included_service_added_cb */
-    CharacteristicAddedCallback,
-    DescriptorAddedCallback,
-    ServiceStartedCallback,
     ServiceStoppedCallback,
     nullptr, /* service_deleted_cb */
     RequestReadCallback,
+    RequestReadCallback,
+    RequestWriteCallback,
     RequestWriteCallback,
     RequestExecWriteCallback,
     ResponseConfirmationCallback,
@@ -510,11 +509,13 @@
 
 bt_status_t ServerInternals::AddCharacteristic(
     const UUID& uuid,
-    int properties,
-    int permissions) {
+    uint8_t properties,
+    uint16_t permissions) {
   bt_uuid_t c_uuid = uuid.GetBlueDroid();
-  return gatt->server->add_characteristic(
-      server_if, service_handle, &c_uuid, properties, permissions);
+
+  pending_svc_decl.push_back({.type = BTGATT_DB_CHARACTERISTIC, .uuid = c_uuid,
+                        .properties = properties, .permissions = permissions});
+  return BT_STATUS_SUCCESS;
 }
 
 ServerInternals::ServerInternals()
@@ -666,37 +667,22 @@
     return false;
   }
 
-  internal_->api_synchronize.wait(lock);
-
   // Next, add the secondary attribute (blob control).
   // Control attributes have fixed permissions/properties.
+  // Remember position at which blob was added.
+  blob_index.insert(pending_svc_decl.size());
   btstat = internal_->AddCharacteristic(
       control_id,
       kPropertyRead | kPropertyWrite,
       kPermissionRead | kPermissionWrite);
-  internal_->api_synchronize.wait(lock);
 
-  // Finally, associate the control attribute with the value attribute.
-  // Also, initialize the control attribute to a readable zero.
-  const int control_attribute = internal_->uuid_to_attribute[control_id];
-  const int blob_attribute = internal_->uuid_to_attribute[id];
-  internal_->controlled_blobs[control_attribute] = blob_attribute;
-  internal_->characteristics[blob_attribute].notify =
-      properties & kPropertyNotify;
-
-  Characteristic &ctrl = internal_->characteristics[control_attribute];
-  ctrl.next_blob.clear();
-  ctrl.next_blob.push_back(0);
-  ctrl.next_blob_pending = true;
-  ctrl.blob_section = 0;
-  ctrl.notify = false;
   return true;
 }
 
 bool Server::Start() {
   std::unique_lock<std::mutex> lock(internal_->lock);
-  bt_status_t btstat = internal_->gatt->server->start_service(
-      internal_->server_if, internal_->service_handle, GATT_TRANSPORT_LE);
+  bt_status_t btstat = internal_->gatt->server->add_service(
+      internal_->server_if, pending_svc_decl);
   if (btstat != BT_STATUS_SUCCESS) {
     LOG_ERROR(LOG_TAG, "Failed to start service with handle: 0x%04x",
               internal_->service_handle);
diff --git a/service/hal/bluetooth_gatt_interface.cc b/service/hal/bluetooth_gatt_interface.cc
index 002894a..a5534dc 100644
--- a/service/hal/bluetooth_gatt_interface.cc
+++ b/service/hal/bluetooth_gatt_interface.cc
@@ -288,56 +288,15 @@
 void ServiceAddedCallback(
     int status,
     int server_if,
-    btgatt_srvc_id_t* srvc_id,
-    int srvc_handle) {
+    vector<btgatt_db_element_t> service) {
   shared_lock<shared_timed_mutex> lock(g_instance_lock);
   VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
-          << " handle: " << srvc_handle;
+          << " count: " << service.size();
   VERIFY_INTERFACE_OR_RETURN();
-  CHECK(srvc_id);
+  CHECK(service.size());
 
   FOR_EACH_SERVER_OBSERVER(ServiceAddedCallback(
-      g_interface, status, server_if, *srvc_id, srvc_handle));
-}
-
-void CharacteristicAddedCallback(
-    int status, int server_if,
-    bt_uuid_t* uuid,
-    int srvc_handle,
-    int char_handle) {
-  shared_lock<shared_timed_mutex> lock(g_instance_lock);
-  VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
-          << " srvc_handle: " << srvc_handle << " char_handle: " << char_handle;
-  VERIFY_INTERFACE_OR_RETURN();
-  CHECK(uuid);
-
-  FOR_EACH_SERVER_OBSERVER(CharacteristicAddedCallback(
-      g_interface, status, server_if, *uuid, srvc_handle, char_handle));
-}
-
-void DescriptorAddedCallback(
-    int status, int server_if,
-    bt_uuid_t* uuid,
-    int srvc_handle,
-    int desc_handle) {
-  shared_lock<shared_timed_mutex> lock(g_instance_lock);
-  VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
-          << " srvc_handle: " << srvc_handle << " desc_handle: " << desc_handle;
-  VERIFY_INTERFACE_OR_RETURN();
-  CHECK(uuid);
-
-  FOR_EACH_SERVER_OBSERVER(DescriptorAddedCallback(
-      g_interface, status, server_if, *uuid, srvc_handle, desc_handle));
-}
-
-void ServiceStartedCallback(int status, int server_if, int srvc_handle) {
-  shared_lock<shared_timed_mutex> lock(g_instance_lock);
-  VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
-          << " handle: " << srvc_handle;
-  VERIFY_INTERFACE_OR_RETURN();
-
-  FOR_EACH_SERVER_OBSERVER(ServiceStartedCallback(
-      g_interface, status, server_if, srvc_handle));
+      g_interface, status, server_if, service));
 }
 
 void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
@@ -360,7 +319,7 @@
       g_interface, status, server_if, srvc_handle));
 }
 
-void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
+void RequestReadCharacteristicCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
                          int attr_handle, int offset, bool is_long) {
   shared_lock<shared_timed_mutex> lock(g_instance_lock);
   VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
@@ -369,11 +328,24 @@
   VERIFY_INTERFACE_OR_RETURN();
   CHECK(bda);
 
-  FOR_EACH_SERVER_OBSERVER(RequestReadCallback(
+  FOR_EACH_SERVER_OBSERVER(RequestReadCharacteristicCallback(
       g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
 }
 
-void RequestWriteCallback(int conn_id, int trans_id,
+void RequestReadDescriptorCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
+                         int attr_handle, int offset, bool is_long) {
+  shared_lock<shared_timed_mutex> lock(g_instance_lock);
+  VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
+          << " attr_handle: " << attr_handle << " offset: " << offset
+          << " is_long: " << is_long;
+  VERIFY_INTERFACE_OR_RETURN();
+  CHECK(bda);
+
+  FOR_EACH_SERVER_OBSERVER(RequestReadDescriptorCallback(
+      g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
+}
+
+void RequestWriteCharacteristicCallback(int conn_id, int trans_id,
                           bt_bdaddr_t* bda,
                           int attr_handle, int offset,
                           bool need_rsp, bool is_prep,
@@ -386,7 +358,25 @@
   VERIFY_INTERFACE_OR_RETURN();
   CHECK(bda);
 
-  FOR_EACH_SERVER_OBSERVER(RequestWriteCallback(
+  FOR_EACH_SERVER_OBSERVER(RequestWriteCharacteristicCallback(
+      g_interface, conn_id, trans_id, *bda, attr_handle, offset,
+      need_rsp, is_prep, std::move(value)));
+}
+
+void RequestWriteDescriptorCallback(int conn_id, int trans_id,
+                          bt_bdaddr_t* bda,
+                          int attr_handle, int offset,
+                          bool need_rsp, bool is_prep,
+                          vector<uint8_t> value) {
+  shared_lock<shared_timed_mutex> lock(g_instance_lock);
+  VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
+          << " attr_handle: " << attr_handle << " offset: " << offset
+          << " length: " << value.size() << " need_rsp: " << need_rsp
+          << " is_prep: " << is_prep;
+  VERIFY_INTERFACE_OR_RETURN();
+  CHECK(bda);
+
+  FOR_EACH_SERVER_OBSERVER(RequestWriteDescriptorCallback(
       g_interface, conn_id, trans_id, *bda, attr_handle, offset,
       need_rsp, is_prep, value));
 }
@@ -470,14 +460,12 @@
     RegisterServerCallback,
     ConnectionCallback,
     ServiceAddedCallback,
-    nullptr,  // included_service_added_cb
-    CharacteristicAddedCallback,
-    DescriptorAddedCallback,
-    ServiceStartedCallback,
     ServiceStoppedCallback,
     ServiceDeletedCallback,
-    RequestReadCallback,
-    RequestWriteCallback,
+    RequestReadCharacteristicCallback,
+    RequestReadDescriptorCallback,
+    RequestWriteCharacteristicCallback,
+    RequestWriteDescriptorCallback,
     RequestExecWriteCallback,
     ResponseConfirmationCallback,
     IndicationSentCallback,
@@ -754,36 +742,7 @@
     BluetoothGattInterface* /* gatt_iface */,
     int /* status */,
     int /* server_if */,
-    const btgatt_srvc_id_t& /* srvc_id */,
-    int /* srvc_handle */) {
-  // Do nothing.
-}
-
-void BluetoothGattInterface::ServerObserver::CharacteristicAddedCallback(
-    BluetoothGattInterface* /* gatt_iface */,
-    int /* status */,
-    int /* server_if */,
-    const bt_uuid_t& /* uuid */,
-    int /* srvc_handle */,
-    int /* char_handle */) {
-  // Do nothing.
-}
-
-void BluetoothGattInterface::ServerObserver::DescriptorAddedCallback(
-    BluetoothGattInterface* /* gatt_iface */,
-    int /* status */,
-    int /* server_if */,
-    const bt_uuid_t& /* uuid */,
-    int /* srvc_handle */,
-    int /* desc_handle */) {
-  // Do nothing.
-}
-
-void BluetoothGattInterface::ServerObserver::ServiceStartedCallback(
-    BluetoothGattInterface* /* gatt_iface */,
-    int /* status */,
-    int /* server_if */,
-    int /* srvc_handle */) {
+    vector<btgatt_db_element_t> /* service */) {
   // Do nothing.
 }
 
@@ -803,7 +762,7 @@
   // Do nothing.
 }
 
-void BluetoothGattInterface::ServerObserver::RequestReadCallback(
+void BluetoothGattInterface::ServerObserver::RequestReadCharacteristicCallback(
     BluetoothGattInterface* /* gatt_iface */,
     int /* conn_id */,
     int /* trans_id */,
@@ -814,7 +773,31 @@
   // Do nothing.
 }
 
-void BluetoothGattInterface::ServerObserver::RequestWriteCallback(
+void BluetoothGattInterface::ServerObserver::RequestReadDescriptorCallback(
+    BluetoothGattInterface* /* gatt_iface */,
+    int /* conn_id */,
+    int /* trans_id */,
+    const bt_bdaddr_t& /* bda */,
+    int /* attr_handle */,
+    int /* offset */,
+    bool /* is_long */) {
+  // Do nothing.
+}
+
+void BluetoothGattInterface::ServerObserver::RequestWriteCharacteristicCallback(
+    BluetoothGattInterface* /* gatt_iface */,
+    int /* conn_id */,
+    int /* trans_id */,
+    const bt_bdaddr_t& /* bda */,
+    int /* attr_handle */,
+    int /* offset */,
+    bool /* need_rsp */,
+    bool /* is_prep */,
+    vector<uint8_t> /* value */) {
+  // Do nothing.
+}
+
+void BluetoothGattInterface::ServerObserver::RequestWriteDescriptorCallback(
     BluetoothGattInterface* /* gatt_iface */,
     int /* conn_id */,
     int /* trans_id */,
diff --git a/service/hal/bluetooth_gatt_interface.h b/service/hal/bluetooth_gatt_interface.h
index a22e3c3..509f863 100644
--- a/service/hal/bluetooth_gatt_interface.h
+++ b/service/hal/bluetooth_gatt_interface.h
@@ -158,27 +158,7 @@
     virtual void ServiceAddedCallback(
         BluetoothGattInterface* gatt_iface,
         int status, int server_if,
-        const btgatt_srvc_id_t& srvc_id,
-        int srvc_handle);
-
-    virtual void CharacteristicAddedCallback(
-        BluetoothGattInterface* gatt_iface,
-        int status, int server_if,
-        const bt_uuid_t& uuid,
-        int srvc_handle,
-        int char_handle);
-
-    virtual void DescriptorAddedCallback(
-        BluetoothGattInterface* gatt_iface,
-        int status, int server_if,
-        const bt_uuid_t& uuid,
-        int srvc_handle,
-        int desc_handle);
-
-    virtual void ServiceStartedCallback(
-        BluetoothGattInterface* gatt_iface,
-        int status, int server_if,
-        int srvc_handle);
+        vector<btgatt_db_element_t> service);
 
     virtual void ServiceStoppedCallback(
         BluetoothGattInterface* gatt_iface,
@@ -190,14 +170,29 @@
         int status, int server_if,
         int srvc_handle);
 
-    virtual void RequestReadCallback(
+    virtual void RequestReadCharacteristicCallback(
         BluetoothGattInterface* gatt_iface,
         int conn_id, int trans_id,
         const bt_bdaddr_t& bda,
         int attr_handle, int offset,
         bool is_long);
 
-    virtual void RequestWriteCallback(
+    virtual void RequestReadDescriptorCallback(
+        BluetoothGattInterface* gatt_iface,
+        int conn_id, int trans_id,
+        const bt_bdaddr_t& bda,
+        int attr_handle, int offset,
+        bool is_long);
+
+    virtual void RequestWriteCharacteristicCallback(
+        BluetoothGattInterface* gatt_iface,
+        int conn_id, int trans_id,
+        const bt_bdaddr_t& bda,
+        int attr_handle, int offset,
+        bool need_rsp, bool is_prep,
+        vector<uint8_t> value);
+
+    virtual void RequestWriteDescriptorCallback(
         BluetoothGattInterface* gatt_iface,
         int conn_id, int trans_id,
         const bt_bdaddr_t& bda,
diff --git a/service/hal/fake_bluetooth_gatt_interface.cc b/service/hal/fake_bluetooth_gatt_interface.cc
index 2e601d0..1dddb87 100644
--- a/service/hal/fake_bluetooth_gatt_interface.cc
+++ b/service/hal/fake_bluetooth_gatt_interface.cc
@@ -109,37 +109,9 @@
 }
 
 bt_status_t FakeAddService(
-    int server_if, btgatt_srvc_id_t* srvc_id, int num_handles) {
+    int server_if, vector<btgatt_db_element_t> service) {
   if (g_server_handler)
-    return g_server_handler->AddService(server_if, srvc_id, num_handles);
-
-  return BT_STATUS_FAIL;
-}
-
-bt_status_t FakeAddCharacteristic(int server_if, int srvc_handle,
-                                  bt_uuid_t *uuid,
-                                  int properties, int permissions) {
-  if (g_server_handler)
-    return g_server_handler->AddCharacteristic(server_if, srvc_handle, uuid,
-                                               properties, permissions);
-
-  return BT_STATUS_FAIL;
-}
-
-bt_status_t FakeAddDescriptor(int server_if, int srvc_handle,
-                              bt_uuid_t* uuid,
-                              int permissions) {
-  if (g_server_handler)
-    return g_server_handler->AddDescriptor(
-        server_if, srvc_handle, uuid, permissions);
-
-  return BT_STATUS_FAIL;
-}
-
-bt_status_t FakeStartService(
-    int server_if, int srvc_handle, int transport) {
-  if (g_server_handler)
-    return g_server_handler->StartService(server_if, srvc_handle, transport);
+    return g_server_handler->AddService(server_if, std::move(service));
 
   return BT_STATUS_FAIL;
 }
@@ -213,10 +185,6 @@
   nullptr,  // connect
   nullptr,  // disconnect
   FakeAddService,
-  nullptr,  // add_included_service
-  FakeAddCharacteristic,
-  FakeAddDescriptor,
-  FakeStartService,
   nullptr,  // stop_service
   FakeDeleteService,
   FakeSendIndication,
@@ -309,57 +277,48 @@
 
 void FakeBluetoothGattInterface::NotifyServiceAddedCallback(
     int status, int server_if,
-    const btgatt_srvc_id_t& srvc_id,
-    int srvc_handle) {
+    vector<btgatt_db_element_t> service) {
   FOR_EACH_OBSERVER(
       ServerObserver, server_observers_,
-      ServiceAddedCallback(this, status, server_if, srvc_id, srvc_handle));
+      ServiceAddedCallback(this, status, server_if, service));
 }
 
-void FakeBluetoothGattInterface::NotifyCharacteristicAddedCallback(
-    int status, int server_if,
-    const bt_uuid_t& uuid,
-    int srvc_handle, int char_handle) {
-  FOR_EACH_OBSERVER(
-      ServerObserver, server_observers_,
-      CharacteristicAddedCallback(
-          this, status, server_if, uuid, srvc_handle, char_handle));
-}
-
-void FakeBluetoothGattInterface::NotifyDescriptorAddedCallback(
-    int status, int server_if,
-    const bt_uuid_t& uuid,
-    int srvc_handle, int desc_handle) {
-  FOR_EACH_OBSERVER(
-      ServerObserver, server_observers_,
-      DescriptorAddedCallback(
-          this, status, server_if, uuid, srvc_handle, desc_handle));
-}
-
-void FakeBluetoothGattInterface::NotifyServiceStartedCallback(
-    int status, int server_if, int srvc_handle) {
-  FOR_EACH_OBSERVER(
-      ServerObserver, server_observers_,
-      ServiceStartedCallback(this, status, server_if, srvc_handle));
-}
-
-void FakeBluetoothGattInterface::NotifyRequestReadCallback(
+void FakeBluetoothGattInterface::NotifyRequestReadCharacteristicCallback(
     int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle,
     int offset, bool is_long) {
   FOR_EACH_OBSERVER(
       ServerObserver, server_observers_,
-      RequestReadCallback(
+      RequestReadCharacteristicCallback(
           this, conn_id, trans_id, bda, attr_handle, offset, is_long));
 }
 
-void FakeBluetoothGattInterface::NotifyRequestWriteCallback(
+void FakeBluetoothGattInterface::NotifyRequestReadDescriptorCallback(
+    int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle,
+    int offset, bool is_long) {
+  FOR_EACH_OBSERVER(
+      ServerObserver, server_observers_,
+      RequestReadDescriptorCallback(
+          this, conn_id, trans_id, bda, attr_handle, offset, is_long));
+}
+
+void FakeBluetoothGattInterface::NotifyRequestWriteCharacteristicCallback(
+    int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle,
+    int offset, bool need_rsp, bool is_prep, vector<uint8_t> value) {
+  FOR_EACH_OBSERVER(
+      ServerObserver, server_observers_,
+      RequestWriteCharacteristicCallback(
+          this, conn_id, trans_id, bda, attr_handle, offset, need_rsp,
+          is_prep, value));
+}
+
+void FakeBluetoothGattInterface::NotifyRequestWriteDescriptorCallback(
     int conn_id, int trans_id,
     const bt_bdaddr_t& bda, int attr_handle,
     int offset, bool need_rsp, bool is_prep,
     vector<uint8_t> value) {
   FOR_EACH_OBSERVER(
       ServerObserver, server_observers_,
-      RequestWriteCallback(
+      RequestWriteDescriptorCallback(
           this, conn_id, trans_id, bda, attr_handle, offset, need_rsp,
           is_prep, value));
 }
diff --git a/service/hal/fake_bluetooth_gatt_interface.h b/service/hal/fake_bluetooth_gatt_interface.h
index 8526107..2b39a97 100644
--- a/service/hal/fake_bluetooth_gatt_interface.h
+++ b/service/hal/fake_bluetooth_gatt_interface.h
@@ -64,15 +64,7 @@
     virtual bt_status_t RegisterServer(bt_uuid_t* app_uuid) = 0;
     virtual bt_status_t UnregisterServer(int server_if) = 0;
     virtual bt_status_t AddService(
-        int server_if, btgatt_srvc_id_t* srvc_id, int num_handles) = 0;
-    virtual bt_status_t AddCharacteristic(int server_if, int srvc_handle,
-                                          bt_uuid_t *uuid,
-                                          int properties, int permissions) = 0;
-    virtual bt_status_t AddDescriptor(int server_if, int srvc_handle,
-                                      bt_uuid_t* uuid,
-                                      int permissions) = 0;
-    virtual bt_status_t StartService(
-        int server_if, int srvc_handle, int transport) = 0;
+        int server_if, vector<btgatt_db_element_t> service) = 0;
     virtual bt_status_t DeleteService(int server_if, int srvc_handle) = 0;
     virtual bt_status_t SendIndication(int server_if, int attribute_handle,
                                        int conn_id, int confirm,
@@ -111,8 +103,7 @@
                                       int connected,
                                       const bt_bdaddr_t& bda);
   void NotifyServiceAddedCallback(int status, int server_if,
-                                  const btgatt_srvc_id_t& srvc_id,
-                                  int srvc_handle);
+                                  vector<btgatt_db_element_t> srvc);
   void NotifyCharacteristicAddedCallback(int status, int server_if,
                                          const bt_uuid_t& uuid,
                                          int srvc_handle, int char_handle);
@@ -120,10 +111,17 @@
                                      const bt_uuid_t& uuid,
                                      int srvc_handle, int desc_handle);
   void NotifyServiceStartedCallback(int status, int server_if, int srvc_handle);
-  void NotifyRequestReadCallback(int conn_id, int trans_id,
+  void NotifyRequestReadCharacteristicCallback(int conn_id, int trans_id,
                                  const bt_bdaddr_t& bda, int attr_handle,
                                  int offset, bool is_long);
-  void NotifyRequestWriteCallback(int conn_id, int trans_id,
+  void NotifyRequestReadDescriptorCallback(int conn_id, int trans_id,
+                                 const bt_bdaddr_t& bda, int attr_handle,
+                                 int offset, bool is_long);
+  void NotifyRequestWriteCharacteristicCallback(int conn_id, int trans_id,
+                                  const bt_bdaddr_t& bda, int attr_handle,
+                                  int offset, bool need_rsp, bool is_prep,
+                                  vector<uint8_t> value);
+  void NotifyRequestWriteDescriptorCallback(int conn_id, int trans_id,
                                   const bt_bdaddr_t& bda, int attr_handle,
                                   int offset, bool need_rsp, bool is_prep,
                                   vector<uint8_t> value);
diff --git a/service/hal/gatt_helpers.cc b/service/hal/gatt_helpers.cc
deleted file mode 100644
index b12abb7..0000000
--- a/service/hal/gatt_helpers.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-//  Copyright (C) 2015 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#include "service/hal/gatt_helpers.h"
-
-namespace bluetooth {
-namespace hal {
-
-// Populates a HAL btgatt_srvc_id_t structure from the given GattIdentifier that
-// represents a service ID.
-void GetHALServiceId(const GattIdentifier& id, btgatt_srvc_id_t* hal_id) {
-  CHECK(hal_id);
-  CHECK(id.IsService());
-
-  memset(hal_id, 0, sizeof(*hal_id));
-  hal_id->is_primary = id.is_primary();
-  hal_id->id.inst_id = id.service_instance_id();
-  hal_id->id.uuid = id.service_uuid().GetBlueDroid();
-}
-
-std::unique_ptr<GattIdentifier> GetServiceIdFromHAL(
-    const btgatt_srvc_id_t& srvc_id) {
-  UUID uuid(srvc_id.id.uuid);
-
-  return GattIdentifier::CreateServiceId(
-      "", srvc_id.id.inst_id, uuid, srvc_id.is_primary);
-}
-
-}  // namespace hal
-}  // namespace bluetooth
diff --git a/service/hal/gatt_helpers.h b/service/hal/gatt_helpers.h
deleted file mode 100644
index 490c64e..0000000
--- a/service/hal/gatt_helpers.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-//  Copyright (C) 2015 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#pragma once
-
-#include <memory>
-
-#include <hardware/bluetooth.h>
-#include <hardware/bt_gatt_types.h>
-
-#include "service/common/bluetooth/gatt_identifier.h"
-
-// Some utility functions for interacting with GATT HAL interfaces.
-
-namespace bluetooth {
-namespace hal {
-
-// Populates a HAL btgatt_srvc_id_t structure from the given GattIdentifier that
-// represents a service ID.
-void GetHALServiceId(const GattIdentifier& id, btgatt_srvc_id_t* hal_id);
-
-// Populates and returns a GattIdentifier for the given HAL btgatt_srvc_id_t
-// structure. Returns nullptr for invalid input.
-std::unique_ptr<GattIdentifier> GetServiceIdFromHAL(
-    const btgatt_srvc_id_t& srvc_id);
-
-}  // namespace hal
-}  // namespace bluetooth
diff --git a/service/ipc/binder/bluetooth_gatt_server_binder_server.cc b/service/ipc/binder/bluetooth_gatt_server_binder_server.cc
index c1078fa..228e9cb 100644
--- a/service/ipc/binder/bluetooth_gatt_server_binder_server.cc
+++ b/service/ipc/binder/bluetooth_gatt_server_binder_server.cc
@@ -62,92 +62,10 @@
   return Status::ok();
 }
 
-Status BluetoothGattServerBinderServer::BeginServiceDeclaration(
-    int server_id, bool is_primary, const android::bluetooth::UUID& uuid,
-    android::bluetooth::GattIdentifier* out_id, bool* _aidl_return) {
-  VLOG(2) << __func__;
-  CHECK(out_id);
-  std::lock_guard<std::mutex> lock(*maps_lock());
-
-  auto gatt_server = GetGattServer(server_id);
-  if (!gatt_server) {
-    LOG(ERROR) << "Unknown server_id: " << server_id;
-    *_aidl_return = false;
-    return Status::ok();
-  }
-
-  auto service_id = gatt_server->BeginServiceDeclaration(uuid, is_primary);
-  if (!service_id) {
-    LOG(ERROR) << "Failed to begin service declaration - server_id: "
-               << server_id << " UUID: " << uuid.ToString();
-    *_aidl_return = false;
-    return Status::ok();
-  }
-
-  *out_id = *service_id;
-
-  *_aidl_return = true;
-  return Status::ok();
-}
-
-Status BluetoothGattServerBinderServer::AddCharacteristic(
-    int server_id, const android::bluetooth::UUID& uuid, int properties,
-    int permissions, android::bluetooth::GattIdentifier* out_id,
+Status BluetoothGattServerBinderServer::AddService(
+    int server_id, const android::bluetooth::BluetoothGattService& service,
     bool* _aidl_return) {
   VLOG(2) << __func__;
-  CHECK(out_id);
-  std::lock_guard<std::mutex> lock(*maps_lock());
-
-  auto gatt_server = GetGattServer(server_id);
-  if (!gatt_server) {
-    LOG(ERROR) << "Unknown server_id: " << server_id;
-    *_aidl_return = false;
-    return Status::ok();
-  }
-
-  auto char_id = gatt_server->AddCharacteristic(uuid, properties, permissions);
-  if (!char_id) {
-    LOG(ERROR) << "Failed to add characteristic - server_id: " << server_id
-               << " UUID: " << uuid.ToString();
-    *_aidl_return = false;
-    return Status::ok();
-  }
-
-  *out_id = *char_id.get();
-  *_aidl_return = true;
-  return Status::ok();
-}
-
-Status BluetoothGattServerBinderServer::AddDescriptor(
-    int server_id, const android::bluetooth::UUID& uuid, int permissions,
-    android::bluetooth::GattIdentifier* out_id, bool* _aidl_return) {
-  VLOG(2) << __func__;
-  CHECK(out_id);
-  std::lock_guard<std::mutex> lock(*maps_lock());
-
-  auto gatt_server = GetGattServer(server_id);
-  if (!gatt_server) {
-    LOG(ERROR) << "Unknown server_id: " << server_id;
-    *_aidl_return = false;
-    return Status::ok();
-  }
-
-  auto desc_id = gatt_server->AddDescriptor(uuid, permissions);
-  if (!desc_id) {
-    LOG(ERROR) << "Failed to add descriptor - server_id: " << server_id
-               << " UUID: " << uuid.ToString();
-    *_aidl_return = false;
-    return Status::ok();
-  }
-
-  *out_id = *desc_id.get();
-  *_aidl_return = true;
-  return Status::ok();
-}
-
-Status BluetoothGattServerBinderServer::EndServiceDeclaration(
-    int server_id, bool* _aidl_return) {
-  VLOG(2) << __func__;
   std::lock_guard<std::mutex> lock(*maps_lock());
 
   auto gatt_server = GetGattServer(server_id);
@@ -161,7 +79,7 @@
   // use after free.
   android::wp<BluetoothGattServerBinderServer> weak_ptr_to_this(this);
   auto callback = [=](bluetooth::BLEStatus status,
-                      const bluetooth::GattIdentifier& service_id) {
+                      const bluetooth::Service& service) {
     auto sp_to_this = weak_ptr_to_this.promote();
     if (!sp_to_this.get()) {
       VLOG(2) << "BluetoothLowEnergyBinderServer was deleted";
@@ -176,11 +94,11 @@
       return;
     }
 
-    gatt_cb->OnServiceAdded(status, service_id);
+    gatt_cb->OnServiceAdded(status, service);
   };
 
-  if (!gatt_server->EndServiceDeclaration(callback)) {
-    LOG(ERROR) << "Failed to end service declaration";
+  if (!gatt_server->AddService(service, callback)) {
+    LOG(ERROR) << "Failed to add service";
     *_aidl_return = false;
     return Status::ok();
   }
@@ -210,8 +128,7 @@
 }
 
 Status BluetoothGattServerBinderServer::SendNotification(
-    int server_id, const String16& device_address,
-    const android::bluetooth::GattIdentifier& characteristic_id, bool confirm,
+    int server_id, const String16& device_address, int handle, bool confirm,
     const std::vector<uint8_t>& value, bool* _aidl_return) {
   VLOG(2) << __func__;
   std::lock_guard<std::mutex> lock(*maps_lock());
@@ -245,7 +162,7 @@
   };
 
   if (!gatt_server->SendNotification(
-          std::string(String8(device_address).string()), characteristic_id,
+          std::string(String8(device_address).string()), handle,
           confirm, value, callback)) {
     LOG(ERROR) << "Failed to send notification";
     *_aidl_return = false;
@@ -258,8 +175,7 @@
 
 void BluetoothGattServerBinderServer::OnCharacteristicReadRequest(
     bluetooth::GattServer* gatt_server, const std::string& device_address,
-    int request_id, int offset, bool is_long,
-    const bluetooth::GattIdentifier& characteristic_id) {
+    int request_id, int offset, bool is_long, uint16_t handle) {
   VLOG(2) << __func__;
   std::lock_guard<std::mutex> lock(*maps_lock());
 
@@ -271,13 +187,12 @@
 
   gatt_cb->OnCharacteristicReadRequest(
       String16(device_address.c_str(), device_address.length()), request_id,
-      offset, is_long, characteristic_id);
+      offset, is_long, handle);
 }
 
 void BluetoothGattServerBinderServer::OnDescriptorReadRequest(
     bluetooth::GattServer* gatt_server, const std::string& device_address,
-    int request_id, int offset, bool is_long,
-    const bluetooth::GattIdentifier& descriptor_id) {
+    int request_id, int offset, bool is_long, uint16_t handle) {
   VLOG(2) << __func__;
   std::lock_guard<std::mutex> lock(*maps_lock());
 
@@ -289,7 +204,7 @@
 
   gatt_cb->OnDescriptorReadRequest(
       String16(device_address.c_str(), device_address.length()), request_id,
-      offset, is_long, descriptor_id);
+      offset, is_long, handle);
 }
 
 android::sp<IBluetoothGattServerCallback>
@@ -324,8 +239,7 @@
 void BluetoothGattServerBinderServer::OnCharacteristicWriteRequest(
     bluetooth::GattServer* gatt_server, const std::string& device_address,
     int request_id, int offset, bool is_prepare_write, bool need_response,
-    const std::vector<uint8_t>& value,
-    const bluetooth::GattIdentifier& characteristic_id) {
+    const std::vector<uint8_t>& value, uint16_t handle) {
   VLOG(2) << __func__;
   std::lock_guard<std::mutex> lock(*maps_lock());
 
@@ -337,14 +251,13 @@
 
   gatt_cb->OnCharacteristicWriteRequest(
       String16(device_address.c_str(), device_address.length()), request_id,
-      offset, is_prepare_write, need_response, value, characteristic_id);
+      offset, is_prepare_write, need_response, value, handle);
 }
 
 void BluetoothGattServerBinderServer::OnDescriptorWriteRequest(
     bluetooth::GattServer* gatt_server, const std::string& device_address,
     int request_id, int offset, bool is_prepare_write, bool need_response,
-    const std::vector<uint8_t>& value,
-    const bluetooth::GattIdentifier& descriptor_id) {
+    const std::vector<uint8_t>& value, uint16_t handle) {
   VLOG(2) << __func__;
   std::lock_guard<std::mutex> lock(*maps_lock());
 
@@ -356,7 +269,7 @@
 
   gatt_cb->OnDescriptorWriteRequest(
       String16(device_address.c_str(), device_address.length()), request_id,
-      offset, is_prepare_write, need_response, value, descriptor_id);
+      offset, is_prepare_write, need_response, value, handle);
 }
 
 void BluetoothGattServerBinderServer::OnExecuteWriteRequest(
diff --git a/service/ipc/binder/bluetooth_gatt_server_binder_server.h b/service/ipc/binder/bluetooth_gatt_server_binder_server.h
index d259dbc..0d8f1d9 100644
--- a/service/ipc/binder/bluetooth_gatt_server_binder_server.h
+++ b/service/ipc/binder/bluetooth_gatt_server_binder_server.h
@@ -51,20 +51,8 @@
       bool* _aidl_return) override;
   Status UnregisterServer(int32_t server_id) override;
   Status UnregisterAll() override;
-  Status BeginServiceDeclaration(int32_t server_id, bool is_primary,
-                                 const ::android::bluetooth::UUID& uuid,
-                                 ::android::bluetooth::GattIdentifier* out_id,
-                                 bool* _aidl_return) override;
-  Status AddCharacteristic(int32_t server_id,
-                           const ::android::bluetooth::UUID& uuid,
-                           int32_t properties, int32_t permissions,
-                           ::android::bluetooth::GattIdentifier* out_id,
-                           bool* _aidl_return) override;
-  Status AddDescriptor(int32_t server_id, const ::android::bluetooth::UUID& uuid,
-                       int32_t permissions,
-                       ::android::bluetooth::GattIdentifier* out_id,
-                       bool* _aidl_return) override;
-  Status EndServiceDeclaration(int32_t server_id, bool* _aidl_return) override;
+  Status AddService(int32_t server_id, const ::android::bluetooth::BluetoothGattService& service,
+                    bool* _aidl_return) override;
   Status SendResponse(int32_t server_id,
                       const ::android::String16& device_address,
                       int32_t request_id, int32_t status, int32_t offset,
@@ -72,29 +60,24 @@
                       bool* _aidl_return) override;
   Status SendNotification(
       int32_t server_id, const ::android::String16& device_address,
-      const ::android::bluetooth::GattIdentifier& characteristic_id,
-      bool confirm, const ::std::vector<uint8_t>& value,
+      int handle, bool confirm, const ::std::vector<uint8_t>& value,
       bool* _aidl_return) override;
 
   // bluetooth::GattServer::Delegate overrides:
   void OnCharacteristicReadRequest(
       bluetooth::GattServer* gatt_server, const std::string& device_address,
-      int request_id, int offset, bool is_long,
-      const bluetooth::GattIdentifier& characteristic_id) override;
+      int request_id, int offset, bool is_long, uint16_t handle) override;
   void OnDescriptorReadRequest(
       bluetooth::GattServer* gatt_server, const std::string& device_address,
-      int request_id, int offset, bool is_long,
-      const bluetooth::GattIdentifier& descriptor_id) override;
+      int request_id, int offset, bool is_long, uint16_t handle) override;
   void OnCharacteristicWriteRequest(
       bluetooth::GattServer* gatt_server, const std::string& device_address,
       int request_id, int offset, bool is_prepare_write, bool need_response,
-      const std::vector<uint8_t>& value,
-      const bluetooth::GattIdentifier& characteristic_id) override;
+      const std::vector<uint8_t>& value, uint16_t handle) override;
   void OnDescriptorWriteRequest(
       bluetooth::GattServer* gatt_server, const std::string& device_address,
       int request_id, int offset, bool is_prepare_write, bool need_response,
-      const std::vector<uint8_t>& value,
-      const bluetooth::GattIdentifier& descriptor_id) override;
+      const std::vector<uint8_t>& value, uint16_t handle) override;
   void OnExecuteWriteRequest(bluetooth::GattServer* gatt_server,
                              const std::string& device_address, int request_id,
                              bool is_execute) override;
diff --git a/service/test/ParcelableTest.aidl b/service/test/ParcelableTest.aidl
index a931345..f71c7d6 100644
--- a/service/test/ParcelableTest.aidl
+++ b/service/test/ParcelableTest.aidl
@@ -11,7 +11,6 @@
 import android.bluetooth.BluetoothGattDescriptor;
 import android.bluetooth.BluetoothGattIncludedService;
 import android.bluetooth.BluetoothGattService;
-import android.bluetooth.GattIdentifier;
 import android.bluetooth.ScanFilter;
 import android.bluetooth.ScanResult;
 import android.bluetooth.ScanSettings;
@@ -20,7 +19,6 @@
 interface ParcelableTest {
   void OnAdvertiseData(in AdvertiseData advertise_data);
   void OnAdvertiseSettings(in AdvertiseSettings advertise_settings);
-  void OnGattIdentifier(in GattIdentifier gatt_identifier);
   void OnScanFilter(in ScanFilter scan_filter);
   void OnScanResult(in ScanResult scan_result);
   void OnScanSettings(in ScanSettings scan_settings);
diff --git a/service/test/gatt_identifier_unittest.cc b/service/test/gatt_identifier_unittest.cc
deleted file mode 100644
index 956edf9..0000000
--- a/service/test/gatt_identifier_unittest.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-//  Copyright (C) 2015 Google, Inc.
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#include <gtest/gtest.h>
-
-#include "service/common/bluetooth/gatt_identifier.h"
-#include "service/common/bluetooth/uuid.h"
-
-namespace bluetooth {
-namespace {
-
-const std::string kAddr0 = "00:01:02:03:04:05";
-const std::string kAddr1 = "06:07:08:08:0a:0b";
-
-const UUID kUUID0;
-const UUID kUUID1("180d");
-
-const int kId0 = 0;
-const int kId1 = 1;
-
-TEST(GattIdentifierTest, ServiceId) {
-  auto service0 = GattIdentifier::CreateServiceId(kAddr0, kId0, kUUID0, true);
-
-  EXPECT_TRUE(service0->IsService());
-  EXPECT_FALSE(service0->IsCharacteristic());
-  EXPECT_FALSE(service0->IsDescriptor());
-
-  EXPECT_FALSE(service0->GetOwningServiceId());
-  EXPECT_FALSE(service0->GetOwningCharacteristicId());
-
-  // Create different variants, swapping one entry at a time.
-  auto service1 = GattIdentifier::CreateServiceId(kAddr1, kId0, kUUID0, true);
-  auto service2 = GattIdentifier::CreateServiceId(kAddr0, kId1, kUUID0, true);
-  auto service3 = GattIdentifier::CreateServiceId(kAddr0, kId0, kUUID1, true);
-  auto service4 = GattIdentifier::CreateServiceId(kAddr0, kId0, kUUID0, false);
-
-  EXPECT_TRUE(*service1 != *service0);
-  EXPECT_TRUE(*service2 != *service0);
-  EXPECT_TRUE(*service3 != *service0);
-  EXPECT_TRUE(*service4 != *service0);
-
-  GattIdentifier service_copy = *service0;
-  EXPECT_TRUE(service_copy == *service0);
-}
-
-TEST(GattIdentifierTest, CharacteristicId) {
-  auto service0 = GattIdentifier::CreateServiceId(kAddr0, kId0, kUUID0, true);
-  auto char0 = GattIdentifier::CreateCharacteristicId(kId1, kUUID1, *service0);
-
-  EXPECT_FALSE(char0->IsService());
-  EXPECT_TRUE(char0->IsCharacteristic());
-  EXPECT_FALSE(char0->IsDescriptor());
-
-  EXPECT_FALSE(char0->GetOwningCharacteristicId());
-  EXPECT_TRUE(*char0->GetOwningServiceId() == *service0);
-
-  auto service1 = GattIdentifier::CreateServiceId(kAddr1, kId0, kUUID0, true);
-
-  auto char1 = GattIdentifier::CreateCharacteristicId(kId0, kUUID1, *service0);
-  auto char2 = GattIdentifier::CreateCharacteristicId(kId1, kUUID0, *service0);
-  auto char3 = GattIdentifier::CreateCharacteristicId(kId1, kUUID1, *service1);
-
-  EXPECT_TRUE(*char1 != *char0);
-  EXPECT_TRUE(*char2 != *char0);
-  EXPECT_TRUE(*char3 != *char0);
-
-  GattIdentifier char_copy = *char0;
-  EXPECT_TRUE(char_copy == *char0);
-
-  EXPECT_TRUE(*service0 != *char0);
-}
-
-TEST(GattIdentifierTest, DescriptorId) {
-  auto service0 = GattIdentifier::CreateServiceId(kAddr0, kId0, kUUID0, true);
-  auto char0 = GattIdentifier::CreateCharacteristicId(kId1, kUUID1, *service0);
-  auto desc0 = GattIdentifier::CreateDescriptorId(kId0, kUUID0, *char0);
-
-  EXPECT_FALSE(desc0->IsService());
-  EXPECT_FALSE(desc0->IsCharacteristic());
-  EXPECT_TRUE(desc0->IsDescriptor());
-
-  EXPECT_TRUE(*desc0->GetOwningCharacteristicId() == *char0);
-  EXPECT_TRUE(*desc0->GetOwningServiceId() == *service0);
-
-  auto char1 = GattIdentifier::CreateCharacteristicId(kId0, kUUID1, *service0);
-
-  auto desc1 = GattIdentifier::CreateDescriptorId(kId1, kUUID0, *char0);
-  auto desc2 = GattIdentifier::CreateDescriptorId(kId0, kUUID1, *char0);
-  auto desc3 = GattIdentifier::CreateDescriptorId(kId0, kUUID0, *char1);
-
-  EXPECT_TRUE(*desc1 != *desc0);
-  EXPECT_TRUE(*desc2 != *desc0);
-  EXPECT_TRUE(*desc3 != *desc0);
-
-  GattIdentifier desc_copy = *desc0;
-  EXPECT_TRUE(desc_copy == *desc0);
-
-  EXPECT_TRUE(*service0 != *char0);
-  EXPECT_TRUE(*service0 != *desc0);
-  EXPECT_TRUE(*char0 != *desc0);
-}
-
-}  // namespace
-}  // namespace bluetooth
diff --git a/service/test/gatt_server_unittest.cc b/service/test/gatt_server_unittest.cc
index 4063a29..68cf1a1 100644
--- a/service/test/gatt_server_unittest.cc
+++ b/service/test/gatt_server_unittest.cc
@@ -20,7 +20,6 @@
 #include "service/common/bluetooth/util/address_helper.h"
 #include "service/gatt_server.h"
 #include "service/hal/fake_bluetooth_gatt_interface.h"
-#include "service/hal/gatt_helpers.h"
 
 using ::testing::_;
 using ::testing::Return;
@@ -36,7 +35,7 @@
 
   MOCK_METHOD1(RegisterServer, bt_status_t(bt_uuid_t*));
   MOCK_METHOD1(UnregisterServer, bt_status_t(int));
-  MOCK_METHOD3(AddService, bt_status_t(int, btgatt_srvc_id_t*, int));
+  MOCK_METHOD2(AddService, bt_status_t(int, vector<btgatt_db_element_t>));
   MOCK_METHOD5(AddCharacteristic, bt_status_t(int, int, bt_uuid_t*, int, int));
   MOCK_METHOD4(AddDescriptor, bt_status_t(int, int, bt_uuid_t*, int));
   MOCK_METHOD3(StartService, bt_status_t(int, int, int));
@@ -66,7 +65,7 @@
     bool is_prep;
     bool need_rsp;
     bool is_exec;
-    GattIdentifier gatt_id;
+    uint16_t handle;
     int count;
     std::vector<uint8_t> write_value;
     bool connected;
@@ -75,28 +74,26 @@
   void OnCharacteristicReadRequest(
       GattServer* gatt_server,
       const std::string& device_address,
-      int request_id, int offset, bool is_long,
-      const bluetooth::GattIdentifier& characteristic_id) override {
+      int request_id, int offset, bool is_long, uint16_t handle) override {
     ASSERT_TRUE(gatt_server);
     char_read_req_.device_address = device_address;
     char_read_req_.id = request_id;
     char_read_req_.offset = offset;
     char_read_req_.is_long = is_long;
-    char_read_req_.gatt_id = characteristic_id;
+    char_read_req_.handle = handle;
     char_read_req_.count++;
   }
 
   void OnDescriptorReadRequest(
       GattServer* gatt_server,
       const std::string& device_address,
-      int request_id, int offset, bool is_long,
-      const bluetooth::GattIdentifier& descriptor_id) override {
+      int request_id, int offset, bool is_long, uint16_t handle) override {
     ASSERT_TRUE(gatt_server);
     desc_read_req_.device_address = device_address;
     desc_read_req_.id = request_id;
     desc_read_req_.offset = offset;
     desc_read_req_.is_long = is_long;
-    desc_read_req_.gatt_id = descriptor_id;
+    desc_read_req_.handle = handle;
     desc_read_req_.count++;
   }
 
@@ -104,15 +101,14 @@
       GattServer* gatt_server,
       const std::string& device_address,
       int request_id, int offset, bool is_prepare_write, bool need_response,
-      const std::vector<uint8_t>& value,
-      const bluetooth::GattIdentifier& characteristic_id) override {
+      const std::vector<uint8_t>& value, uint16_t handle) override {
     ASSERT_TRUE(gatt_server);
     char_write_req_.device_address = device_address;
     char_write_req_.id = request_id;
     char_write_req_.offset = offset;
     char_write_req_.is_prep = is_prepare_write;
     char_write_req_.need_rsp = need_response;
-    char_write_req_.gatt_id = characteristic_id;
+    char_write_req_.handle = handle;
     char_write_req_.count++;
     char_write_req_.write_value = value;
   }
@@ -121,15 +117,14 @@
       GattServer* gatt_server,
       const std::string& device_address,
       int request_id, int offset, bool is_prepare_write, bool need_response,
-      const std::vector<uint8_t>& value,
-      const bluetooth::GattIdentifier& descriptor_id) override {
+      const std::vector<uint8_t>& value, uint16_t handle) override {
     ASSERT_TRUE(gatt_server);
     desc_write_req_.device_address = device_address;
     desc_write_req_.id = request_id;
     desc_write_req_.offset = offset;
     desc_write_req_.is_prep = is_prepare_write;
     desc_write_req_.need_rsp = need_response;
-    desc_write_req_.gatt_id = descriptor_id;
+    desc_write_req_.handle = handle;
     desc_write_req_.count++;
     desc_write_req_.write_value = value;
   }
@@ -242,16 +237,7 @@
   }
 
   void SetUpTestService() {
-    EXPECT_CALL(*mock_handler_, AddService(_, _, _))
-        .Times(1)
-        .WillOnce(Return(BT_STATUS_SUCCESS));
-    EXPECT_CALL(*mock_handler_, AddCharacteristic(_, _, _, _, _))
-        .Times(1)
-        .WillOnce(Return(BT_STATUS_SUCCESS));
-    EXPECT_CALL(*mock_handler_, AddDescriptor(_, _, _, _))
-        .Times(1)
-        .WillOnce(Return(BT_STATUS_SUCCESS));
-    EXPECT_CALL(*mock_handler_, StartService(_, _, _))
+    EXPECT_CALL(*mock_handler_, AddService(_, _))
         .Times(1)
         .WillOnce(Return(BT_STATUS_SUCCESS));
 
@@ -261,37 +247,28 @@
 
     bool register_success = false;
 
-    // Doesn't matter what the permissions/properties are since this is all
-    // fake.
-    test_service_id_ = *gatt_server_->BeginServiceDeclaration(uuid0, true);
-    test_char_id_ = *gatt_server_->AddCharacteristic(uuid1, 0, 0);
-    test_desc_id_ = *gatt_server_->AddDescriptor(uuid2, 0);
-    ASSERT_TRUE(gatt_server_->EndServiceDeclaration([&](
-        BLEStatus status, const GattIdentifier& gatt_id) {
+    Service service(0, true, uuid0, {}, {} );
+
+    ASSERT_TRUE(gatt_server_->AddService(service, [&](
+        BLEStatus status, const Service& added_service) {
       ASSERT_EQ(BLE_STATUS_SUCCESS, status);
-      ASSERT_TRUE(gatt_id == test_service_id_);
+      ASSERT_TRUE(UUID(added_service.uuid()) == UUID(service.uuid()));
+      ASSERT_TRUE(added_service.handle() == 0x0001);
       register_success = true;
     }));
 
-    btgatt_srvc_id_t hal_srvc_id;
-    hal::GetHALServiceId(test_service_id_, &hal_srvc_id);
-    bt_uuid_t hal_uuid1 = uuid1.GetBlueDroid();
-    bt_uuid_t hal_uuid2 = uuid2.GetBlueDroid();
-
     srvc_handle_ = 0x0001;
-    char_handle_ = 0x0003;
+    char_handle_ = 0x0002;
     desc_handle_ = 0x0004;
 
+    vector<btgatt_db_element_t> service_with_handles = {
+      {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = uuid0.GetBlueDroid(), .attribute_handle = srvc_handle_},
+      {.type = BTGATT_DB_CHARACTERISTIC, .uuid = uuid1.GetBlueDroid(), .attribute_handle = char_handle_},
+      {.type = BTGATT_DB_DESCRIPTOR, .uuid = uuid2.GetBlueDroid(), .attribute_handle = desc_handle_},
+    };
+
     fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-        BT_STATUS_SUCCESS, kDefaultServerId, hal_srvc_id, srvc_handle_);
-    fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-        BT_STATUS_SUCCESS, kDefaultServerId, hal_uuid1,
-        srvc_handle_, char_handle_);
-    fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-        BT_STATUS_SUCCESS, kDefaultServerId, hal_uuid2,
-        srvc_handle_, desc_handle_);
-    fake_hal_gatt_iface_->NotifyServiceStartedCallback(
-        BT_STATUS_SUCCESS, kDefaultServerId, srvc_handle_);
+        BT_STATUS_SUCCESS, kDefaultServerId, service_with_handles);
 
     testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
 
@@ -301,12 +278,9 @@
  protected:
   std::unique_ptr<GattServer> gatt_server_;
 
-  GattIdentifier test_service_id_;
-  GattIdentifier test_char_id_;
-  GattIdentifier test_desc_id_;
-  int srvc_handle_;
-  int char_handle_;
-  int desc_handle_;
+  uint16_t srvc_handle_;
+  uint16_t char_handle_;
+  uint16_t desc_handle_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(GattServerPostRegisterTest);
@@ -396,563 +370,6 @@
   EXPECT_EQ(uuid1, cb_uuid);
 }
 
-TEST_F(GattServerPostRegisterTest, SimpleServiceTest) {
-  // Setup a service callback.
-  GattIdentifier cb_id;
-  BLEStatus cb_status = BLE_STATUS_SUCCESS;
-  int cb_count = 0;
-  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
-    cb_id = in_id;
-    cb_status = in_status;
-    cb_count++;
-  };
-
-  // Service declaration not started.
-  EXPECT_FALSE(gatt_server_->EndServiceDeclaration(callback));
-
-  const UUID uuid = UUID::GetRandom();
-  auto service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
-  EXPECT_TRUE(service_id != nullptr);
-  EXPECT_TRUE(service_id->IsService());
-
-  // Already started.
-  EXPECT_FALSE(gatt_server_->BeginServiceDeclaration(uuid, false));
-
-  // Callback is NULL.
-  EXPECT_FALSE(
-      gatt_server_->EndServiceDeclaration(GattServer::ResultCallback()));
-
-  // We should get a call for a service with one handle.
-  EXPECT_CALL(*mock_handler_, AddService(gatt_server_->GetInstanceId(), _, 1))
-      .Times(2)
-      .WillOnce(Return(BT_STATUS_FAIL))
-      .WillOnce(Return(BT_STATUS_SUCCESS));
-
-  // Stack returns failure. This will cause the entire service declaration to
-  // end and needs to be restarted.
-  EXPECT_FALSE(gatt_server_->EndServiceDeclaration(callback));
-
-  service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
-  EXPECT_TRUE(service_id != nullptr);
-  EXPECT_TRUE(service_id->IsService());
-
-  // Stack returns success.
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  // EndServiceDeclaration already in progress.
-  EXPECT_FALSE(gatt_server_->EndServiceDeclaration(callback));
-
-  EXPECT_EQ(0, cb_count);
-
-  btgatt_srvc_id_t hal_id;
-  hal::GetHALServiceId(*service_id, &hal_id);
-  int srvc_handle = 0x0001;
-
-  // Report success for AddService but for wrong server. Should be ignored.
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId + 1, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-
-  // Report success for AddService.
-  EXPECT_CALL(*mock_handler_, StartService(kDefaultServerId, srvc_handle, _))
-      .Times(1)
-      .WillOnce(Return(BT_STATUS_SUCCESS));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-
-  // Report success for StartService but for wrong server. Should be ignored.
-  fake_hal_gatt_iface_->NotifyServiceStartedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId + 1, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-
-  // Report success for StartService.
-  fake_hal_gatt_iface_->NotifyServiceStartedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, srvc_handle);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_EQ(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Start new service declaration with same UUID. We should get a different ID.
-  auto service_id1 = gatt_server_->BeginServiceDeclaration(uuid, true);
-  EXPECT_TRUE(service_id1 != nullptr);
-  EXPECT_TRUE(service_id1->IsService());
-  EXPECT_TRUE(*service_id != *service_id1);
-}
-
-TEST_F(GattServerPostRegisterTest, AddServiceFailures) {
-  // Setup a service callback.
-  GattIdentifier cb_id;
-  BLEStatus cb_status = BLE_STATUS_SUCCESS;
-  int cb_count = 0;
-  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
-    cb_id = in_id;
-    cb_status = in_status;
-    cb_count++;
-  };
-
-  const UUID uuid = UUID::GetRandom();
-  auto service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
-  btgatt_srvc_id_t hal_id;
-  hal::GetHALServiceId(*service_id, &hal_id);
-  int srvc_handle = 0x0001;
-
-  EXPECT_CALL(*mock_handler_, AddService(gatt_server_->GetInstanceId(), _, 1))
-      .Times(3)
-      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  // Report failure for AddService.
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_FAIL, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart. We should get the same ID back.
-  auto service_id1 = gatt_server_->BeginServiceDeclaration(uuid, true);
-  EXPECT_TRUE(*service_id1 == *service_id);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  // Report success for AddService but return failure from StartService.
-  EXPECT_CALL(*mock_handler_, StartService(gatt_server_->GetInstanceId(), 1, _))
-      .Times(2)
-      .WillOnce(Return(BT_STATUS_FAIL))
-      .WillOnce(Return(BT_STATUS_SUCCESS));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(2, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart.
-  service_id = gatt_server_->BeginServiceDeclaration(uuid, true);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  // Report success for AddService, return success from StartService.
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(2, cb_count);
-
-  // Report failure for StartService. Added service data should get deleted.
-  EXPECT_CALL(*mock_handler_,
-              DeleteService(gatt_server_->GetInstanceId(), srvc_handle))
-      .Times(1)
-      .WillOnce(Return(BT_STATUS_SUCCESS));
-  fake_hal_gatt_iface_->NotifyServiceStartedCallback(
-      BT_STATUS_FAIL, kDefaultServerId, srvc_handle);
-  EXPECT_EQ(3, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-}
-
-TEST_F(GattServerPostRegisterTest, AddCharacteristic) {
-  // Just pick some values.
-  const int props = bluetooth::kCharacteristicPropertyRead |
-      bluetooth::kCharacteristicPropertyNotify;
-  const int perms = kAttributePermissionReadEncrypted;
-  const UUID char_uuid = UUID::GetRandom();
-  bt_uuid_t hal_char_uuid = char_uuid.GetBlueDroid();
-
-  // Declaration not started.
-  EXPECT_EQ(nullptr, gatt_server_->AddCharacteristic(char_uuid, props, perms));
-
-  // Start a service declaration.
-  const UUID service_uuid = UUID::GetRandom();
-  auto service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  EXPECT_TRUE(service_id != nullptr);
-  btgatt_srvc_id_t hal_id;
-  hal::GetHALServiceId(*service_id, &hal_id);
-
-  // Add two characteristics with the same UUID.
-  auto char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  auto char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-
-  EXPECT_TRUE(char_id0 != nullptr);
-  EXPECT_TRUE(char_id1 != nullptr);
-  EXPECT_TRUE(char_id0 != char_id1);
-  EXPECT_TRUE(char_id0->IsCharacteristic());
-  EXPECT_TRUE(char_id1->IsCharacteristic());
-  EXPECT_TRUE(*char_id0->GetOwningServiceId() == *service_id);
-  EXPECT_TRUE(*char_id1->GetOwningServiceId() == *service_id);
-
-  // Expect calls for 5 handles in total as we have 2 characteristics.
-  EXPECT_CALL(*mock_handler_, AddService(kDefaultServerId, _, 5))
-      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
-
-  GattIdentifier cb_id;
-  BLEStatus cb_status;
-  int cb_count = 0;
-  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
-    cb_id = in_id;
-    cb_status = in_status;
-    cb_count++;
-  };
-
-  int srvc_handle = 0x0001;
-  int char_handle0 = 0x0002;
-  int char_handle1 = 0x0004;
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  // Cannot add any more characteristics while EndServiceDeclaration is in
-  // progress.
-  EXPECT_EQ(nullptr, gatt_server_->AddCharacteristic(char_uuid, props, perms));
-
-  EXPECT_CALL(*mock_handler_, AddCharacteristic(_, _, _, _, _))
-      .Times(8)
-      .WillOnce(Return(BT_STATUS_FAIL))      // char_id0 - try 1
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 2
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 3
-      .WillOnce(Return(BT_STATUS_FAIL))      // char_id1 - try 3
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 4
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id1 - try 4
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // char_id0 - try 5
-      .WillOnce(Return(BT_STATUS_SUCCESS));  // char_id1 - try 5
-
-  // First AddCharacteristic call will fail.
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart. (try 2)
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(1, cb_count);
-
-  // Report failure for pending AddCharacteristic.
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_FAIL, kDefaultServerId, hal_char_uuid,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(2, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart. (try 3)
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(2, cb_count);
-
-  // Report success for pending AddCharacteristic we should receive a call for
-  // the second characteristic which will fail.
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(3, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart. (try 4)
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(3, cb_count);
-
-  // Report success for pending AddCharacteristic. Second characteristic call
-  // will start normally. We shouldn't receive any new callback.
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(3, cb_count);
-
-  // Report failure for pending AddCharacteristic call for second
-  // characteristic.
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_FAIL, kDefaultServerId, hal_char_uuid,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(4, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart. (try 5)
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid, props, perms);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(4, cb_count);
-
-  // Report success for pending AddCharacteristic. Second characteristic call
-  // will start normally. We shouldn't receive any new callback.
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(4, cb_count);
-
-  // Report success for pending AddCharacteristic call for second
-  // characteristic. We shouldn't receive any new callback but we'll get a call
-  // to StartService.
-  EXPECT_CALL(*mock_handler_, StartService(kDefaultServerId, srvc_handle, _))
-      .Times(1)
-      .WillOnce(Return(BT_STATUS_SUCCESS));
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(4, cb_count);
-}
-
-TEST_F(GattServerPostRegisterTest, AddDescriptor) {
-  // Set up some values for UUIDs, permissions, and properties.
-  const UUID service_uuid = UUID::GetRandom();
-  const UUID char_uuid0 = UUID::GetRandom();
-  const UUID char_uuid1 = UUID::GetRandom();
-  const UUID desc_uuid = UUID::GetRandom();
-  bt_uuid_t hal_char_uuid0 = char_uuid0.GetBlueDroid();
-  bt_uuid_t hal_char_uuid1 = char_uuid1.GetBlueDroid();
-  bt_uuid_t hal_desc_uuid = desc_uuid.GetBlueDroid();
-  const int props = bluetooth::kCharacteristicPropertyRead |
-      bluetooth::kCharacteristicPropertyNotify;
-  const int perms = kAttributePermissionReadEncrypted;
-
-  // Service declaration not started.
-  EXPECT_EQ(nullptr, gatt_server_->AddDescriptor(desc_uuid, perms));
-
-  // Start a service declaration.
-  auto service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  btgatt_srvc_id_t hal_id;
-  hal::GetHALServiceId(*service_id, &hal_id);
-
-  // No characteristic was inserted.
-  EXPECT_EQ(nullptr, gatt_server_->AddDescriptor(desc_uuid, perms));
-
-  // Add two characeristics.
-  auto char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
-  auto char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
-
-  // Add a descriptor.
-  auto desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
-  EXPECT_NE(nullptr, desc_id);
-  EXPECT_TRUE(desc_id->IsDescriptor());
-  EXPECT_TRUE(*desc_id->GetOwningCharacteristicId() == *char_id1);
-  EXPECT_TRUE(*desc_id->GetOwningServiceId() == *service_id);
-
-  // Add a second descriptor with the same UUID.
-  auto desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
-  EXPECT_NE(nullptr, desc_id1);
-  EXPECT_TRUE(*desc_id1 != *desc_id);
-  EXPECT_TRUE(desc_id1->IsDescriptor());
-  EXPECT_TRUE(*desc_id1->GetOwningCharacteristicId() == *char_id1);
-  EXPECT_TRUE(*desc_id1->GetOwningServiceId() == *service_id);
-
-  // Expect calls for 7 handles.
-  EXPECT_CALL(*mock_handler_, AddService(kDefaultServerId, _, 7))
-      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
-  EXPECT_CALL(*mock_handler_, AddCharacteristic(_, _, _, _, _))
-      .WillRepeatedly(Return(BT_STATUS_SUCCESS));
-
-  GattIdentifier cb_id;
-  BLEStatus cb_status;
-  int cb_count = 0;
-  auto callback = [&](BLEStatus in_status, const GattIdentifier& in_id) {
-    cb_id = in_id;
-    cb_status = in_status;
-    cb_count++;
-  };
-
-  int srvc_handle = 0x0001;
-  int char_handle0 = 0x0002;
-  int char_handle1 = 0x0004;
-  int desc_handle0 = 0x0005;
-  int desc_handle1 = 0x0006;
-
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  // Cannot add any more descriptors while EndServiceDeclaration is in progress.
-  EXPECT_EQ(nullptr, gatt_server_->AddDescriptor(desc_uuid, perms));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-
-  EXPECT_CALL(*mock_handler_, AddDescriptor(_, _, _, _))
-      .Times(8)
-      .WillOnce(Return(BT_STATUS_FAIL))      // desc_id0 - try 1
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 2
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 3
-      .WillOnce(Return(BT_STATUS_FAIL))      // desc_id1 - try 3
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 4
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id1 - try 4
-      .WillOnce(Return(BT_STATUS_SUCCESS))   // desc_id0 - try 5
-      .WillOnce(Return(BT_STATUS_SUCCESS));  // desc_id1 - try 5
-
-  // Notify success for both characteristics. First descriptor call will fail.
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart (try 2)
-  cb_count = 0;
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
-  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id);
-  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id1);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(0, cb_count);
-
-  // Notify failure for first descriptor.
-  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-      BT_STATUS_FAIL, kDefaultServerId, hal_desc_uuid,
-      srvc_handle, desc_handle0);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart (try 3)
-  cb_count = 0;
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
-  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id);
-  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id1);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(0, cb_count);
-
-  // Notify success for first descriptor; the second descriptor will fail
-  // immediately.
-  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
-      srvc_handle, desc_handle0);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart (try 4)
-  cb_count = 0;
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
-  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id);
-  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id1);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(0, cb_count);
-
-  // Notify success for first first descriptor and failure for second
-  // descriptor.
-  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
-      srvc_handle, desc_handle0);
-  EXPECT_EQ(0, cb_count);
-
-  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-      BT_STATUS_FAIL, kDefaultServerId, hal_desc_uuid,
-      srvc_handle, desc_handle1);
-  EXPECT_EQ(1, cb_count);
-  EXPECT_NE(BLE_STATUS_SUCCESS, cb_status);
-  EXPECT_TRUE(cb_id == *service_id);
-
-  // Restart (try 5)
-  cb_count = 0;
-  service_id = gatt_server_->BeginServiceDeclaration(service_uuid, true);
-  hal::GetHALServiceId(*service_id, &hal_id);
-  char_id0 = gatt_server_->AddCharacteristic(char_uuid0, props, perms);
-  char_id1 = gatt_server_->AddCharacteristic(char_uuid1, props, perms);
-  desc_id = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id);
-  desc_id1 = gatt_server_->AddDescriptor(desc_uuid, perms);
-  ASSERT_NE(nullptr, desc_id1);
-  EXPECT_TRUE(gatt_server_->EndServiceDeclaration(callback));
-
-  fake_hal_gatt_iface_->NotifyServiceAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_id, srvc_handle);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid0,
-      srvc_handle, char_handle0);
-  EXPECT_EQ(0, cb_count);
-  fake_hal_gatt_iface_->NotifyCharacteristicAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_char_uuid1,
-      srvc_handle, char_handle1);
-  EXPECT_EQ(0, cb_count);
-
-  // Notify success for both descriptors.
-  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
-      srvc_handle, desc_handle0);
-  EXPECT_EQ(0, cb_count);
-
-  // The second descriptor callback should trigger the end routine.
-  EXPECT_CALL(*mock_handler_, StartService(kDefaultServerId, srvc_handle, _))
-      .Times(1)
-      .WillOnce(Return(BT_STATUS_SUCCESS));
-  fake_hal_gatt_iface_->NotifyDescriptorAddedCallback(
-      BT_STATUS_SUCCESS, kDefaultServerId, hal_desc_uuid,
-      srvc_handle, desc_handle1);
-  EXPECT_EQ(0, cb_count);
-}
-
 TEST_F(GattServerPostRegisterTest, RequestRead) {
   SetUpTestService();
 
@@ -983,35 +400,29 @@
       kConnId0, kDefaultServerId, true, hal_addr0);
 
   // Unknown connection ID shouldn't trigger anything.
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
+  fake_hal_gatt_iface_->NotifyRequestReadCharacteristicCallback(
       kConnId0 + 1, kReqId0, hal_addr0, char_handle_, 0, false);
   EXPECT_EQ(0, test_delegate.char_read_req().count);
   EXPECT_EQ(0, test_delegate.desc_read_req().count);
 
   // Unknown device address shouldn't trigger anything.
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
+  fake_hal_gatt_iface_->NotifyRequestReadCharacteristicCallback(
       kConnId0, kReqId0, hal_addr1, char_handle_, 0, false);
   EXPECT_EQ(0, test_delegate.char_read_req().count);
   EXPECT_EQ(0, test_delegate.desc_read_req().count);
 
-  // Unknown attribute handle shouldn't trigger anything.
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
-      kConnId0, kReqId0, hal_addr0, char_handle_ + 50, 0, false);
-  EXPECT_EQ(0, test_delegate.char_read_req().count);
-  EXPECT_EQ(0, test_delegate.desc_read_req().count);
-
   // Characteristic and descriptor handles should trigger correct callbacks.
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
+  fake_hal_gatt_iface_->NotifyRequestReadCharacteristicCallback(
       kConnId0, kReqId0, hal_addr0, char_handle_, 0, false);
   EXPECT_EQ(1, test_delegate.char_read_req().count);
   EXPECT_EQ(kTestAddress0, test_delegate.char_read_req().device_address);
   EXPECT_EQ(kReqId0, test_delegate.char_read_req().id);
   EXPECT_EQ(0, test_delegate.char_read_req().offset);
   EXPECT_FALSE(test_delegate.char_read_req().is_long);
-  EXPECT_TRUE(test_char_id_ == test_delegate.char_read_req().gatt_id);
+  EXPECT_TRUE(char_handle_ == test_delegate.char_read_req().handle);
   EXPECT_EQ(0, test_delegate.desc_read_req().count);
 
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
+  fake_hal_gatt_iface_->NotifyRequestReadDescriptorCallback(
       kConnId0, kReqId1, hal_addr0, desc_handle_, 2, true);
   EXPECT_EQ(1, test_delegate.char_read_req().count);
   EXPECT_EQ(1, test_delegate.desc_read_req().count);
@@ -1019,12 +430,12 @@
   EXPECT_EQ(kReqId1, test_delegate.desc_read_req().id);
   EXPECT_EQ(2, test_delegate.desc_read_req().offset);
   EXPECT_TRUE(test_delegate.desc_read_req().is_long);
-  EXPECT_TRUE(test_desc_id_ == test_delegate.desc_read_req().gatt_id);
+  EXPECT_TRUE(desc_handle_ == test_delegate.desc_read_req().handle);
 
   // Callback with a pending request ID will be ignored.
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
+  fake_hal_gatt_iface_->NotifyRequestReadCharacteristicCallback(
       kConnId0, kReqId0, hal_addr0, char_handle_, 0, false);
-  fake_hal_gatt_iface_->NotifyRequestReadCallback(
+  fake_hal_gatt_iface_->NotifyRequestReadCharacteristicCallback(
       kConnId0, kReqId1, hal_addr0, char_handle_, 0, false);
   EXPECT_EQ(1, test_delegate.char_read_req().count);
   EXPECT_EQ(1, test_delegate.desc_read_req().count);
@@ -1107,28 +518,21 @@
       kConnId0, kDefaultServerId, true, hal_addr0);
 
   // Unknown connection ID shouldn't trigger anything.
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteCharacteristicCallback(
       kConnId0 + 1, kReqId0, hal_addr0, char_handle_, 0,
       true, false, kTestValue);
   EXPECT_EQ(0, test_delegate.char_write_req().count);
   EXPECT_EQ(0, test_delegate.desc_write_req().count);
 
   // Unknown device address shouldn't trigger anything.
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteCharacteristicCallback(
       kConnId0, kReqId0, hal_addr1, char_handle_, 0,
       true, false, kTestValue);
   EXPECT_EQ(0, test_delegate.char_write_req().count);
   EXPECT_EQ(0, test_delegate.desc_write_req().count);
 
-  // Unknown attribute handle shouldn't trigger anything.
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
-      kConnId0, kReqId0, hal_addr0, char_handle_ + 50, 0,
-      true, false, kTestValue);
-  EXPECT_EQ(0, test_delegate.char_write_req().count);
-  EXPECT_EQ(0, test_delegate.desc_write_req().count);
-
   // Characteristic and descriptor handles should trigger correct callbacks.
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteCharacteristicCallback(
       kConnId0, kReqId0, hal_addr0, char_handle_, 0,
       true, false, kTestValue);
   EXPECT_EQ(1, test_delegate.char_write_req().count);
@@ -1138,10 +542,10 @@
   EXPECT_EQ(true, test_delegate.char_write_req().need_rsp);
   EXPECT_EQ(false, test_delegate.char_write_req().is_exec);
   EXPECT_EQ(kTestValue, test_delegate.char_write_req().write_value);
-  EXPECT_TRUE(test_char_id_ == test_delegate.char_write_req().gatt_id);
+  EXPECT_TRUE(char_handle_ == test_delegate.char_write_req().handle);
   EXPECT_EQ(0, test_delegate.desc_write_req().count);
 
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteDescriptorCallback(
       kConnId0, kReqId1, hal_addr0, desc_handle_, 2,
       true, false, kTestValue);
   EXPECT_EQ(1, test_delegate.char_write_req().count);
@@ -1152,13 +556,13 @@
   EXPECT_EQ(true, test_delegate.desc_write_req().need_rsp);
   EXPECT_EQ(false, test_delegate.desc_write_req().is_exec);
   EXPECT_EQ(kTestValue, test_delegate.desc_write_req().write_value);
-  EXPECT_TRUE(test_desc_id_ == test_delegate.desc_write_req().gatt_id);
+  EXPECT_TRUE(desc_handle_ == test_delegate.desc_write_req().handle);
 
   // Callback with a pending request ID will be ignored.
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteCharacteristicCallback(
       kConnId0, kReqId0, hal_addr0, char_handle_, 0,
       true, false, kTestValue);
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteCharacteristicCallback(
       kConnId0, kReqId1, hal_addr0, char_handle_, 0,
       true, false, kTestValue);
   EXPECT_EQ(1, test_delegate.char_write_req().count);
@@ -1206,7 +610,7 @@
       GATT_ERROR_NONE, 0, kTestValue));
 
   // SendResponse should fail for a "Write Without Response".
-  fake_hal_gatt_iface_->NotifyRequestWriteCallback(
+  fake_hal_gatt_iface_->NotifyRequestWriteCharacteristicCallback(
       kConnId0, kReqId0, hal_addr0, char_handle_, 0,
       false, false, kTestValue);
   EXPECT_EQ(false, test_delegate.char_write_req().need_rsp);
@@ -1246,12 +650,12 @@
   // Bad device address.
   EXPECT_FALSE(gatt_server_->SendNotification(
       kInvalidAddress,
-      test_char_id_, false, value, callback));
+      char_handle_, false, value, callback));
 
   // Bad connection.
   EXPECT_FALSE(gatt_server_->SendNotification(
       kTestAddress1,
-      test_char_id_, false, value, callback));
+      char_handle_, false, value, callback));
 
   // We should get a HAL call for each connection for this address. The calls
   // fail.
@@ -1267,7 +671,7 @@
       .WillOnce(Return(BT_STATUS_FAIL));
   EXPECT_FALSE(gatt_server_->SendNotification(
       kTestAddress0,
-      test_char_id_, false, value, callback));
+      char_handle_, false, value, callback));
 
   // One of the calls succeeds.
   EXPECT_CALL(*mock_handler_,
@@ -1282,7 +686,7 @@
       .WillOnce(Return(BT_STATUS_FAIL));
   EXPECT_TRUE(gatt_server_->SendNotification(
       kTestAddress0,
-      test_char_id_, false, value, callback));
+      char_handle_, false, value, callback));
 
   // One of the connections is already pending so there should be only one call.
   // This one we send with confirm=true.
@@ -1293,11 +697,11 @@
       .WillOnce(Return(BT_STATUS_SUCCESS));
   EXPECT_TRUE(gatt_server_->SendNotification(
       kTestAddress0,
-      test_char_id_, true, value, callback));
+      char_handle_, true, value, callback));
 
   // Calls are already pending.
   EXPECT_FALSE(gatt_server_->SendNotification(
-      kTestAddress0, test_char_id_, true, value, callback));
+      kTestAddress0, char_handle_, true, value, callback));
 
   // Trigger one confirmation callback. We should get calls for two callbacks
   // since we have two separate calls pending.
@@ -1323,7 +727,7 @@
       .WillOnce(Return(BT_STATUS_SUCCESS));
   EXPECT_TRUE(gatt_server_->SendNotification(
       kTestAddress0,
-      test_char_id_, false, value, callback));
+      char_handle_, false, value, callback));
 
   // Trigger one confirmation callback. The callback we passed should still be
   // pending. The first callback is for the wrong connection ID.
diff --git a/service/test/parcelable_unittest.cc b/service/test/parcelable_unittest.cc
index c12bcaf..0f44f96 100644
--- a/service/test/parcelable_unittest.cc
+++ b/service/test/parcelable_unittest.cc
@@ -18,7 +18,6 @@
 
 #include "service/common/android/bluetooth/advertise_data.h"
 #include "service/common/android/bluetooth/advertise_settings.h"
-#include "service/common/android/bluetooth/gatt_identifier.h"
 #include "service/common/android/bluetooth/bluetooth_gatt_characteristic.h"
 #include "service/common/android/bluetooth/bluetooth_gatt_descriptor.h"
 #include "service/common/android/bluetooth/bluetooth_gatt_service.h"
@@ -32,7 +31,6 @@
 
 using bluetooth::AdvertiseData;
 using bluetooth::AdvertiseSettings;
-using bluetooth::GattIdentifier;
 using bluetooth::Characteristic;
 using bluetooth::Descriptor;
 using bluetooth::ScanFilter;
@@ -103,27 +101,6 @@
   }
 }
 
-TEST(ParcelableTest, GattIdentifier) {
-  UUID uuid0 = UUID::GetRandom();
-  UUID uuid1 = UUID::GetRandom();
-  UUID uuid2 = UUID::GetRandom();
-
-  auto service_id =
-      GattIdentifier::CreateServiceId("01:23:45:67:89:ab", 5, uuid0, false);
-  auto char_id = GattIdentifier::CreateCharacteristicId(3, uuid1, *service_id);
-  auto desc_id = GattIdentifier::CreateDescriptorId(10, uuid2, *char_id);
-
-  bool result =
-      TestData<GattIdentifier, android::bluetooth::GattIdentifier>(*service_id);
-  EXPECT_TRUE(result);
-  result =
-      TestData<GattIdentifier, android::bluetooth::GattIdentifier>(*char_id);
-  EXPECT_TRUE(result);
-  result =
-      TestData<GattIdentifier, android::bluetooth::GattIdentifier>(*desc_id);
-  EXPECT_TRUE(result);
-}
-
 TEST(ParcelableTest, ScanSettings) {
   ScanSettings settings0;
   ScanSettings settings1(
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index d92665a..5dc6f2d 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -28,6 +28,7 @@
 #include "gatt_int.h"
 #include "btm_int.h"
 #include "hcimsgs.h"
+#include "btcore/include/uuid.h"
 
 #define GAP_CHAR_ICON_SIZE          2
 #define GAP_CHAR_DEV_NAME_SIZE      248
@@ -338,11 +339,13 @@
 
     switch (type)
     {
-        case GATTS_REQ_TYPE_READ:
+        case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_READ_DESCRIPTOR:
             status = gap_proc_read(type, &p_data->read_req, &rsp_msg);
             break;
 
-        case GATTS_REQ_TYPE_WRITE:
+        case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
             if (!p_data->write_req.need_rsp)
                 ignore = TRUE;
 
@@ -380,10 +383,7 @@
 void gap_attr_db_init(void)
 {
     tBT_UUID        app_uuid = {LEN_UUID_128,{0}};
-    tBT_UUID        uuid     = {LEN_UUID_16,{UUID_SERVCLASS_GAP_SERVER}};
     UINT16          service_handle;
-    tGAP_ATTR       *p_db_attr = &gap_cb.gatt_attr[0];
-    tGATT_STATUS    status;
 
     /* Fill our internal UUID with a fixed pattern 0x82 */
     memset (&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
@@ -393,60 +393,48 @@
 
     GATT_StartIf(gap_cb.gatt_if);
 
-    /* Create a GAP service */
-    service_handle = GATTS_CreateService (gap_cb.gatt_if, &uuid, 0, GAP_MAX_ATTR_NUM, TRUE);
+    bt_uuid_t svc_uuid, name_uuid, icon_uuid, pref_uuid, addr_res_uuid;
+    uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_GAP_SERVER);
+    uuid_128_from_16(&name_uuid, GATT_UUID_GAP_DEVICE_NAME);
+    uuid_128_from_16(&icon_uuid, GATT_UUID_GAP_ICON);
+    uuid_128_from_16(&pref_uuid, GATT_UUID_GAP_PREF_CONN_PARAM);
+    uuid_128_from_16(&addr_res_uuid, GATT_UUID_GAP_CENTRAL_ADDR_RESOL);
 
-    GAP_TRACE_EVENT ("gap_attr_db_init service_handle = %d", service_handle);
-
-    /* add Device Name Characteristic
-    */
-    uuid.len = LEN_UUID_16;
-    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
-    p_db_attr ++;
-
-    /* add Icon characteristic
-    */
-    uuid.uu.uuid16   = p_db_attr->uuid = GATT_UUID_GAP_ICON;
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
-                                                &uuid,
-                                                GATT_PERM_READ,
-                                                GATT_CHAR_PROP_BIT_READ);
-    p_db_attr ++;
-
+    btgatt_db_element_t service[] = {
+        {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = svc_uuid},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = name_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = icon_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = addr_res_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ}
 #if BTM_PERIPHERAL_ENABLED == TRUE       /* Only needed for peripheral testing */
-    /* add preferred connection parameter characteristic
-    */
-    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
-    p_db_attr->attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
-    p_db_attr->attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
-    p_db_attr->attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
-    p_db_attr->attr_value.conn_param.sp_tout = GAP_PREFER_CONN_SP_TOUT; /* 2000 */
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
-                                                &uuid,
-                                                GATT_PERM_READ,
-                                                GATT_CHAR_PROP_BIT_READ);
-    p_db_attr ++;
+        ,{.type = BTGATT_DB_CHARACTERISTIC, .uuid = pref_uuid, .properties = GATT_CHAR_PROP_BIT_READ, .permissions = GATT_PERM_READ}
 #endif
+    };
 
-    /* add Central address resolution Characteristic */
-    uuid.len = LEN_UUID_16;
-    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
-    p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
-                                                GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
-    p_db_attr->attr_value.addr_resolution = 0;
-    p_db_attr++;
+    /* Add a GAP service */
+    GATTS_AddService(gap_cb.gatt_if, service, sizeof(service)/sizeof(btgatt_db_element_t));
+    service_handle = service[0].attribute_handle;
 
-    /* start service now */
-    memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
+    GAP_TRACE_EVENT("%s: service_handle = %d",__func__, service_handle);
 
-    status = GATTS_StartService(gap_cb.gatt_if, service_handle, GAP_TRANSPORT_SUPPORTED );
+    gap_cb.gatt_attr[0].uuid = GATT_UUID_GAP_DEVICE_NAME;
+    gap_cb.gatt_attr[0].handle = service[1].attribute_handle;
 
-    GAP_TRACE_EVENT ("GAP App gatt_if: %d  s_hdl = %d start_status=%d",
-                      gap_cb.gatt_if, service_handle, status);
+    gap_cb.gatt_attr[1].uuid = GATT_UUID_GAP_ICON;
+    gap_cb.gatt_attr[1].handle = service[2].attribute_handle;
 
+    gap_cb.gatt_attr[2].uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
+    gap_cb.gatt_attr[2].handle = service[3].attribute_handle;
+    gap_cb.gatt_attr[2].attr_value.addr_resolution = 0;
 
+#if BTM_PERIPHERAL_ENABLED == TRUE      /*  Only needed for peripheral testing */
 
+    gap_cb.gatt_attr[3].uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
+    gap_cb.gatt_attr[3].attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
+    gap_cb.gatt_attr[3].attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
+    gap_cb.gatt_attr[3].attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
+    gap_cb.gatt_attr[3].attr_value.conn_param.sp_tout = GAP_PREFER_CONN_SP_TOUT; /* 2000 */
+    gap_cb.gatt_attr[3].handle = service[4].attribute_handle;
+#endif
 }
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 2b3fd13..96f603c 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -120,124 +120,152 @@
     return status;
 }
 
+
+static unsigned char BASE_UUID[16] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+    0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb, };
+
+static int uuidType(unsigned char* p_uuid)
+{
+    if (memcmp(p_uuid+4, BASE_UUID+4, 12) != 0)
+        return LEN_UUID_128;
+    if (memcmp(p_uuid, BASE_UUID, 2) != 0)
+        return LEN_UUID_32;
+
+    return LEN_UUID_16;
+}
+
+/*******************************************************************************
+ * BTIF -> BTA conversion functions
+ *******************************************************************************/
+
+static void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src)
+{
+    char *p_byte = (char*)p_src;
+    int i = 0;
+
+    p_dest->len = uuidType(p_src->uu);
+
+    switch (p_dest->len)
+    {
+        case LEN_UUID_16:
+            p_dest->uu.uuid16 = (p_src->uu[2] << 8) + p_src->uu[3];
+            break;
+
+        case LEN_UUID_32:
+            p_dest->uu.uuid32  = (p_src->uu[0] << 24) + (p_src->uu[1] << 16)
+                               + (p_src->uu[2] <<  8) + p_src->uu[3];
+            break;
+
+        case LEN_UUID_128:
+            for(i = 0; i != 16; ++i)
+                p_dest->uu.uuid128[i] = p_byte[i];
+            break;
+
+        default:
+            GATT_TRACE_ERROR("%s: Unknown UUID length %d!", __func__, p_dest->len);
+            break;
+    }
+}
+
+static UINT16 compute_service_size(btgatt_db_element_t *service, int count) {
+    int db_size = 0;
+    btgatt_db_element_t *el = service;
+
+    for (int i = 0; i<count; i++, el++)
+        if (el->type == BTGATT_DB_PRIMARY_SERVICE ||
+            el->type == BTGATT_DB_SECONDARY_SERVICE ||
+            el->type == BTGATT_DB_DESCRIPTOR ||
+            el->type == BTGATT_DB_INCLUDED_SERVICE)
+            db_size += 1;
+        else if (el->type == BTGATT_DB_CHARACTERISTIC)
+            db_size += 2;
+        else
+            GATT_TRACE_ERROR("%s: Unknown element type: %d", __func__, el->type);
+
+    return db_size;
+}
 /*******************************************************************************
 **
 ** Function         GATTS_CreateService
 **
-** Description      This function is called to reserve a block of handles for a service.
+** Description      This function is called to add GATT service.
 **
-**                  *** It should be called only once per service instance  ***
+** Parameter        gatt_if : application if
+**                  service : pseudo-representation of service and it's content
+**                  count   : size of service
 **
-** Parameter        gatt_if       : application if
-**                  p_svc_uuid    : service UUID
-**                  svc_inst      : instance of the service inside the application
-**                  num_handles   : number of handles needed by the service.
-**                  is_pri        : is a primary service or not.
-**
-** Returns          service handle if sucessful, otherwise 0.
+** Returns          on success GATT_SERVICE_STARTED is returned, and
+**                  attribute_handle field inside service elements are filled.
+**                  on error error status is returned.
 **
 *******************************************************************************/
-UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
-                            UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri)
-{
-
+UINT16 GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t *service, int count) {
     tGATT_HDL_LIST_INFO     *p_list_info= &gatt_cb.hdl_list_info;
     tGATT_HDL_LIST_ELEM     *p_list=NULL;
     UINT16                  s_hdl=0;
     BOOLEAN                 save_hdl=FALSE;
-    tGATTS_PENDING_NEW_SRV_START      *p_buf=NULL;
     tGATT_REG              *p_reg = gatt_get_regcb(gatt_if);
     tBT_UUID     *p_app_uuid128;
 
+    bool is_pri = (service->type == BTGATT_DB_PRIMARY_SERVICE) ? true : false;
+    tBT_UUID svc_uuid;
+    btif_to_bta_uuid(&svc_uuid, &service->uuid);
 
-    GATT_TRACE_API ("GATTS_CreateService" );
+    GATT_TRACE_API("%s", __func__);
 
     if (p_reg == NULL)
     {
         GATT_TRACE_ERROR ("Inavlid gatt_if=%d", gatt_if);
-        return(0);
+        return GATT_INTERNAL_ERROR;
     }
 
     p_app_uuid128 = &p_reg->app_uuid128;
 
-    if ((p_list = gatt_find_hdl_buffer_by_app_id(p_app_uuid128, p_svc_uuid, svc_inst)) != NULL)
-    {
-        s_hdl = p_list->asgn_range.s_handle;
-        GATT_TRACE_DEBUG ("Service already been created!!");
-    }
-    else
-    {
-        if ( (p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GATT_SERVER))
-        {
+    UINT16 num_handles = compute_service_size(service, count);
+
+    if ( (svc_uuid.len == LEN_UUID_16) && (svc_uuid.uu.uuid16 == UUID_SERVCLASS_GATT_SERVER)) {
             s_hdl=  gatt_cb.hdl_cfg.gatt_start_hdl;
-        }
-        else if ((p_svc_uuid->len == LEN_UUID_16) && (p_svc_uuid->uu.uuid16 == UUID_SERVCLASS_GAP_SERVER))
-        {
+    } else if ((svc_uuid.len == LEN_UUID_16) && (svc_uuid.uu.uuid16 == UUID_SERVCLASS_GAP_SERVER)) {
             s_hdl= gatt_cb.hdl_cfg.gap_start_hdl;
-        }
-        else
-        {
-            p_list = p_list_info->p_first;
+    } else {
+        p_list = p_list_info->p_first;
 
-            if (p_list)
-            {
-                s_hdl = p_list->asgn_range.e_handle + 1;
-            }
+        if (p_list)
+            s_hdl = p_list->asgn_range.e_handle + 1;
 
-            if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
-            {
+        if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
+            s_hdl= gatt_cb.hdl_cfg.app_start_hdl;
 
-                s_hdl= gatt_cb.hdl_cfg.app_start_hdl;
-            }
-            save_hdl = TRUE;
-        }
-
-        /* check for space */
-        if (num_handles > (0xFFFF - s_hdl + 1))
-        {
-            GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl, num_handles);
-            return(0);
-        }
-
-        if ( (p_list = gatt_alloc_hdl_buffer()) == NULL)
-        {
-            /* No free entry */
-            GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
-            return(0);
-        }
-
-        p_list->asgn_range.app_uuid128 = *p_app_uuid128;
-        p_list->asgn_range.svc_uuid    = *p_svc_uuid;
-        p_list->asgn_range.svc_inst    = svc_inst;
-        p_list->asgn_range.s_handle    = s_hdl;
-        p_list->asgn_range.e_handle    = s_hdl+num_handles-1;
-        p_list->asgn_range.is_primary  = is_pri;
-
-        gatt_add_an_item_to_list(p_list_info, p_list);
-
-        if (save_hdl)
-        {
-            if (gatt_cb.cb_info.p_nv_save_callback)
-                (*gatt_cb.cb_info.p_nv_save_callback)(TRUE, &p_list->asgn_range);
-            /* add a pending new  service change item to the list */
-            if ( (p_buf = gatt_add_pending_new_srv_start(&p_list->asgn_range)) == NULL)
-            {
-                /* No free entry */
-                GATT_TRACE_ERROR ("gatt_add_pending_new_srv_start: no free blocks");
-
-                if (p_list)
-                {
-                    gatt_remove_an_item_from_list(p_list_info, p_list);
-                    gatt_free_hdl_buffer(p_list);
-                }
-                return(0);
-            }
-
-            GATT_TRACE_DEBUG ("Add a new srv chg item");
-        }
+        save_hdl = TRUE;
     }
 
-    if (!gatts_init_service_db(&p_list->svc_db, p_svc_uuid, is_pri, s_hdl , num_handles))
+    /* check for space */
+    if (num_handles > (0xFFFF - s_hdl + 1)) {
+        GATT_TRACE_ERROR ("GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl, num_handles);
+        return GATT_INTERNAL_ERROR;
+    }
+
+    if ( (p_list = gatt_alloc_hdl_buffer()) == NULL) {
+        /* No free entry */
+        GATT_TRACE_ERROR ("GATTS_ReserveHandles: no free handle blocks");
+        return GATT_INTERNAL_ERROR;
+    }
+
+    p_list->asgn_range.app_uuid128 = *p_app_uuid128;
+    p_list->asgn_range.svc_uuid    = svc_uuid;
+    p_list->asgn_range.s_handle    = s_hdl;
+    p_list->asgn_range.e_handle    = s_hdl+num_handles-1;
+    p_list->asgn_range.is_primary  = is_pri;
+
+    gatt_add_an_item_to_list(p_list_info, p_list);
+
+    if (save_hdl) {
+        if (gatt_cb.cb_info.p_nv_save_callback)
+            (*gatt_cb.cb_info.p_nv_save_callback)(TRUE, &p_list->asgn_range);
+    }
+
+    if (!gatts_init_service_db(&p_list->svc_db, &svc_uuid, is_pri, s_hdl , num_handles))
     {
         GATT_TRACE_ERROR ("GATTS_ReserveHandles: service DB initialization failed");
         if (p_list)
@@ -246,146 +274,92 @@
             gatt_free_hdl_buffer(p_list);
         }
 
-        if (p_buf)
-            osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
-        return(0);
+        return GATT_INTERNAL_ERROR;
     }
 
-    GATT_TRACE_DEBUG ("GATTS_CreateService(success): handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d",
+    GATT_TRACE_DEBUG ("%d: handles needed:%u s_hdl=%u e_hdl=%u %s[%x] is_primary=%d", __func__,
                        num_handles, p_list->asgn_range.s_handle , p_list->asgn_range.e_handle,
                        ((p_list->asgn_range.svc_uuid.len == 2) ? "uuid16": "uuid128" ),
                        p_list->asgn_range.svc_uuid.uu.uuid16,
                        p_list->asgn_range.is_primary);
 
-    return(s_hdl);
+    service->attribute_handle = s_hdl;
+
+    btgatt_db_element_t *el = service +1;
+    for (int i = 0; i<count-1; i++, el++) {
+        tBT_UUID uuid;
+        btif_to_bta_uuid(&uuid, &el->uuid);
+
+        if (el->type == BTGATT_DB_CHARACTERISTIC) {
+            /* data validity checking */
+            if (((el->properties & GATT_CHAR_PROP_BIT_AUTH) && !(el->permissions & GATT_WRITE_SIGNED_PERM)) ||
+                ((el->permissions & GATT_WRITE_SIGNED_PERM) && !(el->properties & GATT_CHAR_PROP_BIT_AUTH)) ) {
+                GATT_TRACE_DEBUG("Invalid configuration property=0x%02x perm=0x%04x ", el->properties, el->permissions);
+                return GATT_INTERNAL_ERROR;
+            }
+
+            el->attribute_handle = gatts_add_characteristic(&p_list->svc_db, el->permissions, el->properties, &uuid);
+        } else if (el->type == BTGATT_DB_DESCRIPTOR) {
+            el->attribute_handle = gatts_add_char_descr(&p_list->svc_db, el->permissions, &uuid);
+        } else if (el->type == BTGATT_DB_INCLUDED_SERVICE) {
+            tGATT_HDL_LIST_ELEM  *p_incl_decl;
+            if ((p_incl_decl = gatt_find_hdl_buffer_by_handle(el->attribute_handle)) == NULL) {
+                GATT_TRACE_DEBUG("Included Service not created");
+                return GATT_INTERNAL_ERROR;
+            }
+
+            el->attribute_handle = gatts_add_included_service(&p_list->svc_db,
+                                              p_incl_decl->asgn_range.s_handle,
+                                              p_incl_decl->asgn_range.e_handle,
+                                              p_incl_decl->asgn_range.svc_uuid);
+        }
+    }
+
+    tGATT_SR_REG            *p_sreg;
+    UINT8                    i_sreg;
+    tBT_UUID                *p_uuid;
+
+    GATT_TRACE_API ("%s: service parsed correctly, now starting", __func__);
+
+    /*this is a new application servoce start */
+    if ((i_sreg = gatt_sr_alloc_rcb(p_list)) ==  GATT_MAX_SR_PROFILES) {
+        GATT_TRACE_ERROR ("%s: no free server registration block", __func__);
+        return GATT_NO_RESOURCES;
+    }
+
+    p_sreg = &gatt_cb.sr_reg[i_sreg];
+    p_sreg->gatt_if = gatt_if;
+
+    if (p_sreg->type == GATT_UUID_PRI_SERVICE) {
+        p_uuid = gatts_get_service_uuid(p_sreg->p_db);
+        p_sreg->sdp_handle = gatt_add_sdp_record(p_uuid, p_sreg->s_hdl, p_sreg->e_hdl);
+    }
+
+    gatts_update_srv_list_elem(i_sreg, p_sreg->s_hdl,
+                               p_list->asgn_range.is_primary);
+
+    gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
+
+    GATT_TRACE_DEBUG ("%s: allocated i_sreg=%d ",__func__, i_sreg);
+    GATT_TRACE_DEBUG ("%s: s_hdl=%d e_hdl=%d type=0x%x sdp_hdl=0x%x", __func__,
+                       p_sreg->s_hdl,p_sreg->e_hdl,
+                       p_sreg->type,
+                       p_sreg->sdp_handle);
+
+    gatt_proc_srv_chg();
+
+    return GATT_SERVICE_STARTED;
 }
 
 /*******************************************************************************
 **
-** Function         GATTS_AddIncludeService
-**
-** Description      This function is called to add an included service.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  include_svc_handle    : included service handle.
-**
-** Returns          included service attribute handle. If 0, add included service
-**                  fail.
-**
-*******************************************************************************/
-UINT16 GATTS_AddIncludeService (UINT16 service_handle, UINT16 include_svc_handle)
-
-{
-    tGATT_HDL_LIST_ELEM  *p_decl, *p_incl_decl;
-
-    if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Service not created");
-        return 0;
-    }
-    if ((p_incl_decl = gatt_find_hdl_buffer_by_handle(include_svc_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Included Service not created");
-        return 0;
-    }
-
-    return gatts_add_included_service(&p_decl->svc_db,
-                                      p_incl_decl->asgn_range.s_handle,
-                                      p_incl_decl->asgn_range.e_handle,
-                                      p_incl_decl->asgn_range.svc_uuid);
-}
-/*******************************************************************************
-**
-** Function         GATTS_AddCharacteristic
-**
-** Description      This function is called to add a characteristic into a service.
-**                  It will add a characteristic declaration and characteristic
-**                  value declaration into the service database identified by the
-**                  service handle.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  char_uuid : Characteristic UUID.
-**                  perm      : Characteristic value declaration attribute permission.
-**                  property  : Characteristic Properties
-**
-** Returns          Characteristic value declaration attribute handle. 0 if failed.
-**
-*******************************************************************************/
-UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *p_char_uuid,
-                                tGATT_PERM perm,tGATT_CHAR_PROP property)
-{
-    tGATT_HDL_LIST_ELEM  *p_decl;
-
-    if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Service not created");
-        return 0;
-    }
-    /* data validity checking */
-    if (  ((property & GATT_CHAR_PROP_BIT_AUTH) && !(perm & GATT_WRITE_SIGNED_PERM)) ||
-          ((perm & GATT_WRITE_SIGNED_PERM) && !(property & GATT_CHAR_PROP_BIT_AUTH)) )
-    {
-        GATT_TRACE_DEBUG("Invalid configuration property=0x%x perm=0x%x ", property, perm);
-        return 0;
-    }
-
-    return gatts_add_characteristic(&p_decl->svc_db,
-                                    perm,
-                                    property,
-                                    p_char_uuid);
-}
-/*******************************************************************************
-**
-** Function         GATTS_AddCharDescriptor
-**
-** Description      This function is called to add a characteristic descriptor
-**                  into a service database. Add descriptor should follow add char
-**                  to which it belongs, and next add char should be done only
-**                  after all add descriptors for the previous char.
-**
-** Parameter        service_handle  : To which service this characteristic descriptor
-**                                    is added to.
-**                  perm            : Characteristic value declaration attribute
-**                                    permission.
-**                  p_descr_uuid    : Characteristic descriptor UUID
-**
-** Returns         Characteristic descriptor attribute handle. 0 if add
-**                 characteristic descriptor failed.
-**
-*******************************************************************************/
-UINT16 GATTS_AddCharDescriptor (UINT16 service_handle,
-                                 tGATT_PERM perm,
-                                 tBT_UUID  * p_descr_uuid)
-{
-    tGATT_HDL_LIST_ELEM  *p_decl;
-
-    if ((p_decl = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        GATT_TRACE_DEBUG("Service not created");
-        return 0;
-    }
-    if (p_descr_uuid == NULL ||
-        (p_descr_uuid->len != LEN_UUID_128 && p_descr_uuid->len !=  LEN_UUID_16
-         && p_descr_uuid->len !=  LEN_UUID_32))
-    {
-        GATT_TRACE_DEBUG("Illegal parameter");
-        return 0;
-    }
-
-    return gatts_add_char_descr(&p_decl->svc_db,
-                                perm,
-                                p_descr_uuid);
-
-}
-/*******************************************************************************
-**
 ** Function         GATTS_DeleteService
 **
 ** Description      This function is called to delete a service.
 **
 ** Parameter        gatt_if       : application interface
 **                  p_svc_uuid    : service UUID
-**                  svc_inst      : instance of the service inside the application
+**                  start_handle  : start handle of the service
 **
 ** Returns          TRUE if operation succeed, FALSE if handle block was not found.
 **
@@ -396,7 +370,6 @@
     tGATT_HDL_LIST_INFO             *p_list_info= &gatt_cb.hdl_list_info;
     tGATT_HDL_LIST_ELEM             *p_list=NULL;
     UINT8                           i_sreg;
-    tGATTS_PENDING_NEW_SRV_START    *p_buf;
     tGATT_REG       *p_reg = gatt_get_regcb(gatt_if);
     tBT_UUID *p_app_uuid128;
 
@@ -415,17 +388,7 @@
         return(FALSE);
     }
 
-    if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
-                                         &p_list->asgn_range.svc_uuid,
-                                         p_list->asgn_range.svc_inst)) != NULL)
-    {
-        GATT_TRACE_DEBUG ("Delete a new service changed item - the service has not yet started");
-        osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
-    }
-    else
-    {
-        gatt_proc_srv_chg();
-    }
+    gatt_proc_srv_chg();
 
     if ((i_sreg = gatt_sr_find_i_rcb_by_app_id (p_app_uuid128,
                                                 p_svc_uuid,
@@ -449,104 +412,6 @@
 
 /*******************************************************************************
 **
-** Function         GATTS_StartService
-**
-** Description      This function is called to start a service with GATT
-**
-** Parameter        gatt_if : service handle.
-**                  p_cback       : application service callback functions.
-**                  sup_transport : supported transport(s) for this primary service
-**
-** return           GATT_SUCCESS if sucessfully started; otherwise error code.
-**
-*******************************************************************************/
-tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
-                                 tGATT_TRANSPORT sup_transport)
-{
-    tGATT_SR_REG            *p_sreg;
-    tGATT_HDL_LIST_ELEM      *p_list=NULL;
-    UINT8                    i_sreg;
-    tBT_UUID                *p_uuid;
-    tGATT_REG              *p_reg = gatt_get_regcb(gatt_if);
-
-    tGATTS_PENDING_NEW_SRV_START *p_buf;
-
-    GATT_TRACE_API ("GATTS_StartService");
-
-    if (p_reg == NULL)
-    {
-        /* Not found  */
-        GATT_TRACE_ERROR ("Applicaiton not found ");
-        return GATT_NOT_FOUND;
-    }
-
-    if ((p_list = gatt_find_hdl_buffer_by_handle(service_handle)) == NULL)
-    {
-        /* Not found  */
-        GATT_TRACE_ERROR ("no service found");
-        return GATT_NOT_FOUND;
-    }
-
-    if (gatt_sr_find_i_rcb_by_app_id (&p_list->asgn_range.app_uuid128,
-                                      &p_list->asgn_range.svc_uuid,
-                                      p_list->asgn_range.svc_inst) != GATT_MAX_SR_PROFILES)
-    {
-        GATT_TRACE_ERROR ("Duplicate Service start - Service already started");
-        return GATT_SERVICE_STARTED;
-    }
-
-    /*this is a new application servoce start */
-    if ((i_sreg = gatt_sr_alloc_rcb(p_list)) ==  GATT_MAX_SR_PROFILES)
-    {
-        GATT_TRACE_ERROR ("GATTS_StartService: no free server registration block");
-        return GATT_NO_RESOURCES;
-    }
-
-    p_sreg = &gatt_cb.sr_reg[i_sreg];
-    p_sreg->gatt_if = gatt_if;
-
-    switch (sup_transport)
-    {
-        case GATT_TRANSPORT_BR_EDR:
-        case GATT_TRANSPORT_LE_BR_EDR:
-            if (p_sreg->type == GATT_UUID_PRI_SERVICE)
-            {
-                p_uuid = gatts_get_service_uuid (p_sreg->p_db);
-
-                p_sreg->sdp_handle = gatt_add_sdp_record(p_uuid, p_sreg->s_hdl, p_sreg->e_hdl);
-            }
-            break;
-        default:
-            break;
-    }
-
-    gatts_update_srv_list_elem(i_sreg, p_sreg->s_hdl,
-                               p_list->asgn_range.is_primary);
-
-    gatt_add_a_srv_to_list(&gatt_cb.srv_list_info, &gatt_cb.srv_list[i_sreg]);
-
-    GATT_TRACE_DEBUG ("allocated i_sreg=%d ",i_sreg);
-
-    GATT_TRACE_DEBUG ("s_hdl=%d e_hdl=%d type=0x%x svc_inst=%d sdp_hdl=0x%x",
-                       p_sreg->s_hdl,p_sreg->e_hdl,
-                       p_sreg->type,  p_sreg->service_instance,
-                       p_sreg->sdp_handle);
-
-
-    if ( (p_buf = gatt_sr_is_new_srv_chg(&p_list->asgn_range.app_uuid128,
-                                         &p_list->asgn_range.svc_uuid,
-                                         p_list->asgn_range.svc_inst)) != NULL)
-    {
-        gatt_proc_srv_chg();
-        /* remove the new service element after the srv changed processing is completed*/
-
-        osi_free(fixed_queue_try_remove_from_queue(gatt_cb.pending_new_srv_start_q, p_buf));
-    }
-    return GATT_SUCCESS;
-}
-
-/*******************************************************************************
-**
 ** Function         GATTS_StopService
 **
 ** Description      This function is called to stop a service
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 9a2c6fa..e2d01a6 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -28,6 +28,7 @@
 
 #include "gatt_api.h"
 #include "gatt_int.h"
+#include "btcore/include/uuid.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -191,11 +192,13 @@
 
     switch (type)
     {
-        case GATTS_REQ_TYPE_READ:
+        case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_READ_DESCRIPTOR:
             status = GATT_READ_NOT_PERMIT;
             break;
 
-        case GATTS_REQ_TYPE_WRITE:
+        case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
             status = GATT_WRITE_NOT_PERMIT;
             break;
 
@@ -266,35 +269,33 @@
 void gatt_profile_db_init (void)
 {
     tBT_UUID          app_uuid = {LEN_UUID_128, {0}};
-    tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}};
     UINT16            service_handle = 0;
-    tGATT_STATUS      status;
 
     /* Fill our internal UUID with a fixed pattern 0x81 */
     memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
 
-
     /* Create a GATT profile service */
     gatt_cb.gatt_if = GATT_Register(&app_uuid, &gatt_profile_cback);
     GATT_StartIf(gatt_cb.gatt_if);
 
-    service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
-    /* add Service Changed characteristic
-    */
-    uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
-    gatt_cb.gattp_attr.service_change = 0;
-    gatt_cb.gattp_attr.handle   =
-    gatt_cb.handle_of_h_r       = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
+    bt_uuid_t service_uuid;
+    uuid_128_from_16(&service_uuid, UUID_SERVCLASS_GATT_SERVER);
 
-    GATT_TRACE_DEBUG ("gatt_profile_db_init:  handle of service changed%d",
-                       gatt_cb.handle_of_h_r  );
+    bt_uuid_t char_uuid;
+    uuid_128_from_16(&char_uuid, GATT_UUID_GATT_SRV_CHGD);
 
-    /* start service
-    */
-    status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
+    btgatt_db_element_t service[] = {
+        {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid = service_uuid},
+        {.type = BTGATT_DB_CHARACTERISTIC, .uuid = char_uuid,
+            .properties = GATT_CHAR_PROP_BIT_INDICATE, .permissions = 0}
+    };
 
-    GATT_TRACE_DEBUG ("gatt_profile_db_init:  gatt_if=%d   start status%d",
-                       gatt_cb.gatt_if,  status);
+    GATTS_AddService(gatt_cb.gatt_if, service, sizeof(service)/sizeof(btgatt_db_element_t));
+
+    service_handle = service[0].attribute_handle;
+    gatt_cb.handle_of_h_r = service[1].attribute_handle;
+
+    GATT_TRACE_ERROR("gatt_profile_db_init:  gatt_if=%d", gatt_cb.gatt_if);
 }
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index 91da722..5f8c406 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -45,7 +45,8 @@
 
 static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri);
 static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
-                                                UINT16 handle, UINT16 offset, UINT32 trans_id);
+                                                UINT16 handle, UINT16 offset, UINT32 trans_id,
+                                                bt_gatt_db_attribute_type_t gatt_type);
 
 /*******************************************************************************
 **
@@ -133,32 +134,32 @@
 
     if (!(perm & GATT_READ_ALLOWED))
     {
-        GATT_TRACE_ERROR( "GATT_READ_NOT_PERMIT");
+        GATT_TRACE_ERROR("%s: GATT_READ_NOT_PERMIT", __func__);
         return GATT_READ_NOT_PERMIT;
     }
 
     if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
         !(sec_flag & BTM_SEC_FLAG_ENCRYPTED))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION", __func__);
         return GATT_INSUF_AUTHENTICATION;
     }
 
     if ((perm & GATT_READ_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_AUTHENTICATION: MITM Required");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION: MITM Required", __func__);
         return GATT_INSUF_AUTHENTICATION;
     }
 
     if ((perm & GATT_READ_ENCRYPTED_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_ENCRYPTION");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_ENCRYPTION", __func__);
         return GATT_INSUF_ENCRYPTION;
     }
 
     if ( (perm & GATT_READ_ENCRYPTED_REQUIRED) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size))
     {
-        GATT_TRACE_ERROR( "GATT_INSUF_KEY_SIZE");
+        GATT_TRACE_ERROR("%s: GATT_INSUF_KEY_SIZE", __func__);
         return GATT_INSUF_KEY_SIZE;
     }
 
@@ -175,7 +176,7 @@
             case GATT_UUID_CHAR_CLIENT_CONFIG:
             case GATT_UUID_CHAR_SRVR_CONFIG:
             case GATT_UUID_CHAR_PRESENT_FORMAT:
-                GATT_TRACE_ERROR("GATT_NOT_LONG");
+                GATT_TRACE_ERROR("%s: GATT_NOT_LONG", __func__);
                 return GATT_NOT_LONG;
 
             default:
@@ -218,7 +219,7 @@
     tGATT_STATUS    status;
     tGATT_ATTR    *p_attr16  = (tGATT_ATTR  *)p_attr;
 
-    GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%0x sec_flag=0x%x offset=%d read_long=%d",
+    GATT_TRACE_DEBUG("read_attr_value uuid=0x%04x perm=0x%02x sec_flag=0x%x offset=%d read_long=%d",
                       p_attr16->uuid,
                       p_attr16->permission,
                       sec_flag,
@@ -359,7 +360,8 @@
 
                 if (status == GATT_PENDING)
                 {
-                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0, trans_id);
+                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, 0,
+                                                         trans_id, p_attr->gatt_type);
 
                     /* one callback at a time */
                     break;
@@ -479,7 +481,7 @@
     tGATT_ATTR     *p_char_decl, *p_char_val;
     tBT_UUID        uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
 
-    GATT_TRACE_DEBUG("gatts_add_characteristic perm=0x%0x property=0x%0x", perm, property);
+    GATT_TRACE_DEBUG("%s: perm=0x%0x property=0x%0x", __func__, perm, property);
 
     if ((p_char_decl = (tGATT_ATTR *)allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ)) != NULL)
     {
@@ -500,6 +502,7 @@
         p_char_decl->p_value->char_decl.property = property;
         p_char_decl->p_value->char_decl.char_val_handle  = p_char_val->handle;
 
+        p_char_val->gatt_type = BTGATT_DB_CHARACTERISTIC;
         p_char_val->p_value = NULL;
 
         return p_char_val->handle;
@@ -584,6 +587,7 @@
     }
     else
     {
+        p_char_dscptr->gatt_type = BTGATT_DB_DESCRIPTOR;
         return p_char_dscptr->handle;
     }
 }
@@ -638,7 +642,8 @@
 
                 if (status == GATT_PENDING)
                 {
-                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset, trans_id);
+                    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset,
+                                                         trans_id, p_attr->gatt_type);
                 }
                 break;
             }
@@ -724,8 +729,8 @@
     tGATT_PERM      perm;
     UINT16          min_key_size;
 
-    GATT_TRACE_DEBUG( "gatts_write_attr_perm_check op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x key_size=%d",
-                       op_code, handle, offset, len, sec_flag, key_size);
+    GATT_TRACE_DEBUG( "%s: op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x key_size=%d",
+                       __func__, op_code, handle, offset, len, sec_flag, key_size);
 
     if (p_db != NULL)
     {
@@ -741,9 +746,8 @@
                 {
                     min_key_size +=6;
                 }
-                GATT_TRACE_DEBUG( "gatts_write_attr_perm_check p_attr->permission =0x%04x min_key_size==0x%04x",
-                                   p_attr->permission,
-                                   min_key_size);
+                GATT_TRACE_DEBUG( "%s: p_attr->permission =0x%04x min_key_size==0x%04x",
+                                   __func__, p_attr->permission, min_key_size);
 
                 if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE)
                     && (perm & GATT_WRITE_SIGNED_PERM))
@@ -768,45 +772,45 @@
                 if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM))
                 {
                     status = GATT_WRITE_NOT_PERMIT;
-                    GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed");
+                    GATT_TRACE_DEBUG( "%s: sign cmd write not allowed", __func__);
                 }
                  if ((op_code == GATT_SIGN_CMD_WRITE) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED))
                 {
                     status = GATT_INVALID_PDU;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encypted link");
+                    GATT_TRACE_ERROR( "%s: Error!! sign cmd write sent on a encypted link", __func__);
                 }
                 else if (!(perm & GATT_WRITE_ALLOWED))
                 {
                     status = GATT_WRITE_NOT_PERMIT;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT");
+                    GATT_TRACE_ERROR( "%s: GATT_WRITE_NOT_PERMIT", __func__);
                 }
                 /* require authentication, but not been authenticated */
                 else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
                 {
                     status = GATT_INSUF_AUTHENTICATION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_AUTHENTICATION", __func__);
                 }
                 else if ((perm & GATT_WRITE_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED))
                 {
                     status = GATT_INSUF_AUTHENTICATION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_AUTHENTICATION: MITM required", __func__);
                 }
                 else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
                 {
                     status = GATT_INSUF_ENCRYPTION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_ENCRYPTION", __func__);
                 }
                 else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size))
                 {
                     status = GATT_INSUF_KEY_SIZE;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_KEY_SIZE", __func__);
                 }
                 /* LE security mode 2 attribute  */
                 else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)
                     &&  (perm & GATT_WRITE_ALLOWED) == 0)
                 {
                     status = GATT_INSUF_AUTHENTICATION;
-                    GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
+                    GATT_TRACE_ERROR( "%s: GATT_INSUF_AUTHENTICATION: LE security mode 2 required", __func__);
                 }
                 else /* writable: must be char value declaration or char descritpors */
                 {
@@ -855,12 +859,12 @@
                         if (op_code == GATT_REQ_PREPARE_WRITE && offset != 0) /* does not allow write blob */
                         {
                             status = GATT_NOT_LONG;
-                            GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_NOT_LONG");
+                            GATT_TRACE_ERROR( "%s: GATT_NOT_LONG", __func__);
                         }
                         else if (len != max_size)    /* data does not match the required format */
                         {
                             status = GATT_INVALID_ATTR_LEN;
-                            GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INVALID_PDU");
+                            GATT_TRACE_ERROR( "%s: GATT_INVALID_PDU", __func__);
                         }
                         else
                         {
@@ -1086,7 +1090,8 @@
 **
 *******************************************************************************/
 static tGATT_STATUS gatts_send_app_read_request(tGATT_TCB *p_tcb, UINT8 op_code,
-                                                UINT16 handle, UINT16 offset, UINT32 trans_id)
+                                                UINT16 handle, UINT16 offset, UINT32 trans_id,
+                                                bt_gatt_db_attribute_type_t gatt_type)
 {
     tGATTS_DATA   sr_data;
     UINT8       i_rcb;
@@ -1111,8 +1116,19 @@
         sr_data.read_req.is_long = (BOOLEAN)(op_code == GATT_REQ_READ_BLOB);
         sr_data.read_req.offset = offset;
 
+        UINT8 opcode;
+        if (gatt_type == BTGATT_DB_DESCRIPTOR) {
+            opcode = GATTS_REQ_TYPE_READ_DESCRIPTOR;
+        } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
+            opcode = GATTS_REQ_TYPE_READ_CHARACTERISTIC;
+        } else {
+            GATT_TRACE_ERROR("%s: Attempt to read attribute that's not tied with"
+                             " characteristic or descriptor value.", __func__);
+            return GATT_ERROR;
+        }
+
         gatt_sr_send_req_callback(conn_id,
-                                  trans_id, GATTS_REQ_TYPE_READ, &sr_data);
+                                  trans_id, opcode, &sr_data);
         return(tGATT_STATUS) GATT_PENDING;
     }
     else
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index f1dc1fc..cc9568a 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -183,6 +183,7 @@
     tGATT_PERM                          permission;
     UINT16                              handle;
     tBT_UUID                            uuid;
+    bt_gatt_db_attribute_type_t         gatt_type;
 } tGATT_ATTR;
 
 /* Service Database definition
@@ -207,7 +208,6 @@
     tGATT_SVC_DB    *p_db;      /* pointer to the service database */
     tBT_UUID        app_uuid;           /* applicatino UUID */
     UINT32          sdp_handle; /* primamry service SDP handle */
-    UINT16          service_instance;   /* service instance number */
     UINT16          type;       /* service type UUID, primary or secondary */
     UINT16          s_hdl;      /* service starting handle */
     UINT16          e_hdl;      /* service ending handle */
@@ -452,7 +452,6 @@
     tGATT_SRV_LIST_ELEM srv_list[GATT_MAX_SR_PROFILES];
 
     fixed_queue_t       *srv_chg_clt_q; /* service change clients queue */
-    fixed_queue_t       *pending_new_srv_start_q; /* pending new service start queue */
     tGATT_REG           cl_rcb[GATT_MAX_APPS];
     tGATT_CLCB          clcb[GATT_CL_MAX_LCB];  /* connection link control block*/
     tGATT_SCCB          sccb[GATT_MAX_SCCB];    /* sign complete callback function GATT_MAX_SCCB <= GATT_CL_MAX_LCB */
@@ -545,8 +544,6 @@
 extern void gatt_dbg_display_uuid(tBT_UUID bt_uuid);
 extern tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb );
 
-extern tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
-
 extern BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb);
 extern tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda);
 
@@ -554,7 +551,6 @@
 extern void gatt_set_srv_chg(void);
 extern void gatt_delete_dev_from_srv_chg_clt_list(BD_ADDR bd_addr);
 extern tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB  *p_tcb, tGATT_VALUE *p_ind);
-extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start);
 extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id);
 extern BOOLEAN gatt_update_listen_mode(void);
 extern BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb);
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 3637981..7914217 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -106,7 +106,6 @@
     gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
     gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX);
     gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX);
-    gatt_cb.pending_new_srv_start_q = fixed_queue_new(SIZE_MAX);
     /* First, register fixed L2CAP channel for ATT over BLE */
     fixed_reg.fixed_chnl_opts.mode         = L2CAP_FCR_BASIC_MODE;
     fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;
@@ -157,8 +156,6 @@
     gatt_cb.sign_op_queue = NULL;
     fixed_queue_free(gatt_cb.srv_chg_clt_q, NULL);
     gatt_cb.srv_chg_clt_q = NULL;
-    fixed_queue_free(gatt_cb.pending_new_srv_start_q, NULL);
-    gatt_cb.pending_new_srv_start_q = NULL;
     for (i = 0; i < GATT_MAX_PHY_CHANNEL; i++)
     {
         fixed_queue_free(gatt_cb.tcb[i].pending_enc_clcb, NULL);
@@ -979,7 +976,6 @@
     UINT8   op_code, pseudo_op_code;
     UINT16  msg_len;
 
-
     if (p_buf->len > 0)
     {
         msg_len = p_buf->len - 1;
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index e55b6bb..58d28b7 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -1038,7 +1038,8 @@
 **
 *******************************************************************************/
 void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
-                              UINT8 op_code, UINT16 len, UINT8 *p_data)
+                              UINT8 op_code, UINT16 len, UINT8 *p_data,
+                              bt_gatt_db_attribute_type_t gatt_type)
 {
     tGATTS_DATA     sr_data;
     UINT32          trans_id;
@@ -1101,12 +1102,22 @@
         {
             p_sreg = &gatt_cb.sr_reg[i_rcb];
             conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
-            gatt_sr_send_req_callback(conn_id,
-                                      trans_id,
-                                      GATTS_REQ_TYPE_WRITE,
-                                      &sr_data);
 
-            status = GATT_PENDING;
+            UINT8 opcode = 0;
+            if (gatt_type == BTGATT_DB_DESCRIPTOR) {
+                opcode = GATTS_REQ_TYPE_WRITE_DESCRIPTOR;
+            } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
+                opcode = GATTS_REQ_TYPE_WRITE_CHARACTERISTIC;
+            } else {
+                GATT_TRACE_ERROR("%s: Attempt to write attribute that's not tied with"
+                                 " characteristic or descriptor value.", __func__);
+                status = GATT_ERROR;
+            }
+
+            if (opcode) {
+                gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data);
+                status = GATT_PENDING;
+            }
         }
         else
         {
@@ -1248,7 +1259,8 @@
                             case GATT_CMD_WRITE:
                             case GATT_SIGN_CMD_WRITE:
                             case GATT_REQ_PREPARE_WRITE:
-                                gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
+                                gatts_process_write_req(p_tcb, i, handle, op_code, len, p,
+                                                        p_attr->gatt_type);
                                 break;
                             default:
                                 break;
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index 03d6192..e8a6cf1 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -191,39 +191,6 @@
 
 /*******************************************************************************
 **
-** Function         gatt_sr_is_new_srv_chg
-**
-** Description     Find the app id in on the new service changed list
-**
-** Returns     Pointer to the found new service changed item othwerwise NULL
-**
-*******************************************************************************/
-tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
-{
-    tGATTS_PENDING_NEW_SRV_START *p_buf = NULL;
-
-    if (fixed_queue_is_empty(gatt_cb.pending_new_srv_start_q))
-        return NULL;
-
-    list_t *list = fixed_queue_get_list(gatt_cb.pending_new_srv_start_q);
-    for (const list_node_t *node = list_begin(list); node != list_end(list);
-         node = list_next(node)) {
-        p_buf = (tGATTS_PENDING_NEW_SRV_START *)list_node(node);
-        tGATTS_HNDL_RANGE *p = p_buf->p_new_srv_start;
-        if (gatt_uuid_compare(*p_app_uuid128, p->app_uuid128)
-            && gatt_uuid_compare (*p_svc_uuid, p->svc_uuid)
-            && (svc_inst == p->svc_inst)) {
-            GATT_TRACE_DEBUG("gatt_sr_is_new_srv_chg: Yes");
-            break;
-        }
-    }
-
-    return p_buf;
-}
-
-
-/*******************************************************************************
-**
 ** Function     gatt_add_pending_ind
 **
 ** Description  Add a pending indication
@@ -246,30 +213,6 @@
 
 /*******************************************************************************
 **
-** Function     gatt_add_pending_new_srv_start
-**
-** Description  Add a pending new srv start to the new service start queue
-**
-** Returns    Pointer to the new service start buffer, NULL no buffer available
-**
-*******************************************************************************/
-tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start(tGATTS_HNDL_RANGE *p_new_srv_start)
-{
-    tGATTS_PENDING_NEW_SRV_START *p_buf =
-        (tGATTS_PENDING_NEW_SRV_START *)osi_malloc(sizeof(tGATTS_PENDING_NEW_SRV_START));
-
-    GATT_TRACE_DEBUG("%s", __func__);
-    GATT_TRACE_DEBUG("enqueue a new pending new srv start");
-
-    p_buf->p_new_srv_start = p_new_srv_start;
-    fixed_queue_enqueue(gatt_cb.pending_new_srv_start_q, p_buf);
-
-    return p_buf;
-}
-
-
-/*******************************************************************************
-**
 ** Function     gatt_add_srv_chg_clt
 **
 ** Description  Add a service chnage client to the service change client queue
@@ -356,7 +299,7 @@
 *******************************************************************************/
 tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128,
                                                      tBT_UUID *p_svc_uuid,
-                                                     UINT16 svc_inst)
+                                                     UINT16 start_handle)
 {
     tGATT_HDL_LIST_INFO *p_list_info= &gatt_cb.hdl_list_info;
     tGATT_HDL_LIST_ELEM      *p_list = NULL;
@@ -367,7 +310,7 @@
     {
         if ( gatt_uuid_compare (*p_app_uuid128, p_list->asgn_range.app_uuid128)
              &&  gatt_uuid_compare (*p_svc_uuid,    p_list->asgn_range.svc_uuid)
-             &&  (svc_inst == p_list->asgn_range.svc_inst) )
+             &&  (start_handle == p_list->asgn_range.s_handle) )
         {
             GATT_TRACE_DEBUG ("Already allocated handles for this service before!!");
             return(p_list);
@@ -1360,7 +1303,7 @@
 ** Returns          0 if not found. Otherwise index of th eservice.
 **
 *******************************************************************************/
-UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst)
+UINT8 gatt_sr_find_i_rcb_by_app_id(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 start_handle)
 {
     UINT8           i_rcb = 0;
     tGATT_SR_REG    *p_sreg;
@@ -1375,7 +1318,7 @@
             if (p_this_uuid &&
                 gatt_uuid_compare (*p_app_uuid128, p_sreg->app_uuid ) &&
                 gatt_uuid_compare (*p_svc_uuid, *p_this_uuid) &&
-                (svc_inst == p_sreg->service_instance))
+                (start_handle == p_sreg->s_hdl))
             {
                 GATT_TRACE_ERROR ("Active Service Found ");
                 gatt_dbg_display_uuid(*p_svc_uuid);
@@ -1410,7 +1353,6 @@
             p_sreg->in_use = TRUE;
             memcpy (&p_sreg->app_uuid, &p_list->asgn_range.app_uuid128, sizeof(tBT_UUID));
 
-            p_sreg->service_instance    = p_list->asgn_range.svc_inst;
             p_sreg->type                = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
             p_sreg->s_hdl               = p_list->asgn_range.s_handle;
             p_sreg->e_hdl               = p_list->asgn_range.e_handle;
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 8b8d765..b2bf9d3 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -349,6 +349,7 @@
     UINT16        handle;
     UINT16        offset;
     BOOLEAN       is_long;
+    bt_gatt_db_attribute_type_t gatt_type; /* are we writing characteristic or descriptor */
 } tGATT_READ_REQ;
 
 /* write request data */
@@ -360,6 +361,7 @@
     UINT8           value[GATT_MAX_ATTR_LEN];  /* the actual attribute value */
     BOOLEAN         need_rsp;   /* need write response */
     BOOLEAN         is_prep;    /* is prepare write */
+    bt_gatt_db_attribute_type_t gatt_type; /* are we writing characteristic or descriptor */
 } tGATT_WRITE_REQ;
 
 /* callback data for server access request from client */
@@ -379,8 +381,10 @@
 
 enum
 {
-    GATTS_REQ_TYPE_READ = 1,        /* Attribute read request */
-    GATTS_REQ_TYPE_WRITE,           /* Attribute write request */
+    GATTS_REQ_TYPE_READ_CHARACTERISTIC = 1, /* Char read request */
+    GATTS_REQ_TYPE_READ_DESCRIPTOR,         /* Desc read request */
+    GATTS_REQ_TYPE_WRITE_CHARACTERISTIC,    /* Char write request */
+    GATTS_REQ_TYPE_WRITE_DESCRIPTOR,        /* Desc write request */
     GATTS_REQ_TYPE_WRITE_EXEC,      /* Execute write */
     GATTS_REQ_TYPE_MTU,             /* MTU exchange information */
     GATTS_REQ_TYPE_CONF             /* handle value confirmation */
@@ -608,7 +612,6 @@
 {
     tBT_UUID app_uuid128;
     tBT_UUID svc_uuid;
-    UINT16   svc_inst;
     UINT16   s_handle;
     UINT16   e_handle;
     BOOLEAN  is_primary;      /* primary service or secondary */
@@ -642,13 +645,6 @@
     UINT8 num_clients;
 } tGATTS_SRV_CHG_RSP;
 
-
-
-typedef struct
-{
-    tGATTS_HNDL_RANGE   *p_new_srv_start;
-} tGATTS_PENDING_NEW_SRV_START;
-
 /* Attibute server handle ranges NV storage callback functions
 */
 typedef void  (tGATTS_NV_SAVE_CBACK)(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
@@ -719,84 +715,22 @@
 
 /*******************************************************************************
 **
-** Function         GATTS_CreateService
+** Function         BTA_GATTS_AddService
 **
-** Description      This function is called to reserve a block of handles for a service.
+** Description      Add a service. When service is ready, a callback
+**                  event BTA_GATTS_ADD_SRVC_EVT is called to report status
+**                  and handles to the profile.
 **
-**                  *** It should be called only once per service instance  ***
+** Parameters       server_if: server interface.
+**                  service: pointer array describing service.
+**                  count: number of elements in service array.
 **
-** Parameter        gatt_if       : application if
-**                  p_svc_uuid    : service UUID
-**                  svc_inst      : instance of the service inside the application
-**                  num_handles   : number of handles needed by the service.
-**                  is_pri        : is a primary service or not.
-**
-** Returns          service handle if sucessful, otherwise 0.
+** Returns          on success GATT_SERVICE_STARTED is returned, and
+**                  attribute_handle field inside service elements are filled.
+**                  on error error status is returned.
 **
 *******************************************************************************/
-extern UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
-                                   UINT16 svc_inst, UINT16 num_handles, BOOLEAN is_pri);
-
-
-/*******************************************************************************
-**
-** Function         GATTS_AddIncludeService
-**
-** Description      This function is called to add an included service.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  include_svc_handle    : included service handle.
-**
-** Returns          included service attribute handle. If 0, add included service
-**                  fail.
-**
-*******************************************************************************/
-extern UINT16 GATTS_AddIncludeService (UINT16 service_handle,
-                                       UINT16 include_svc_handle);
-
-
-/*******************************************************************************
-**
-** Function         GATTS_AddCharacteristic
-**
-** Description      This function is called to add a characteristic into a service.
-**                  It will add a characteristic declaration and characteristic
-**                  value declaration into the service database identified by the
-**                  service handle.
-**
-** Parameter        service_handle : To which service this included service is added to.
-**                  char_uuid : Characteristic UUID.
-**                  perm      : Characteristic value declaration attribute permission.
-**                  property  : Characteristic Properties
-**
-** Returns          Characteristic value declaration attribute handle. 0 if add
-**                  characteristic failed.
-**
-*******************************************************************************/
-extern UINT16 GATTS_AddCharacteristic (UINT16 service_handle, tBT_UUID *char_uuid,
-                                       tGATT_PERM perm,tGATT_CHAR_PROP property);
-
-/*******************************************************************************
-**
-** Function         GATTS_AddCharDescriptor
-**
-** Description      This function is called to add a characteristic descriptor
-**                  into a service database. Add descriptor should follow add char
-**                  to which it belongs, and next add char should be done only
-**                  after all add descriptors for the previous char.
-**
-** Parameter        service_handle  : To which service this characteristic descriptor
-**                                    is added to.
-**                  perm            : Characteristic value declaration attribute
-**                                    permission.
-**                  p_descr_uuid    : Characteristic descriptor UUID.
-**
-** Returns         Characteristic descriptor attribute handle. 0 if add
-**                 characteristic descriptor failed.
-**
-*******************************************************************************/
-extern UINT16 GATTS_AddCharDescriptor (UINT16 service_handle, tGATT_PERM perm,
-                                       tBT_UUID * p_descr_uuid);
+extern UINT16 GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t *service, int count);
 
 /*******************************************************************************
 **
@@ -814,22 +748,6 @@
 extern BOOLEAN GATTS_DeleteService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid,
                                     UINT16 svc_inst);
 
-/*******************************************************************************
-**
-** Function         GATTS_StartService
-**
-** Description      This function is called to start a service with GATT
-**
-** Parameter        gatt_if : service handle.
-**                  p_cback       : application service callback functions.
-**                  sup_transport : supported transport(s) for this primary service
-**
-** return           GATT_SUCCESS if sucessfully started; otherwise error code.
-**
-*******************************************************************************/
-extern tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle,
-                                        tGATT_TRANSPORT sup_transport);
-
 
 /*******************************************************************************
 **
diff --git a/stack/srvc/srvc_battery.c b/stack/srvc/srvc_battery.c
index 90632df..56151d5 100644
--- a/stack/srvc/srvc_battery.c
+++ b/stack/srvc/srvc_battery.c
@@ -22,6 +22,7 @@
 #include "gatt_int.h"
 #include "srvc_eng_int.h"
 #include "srvc_battery_int.h"
+#include "btcore/include/uuid.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -197,11 +198,9 @@
 *******************************************************************************/
 UINT16 Battery_Instantiate (UINT8 app_id, tBA_REG_INFO *p_reg_info)
 {
-    tBT_UUID            uuid = {LEN_UUID_16, {UUID_SERVCLASS_BATTERY}};
-    UINT16              srvc_hdl;
+    UINT16              srvc_hdl = 0;
     tGATT_STATUS        status = GATT_ERROR;
     tBA_INST            *p_inst;
-    tGATT_CHAR_PROP     prop = GATT_CHAR_PROP_BIT_READ;
 
     if (battery_cb.inst_id == BA_MAX_INT_NUM)
     {
@@ -211,16 +210,59 @@
 
     p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
 
-    srvc_hdl = GATTS_CreateService (srvc_eng_cb.gatt_if ,
-                                            &uuid,
-                                            battery_cb.inst_id ,
-                                            BA_MAX_ATTR_NUM,
-                                            p_reg_info->is_pri);
+    btgatt_db_element_t service[BA_MAX_ATTR_NUM] = {};
 
-    if (srvc_hdl == 0)
-    {
-        GATT_TRACE_ERROR("Can not create service, Battery_Instantiate() failed!");
-        return 0;
+    bt_uuid_t service_uuid;
+    uuid_128_from_16(&service_uuid, UUID_SERVCLASS_BATTERY);
+    service[0].type = /* p_reg_info->is_pri */ BTGATT_DB_PRIMARY_SERVICE;
+    service[0].uuid = service_uuid;
+
+    bt_uuid_t char_uuid;
+    uuid_128_from_16(&char_uuid, GATT_UUID_BATTERY_LEVEL);
+    service[1].type = BTGATT_DB_CHARACTERISTIC;
+    service[1].uuid = char_uuid;
+    service[1].properties = GATT_CHAR_PROP_BIT_READ;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
+        service[1].properties |= GATT_CHAR_PROP_BIT_NOTIFY;
+
+    int i=2;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
+        bt_uuid_t desc_uuid;
+        uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_CLIENT_CONFIG);
+
+        service[i].type = BTGATT_DB_DESCRIPTOR;
+        service[i].uuid = desc_uuid;
+        service[i].permissions = (GATT_PERM_READ|GATT_PERM_WRITE);
+        i++;
+    }
+
+    /* need presentation format descriptor? */
+    if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
+        bt_uuid_t desc_uuid;
+        uuid_128_from_16(&desc_uuid, GATT_UUID_CHAR_PRESENT_FORMAT);
+
+        service[i].type = BTGATT_DB_DESCRIPTOR;
+        service[i].uuid = desc_uuid;
+        service[i].permissions = GATT_PERM_READ;
+        i++;
+    }
+
+    /* need presentation format descriptor? */
+    if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
+        bt_uuid_t desc_uuid;
+        uuid_128_from_16(&desc_uuid, GATT_UUID_RPT_REF_DESCR);
+
+        service[i].type = BTGATT_DB_DESCRIPTOR;
+        service[i].uuid = desc_uuid;
+        service[i].permissions = GATT_PERM_READ;
+        i++;
+    }
+
+    GATTS_AddService(srvc_eng_cb.gatt_if, service, i);
+
+    if (status != GATT_SUCCESS) {
+        battery_cb.inst_id --;
+        GATT_TRACE_ERROR("%s: Failed to add battery servuce!", __func__);
     }
 
     battery_cb.inst_id ++;
@@ -228,71 +270,23 @@
     p_inst->app_id  =   app_id;
     p_inst->p_cback =   p_reg_info->p_cback;
 
-    /* add battery level
-    */
-    uuid.uu.uuid16 = GATT_UUID_BATTERY_LEVEL;
+    srvc_hdl = service[0].attribute_handle;
+    p_inst->ba_level_hdl = service[1].attribute_handle;
 
-    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
-        prop |= GATT_CHAR_PROP_BIT_NOTIFY;
-
-    if ((p_inst->ba_level_hdl  = GATTS_AddCharacteristic(srvc_hdl,
-                                                &uuid,
-                                                BATTER_LEVEL_PERM,
-                                                prop)) == 0)
-    {
-        GATT_TRACE_ERROR("Can not add Battery Level, Battery_Instantiate() failed!");
-        status = GATT_ERROR;
-    }
-    else
-    {
-        if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
-        {
-            uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG;
-            p_inst->clt_cfg_hdl  = GATTS_AddCharDescriptor(srvc_hdl,
-                                                           (GATT_PERM_READ|GATT_PERM_WRITE),
-                                                           &uuid);
-            if (p_inst->clt_cfg_hdl == 0)
-            {
-                GATT_TRACE_ERROR("Add battery level client notification FAILED!");
-            }
-        }
-        /* need presentation format descriptor? */
-        if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT)
-        {
-            uuid.uu.uuid16 = GATT_UUID_CHAR_PRESENT_FORMAT;
-            if ( (p_inst->pres_fmt_hdl = GATTS_AddCharDescriptor(srvc_hdl,
-                                                                 GATT_PERM_READ,
-                                                                 &uuid))
-                                       == 0)
-            {
-                GATT_TRACE_ERROR("Add battery level presentation format descriptor FAILED!");
-            }
-
-        }
-        /* need presentation format descriptor? */
-        if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF)
-        {
-            uuid.uu.uuid16 = GATT_UUID_RPT_REF_DESCR;
-            if ( (p_inst->rpt_ref_hdl = GATTS_AddCharDescriptor(srvc_hdl,
-                                                                GATT_PERM_READ,
-                                                                &uuid))
-                                       == 0)
-            {
-                GATT_TRACE_ERROR("Add battery level report reference descriptor FAILED!");
-            }
-
-        }
-        /* start service
-        */
-        status = GATTS_StartService (srvc_eng_cb.gatt_if, srvc_hdl, p_reg_info->transport);
+    i=2;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
+        p_inst->clt_cfg_hdl = service[i].attribute_handle;
+        i++;
     }
 
-    if (status != GATT_SUCCESS)
-    {
-        battery_cb.inst_id --;
-        uuid.uu.uuid16 = UUID_SERVCLASS_BATTERY;
-        GATTS_DeleteService(srvc_eng_cb.gatt_if, &uuid, battery_cb.inst_id);
-        srvc_hdl = 0;
+    if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
+        p_inst->pres_fmt_hdl = service[i].attribute_handle;
+        i++;
+    }
+
+    if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
+        p_inst->rpt_ref_hdl = service[i].attribute_handle;
+        i++;
     }
 
     return srvc_hdl;
diff --git a/stack/srvc/srvc_dis.c b/stack/srvc/srvc_dis.c
index ead8283..9fb5af2 100644
--- a/stack/srvc/srvc_dis.c
+++ b/stack/srvc/srvc_dis.c
@@ -25,6 +25,7 @@
 #include "osi/include/log.h"
 #include "srvc_dis_int.h"
 #include "srvc_eng_int.h"
+#include "btcore/include/uuid.h"
 
 #if BLE_INCLUDED == TRUE
 
@@ -342,46 +343,54 @@
 *******************************************************************************/
 tDIS_STATUS DIS_SrInit (tDIS_ATTR_MASK dis_attr_mask)
 {
-    tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_DEVICE_INFO}};
-    UINT16            i = 0;
     tGATT_STATUS      status;
-    tDIS_DB_ENTRY        *p_db_attr = &dis_cb.dis_attr[0];
 
-    if (dis_cb.enabled)
-    {
+    if (dis_cb.enabled) {
         GATT_TRACE_ERROR("DIS already initalized");
         return DIS_SUCCESS;
     }
 
     memset(&dis_cb, 0, sizeof(tDIS_CB));
 
-    dis_cb.service_handle = GATTS_CreateService (srvc_eng_cb.gatt_if , &uuid, 0, DIS_MAX_ATTR_NUM, TRUE);
+    btgatt_db_element_t service[DIS_MAX_ATTR_NUM] = { };
 
-    if (dis_cb.service_handle == 0)
-    {
-        GATT_TRACE_ERROR("Can not create service, DIS_Init failed!");
-        return GATT_ERROR;
-    }
-    dis_cb.max_handle = dis_cb.service_handle + DIS_MAX_ATTR_NUM;
+    bt_uuid_t svc_uuid;
+    uuid_128_from_16(&svc_uuid, UUID_SERVCLASS_DEVICE_INFO);
+    service[0].type = BTGATT_DB_PRIMARY_SERVICE;
+    service[0].uuid = svc_uuid;
 
-    while (dis_attr_mask != 0 && i < DIS_MAX_CHAR_NUM)
-    {
-        /* add Manufacturer name
-        */
-        uuid.uu.uuid16 = p_db_attr->uuid = dis_attr_uuid[i];
-        p_db_attr->handle  = GATTS_AddCharacteristic(dis_cb.service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
-        GATT_TRACE_DEBUG ("DIS_SrInit:  handle of new attribute 0x%04 = x%d", uuid.uu.uuid16, p_db_attr->handle  );
-        p_db_attr ++;
-        i ++;
+    for(int i=0; dis_attr_mask != 0 && i < DIS_MAX_CHAR_NUM; i++) {
+        dis_cb.dis_attr[i].uuid = dis_attr_uuid[i];
+
+        bt_uuid_t char_uuid;
+        uuid_128_from_16(&char_uuid, dis_cb.dis_attr[i].uuid);
+        /* index 0 is service, so characteristics start from 1 */
+        service[i+1].type = BTGATT_DB_CHARACTERISTIC;
+        service[i+1].uuid = char_uuid;
+        service[i+1].properties = GATT_CHAR_PROP_BIT_READ;
+        service[i+1].permissions = GATT_PERM_READ;
+
         dis_attr_mask >>= 1;
     }
 
-    /* start service
-    */
-    status = GATTS_StartService (srvc_eng_cb.gatt_if, dis_cb.service_handle, GATT_TRANSPORT_LE_BR_EDR);
+    /* Add a GAP service */
+    status = GATTS_AddService(srvc_eng_cb.gatt_if, service, sizeof(service)/sizeof(btgatt_db_element_t));
+    if (status != GATT_SERVICE_STARTED) {
+        GATT_TRACE_ERROR("Can not create service, DIS_Init failed!");
+        return GATT_ERROR;
+    }
+
+    dis_cb.service_handle = service[0].attribute_handle;
+    dis_cb.max_handle = dis_cb.service_handle + DIS_MAX_ATTR_NUM;
+
+    for (int i = 0; i < DIS_MAX_CHAR_NUM; i++) {
+        dis_cb.dis_attr[i].handle = service[i+1].attribute_handle;
+
+        GATT_TRACE_DEBUG ("%s:  handle of new attribute 0x%04 = x%d", __func__,
+            dis_cb.dis_attr[i].uuid, dis_cb.dis_attr[i].handle);
+    }
 
     dis_cb.enabled = TRUE;
-
     return (tDIS_STATUS) status;
 }
 /*******************************************************************************
diff --git a/stack/srvc/srvc_eng.c b/stack/srvc/srvc_eng.c
index 1c03b88..6ded138 100644
--- a/stack/srvc/srvc_eng.c
+++ b/stack/srvc/srvc_eng.c
@@ -278,11 +278,13 @@
 
     switch (type)
     {
-        case GATTS_REQ_TYPE_READ:
+        case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_READ_DESCRIPTOR:
             act = srvc_eng_process_read_req(clcb_idx, &p_data->read_req, &rsp_msg, &status);
             break;
 
-        case GATTS_REQ_TYPE_WRITE:
+        case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
+        case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
             act = srvc_eng_process_write_req(clcb_idx, &p_data->write_req, &rsp_msg, &status);
             if (!p_data->write_req.need_rsp)
                 act = SRVC_ACT_IGNORE;
diff --git a/test/suite/gatt/gatt_test.cc b/test/suite/gatt/gatt_test.cc
index 48f279e..b068d35 100644
--- a/test/suite/gatt/gatt_test.cc
+++ b/test/suite/gatt/gatt_test.cc
@@ -47,9 +47,6 @@
 
   register_server_callback_sem_ = semaphore_new(0);
   service_added_callback_sem_ = semaphore_new(0);
-  characteristic_added_callback_sem_ = semaphore_new(0);
-  descriptor_added_callback_sem_ = semaphore_new(0);
-  service_started_callback_sem_ = semaphore_new(0);
   service_stopped_callback_sem_ = semaphore_new(0);
   service_deleted_callback_sem_ = semaphore_new(0);
 
@@ -76,9 +73,6 @@
 
   semaphore_free(register_server_callback_sem_);
   semaphore_free(service_added_callback_sem_);
-  semaphore_free(characteristic_added_callback_sem_);
-  semaphore_free(descriptor_added_callback_sem_);
-  semaphore_free(service_started_callback_sem_);
   semaphore_free(service_stopped_callback_sem_);
   semaphore_free(service_deleted_callback_sem_);
 
@@ -130,45 +124,13 @@
 
 void GattTest::ServiceAddedCallback(
     bluetooth::hal::BluetoothGattInterface* /* unused */,
-    int status, int server_if, const btgatt_srvc_id_t& srvc_id,
-    int srvc_handle) {
+    int status, int server_if, vector<btgatt_db_element_t> service) {
   status_ = status;
   server_interface_id_ = server_if;
-  service_handle_ = srvc_handle;
+  service_handle_ = service[0].attribute_handle;
   semaphore_post(service_added_callback_sem_);
 }
 
-void GattTest::CharacteristicAddedCallback(
-    bluetooth::hal::BluetoothGattInterface* /* unused */,
-    int status, int server_if, const bt_uuid_t& char_id,
-    int srvc_handle, int char_handle) {
-  status_ = status;
-  server_interface_id_ = server_if;
-  service_handle_ = srvc_handle;
-  characteristic_handle_ = char_handle;
-  semaphore_post(characteristic_added_callback_sem_);
-}
-
-void GattTest::DescriptorAddedCallback(
-    bluetooth::hal::BluetoothGattInterface* /* unused */,
-    int status, int server_if, const bt_uuid_t& descr_id,
-    int srvc_handle, int descr_handle) {
-  status_ = status;
-  server_interface_id_ = server_if;
-  service_handle_ = srvc_handle;
-  descriptor_handle_ = descr_handle;
-  semaphore_post(descriptor_added_callback_sem_);
-}
-
-void GattTest::ServiceStartedCallback(
-    bluetooth::hal::BluetoothGattInterface* /* unused */,
-    int status, int server_if, int srvc_handle) {
-  status_ = status;
-  server_interface_id_ = server_if;
-  service_handle_ = srvc_handle;
-  semaphore_post(service_started_callback_sem_);
-}
-
 void GattTest::ServiceStoppedCallback(
     bluetooth::hal::BluetoothGattInterface* /* unused */,
     int status, int server_if, int srvc_handle) {
diff --git a/test/suite/gatt/gatt_test.h b/test/suite/gatt/gatt_test.h
index 3c09d2e..d4cc664 100644
--- a/test/suite/gatt/gatt_test.h
+++ b/test/suite/gatt/gatt_test.h
@@ -69,19 +69,7 @@
       int status, int server_if, const bt_uuid_t& uuid) override;
   void ServiceAddedCallback(
       bluetooth::hal::BluetoothGattInterface* /* unused */,
-      int status, int server_if, const btgatt_srvc_id_t& srvc_id,
-      int srvc_handle) override;
-  void CharacteristicAddedCallback(
-      bluetooth::hal::BluetoothGattInterface* /* unused */,
-      int status, int server_if, const bt_uuid_t& char_id,
-      int srvc_handle, int char_handle) override;
-  void DescriptorAddedCallback(
-      bluetooth::hal::BluetoothGattInterface* /* unused */,
-      int status, int server_if, const bt_uuid_t& descr_id,
-      int srvc_handle, int descr_handle) override;
-  void ServiceStartedCallback(
-      bluetooth::hal::BluetoothGattInterface* /* unused */,
-      int status, int server_if, int srvc_handle) override;
+      int status, int server_if, vector<btgatt_db_element_t> service) override;
   void ServiceStoppedCallback(
       bluetooth::hal::BluetoothGattInterface* /* unused */,
       int status, int server_if, int srvc_handle) override;
diff --git a/test/suite/gatt/gatt_unittest.cc b/test/suite/gatt/gatt_unittest.cc
index e731634..9fc4f02 100644
--- a/test/suite/gatt/gatt_unittest.cc
+++ b/test/suite/gatt/gatt_unittest.cc
@@ -107,10 +107,8 @@
     << "Error registering GATT server app callback.";
 
   // Service UUID.
-  btgatt_srvc_id_t srvc_id;
-  srvc_id.id.inst_id = 0;   // there is only one instance of this service.
-  srvc_id.is_primary = 1;   // this service is primary.
-  create_random_uuid(&srvc_id.id.uuid, -1);
+  bt_uuid_t srvc_uuid;
+  create_random_uuid(&srvc_uuid, -1);
 
   // Characteristics UUID.
   bt_uuid_t char_uuid;
@@ -122,37 +120,25 @@
 
   // Adds service.
   int server_if = server_interface_id();
-  gatt_server_interface()->add_service(server_if, &srvc_id, 4 /* # handles */);
+
+  vector<btgatt_db_element_t> service = {
+    {.type = BTGATT_DB_PRIMARY_SERVICE, .uuid=srvc_uuid},
+    {.type = BTGATT_DB_CHARACTERISTIC, .uuid=char_uuid,
+     .properties = 0x10 /* notification */, .permissions = 0x01  /* read only */},
+    {.type = BTGATT_DB_DESCRIPTOR, .uuid=desc_uuid, .permissions = 0x01}
+  };
+
+  gatt_server_interface()->add_service(server_if, service);
   semaphore_wait(service_added_callback_sem_);
   EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error adding service.";
 
-  // Adds characteristics.
-  int srvc_handle = service_handle();
-  gatt_server_interface()->add_characteristic(server_if, srvc_handle,
-      &char_uuid, 0x10 /* notification */, 0x01 /* read only */);
-  semaphore_wait(characteristic_added_callback_sem_);
-  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
-      << "Error adding characteristics.";
-
-  // Adds descriptor.
-  gatt_server_interface()->add_descriptor(server_if, srvc_handle,
-                                          &desc_uuid, 0x01);
-  semaphore_wait(descriptor_added_callback_sem_);
-  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
-      << "Error adding descriptor.";
-
-  // Starts server.
-  gatt_server_interface()->start_service(server_if, srvc_handle, 2 /*BREDR/LE*/);
-  semaphore_wait(service_started_callback_sem_);
-  EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error starting server.";
-
   // Stops server.
-  gatt_server_interface()->stop_service(server_if, srvc_handle);
+  gatt_server_interface()->stop_service(server_if, service_handle());
   semaphore_wait(service_stopped_callback_sem_);
   EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error stopping server.";
 
   // Deletes service.
-  gatt_server_interface()->delete_service(server_if, srvc_handle);
+  gatt_server_interface()->delete_service(server_if, service_handle());
   semaphore_wait(service_deleted_callback_sem_);
   EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error deleting service.";