OSDN Git Service

Don't unregister notifications for unmodified services
authorJakub Pawlowski <jpawlowski@google.com>
Thu, 4 Feb 2016 01:22:50 +0000 (17:22 -0800)
committerJakub Pawlowski <jpawlowski@google.com>
Thu, 4 Feb 2016 02:05:26 +0000 (18:05 -0800)
Change-Id: Ie02dd72a2d4a423ab532ec84a4d588ab83f3e22b

bta/gatt/bta_gattc_act.c
bta/gatt/bta_gattc_int.h
bta/gatt/bta_gattc_utils.c

index 0005be9..b861a27 100644 (file)
@@ -1938,7 +1938,7 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
                                        tBTA_GATTC_SERV     *p_srcb,
                                        tBTA_GATTC_CLCB      *p_clcb,
                                        tBTA_GATTC_NOTIFY    *p_notify,
-                                       UINT16 handle)
+                                       tGATT_VALUE *att_value)
 {
     tBT_UUID        gattp_uuid, srvc_chg_uuid;
     BOOLEAN         processed = FALSE;
@@ -1953,11 +1953,23 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
     if (bta_gattc_uuid_compare(&p_notify->char_id.srvc_id.id.uuid, &gattp_uuid, TRUE) &&
         bta_gattc_uuid_compare(&p_notify->char_id.char_id.uuid, &srvc_chg_uuid, TRUE))
     {
+        if (att_value->len != BTA_GATTC_SERVICE_CHANGED_LEN) {
+            APPL_TRACE_ERROR("%s: received malformed service changed indication, skipping", __func__);
+            return FALSE;
+        }
+
+        UINT8 *p = att_value->value;
+        UINT16 s_handle = ((UINT16)(*(p    )) + (((UINT16)(*(p + 1))) << 8));
+        UINT16 e_handle = ((UINT16)(*(p + 2)) + (((UINT16)(*(p + 3))) << 8));
+
+        APPL_TRACE_ERROR("%s: service changed s_handle:0x%04x e_handle:0x%04x",
+                         __func__, s_handle, e_handle);
+
         processed = TRUE;
         /* mark service handle change pending */
         p_srcb->srvc_hdl_chg = TRUE;
         /* clear up all notification/indication registration */
-        bta_gattc_clear_notif_registration(conn_id);
+        bta_gattc_clear_notif_registration(p_srcb, conn_id, s_handle, e_handle);
         /* service change indication all received, do discovery update */
         if ( ++ p_srcb->update_count == bta_gattc_num_reg_app())
         {
@@ -1977,7 +1989,7 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
                 }
             }
             /* send confirmation here if this is an indication, it should always be */
-            GATTC_SendHandleValueConfirm(conn_id, handle);
+            GATTC_SendHandleValueConfirm(conn_id, att_value->handle);
 
             /* if connection available, refresh cache by doing discovery now */
             if (p_clcb != NULL)
@@ -2074,7 +2086,7 @@ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPL
                             &notify.descr_type))
     {
         /* if non-service change indication/notification, forward to application */
-        if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, handle))
+        if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, &p_data->att_value))
         {
             /* if app registered for the notification */
             if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify))
index 592b968..33a8376 100644 (file)
@@ -78,6 +78,8 @@ enum
 };
 typedef UINT16 tBTA_GATTC_INT_EVT;
 
+#define BTA_GATTC_SERVICE_CHANGED_LEN    4
+
 /* max client application GATTC can support */
 #ifndef     BTA_GATTC_CL_MAX
 #define     BTA_GATTC_CL_MAX    32
@@ -525,7 +527,7 @@ extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT
 extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
 extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role);
 extern UINT8 bta_gattc_num_reg_app(void);
-extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
+extern void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV *p_srcb, UINT16 conn_id, UINT16 start_handle, UINT16 end_handle);
 extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
 extern BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar);
 extern BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar);
index a8c4ac3..68fbaa5 100644 (file)
@@ -589,33 +589,40 @@ BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV
 **
 ** Function         bta_gattc_clear_notif_registration
 **
-** Description      clear up the notification registration information by BD_ADDR.
+** Description      Clear up the notification registration information by BD_ADDR.
+**                  Where handle is between start_handle and end_handle, and
+**                  start_handle and end_handle are boundaries of service
+**                  containing characteristic.
 **
 ** Returns          None.
 **
 *******************************************************************************/
-void bta_gattc_clear_notif_registration(UINT16 conn_id)
+void bta_gattc_clear_notif_registration(tBTA_GATTC_SERV *p_srcb, UINT16 conn_id,
+                                        UINT16 start_handle, UINT16 end_handle)
 {
     BD_ADDR             remote_bda;
     tBTA_GATTC_IF       gatt_if;
     tBTA_GATTC_RCB      *p_clrcb ;
     UINT8       i;
     tGATT_TRANSPORT     transport;
+    UINT16              handle;
 
-    if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport))
-    {
-        if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
-        {
-            for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
-            {
+    if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda, &transport)) {
+        if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL) {
+            for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
                 if (p_clrcb->notif_reg[i].in_use &&
                     !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
-                    memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+
+                    /* It's enough to get service or characteristic handle, as
+                     * clear boundaries are always around service.
+                     */
+                    handle = bta_gattc_id2handle(p_srcb, &p_clrcb->notif_reg[i].char_id.srvc_id,
+                                                 &p_clrcb->notif_reg[i].char_id.char_id, NULL);
+                    if (handle >= start_handle && handle <= end_handle)
+                        memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
             }
         }
-    }
-    else
-    {
+    } else {
         APPL_TRACE_ERROR("can not clear indication/notif registration for unknown app");
     }
     return;