OSDN Git Service

Restructure GATTC
authorJakub Pawlowski <jpawlowski@google.com>
Tue, 15 Mar 2016 22:35:00 +0000 (15:35 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Tue, 22 Mar 2016 03:18:07 +0000 (20:18 -0700)
This patch changes how GATTC is structured. Up till now, it
contained tBTA_GATTC_CACHE and tBTA_GATTC_CACHE_ATTR. Those
structures were so ugly, someone hide them inside internal
header, to make sure noone would ever access them from outside
GATTC. They are now replaced with:
tBTA_GATTC_SERVICE,
tBTA_GATTC_CHARACTERISTIC,
tBTA_GATTC_DESCRIPTOR and
tBTA_GATTC_INCLUDED_SVC.

Those looks much better, and were made globally avaliable.
Thanks to way they're build, we no longer need set of access
methods, which were also very ugly:
BTA_GATTC_GetFirstChar
BTA_GATTC_GetNextChar
BTA_GATTC_GetFirstIncludedService
etc.

This patch breaks HID, DO NOT SUBMIT without HID refactor.

Bug: 27455533
Change-Id: Ic42cfff175e0cc1a0d8e1a1216e2b4b756cbf77d

bta/gatt/bta_gattc_api.c
bta/gatt/bta_gattc_cache.c
bta/gatt/bta_gattc_int.h
bta/include/bta_gatt_api.h

index 8e6d1d4..923eb20 100644 (file)
@@ -259,168 +259,49 @@ void BTA_GATTC_ServiceSearchRequest (UINT16 conn_id, tBT_UUID *p_srvc_uuid)
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstChar
+** Function         BTA_GATTC_GetServices
 **
-** Description      This function is called to find the first characteristic of the
-**                  service on the given server.
+** Description      This function is called to find the services on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_char_result: output parameter which will store the GATT
-**                                  characteristic ID.
-**                  p_property: output parameter to carry the characteristic property.
 **
-** Returns          returns status.
+** Returns          returns list_t of tBTA_GATTC_SERVICE or NULL.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
-                                          tBT_UUID *p_char_uuid_cond,
-                                          tBTA_GATTC_CHAR_ID *p_char_result,
-                                          tBTA_GATT_CHAR_PROP *p_property)
-{
-    tBTA_GATT_STATUS    status;
-
-    if (!p_srvc_id || !p_char_result)
-        return BTA_GATT_ILLEGAL_PARAMETER;
-
-    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR, p_srvc_id, NULL,
-                                        p_char_uuid_cond, &p_char_result->char_id, (void *)p_property))
-        == BTA_GATT_OK)
-    {
-        memcpy(&p_char_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
-
-    return status;
-
-}
-/*******************************************************************************
-**
-** Function         BTA_GATTC_GetNextChar
-**
-** Description      This function is called to find the next characteristic of the
-**                  service on the given server.
-**
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_start_char_id: start the characteristic search from the next record
-**                           after the one identified by char_id.
-**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_char_result: output parameter which will store the GATT
-**                                  characteristic ID.
-**                  p_property: output parameter to carry the characteristic property.
-**
-** Returns          returns status.
-**
-*******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
-                                         tBTA_GATTC_CHAR_ID *p_start_char_id,
-                                         tBT_UUID           *p_char_uuid_cond,
-                                         tBTA_GATTC_CHAR_ID *p_char_result,
-                                         tBTA_GATT_CHAR_PROP    *p_property)
-{
-    tBTA_GATT_STATUS    status;
-
-    if (!p_start_char_id || !p_char_result)
-        return BTA_GATT_ILLEGAL_PARAMETER;
-
-    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR,
-                                        &p_start_char_id->srvc_id,
-                                        &p_start_char_id->char_id,
-                                        p_char_uuid_cond,
-                                        &p_char_result->char_id,
-                                        (void *) p_property))
-        == BTA_GATT_OK)
-    {
-        memcpy(&p_char_result->srvc_id, &p_start_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
-
-    return status;
+const list_t* BTA_GATTC_GetServices(UINT16 conn_id) {
+    return bta_gattc_get_services(conn_id);
 }
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstCharDescr
+** Function         BTA_GATTC_GetCharacteristic
 **
-** Description      This function is called to find the first characteristic descriptor of the
-**                  characteristic on the given server.
+** Description      This function is called to find the characteristic on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
-**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
-**                               characteristic.
-**                  p_descr_result: output parameter which will store the GATT
-**                                  characteristic descriptor ID.
+**                  handle: characteristic handle
 **
-** Returns          returns status.
+** Returns          returns pointer to tBTA_GATTC_CHARACTERISTIC or NULL.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
-                                                tBT_UUID *p_descr_uuid_cond,
-                                                tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
-{
-    tBTA_GATT_STATUS    status;
-
-    if (!p_char_id || !p_descr_result)
-        return BTA_GATT_ILLEGAL_PARAMETER;
-
-    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
-
-    if ((status = bta_gattc_query_cache(conn_id,
-                                        BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
-                                        &p_char_id->srvc_id,
-                                        &p_char_id->char_id,
-                                        p_descr_uuid_cond,
-                                        &p_descr_result->char_id.char_id,
-                                        NULL))
-        == BTA_GATT_OK)
-    {
-        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
-        memcpy(&p_descr_result->char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
-    }
-    return status;
-
+const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetCharacteristic(UINT16 conn_id, UINT16 handle) {
+    return bta_gattc_get_characteristic(conn_id, handle);
 }
 
 /*******************************************************************************
 **
-** Function         BTA_GATTC_GetFirstIncludedService
+** Function         BTA_GATTC_GetCharacteristic
 **
-** Description      This function is called to find the first included service of the
-**                  service on the given server.
+** Description      This function is called to find the characteristic on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  p_uuid_cond: Characteristic UUID, if NULL find the first available
-**                               characteristic.
-**                  p_result: output parameter which will store the GATT ID
-**                              of the included service found.
+**                  handle: descriptor handle
 **
-** Returns          returns status.
+** Returns          returns pointer to tBTA_GATTC_DESCRIPTOR or NULL.
 **
 *******************************************************************************/
-tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
-                                                    tBT_UUID *p_uuid_cond, tBTA_GATTC_INCL_SVC_ID *p_result)
-{
-    tBTA_GATT_STATUS    status;
-
-    if (!p_srvc_id || !p_result)
-        return BTA_GATT_ILLEGAL_PARAMETER;
-
-    if ((status = bta_gattc_query_cache(conn_id,
-                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
-                                        p_srvc_id,
-                                        NULL,
-                                        p_uuid_cond,
-                                        &p_result->incl_svc_id.id,
-                                        (void *)&p_result->incl_svc_id.is_primary))
-        == BTA_GATT_OK)
-    {
-        memcpy(&p_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
-    }
-
-    return status;
+const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(UINT16 conn_id, UINT16 handle) {
+    return bta_gattc_get_descriptor(conn_id, handle);
 }
 
 /*******************************************************************************
index 31cc2ef..8dcd21e 100644 (file)
@@ -48,11 +48,14 @@ static void bta_gattc_cache_write(BD_ADDR server_bda, UINT16 num_attr, tBTA_GATT
 static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
 static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
 extern void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
+tBTA_GATTC_SERVICE*  bta_gattc_find_matching_service(const list_t *services, UINT16 handle);
+tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
+tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle);
 
 #define BTA_GATT_SDP_DB_SIZE 4096
 
 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
-#define GATT_CACHE_VERSION 1
+#define GATT_CACHE_VERSION 2
 
 static void bta_gattc_generate_cache_file_name(char *buffer, BD_ADDR bda)
 {
@@ -82,21 +85,21 @@ static char *bta_gattc_attr_type[] =
 bool display_cache_attribute(void *data, void *context) {
     tBTA_GATTC_CACHE_ATTR *p_attr = data;
     APPL_TRACE_ERROR("\t Attr handle[%d] uuid[0x%04x] type[%s] prop[0x%1x]",
-                      p_attr->attr_handle, p_attr->uuid.uu.uuid16,
+                      p_attr->handle, p_attr->uuid.uu.uuid16,
                       bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
     return true;
 }
 
 bool display_cache_service(void *data, void *context) {
-    tBTA_GATTC_CACHE    *p_cur_srvc = data;
+    tBTA_GATTC_SERVICE    *p_cur_srvc = data;
     APPL_TRACE_ERROR("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]",
                       p_cur_srvc->s_handle, p_cur_srvc->e_handle,
                       ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
                       p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
                       p_cur_srvc->service_uuid.id.inst_id);
 
-    if (p_cur_srvc->p_attr != NULL) {
-        list_foreach(p_cur_srvc->p_attr, display_cache_attribute, NULL);
+    if (p_cur_srvc->characteristics != NULL) {
+        list_foreach(p_cur_srvc->characteristics, display_cache_attribute, NULL);
     }
 
     return true;
@@ -169,17 +172,19 @@ tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
     p_srvc_cb->cur_char_idx = 0;
     p_srvc_cb->next_avail_idx = 0;
 
-    p_srvc_cb->p_cur_srvc = NULL;
-
     return BTA_GATT_OK;
 }
 
-void service_free(void *ptr) {
-  tBTA_GATTC_CACHE *srvc = ptr;
-
-  if (srvc->p_attr)
-    list_free(srvc->p_attr);
+static void characteristic_free(void *ptr) {
+  tBTA_GATTC_CHARACTERISTIC *p_char = ptr;
+  list_free(p_char->descriptors);
+  osi_free(p_char);
+}
 
+static void service_free(void *ptr) {
+  tBTA_GATTC_SERVICE *srvc = ptr;
+  list_free(srvc->characteristics);
+  list_free(srvc->included_svc);
   osi_free(srvc);
 }
 
@@ -201,7 +206,7 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
     APPL_TRACE_DEBUG("Add a service into Service");
 #endif
 
-    tBTA_GATTC_CACHE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_CACHE));
+    tBTA_GATTC_SERVICE *p_new_srvc = osi_malloc(sizeof(tBTA_GATTC_SERVICE));
 
     /* update service information */
     p_new_srvc->s_handle = s_handle;
@@ -209,10 +214,8 @@ static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
     p_new_srvc->service_uuid.is_primary = is_primary;
     memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
     p_new_srvc->service_uuid.id.inst_id = s_handle;
-    p_new_srvc->p_attr = NULL;
-
-    p_srvc_cb->p_cur_srvc = p_new_srvc;
-    p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
+    p_new_srvc->characteristics = list_new(characteristic_free);
+    p_new_srvc->included_svc = list_new(osi_free);
 
     if (p_srvc_cb->p_srvc_cache == NULL) {
         p_srvc_cb->p_srvc_cache = list_new(service_free);
@@ -234,35 +237,68 @@ static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
                                                     UINT16 handle,
                                                     tBT_UUID *p_uuid,
                                                     UINT8 property,
+                                                    UINT16 incl_srvc_s_handle,
                                                     tBTA_GATTC_ATTR_TYPE type)
 {
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
     APPL_TRACE_DEBUG("%s: Add a [%s] into Service", __func__, bta_gattc_attr_type[type]);
-    APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
+    APPL_TRACE_DEBUG("handle=%d uuid16=0x%x property=0x%x type=%d",
+                      handle, p_uuid->uu.uuid16, property, type);
 #endif
 
-    if (p_srvc_cb->p_cur_srvc == NULL) {
-        APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc before adding a service!");
+    tBTA_GATTC_SERVICE *service = bta_gattc_find_matching_service(p_srvc_cb->p_srvc_cache, handle);
+    if (!service) {
+        APPL_TRACE_ERROR("Illegal action to add char/descr/incl srvc for non-existing service!");
         return GATT_WRONG_STATE;
     }
 
-    tBTA_GATTC_CACHE_ATTR *p_attr =
-        osi_malloc(sizeof(tBTA_GATTC_CACHE_ATTR));
+    if (type == BTA_GATTC_ATTR_TYPE_CHAR) {
+        tBTA_GATTC_CHARACTERISTIC *characteristic =
+            osi_malloc(sizeof(tBTA_GATTC_CHARACTERISTIC));
+
+        characteristic->handle = handle;
+        characteristic->properties = property;
+        characteristic->descriptors = list_new(osi_free);
+        memcpy(&characteristic->uuid, p_uuid, sizeof(tBT_UUID));
+
+        characteristic->service = service;
+        list_append(service->characteristics, characteristic);
+    } else if (type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) {
+        tBTA_GATTC_INCLUDED_SVC *isvc =
+            osi_malloc(sizeof(tBTA_GATTC_INCLUDED_SVC));
+
+        isvc->handle = handle;
+        memcpy(&isvc->uuid, p_uuid, sizeof(tBT_UUID));
+
+        isvc->owning_service = service;
+        isvc->included_service = bta_gattc_find_matching_service(
+                                    p_srvc_cb->p_srvc_cache, incl_srvc_s_handle);
+        if (!isvc->included_service) {
+            APPL_TRACE_ERROR("%s: Illegal action to add non-existing included service!", __func__);
+            osi_free(isvc);
+            return GATT_WRONG_STATE;
+        }
 
-    p_attr->attr_handle = handle;
-    p_attr->attr_type   = type;
-    p_attr->property    = property;
-    memcpy(&p_attr->uuid, p_uuid, sizeof(tBT_UUID));
+        list_append(service->included_svc, isvc);
+    } else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
+        tBTA_GATTC_DESCRIPTOR *descriptor =
+            osi_malloc(sizeof(tBTA_GATTC_DESCRIPTOR));
 
-    if (p_srvc_cb->p_cur_srvc->p_attr == NULL) {
-        p_srvc_cb->p_cur_srvc->p_attr = list_new(osi_free);
-    }
+        descriptor->handle = handle;
+        memcpy(&descriptor->uuid, p_uuid, sizeof(tBT_UUID));
 
-    list_append(p_srvc_cb->p_cur_srvc->p_attr, p_attr);
+        if (service->characteristics == NULL) {
+            APPL_TRACE_ERROR("%s: Illegal action to add descriptor before adding a characteristic!",
+                             __func__);
+            osi_free(descriptor);
+            return GATT_WRONG_STATE;
+        }
 
-    if (type == BTA_GATTC_ATTR_TYPE_CHAR)
-        p_srvc_cb->p_cur_srvc->p_cur_char = list_back_node(p_srvc_cb->p_cur_srvc->p_attr);
+        tBTA_GATTC_CHARACTERISTIC *char_node = list_back(service->characteristics);
 
+        descriptor->characteristic = char_node;
+        list_append(char_node->descriptors, descriptor);
+    }
     return BTA_GATT_OK;
 }
 
@@ -493,6 +529,7 @@ static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
                                      p_rec->s_handle,
                                      &p_rec->uuid,
                                      p_rec->property,
+                                     0 /* incl_srvc_handle */,
                                      BTA_GATTC_ATTR_TYPE_CHAR);
 
         /* start discoverying characteristic descriptor , if failed, disc for next char*/
@@ -526,6 +563,7 @@ static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_sr
                                      p_rec->s_handle,
                                      &p_rec->uuid,
                                      p_rec->property,
+                                     0 /* incl_srvc_handle */,
                                      BTA_GATTC_ATTR_TYPE_CHAR);
 
         /* start discoverying next characteristic for char descriptor */
