Merge "Implement GATT service cache" into lmp-dev
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index a37b24c..e79bf1a 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -1667,20 +1667,19 @@
 
     APPL_TRACE_DEBUG("bta_gattc_ci_load conn_id=%d load status=%d" ,
                       p_clcb->bta_conn_id, p_data->ci_load.status );
-    bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
 
-    if ((p_data->ci_load.status == BTA_GATT_OK ||
-         p_data->ci_load.status == BTA_GATT_MORE) &&
-        p_data->ci_load.num_attr > 0)
+    if (p_data->ci_load.status == BTA_GATT_OK ||
+         p_data->ci_load.status == BTA_GATT_MORE)
     {
-        bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr,
+        if (p_data->ci_load.num_attr != 0)
+            bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr,
                                 p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
 
         if (p_data->ci_load.status == BTA_GATT_OK)
         {
             p_clcb->p_srcb->attr_index = 0;
             bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
-
+            bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
         }
         else /* load more */
         {
@@ -1694,6 +1693,7 @@
     }
     else
     {
+        bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
         p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
         p_clcb->p_srcb->attr_index = 0;
         /* cache load failure, start discovery */
diff --git a/btif/co/bta_gattc_co.c b/btif/co/bta_gattc_co.c
index 29fbb09..8541aa3 100644
--- a/btif/co/bta_gattc_co.c
+++ b/btif/co/bta_gattc_co.c
@@ -25,6 +25,43 @@
 #if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
 #if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
 
+#define GATT_CACHE_PREFIX "/data/misc/bluedroid/gatt_cache_"
+
+static FILE* sCacheFD = 0;
+
+static void getFilename(char *buffer, BD_ADDR bda)
+{
+    sprintf(buffer, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX
+        , bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+}
+
+static void cacheClose()
+{
+    if (sCacheFD != 0)
+    {
+        fclose(sCacheFD);
+        sCacheFD = 0;
+    }
+}
+
+static bool cacheOpen(BD_ADDR bda, bool to_save)
+{
+    char fname[255] = {0};
+    getFilename(fname, bda);
+
+    cacheClose();
+    sCacheFD = fopen(fname, to_save ? "w" : "r");
+
+    return (sCacheFD != 0);
+}
+
+static void cacheReset(BD_ADDR bda)
+{
+    char fname[255] = {0};
+    getFilename(fname, bda);
+    unlink(fname);
+}
+
 
 /*****************************************************************************
 **  Function Declarations
@@ -47,10 +84,12 @@
 *******************************************************************************/
 void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt, UINT16 conn_id, BOOLEAN to_save)
 {
-    tBTA_GATT_STATUS    status = BTA_GATT_OK;
-    UNUSED(to_save);
-
     /* open NV cache and send call in */
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    if (!cacheOpen(server_bda, to_save))
+        status = BTA_GATT_ERROR;
+
+    BTIF_TRACE_DEBUG("%s() - status=%d", __FUNCTION__, status);
     bta_gattc_ci_cache_open(server_bda, evt, status, conn_id);
 }
 
@@ -73,11 +112,19 @@
 {
     UINT16              num_attr = 0;
     tBTA_GATTC_NV_ATTR  attr[BTA_GATTC_NV_LOAD_MAX];
-    tBTA_GATT_STATUS    status = BTA_GATT_MORE;
-    UNUSED(start_index);
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
 
+    if (sCacheFD && (0 == fseek(sCacheFD, start_index * sizeof(tBTA_GATTC_NV_ATTR), SEEK_SET)))
+    {
+        num_attr = fread(attr, sizeof(tBTA_GATTC_NV_ATTR), BTA_GATTC_NV_LOAD_MAX, sCacheFD);
+        status = (num_attr < BTA_GATTC_NV_LOAD_MAX ? BTA_GATT_OK : BTA_GATT_MORE);
+    }
+
+    BTIF_TRACE_DEBUG("%s() - sCacheFD=%p, start_index=%d, read=%d, status=%d",
+        __FUNCTION__, sCacheFD, start_index, num_attr, status);
     bta_gattc_ci_cache_load(server_bda, evt, num_attr, attr, status, conn_id);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_gattc_co_cache_save
@@ -98,10 +145,14 @@
                               tBTA_GATTC_NV_ATTR *p_attr_list, UINT16 attr_index, UINT16 conn_id)
 {
     tBTA_GATT_STATUS    status = BTA_GATT_OK;
-    UNUSED(num_attr);
-    UNUSED(p_attr_list);
     UNUSED(attr_index);
 
+    if (sCacheFD != 0)
+    {
+        int num = fwrite(p_attr_list, sizeof(tBTA_GATTC_NV_ATTR), num_attr, sCacheFD);
+        BTIF_TRACE_DEBUG("%s() wrote %d", __FUNCTION__, num);
+    }
+
     bta_gattc_ci_cache_save(server_bda, evt, status, conn_id);
 }
 
@@ -122,8 +173,13 @@
 {
     UNUSED(server_bda);
     UNUSED(conn_id);
+
+    cacheClose();
+
     /* close NV when server cache is done saving or loading,
        does not need to do anything for now on Insight */
+
+    BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
 }
 
 /*******************************************************************************
@@ -140,7 +196,8 @@
 *******************************************************************************/
 void bta_gattc_co_cache_reset(BD_ADDR server_bda)
 {
-    UNUSED(server_bda);
+    BTIF_TRACE_DEBUG("%s()", __FUNCTION__);
+    cacheReset(server_bda);
 }
 
 #endif