merge in nyc-dr1-release history after reset to nyc-dr1-dev
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 388d9a4..01b06b8 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -518,7 +518,7 @@
 
     /* open/hold a connection */
     if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda,
-                      TRUE, p_data->api_conn.transport))
+                      true, p_data->api_conn.transport, false))
     {
         APPL_TRACE_ERROR("Connection open failure");
 
@@ -558,7 +558,7 @@
     if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))
     {
         /* always call open to hold a connection */
-        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE, p_data->transport))
+        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, false, p_data->transport, false))
         {
             uint8_t *bda = (uint8_t *)p_data->remote_bda;
             status = BTA_GATT_ERROR;
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index 4c35b0c..3f357bf 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -689,7 +689,7 @@
     {
         /* should always get the connection ID */
         if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda,
-                        p_msg->api_open.is_direct, p_msg->api_open.transport))
+                        p_msg->api_open.is_direct, p_msg->api_open.transport, false))
         {
             status = BTA_GATT_OK;
 
diff --git a/btif/src/btif_gatt_test.c b/btif/src/btif_gatt_test.c
index 349674e..ab1c1d2 100644
--- a/btif/src/btif_gatt_test.c
+++ b/btif/src/btif_gatt_test.c
@@ -240,7 +240,7 @@
             if (params->u1 == BT_DEVICE_TYPE_BLE)
                 BTM_SecAddBleDevice(params->bda1->address, NULL, BT_DEVICE_TYPE_BLE, params->u2);
 
-            if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE, BT_TRANSPORT_LE) )
+            if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, true, BT_TRANSPORT_LE, false) )
             {
                 LOG_ERROR(LOG_TAG, "%s: GATT_Connect failed!", __FUNCTION__);
             }
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index d92665a..e14b13e 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -708,7 +708,7 @@
         p_clcb->connected = TRUE;
 
     /* hold the link here */
-    if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
+    if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE, false))
         return started;
 
     /* enqueue the request */
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index b8c45d3..597dc63 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -1357,7 +1357,8 @@
 ** Returns          TRUE if connection started; FALSE if connection start failure.
 **
 *******************************************************************************/
-BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct, tBT_TRANSPORT transport)
+BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct,
+                      tBT_TRANSPORT transport, BOOLEAN opportunistic)
 {
     tGATT_REG    *p_reg;
     BOOLEAN status = FALSE;
@@ -1372,7 +1373,7 @@
     }
 
     if (is_direct)
-        status = gatt_act_connect (p_reg, bd_addr, transport);
+        status = gatt_act_connect (p_reg, bd_addr, transport, opportunistic);
     else
     {
         if (transport == BT_TRANSPORT_LE)
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index 596ea9b..74f0f35 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -457,7 +457,7 @@
         p_clcb->connected = TRUE;
     }
     /* hold the link here */
-    GATT_Connect(gatt_cb.gatt_if, remote_bda, TRUE, transport);
+    GATT_Connect(gatt_cb.gatt_if, remote_bda, TRUE, transport, true);
     p_clcb->ccc_stage = GATT_SVC_CHANGED_CONNECTING;
 
     if (!p_clcb->connected)
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 56760e9..1f97cb7 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -532,7 +532,7 @@
 
 /* from gatt_main.c */
 extern BOOLEAN gatt_disconnect (tGATT_TCB *p_tcb);
-extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport);
+extern BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport, bool opportunistic);
 extern BOOLEAN gatt_connect (BD_ADDR rem_bda,  tGATT_TCB *p_tcb, tBT_TRANSPORT transport);
 extern void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf);
 extern void gatt_update_app_use_link_flag ( tGATT_IF gatt_if, tGATT_TCB *p_tcb, BOOLEAN is_add, BOOLEAN check_acl_link);
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 8bbd650..4f1568a 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);
         }
     }
 }
@@ -370,7 +349,8 @@
 ** Returns          void.
 **
 *******************************************************************************/
-BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr, tBT_TRANSPORT transport)
+BOOLEAN gatt_act_connect (tGATT_REG *p_reg, BD_ADDR bd_addr,
+                          tBT_TRANSPORT transport, BOOLEAN opportunistic)
 {
     BOOLEAN     ret = FALSE;
     tGATT_TCB   *p_tcb;
@@ -417,7 +397,11 @@
 
     if (ret)
     {
-        gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
+        if (!opportunistic)
+            gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, FALSE);
+        else
+            GATT_TRACE_DEBUG("%s: connection is opportunistic, not updating app usage",
+                            __func__);
     }
 
     return ret;
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index a042bb9..182b5ba 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -1070,14 +1070,18 @@
 **
 ** Parameters       gatt_if: applicaiton interface
 **                  bd_addr: peer device address.
-**                  is_direct: is a direct conenection or a background auto connection
+**                  is_direct: is a direct connection or a background auto connection
 **                  transport : Physical transport for GATT connection (BR/EDR or LE)
+**                  opportunistic: will not keep device connected if other apps
+**                      disconnect, will not update connected apps counter, when
+**                      disconnected won't cause physical disconnection.
 **
 ** Returns          TRUE if connection started; FALSE if connection start failure.
 **
 *******************************************************************************/
 extern BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr,
-                             BOOLEAN is_direct, tBT_TRANSPORT transport);
+                             BOOLEAN is_direct, tBT_TRANSPORT transport,
+                             BOOLEAN opportunistic);
 
 
 /*******************************************************************************
diff --git a/stack/srvc/srvc_dis.c b/stack/srvc/srvc_dis.c
index c17c660..12ae5a5 100644
--- a/stack/srvc/srvc_dis.c
+++ b/stack/srvc/srvc_dis.c
@@ -472,7 +472,7 @@
 
     if (conn_id == GATT_INVALID_CONN_ID)
     {
-        return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE, BT_TRANSPORT_LE);
+        return GATT_Connect(srvc_eng_cb.gatt_if, peer_bda, TRUE, BT_TRANSPORT_LE, false);
     }
 
     return dis_gatt_c_read_dis_req(conn_id);