@@ -840,6 +878,7 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
                                             p_data->handle,
                                             &p_data->value.incl_service.service_type,
                                             pri_srvc,
+                                            p_data->value.incl_service.s_handle,
                                             BTA_GATTC_ATTR_TYPE_INCL_SRVC);
                 break;
 
@@ -854,6 +893,7 @@ void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_
 
             case GATT_DISC_CHAR_DSCPT:
                 bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0,
+                                            0 /* incl_srvc_handle */,
                                             BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
                 break;
         }
@@ -917,9 +957,6 @@ void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT
 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
                             tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
 {
-
-    tBTA_GATTC_CACHE_ATTR *p_char = NULL;
-
     memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
     memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
     memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
@@ -927,59 +964,24 @@ BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SR
     if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
         return FALSE;
 
-    for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
-         sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
-        tBTA_GATTC_CACHE *p_cache = list_node(sn);
-
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-        APPL_TRACE_DEBUG("Service: handle[%d] uuid[0x%04x]",
-                          p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16);
-#endif
-        /* a service found */
-        if (p_cache->s_handle == handle) {
-            memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
-            return TRUE;
-        }
+    tBTA_GATTC_DESCRIPTOR* p_desc = bta_gattc_get_descriptor_srcb(p_srcb, handle);
+    tBTA_GATTC_CHARACTERISTIC* p_char = NULL;
+    if (p_desc) {
+        memcpy(&p_descr_type->uuid, &p_desc->uuid, sizeof(tBT_UUID));
+        p_descr_type->inst_id = p_desc->handle;
 
-        if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
-            continue;
+        p_char = p_desc->characteristic;
+    } else {
+        p_char = bta_gattc_get_characteristic_srcb(p_srcb, handle);
+    }
 
-        for (list_node_t *an = list_begin(p_cache->p_attr);
-             an != list_end(p_cache->p_attr); an = list_next(an)) {
-            tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
-        /* start looking for attributes within the service */
+    if (p_char) {
+        memcpy(&p_char_id->uuid, &p_char->uuid, sizeof(tBT_UUID));
+        p_char_id->inst_id = p_char->handle;
 
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-            APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] type[%d]",
-                              p_attr->attr_handle, p_attr->uuid.uu.uuid16,
-                              p_attr->attr_type);
-#endif
-            if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
-                p_char = p_attr;
-
-            if (handle == p_attr->attr_handle) {
-                memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
-
-                if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
-                    memcpy(&p_descr_type->uuid, &p_attr->uuid, sizeof(tBT_UUID));
-                    p_descr_type->inst_id = p_attr->attr_handle;
-
-                    if (p_char != NULL) {
-                        memcpy(&p_char_id->uuid, &p_char->uuid, sizeof(tBT_UUID));
-                        p_char_id->inst_id = p_char->attr_handle;
-                    } else {
-                        APPL_TRACE_ERROR("descptr does not belong to any chracteristic");
-                    }
-                } else {
-                    /* is a characterisitc value or included service */
-                    memcpy(&p_char_id->uuid, &p_attr->uuid, sizeof(tBT_UUID));
-                    p_char_id->inst_id =p_attr->attr_handle;
-                }
-                return TRUE;
-            }
-        }
+        memcpy(p_service_id, &p_char->service->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+        return TRUE;
     }
