GATT: don't update link status for apps that were never connected

Right now, in GATT_Deregister we make a call to
gatt_update_app_use_link_flag, which might result in a call to
GATT_SetIddleTimeout on links that this client was never connected to.

In order to fix that, we must check if gatt_update_app_hold_link_status
made any changes to p_tcb->app_hold_link. If not, then skip updating
the timer.

Change-Id: I6f18ec7fe4e80e048adc9e360cae703b7d64d62a
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 8bbd650..3637981 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -274,49 +274,25 @@
 **
 ** Description      Update the application use link status
 **
-** Returns          void.
+** Returns          true if any modifications are made, false otherwise.
 **
 *******************************************************************************/
-void gatt_update_app_hold_link_status (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
+BOOLEAN gatt_update_app_hold_link_status(tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add)
 {
-    UINT8 i;
-    BOOLEAN found=FALSE;
-
-    if (p_tcb == NULL)
-    {
-        GATT_TRACE_ERROR("gatt_update_app_hold_link_status p_tcb=NULL");
-        return;
-    }
-
-
-    for (i=0; i<GATT_MAX_APPS; i++)
-    {
-        if (p_tcb->app_hold_link[i] ==  gatt_if)
-        {
-            found = TRUE;
-            if (!is_add)
-            {
-                p_tcb->app_hold_link[i] = 0;
-                break;
-            }
+    for (int i=0; i<GATT_MAX_APPS; i++) {
+        if (p_tcb->app_hold_link[i] == 0 && is_add) {
+            p_tcb->app_hold_link[i] = gatt_if;
+            GATT_TRACE_DEBUG("%s: added gatt_if=%d idx=%d ", __func__, gatt_if, i);
+            return TRUE;
+        } else if (p_tcb->app_hold_link[i] == gatt_if && !is_add) {
+            p_tcb->app_hold_link[i] = 0;
+            GATT_TRACE_DEBUG("%s: removed gatt_if=%d idx=%d", __func__, gatt_if, i);
+            return TRUE;
         }
     }
 
-    if (!found && is_add)
-    {
-        for (i=0; i<GATT_MAX_APPS; i++)
-        {
-            if (p_tcb->app_hold_link[i] ==  0)
-            {
-                p_tcb->app_hold_link[i] = gatt_if;
-                found = TRUE;
-                break;
-            }
-        }
-    }
-
-    GATT_TRACE_DEBUG("gatt_update_app_hold_link_status found=%d[1-found] idx=%d gatt_if=%d is_add=%d", found, i, gatt_if, is_add);
-
+    GATT_TRACE_DEBUG("%s: gatt_if=%d not found; is_add=%d", __func__, gatt_if, is_add);
+    return FALSE;
 }
 
 /*******************************************************************************
@@ -329,34 +305,37 @@
 ** Returns          void.
 **
 *******************************************************************************/
-void gatt_update_app_use_link_flag (tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link)
+void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add,
+                                   BOOLEAN check_acl_link)
 {
-    GATT_TRACE_DEBUG("gatt_update_app_use_link_flag  is_add=%d chk_link=%d",
-                      is_add, check_acl_link);
+    GATT_TRACE_DEBUG("%s: is_add=%d chk_link=%d", __func__, is_add, check_acl_link);
 
-    gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add);
+    if (!p_tcb)
+        return;
 
-    if (check_acl_link &&
-        p_tcb &&
-         p_tcb->att_lcid == L2CAP_ATT_CID && /* only update link idle timer for fixed channel */
-        (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) != GATT_INVALID_ACL_HANDLE))
-    {
-        if (is_add)
-        {
-            GATT_TRACE_DEBUG("GATT disables link idle timer");
-            /* acl link is connected disable the idle timeout */
-            GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
-        }
-        else
-        {
-            if (!gatt_num_apps_hold_link(p_tcb))
-            {
-                /* acl link is connected but no application needs to use the link
-                   so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
-                GATT_TRACE_DEBUG("GATT starts link idle timer =%d sec", GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
-                GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, p_tcb->transport);
-            }
+    // If we make no modification, i.e. kill app that was never connected to a device,
+    // skip updating the device state.
+    if (!gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add))
+        return;
 
+    if (!check_acl_link ||
+            p_tcb->att_lcid != L2CAP_ATT_CID || /* only update link idle timer for fixed channel */
+            (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) == GATT_INVALID_ACL_HANDLE)) {
+        return;
+    }
+
+    if (is_add) {
+        GATT_TRACE_DEBUG("%s: disable link idle timer", __func__);
+        /* acl link is connected disable the idle timeout */
+        GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT, p_tcb->transport);
+    } else {
+        if (!gatt_num_apps_hold_link(p_tcb)) {
+            /* acl link is connected but no application needs to use the link
+               so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
+            GATT_TRACE_DEBUG("%s: start link idle timer =%d sec", __func__,
+                             GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP);
+            GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
+                                p_tcb->transport);
         }
     }
 }