Add GattNotifyTest

Change-Id: I178808449251963d399c61a1031bd25ce9e159e3
(cherry picked from commit 935eebf6577e0b3ee2785b4b586d0cd90ca3d600)
diff --git a/acts/framework/acts/test_utils/bt/GattConnectedBaseTest.py b/acts/framework/acts/test_utils/bt/GattConnectedBaseTest.py
index bee69f2..ef269d4 100644
--- a/acts/framework/acts/test_utils/bt/GattConnectedBaseTest.py
+++ b/acts/framework/acts/test_utils/bt/GattConnectedBaseTest.py
@@ -42,6 +42,9 @@
     READABLE_DESC_UUID = "aa7edd5a-4d1d-4f0e-883a-d145616a1630"
     WRITABLE_CHAR_UUID = "aa7edd5a-4d1d-4f0e-883a-d145616a1630"
     WRITABLE_DESC_UUID = "76d5ed92-ca81-4edb-bb6b-9f019665fb32"
+    NOTIFIABLE_CHAR_UUID = "b2c83efa-34ca-11e6-ac61-9e71128cae77"
+    # CCC == Client Characteristic Configuration
+    CCC_DESC_UUID = "00002902-0000-1000-8000-00805f9b34fb"
 
     def __init__(self, controllers):
         BluetoothBaseTest.__init__(self, controllers)
@@ -125,14 +128,13 @@
             },
             {
                 'uuid': self.READABLE_CHAR_UUID,
-                'property': GattCharacteristic.PROPERTY_NOTIFY.value |
-                GattCharacteristic.PROPERTY_READ.value,
+                'property': GattCharacteristic.PROPERTY_READ.value,
                 'permission': GattCharacteristic.PERMISSION_READ.value
             },
             {
-                'uuid': "6774191f-6ec3-4aa2-b8a8-cf830e41fda6",
+                'uuid': self.NOTIFIABLE_CHAR_UUID,
                 'property': GattCharacteristic.PROPERTY_NOTIFY.value |
-                GattCharacteristic.PROPERTY_READ.value,
+                GattCharacteristic.PROPERTY_INDICATE.value,
                 'permission': GattCharacteristic.PERMISSION_READ.value
             },
         ]
@@ -146,10 +148,16 @@
                 'uuid': self.READABLE_DESC_UUID,
                 'property': GattDescriptor.PERMISSION_READ.value |
                 GattDescriptor.PERMISSION_WRITE.value,
+            },
+            {
+                'uuid': self.CCC_DESC_UUID,
+                'property': GattDescriptor.PERMISSION_READ.value |
+                GattDescriptor.PERMISSION_WRITE.value,
             }
         ]
         characteristic_list = setup_gatt_characteristics(droid,
                                                          characteristic_input)
+        self.notifiable_char_index = characteristic_list[2];
         descriptor_list = setup_gatt_descriptors(droid, descriptor_input)
         return characteristic_list, descriptor_list
 
@@ -190,6 +198,8 @@
             characteristic_list[0], descriptor_list[0])
         self.per_ad.droid.gattServerCharacteristicAddDescriptor(
             characteristic_list[1], descriptor_list[1])
+        self.per_ad.droid.gattServerCharacteristicAddDescriptor(
+            characteristic_list[2], descriptor_list[2])
         gatt_service3 = self.per_ad.droid.gattServerCreateService(
             self.TEST_SERVICE_UUID, GattService.SERVICE_TYPE_PRIMARY.value)
         for characteristic in characteristic_list:
diff --git a/acts/framework/acts/test_utils/bt/GattEnum.py b/acts/framework/acts/test_utils/bt/GattEnum.py
index 24cb3f1..6b512bc 100644
--- a/acts/framework/acts/test_utils/bt/GattEnum.py
+++ b/acts/framework/acts/test_utils/bt/GattEnum.py
@@ -32,7 +32,7 @@
     SERV_ADDED_ERR = "Service Added event not found. Expected {}"
     MTU_CHANGED_ERR = "MTU Changed event not found. Expected {}"
     GATT_CONN_CHANGE_ERR = "GATT Connection Changed event not found. Expected {}"
-
+    CHAR_CHANGE_ERR = "GATT Characteristic Changed event not fond. Expected {}"
 
 class GattCbStrings(Enum):
     CHAR_WRITE_REQ = "GattServer{}onCharacteristicWriteRequest"