-
     return FALSE;
 }
 
@@ -1001,7 +1003,7 @@ void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
 
     for (list_node_t *sn = list_begin(p_clcb->p_srcb->p_srvc_cache);
          sn != list_end(p_clcb->p_srcb->p_srvc_cache); sn = list_next(sn)) {
-        tBTA_GATTC_CACHE *p_cache = list_node(sn);
+        tBTA_GATTC_SERVICE *p_cache = list_node(sn);
 
         if (!bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
             continue;
@@ -1024,184 +1026,107 @@ void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
         (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
     }
 }
-/*******************************************************************************
-**
-** Function         bta_gattc_find_record
-**
-** Description      search local cache for matching attribute record.
-**
-** Parameter        p_result: output parameter to store the characteristic/
-**                            included service GATT ID.
-**
-** Returns          GATT_ERROR is no recording found. BTA_GATT_OK if record found.
-**
-*******************************************************************************/
-static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
-                                              tBTA_GATTC_ATTR_TYPE attr_type,
-                                              tBTA_GATT_SRVC_ID *p_service_id,
-                                              tBTA_GATT_ID  *p_start_rec,
-                                              tBT_UUID      * p_uuid_cond,
-                                              tBTA_GATT_ID  *p_result,
-                                              void *p_param)
-{
-    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
-    BOOLEAN             char_found = FALSE, descr_found = FALSE;
-    tBTA_GATT_ID        *p_descr_id = (tBTA_GATT_ID *)p_param;;
 
-    if (!p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
-        return FALSE;
+list_t* bta_gattc_get_services_srcb(tBTA_GATTC_SERV *p_srcb) {
+    if (!p_srcb || !p_srcb->p_srvc_cache || list_is_empty(p_srcb->p_srvc_cache))
+        return NULL;
 
-    for (list_node_t *sn = list_begin(p_srcb->p_srvc_cache);
-         sn != list_end(p_srcb->p_srvc_cache); sn = list_next(sn)) {
-        tBTA_GATTC_CACHE *p_cache = list_node(sn);
+    return p_srcb->p_srvc_cache;
+}
 
-        if (status == BTA_GATT_OK)
-            break;
+const list_t* bta_gattc_get_services(UINT16 conn_id) {
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
-        if (!bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
-            continue;
+    if (p_clcb == NULL )
+        return NULL;
 
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-        APPL_TRACE_DEBUG("found matching service [0x%04x], inst[%d]",
-                          p_cache->service_uuid.id.uuid.uu.uuid16,
-                          p_cache->service_uuid.id.inst_id);
-#endif
-        if (!p_cache->p_attr || list_is_empty(p_cache->p_attr))
-            continue;
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
 
-        for (list_node_t *an = list_begin(p_cache->p_attr);
-             an != list_end(p_cache->p_attr); an = list_next(an)) {
-            tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
+    return bta_gattc_get_services_srcb(p_srcb);
+}
 
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-            APPL_TRACE_DEBUG("\t Attr handle[0x%04x] uuid[0x%04x] type[%d]",
-                              p_attr->attr_handle,
-                              p_attr->uuid.uu.uuid16,
-                              p_attr->attr_type);
-#endif
-            memcpy(&p_result->uuid, &p_attr->uuid, sizeof(tBT_UUID));
-
-            if (p_start_rec != NULL && char_found == FALSE) {
-                /* find the starting record first */
-                if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
-                    p_start_rec->inst_id  == p_attr->attr_handle &&
-                    (attr_type == p_attr->attr_type ||
-                    /* find descriptor would look for characteristic first */
-                     (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
-                      p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
-                    char_found = TRUE;
-            } else {
-                /* if looking for descriptor, here is the where the descrptor to be found */
-                if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) {
-                    /* next characeteristic already, return error */
-                    if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
-                        break;
-
-                    /* find starting descriptor */
-                    if (p_descr_id != NULL && !descr_found) {
-                        if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
-                            && p_descr_id->inst_id == p_attr->attr_handle)
-                                descr_found = TRUE;
-                    } else {
-                        /* with matching descriptor */
-                        if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
-                        {
-                            p_result->inst_id = p_attr->attr_handle;
-                            status = BTA_GATT_OK;
-                            break;
-                        }
-                    }
-                } else {
-                    if (!bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) ||
-                        attr_type != p_attr->attr_type)
-                        continue;
+tBTA_GATTC_SERVICE*  bta_gattc_find_matching_service(const list_t *services, UINT16 handle) {
+    if (!services || list_is_empty(services))
+        return NULL;
 
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-                    APPL_TRACE_DEBUG("found char handle mapping characteristic");
-#endif
-                    p_result->inst_id = p_attr->attr_handle;
+    for (list_node_t *sn = list_begin(services);
+         sn != list_end(services); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *service = list_node(sn);
 
-                    if (p_param != NULL && (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
-                        attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC))
-                            *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
+        if (handle >= service->s_handle && handle <= service->e_handle)
+            return service;
+    }
 
-                    status = BTA_GATT_OK;
-                    break;
-                }
-            }
-        }
-#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
-        if (status)
-            APPL_TRACE_ERROR("In the given service, can not find matching record");
-#endif
+    return NULL;
+}
+
+const tBTA_GATTC_SERVICE*  bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) {
+    const list_t *services = bta_gattc_get_services_srcb(p_srcb);
+
+    return bta_gattc_find_matching_service(services, handle);
+}
+
+const tBTA_GATTC_SERVICE*  bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle) {
+    const list_t *services = bta_gattc_get_services(conn_id);
+
+    return bta_gattc_find_matching_service(services, handle);
+}
+
+tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) {
+    const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
+
+    if (!service)
+        return NULL;
+
+    for (list_node_t *cn = list_begin(service->characteristics);
+         cn != list_end(service->characteristics); cn = list_next(cn)) {
+        tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+        if (handle == p_char->handle)
+            return p_char;
     }
-    return status;
+
+    return NULL;
 }
 
-/*******************************************************************************
-**
-** Function         bta_gattc_query_cache
-**
-** Description      search local cache for matching attribute record.
-**
-** Parameters       conn_id: connection ID which identify the server.
-**                  p_srvc_id: the service ID of which the characteristic is belonged to.
-**                  *p_start_rec: start the search from the next record
-**                                  after the one identified by *p_start_rec.
-**                  p_uuid_cond: UUID, if NULL find the first available
-**                               characteristic/included service.
-**                  p_output:   output parameter which will store the GATT ID
-**                              of the characteristic /included service found.
-**
-** Returns          BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
-**
-*******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
-                                       tBTA_GATTC_ATTR_TYPE query_type,
-                                       tBTA_GATT_SRVC_ID *p_srvc_id,
-                                       tBTA_GATT_ID *p_start_rec,
-                                       tBT_UUID *p_uuid_cond,
-                                       tBTA_GATT_ID *p_output,
-                                       void *p_param)
-{
-    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
-    tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+tBTA_GATTC_CHARACTERISTIC*  bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle) {
+   tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
-    if (p_clcb != NULL )
-    {
-        if (p_clcb->state == BTA_GATTC_CONN_ST)
-        {
-            if (p_clcb->p_srcb &&
-                !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
-                p_clcb->p_srcb->p_srvc_cache)
-            {
-                status = bta_gattc_find_record(p_clcb->p_srcb,
-                                               query_type,
-                                               p_srvc_id,
-                                               p_start_rec,
-                                               p_uuid_cond,
-                                               p_output,
-                                               p_param);
-            }
-            else
-            {
-                status = BTA_GATT_ERROR;
-                APPL_TRACE_ERROR("No server cache available");
-            }
-        }
-        else
-        {
-            APPL_TRACE_ERROR("server cache not available, CLCB state = %d", p_clcb->state);
+    if (p_clcb == NULL )
+        return NULL;
 
-            status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
-        }
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    return bta_gattc_get_characteristic_srcb(p_srcb, handle);
+}
+
+tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV *p_srcb, UINT16 handle) {
+    const tBTA_GATTC_SERVICE* service = bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
+
+    if (!service) {
+        return NULL;
     }
-    else
-    {
-        APPL_TRACE_ERROR("Unknown conn ID: %d", conn_id);
+
+    for (list_node_t *cn = list_begin(service->characteristics);
+         cn != list_end(service->characteristics); cn = list_next(cn)) {
+        tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+        for (list_node_t *dn = list_begin(p_char->descriptors);
+             dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+            tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+            if (handle == p_desc->handle)
+                return p_desc;
+        }
     }
 
-    return status;
+    return NULL;
+}
+
+tBTA_GATTC_DESCRIPTOR*  bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle) {
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb == NULL )
+        return NULL;
+
+    tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+    return bta_gattc_get_descriptor_srcb(p_srcb, handle);
 }
 
 /*******************************************************************************
@@ -1240,7 +1165,7 @@ static size_t bta_gattc_get_db_size(list_t *services,
 
     for (list_node_t *sn = list_begin(services);
          sn != list_end(services); sn = list_next(sn)) {
-        tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
 
         if (p_cur_srvc->s_handle < start_handle)
             continue;
@@ -1249,8 +1174,21 @@ static size_t bta_gattc_get_db_size(list_t *services,
             break;
 
         db_size++;
-        if (p_cur_srvc->p_attr)
-            db_size += list_length(p_cur_srvc->p_attr);
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics))
+            continue;
+
+        for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+             cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+            tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+            db_size++;
+
+            if (p_char->descriptors)
+                db_size += list_length(p_char->descriptors);
+        }
+
+        if (p_cur_srvc->included_svc) {
+            db_size += list_length(p_cur_srvc->included_svc);
+        }
     }
 
     return db_size;
@@ -1276,7 +1214,8 @@ static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
                                        btgatt_db_element_t **db,
                                        int *count)
 {
-    APPL_TRACE_DEBUG(LOG_TAG, "%s", __func__);
+    APPL_TRACE_DEBUG(LOG_TAG, "%s: start_handle 0x%04x, end_handle 0x%04x",
+                     __func__, start_handle, end_handle);
 
     if (!p_srvc_cb->p_srvc_cache || list_is_empty(p_srvc_cb->p_srvc_cache)) {
         *count = 0;
@@ -1291,7 +1230,7 @@ static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
 
     for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
          sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
-        tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
 
         if (p_cur_srvc->s_handle < start_handle)
             continue;
@@ -1311,42 +1250,57 @@ static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV *p_srvc_cb,
                                   0 /* prop */);
         curr_db_attr++;
 