@@ -49,6 +49,7 @@
     SERV_ADDED = "GattServer{}onServiceAdded"
     MTU_CHANGED = "GattConnect{}onMtuChanged"
     GATT_CONN_CHANGE = "GattConnect{}onConnectionStateChange"
+    CHAR_CHANGE = "GattConnect{}onCharacteristicChanged"
 
 
 class GattEvent(Enum):
@@ -80,6 +81,8 @@
                    "err": GattCbErr.MTU_CHANGED_ERR.value}
     GATT_CONN_CHANGE = {"evt": GattCbStrings.GATT_CONN_CHANGE.value,
                         "err": GattCbErr.GATT_CONN_CHANGE_ERR.value}
+    CHAR_CHANGE = {"evt": GattCbStrings.CHAR_CHANGE.value,
+                        "err": GattCbErr.CHAR_CHANGE_ERR.value}
 
 
 class GattConnectionState(Enum):
diff --git a/acts/tests/google/ble/gatt/GattNotifyTest.py b/acts/tests/google/ble/gatt/GattNotifyTest.py
new file mode 100644
index 0000000..3e1a99b
--- /dev/null
+++ b/acts/tests/google/ble/gatt/GattNotifyTest.py
@@ -0,0 +1,96 @@
+#/usr/bin/env python3.4
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+"""
+This test script exercises GATT notify/indicate procedures.
+"""
+
+from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
+from acts.test_utils.bt.GattConnectedBaseTest import GattConnectedBaseTest
+from acts.test_utils.bt.GattEnum import GattCharacteristic
+from acts.test_utils.bt.GattEnum import GattDescriptor
+from acts.test_utils.bt.GattEnum import MtuSize
+from acts.test_utils.bt.GattEnum import GattEvent
+from acts.test_utils.bt.GattEnum import GattCbStrings
+from acts.test_utils.bt.GattEnum import GattConnectionPriority
+from math import ceil
+
+
+class GattNotifyTest(GattConnectedBaseTest):
+    @BluetoothBaseTest.bt_test_wrap
+    def test_notify_char(self):
+        """Test notify characteristic value.
+
+        Test GATT notify characteristic value.
+
+        Steps:
+        1. Central: write CCC - register for notifications.
+        2. Peripheral: receive CCC modification.
+        3. Peripheral: send characteristic notification.
+        4. Central: receive notification, verify it's conent matches what was
+           sent
+
+        Expected Result:
+        Verify that notification registration and delivery works.
+
+        Returns:
+          Pass if True
+          Fail if False
+
+        TAGS: LE, GATT, Characteristic
+        Priority: 0
+        """
+        #write CCC descriptor to enable notifications
+        self.cen_ad.droid.gattClientDescriptorSetValue(
+            self.bluetooth_gatt, self.discovered_services_index,
+            self.test_service_index, self.NOTIFIABLE_CHAR_UUID,
+            self.CCC_DESC_UUID, GattDescriptor.ENABLE_NOTIFICATION_VALUE.value)
+
+        self.cen_ad.droid.gattClientWriteDescriptor(
+            self.bluetooth_gatt, self.discovered_services_index,
+            self.test_service_index, self.NOTIFIABLE_CHAR_UUID,
+            self.CCC_DESC_UUID)
+
+        #enable notifications in app
+        self.cen_ad.droid.gattClientSetCharacteristicNotification(
+            self.bluetooth_gatt, self.discovered_services_index,
+            self.test_service_index, self.NOTIFIABLE_CHAR_UUID, True)
+
+        event = self._server_wait(GattEvent.DESC_WRITE_REQ)
+
+        request_id = event['data']['requestId']
+        bt_device_id = 0
+        status = 0
+        #confirm notification registration was successful
+        self.per_ad.droid.gattServerSendResponse(
+            self.gatt_server, bt_device_id, request_id, status, 0, [])
+        #wait for client to get response
+        event = self._client_wait(GattEvent.DESC_WRITE)
+
+        #set notified value
+        notified_value = [1,5,9,7,5,3,6,4,8,2]
+        self.per_ad.droid.gattServerCharacteristicSetValue(
+            self.notifiable_char_index, notified_value)
+
+        #send notification
+        self.per_ad.droid.gattServerNotifyCharacteristicChanged(
+            self.bluetooth_gatt, bt_device_id,
+            self.notifiable_char_index, False)
+
+        #wait for client to receive the notification
+        event = self._client_wait(GattEvent.CHAR_CHANGE)
+        self.assertEqual(notified_value, event["data"]["CharacteristicValue"])
+
+        return True