-        if (!p_cur_srvc->p_attr || list_is_empty(p_cur_srvc->p_attr))
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics))
             continue;
 
-        for (list_node_t *an = list_begin(p_cur_srvc->p_attr);
-             an != list_end(p_cur_srvc->p_attr); an = list_next(an)) {
-            tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
+        for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+             cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+            tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
 
-            bt_gatt_db_attribute_type_t type;
-            switch (p_attr->attr_type)
-            {
-                case BTA_GATTC_ATTR_TYPE_CHAR:
-                    type = BTGATT_DB_CHARACTERISTIC;
-                    break;
-
-                case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
-                    type = BTGATT_DB_DESCRIPTOR;
-                    break;
-
-                case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
-                    type = BTGATT_DB_INCLUDED_SERVICE;
-                    break;
-
-                default:
-                    LOG_ERROR(LOG_TAG, "%s unknown gatt db attribute type: %d",
-                              __func__, p_attr->attr_type);
-                    continue;
+            bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                      BTGATT_DB_CHARACTERISTIC,
+                                      p_char->handle,
+                                      0 /* s_handle */,
+                                      0 /* e_handle */,
+                                      p_char->handle,
+                                      p_char->uuid,
+                                      p_char->properties);
+            curr_db_attr++;
+
+            if (!p_char->descriptors || list_is_empty(p_char->descriptors))
+                continue;
+
+            for (list_node_t *dn = list_begin(p_char->descriptors);
+                 dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+
+                bta_gattc_fill_gatt_db_el(curr_db_attr,
+                                          BTGATT_DB_DESCRIPTOR,
+                                          p_desc->handle,
+                                          0 /* s_handle */,
+                                          0 /* e_handle */,
+                                          p_desc->handle,
+                                          p_desc->uuid,
+                                          0 /* property */);
+                curr_db_attr++;
             }
+        }
+
+        if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
+            continue;
+
+        for (list_node_t *isn = list_begin(p_cur_srvc->included_svc);
+             isn != list_end(p_cur_srvc->included_svc); isn = list_next(isn)) {
+            tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(isn);
 
             bta_gattc_fill_gatt_db_el(curr_db_attr,
-                                      type,
-                                      p_attr->attr_handle,
+                                      BTGATT_DB_INCLUDED_SERVICE,
+                                      p_isvc->handle,
                                       0 /* s_handle */,
                                       0 /* e_handle */,
-                                      p_attr->attr_handle,
-                                      p_attr->uuid,
-                                      p_attr->property);
+                                      p_isvc->handle,
+                                      p_isvc->uuid,
+                                      0 /* property */);
             curr_db_attr++;
         }
     }
@@ -1412,7 +1366,6 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
 
     list_free(p_srvc_cb->p_srvc_cache);
     p_srvc_cb->p_srvc_cache = NULL;
-    p_srvc_cb->p_cur_srvc = NULL;
 
     while (num_attr > 0 && p_attr != NULL)
     {
@@ -1433,6 +1386,7 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
                                             p_attr->s_handle,
                                             &p_attr->uuid,
                                             p_attr->prop,
+                                            p_attr->incl_srvc_handle,
                                             p_attr->attr_type);
                 break;
         }
@@ -1451,7 +1405,7 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
 **
 *******************************************************************************/
 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
-                            UINT16 e_handle, tBT_UUID uuid, UINT8 prop,
+                            UINT16 e_handle, tBT_UUID uuid, UINT8 prop, UINT16 incl_srvc_handle,
                             BOOLEAN is_primary)
 {
     p_attr->s_handle    = s_handle;
@@ -1460,6 +1414,7 @@ void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_han
     p_attr->is_primary  = is_primary;
     p_attr->id          = 0;
     p_attr->prop        = prop;
+    p_attr->incl_srvc_handle = incl_srvc_handle;
 
     memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
 }
@@ -1484,29 +1439,70 @@ void bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
 
     for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
          sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
-        tBTA_GATTC_CACHE *p_cur_srvc = list_node(sn);
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
 
         bta_gattc_fill_nv_attr(&nv_attr[i++],
                                 BTA_GATTC_ATTR_TYPE_SRVC,
                                p_cur_srvc->s_handle,
                                p_cur_srvc->e_handle,
                                p_cur_srvc->service_uuid.id.uuid,
-                               0,
+                               0 /* properties */,
+                               0 /* incl_srvc_handle */,
                                p_cur_srvc->service_uuid.is_primary);
+    }
+
+    for (list_node_t *sn = list_begin(p_srvc_cb->p_srvc_cache);
+         sn != list_end(p_srvc_cb->p_srvc_cache); sn = list_next(sn)) {
+        tBTA_GATTC_SERVICE *p_cur_srvc = list_node(sn);
+
+        if (!p_cur_srvc->characteristics || list_is_empty(p_cur_srvc->characteristics))
+            continue;
+
+        for (list_node_t *cn = list_begin(p_cur_srvc->characteristics);
+             cn != list_end(p_cur_srvc->characteristics); cn = list_next(cn)) {
+            tBTA_GATTC_CHARACTERISTIC *p_char = list_node(cn);
+
+            bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                   BTA_GATTC_ATTR_TYPE_CHAR,
+                                   p_char->handle,
+                                   0,
+                                   p_char->uuid,
+                                   p_char->properties,
+                                   0 /* incl_srvc_handle */,
+                                   FALSE);
+
+            if (!p_char->descriptors || list_is_empty(p_char->descriptors))
+                continue;
+
+            for (list_node_t *dn = list_begin(p_char->descriptors);
+                 dn != list_end(p_char->descriptors); dn = list_next(dn)) {
+                tBTA_GATTC_DESCRIPTOR *p_desc = list_node(dn);
+
+                bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                       BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+                                       p_desc->handle,
+                                       0,
+                                       p_desc->uuid,
+                                       0 /* properties */,
+                                       0 /* incl_srvc_handle */,
+                                       FALSE);
+            }
+        }
 
-        if (!p_cur_srvc->p_attr || list_is_empty(p_cur_srvc->p_attr))
+        if (!p_cur_srvc->included_svc || list_is_empty(p_cur_srvc->included_svc))
             continue;
 
-        for (list_node_t *an = list_begin(p_cur_srvc->p_attr);
-             an != list_end(p_cur_srvc->p_attr); an = list_next(an)) {
-            tBTA_GATTC_CACHE_ATTR *p_attr = list_node(an);
+        for (list_node_t *an = list_begin(p_cur_srvc->included_svc);
+             an != list_end(p_cur_srvc->included_svc); an = list_next(an)) {
+            tBTA_GATTC_INCLUDED_SVC *p_isvc = list_node(an);
 
             bta_gattc_fill_nv_attr(&nv_attr[i++],
-                                   p_attr->attr_type,
-                                   p_attr->attr_handle,
+                                   BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+                                   p_isvc->handle,
                                    0,
-                                   p_attr->uuid,
-                                   p_attr->property,
+                                   p_isvc->uuid,
+                                   0 /* properties */,
+                                   p_isvc->included_service->s_handle,
                                    FALSE);
         }
     }
index 878c19b..b40408b 100644 (file)
@@ -237,28 +237,6 @@ typedef union
 
 
 /* GATT server cache on the client */
-typedef struct
-{
-    tBT_UUID                uuid;
-    UINT16                  attr_handle;
-    tBTA_GATT_CHAR_PROP     property; /* if characteristic, it is char property;
-                                         if included service, flag primary,
-                                         if descriptor, not used */
-    tBTA_GATTC_ATTR_TYPE    attr_type;
-// btla-specific ++
-} __attribute__((packed)) tBTA_GATTC_CACHE_ATTR;
-// btla-specific --
-
-typedef struct
-{
-    tBTA_GATT_SRVC_ID       service_uuid;
-    list_t                 *p_attr; /* list of tBTA_GATTC_CACHE_ATTR */
-    UINT16                  s_handle;
-    UINT16                  e_handle;
-    list_node_t            *p_cur_char; /* node pointing to p_attr */
-// btla-specific ++
-} __attribute__((packed)) tBTA_GATTC_CACHE;
-// btla-specific --
 
 typedef struct
 {
@@ -300,8 +278,7 @@ typedef struct
 
     UINT8               state;
 
-    list_t              *p_srvc_cache;  /* list of tBTA_GATTC_CACHE */
-    tBTA_GATTC_CACHE    *p_cur_srvc;
+    list_t              *p_srvc_cache;  /* list of tBTA_GATTC_SERVICE */
     UINT8               update_count;   /* indication received */
     UINT8               num_clcb;       /* number of associated CLCB */
 
@@ -508,9 +485,10 @@ extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type
 extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
 extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
 extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid);
-extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
-                                              tBTA_GATT_ID *p_start_rec,tBT_UUID *p_uuid_cond,
-                                              tBTA_GATT_ID *p_output, void *p_param);
+extern const list_t* bta_gattc_get_services(UINT16 conn_id);
+extern const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(UINT16 conn_id, UINT16 handle);
+extern tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(UINT16 conn_id, UINT16 handle);
+extern tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(UINT16 conn_id, UINT16 handle);
 extern void bta_gattc_get_gatt_db(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle, btgatt_db_element_t **db, int *count);
 extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
 extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *attr);
index b3c4f4b..0cee53d 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "bta_api.h"
 #include "gatt_api.h"
+#include "osi/include/list.h"
 
 #ifndef     BTA_GATT_INCLUDED
 #warning BTA_GATT_INCLUDED not defined
@@ -278,6 +279,7 @@ typedef struct
     UINT8       id;
     UINT8       prop;       /* used when attribute type is characteristic */
     BOOLEAN     is_primary; /* used when attribute type is service */
+    UINT16      incl_srvc_handle; /* used when attribute type is included service */
 }tBTA_GATTC_NV_ATTR;
 
 /* callback data structure */
@@ -624,6 +626,39 @@ typedef void (tBTA_GATTS_ENB_CBACK)(tBTA_GATT_STATUS status);
 /* Server callback function */
 typedef void (tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event,  tBTA_GATTS *p_data);
 
+typedef struct
+{
+    tBTA_GATT_SRVC_ID       service_uuid;
+    UINT16                  s_handle;
+    UINT16                  e_handle;
+    list_t                 *characteristics; /* list of tBTA_GATTC_CHARACTERISTIC */
+    list_t                 *included_svc; /* list of tBTA_GATTC_INCLUDED_SVC */
+} __attribute__((packed)) tBTA_GATTC_SERVICE;
+
+typedef struct
+{
+    tBT_UUID                uuid;
+    UINT16                  handle;
+    tBTA_GATT_CHAR_PROP     properties;
+    tBTA_GATTC_SERVICE     *service; /* owning service*/
+    list_t                 *descriptors; /* list of tBTA_GATTC_DESCRIPTOR */
+} __attribute__((packed)) tBTA_GATTC_CHARACTERISTIC;
+
+typedef struct
+{
+    tBT_UUID                    uuid;
+    UINT16                      handle;
+    tBTA_GATTC_CHARACTERISTIC  *characteristic; /* owning characteristic */
+} __attribute__((packed)) tBTA_GATTC_DESCRIPTOR;
+
+typedef struct
+{
+    tBT_UUID                uuid;
+    UINT16                  handle;
+    tBTA_GATTC_SERVICE     *owning_service; /* owning service*/
+    tBTA_GATTC_SERVICE     *included_service;
+} __attribute__((packed)) tBTA_GATTC_INCLUDED_SVC;
+
 /*****************************************************************************
 **  External Function Declarations
 *****************************************************************************/
@@ -745,6 +780,47 @@ extern void BTA_GATTC_ServiceSearchRequest(UINT16 conn_id, tBT_UUID *p_srvc_uuid
 
 /*******************************************************************************
 **
+** Function         BTA_GATTC_GetServices
+**
+** Description      This function is called to find the services on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**
+** Returns          returns list_t of tBTA_GATTC_SERVICE or NULL.
+**
+*******************************************************************************/
+extern const list_t* BTA_GATTC_GetServices(UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetCharacteristic
+**
+** Description      This function is called to find the characteristic on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  handle: characteristic handle
+**
+** Returns          returns pointer to tBTA_GATTC_CHARACTERISTIC or NULL.
+**
+*******************************************************************************/
+extern const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetCharacteristic(UINT16 conn_id, UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetCharacteristic
+**
+** Description      This function is called to find the characteristic on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  handle: descriptor handle
+**
+** Returns          returns pointer to tBTA_GATTC_DESCRIPTOR or NULL.
+**
+*******************************************************************************/
+extern const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(UINT16 conn_id, UINT16 handle);
+
+/*******************************************************************************
+**
 ** Function         BTA_GATTC_GetFirstChar
 **
 ** Description      This function is called to find the first charatceristic of the