Use handles to identify GATT attributes (3/4)

Bug: 27778668
Change-Id: Id6ec1229998c9fc2ecd4d0a908405a7148703bec
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index 76b2109..2261f63 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -282,12 +282,11 @@
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
-void btgattc_register_for_notification_cb(int conn_id, int registered, int status,
-                                          btgatt_srvc_id_t *srvc_id, btgatt_gatt_id_t *char_id)
+void btgattc_register_for_notification_cb(int conn_id, int registered, int status, uint16_t handle)
 {
     CHECK_CALLBACK_ENV
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRegisterForNotifications
-        , conn_id, status, registered, SRVC_ID_PARAMS(srvc_id), GATT_ID_PARAMS(char_id));
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRegisterForNotifications,
+        conn_id, status, registered, handle);
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
@@ -305,8 +304,7 @@
     sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->len, (jbyte *) p_data->value);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNotify
-        , conn_id, address, SRVC_ID_PARAMS((&p_data->srvc_id))
-        , GATT_ID_PARAMS((&p_data->char_id)), p_data->is_notify, jb);
+        , conn_id, address, p_data->handle, p_data->is_notify, jb);
 
     sCallbackEnv->DeleteLocalRef(address);
     sCallbackEnv->DeleteLocalRef(jb);
@@ -329,19 +327,17 @@
         sCallbackEnv->SetByteArrayRegion(jb, 0, 1, (jbyte *) &value);
     }
 
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadCharacteristic
-        , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
-        , GATT_ID_PARAMS((&p_data->char_id)), p_data->value_type, jb);
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadCharacteristic,
+        conn_id, status, p_data->handle, jb);
     sCallbackEnv->DeleteLocalRef(jb);
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
-void btgattc_write_characteristic_cb(int conn_id, int status, btgatt_write_params_t *p_data)
+void btgattc_write_characteristic_cb(int conn_id, int status, uint16_t handle)
 {
     CHECK_CALLBACK_ENV
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteCharacteristic
-        , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
-        , GATT_ID_PARAMS((&p_data->char_id)));
+        , conn_id, status, handle);
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
@@ -367,22 +363,18 @@
         jb = sCallbackEnv->NewByteArray(1);
     }
 
-    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadDescriptor
-        , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
-        , GATT_ID_PARAMS((&p_data->char_id)), GATT_ID_PARAMS((&p_data->descr_id))
-        , p_data->value_type, jb);
+    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadDescriptor,
+        conn_id, status, p_data->handle, jb);
 
     sCallbackEnv->DeleteLocalRef(jb);
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
-void btgattc_write_descriptor_cb(int conn_id, int status, btgatt_write_params_t *p_data)
+void btgattc_write_descriptor_cb(int conn_id, int status, uint16_t handle)
 {
     CHECK_CALLBACK_ENV
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteDescriptor
-        , conn_id, status, SRVC_ID_PARAMS((&p_data->srvc_id))
-        , GATT_ID_PARAMS((&p_data->char_id))
-        , GATT_ID_PARAMS((&p_data->descr_id)));
+        , conn_id, status, handle);
     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
@@ -873,14 +865,14 @@
     method_onScanResult = env->GetMethodID(clazz, "onScanResult", "(Ljava/lang/String;I[B)V");
     method_onConnected   = env->GetMethodID(clazz, "onConnected", "(IIILjava/lang/String;)V");
     method_onDisconnected = env->GetMethodID(clazz, "onDisconnected", "(IIILjava/lang/String;)V");
-    method_onReadCharacteristic = env->GetMethodID(clazz, "onReadCharacteristic", "(IIIIJJIJJI[B)V");
-    method_onWriteCharacteristic = env->GetMethodID(clazz, "onWriteCharacteristic", "(IIIIJJIJJ)V");
+    method_onReadCharacteristic = env->GetMethodID(clazz, "onReadCharacteristic", "(III[B)V");
+    method_onWriteCharacteristic = env->GetMethodID(clazz, "onWriteCharacteristic", "(III)V");
     method_onExecuteCompleted = env->GetMethodID(clazz, "onExecuteCompleted",  "(II)V");
     method_onSearchCompleted = env->GetMethodID(clazz, "onSearchCompleted",  "(II)V");
-    method_onReadDescriptor = env->GetMethodID(clazz, "onReadDescriptor", "(IIIIJJIJJIJJI[B)V");
-    method_onWriteDescriptor = env->GetMethodID(clazz, "onWriteDescriptor", "(IIIIJJIJJIJJ)V");
-    method_onNotify = env->GetMethodID(clazz, "onNotify", "(ILjava/lang/String;IIJJIJJZ[B)V");
-    method_onRegisterForNotifications = env->GetMethodID(clazz, "onRegisterForNotifications", "(IIIIIJJIJJ)V");
+    method_onReadDescriptor = env->GetMethodID(clazz, "onReadDescriptor", "(III[B)V");
+    method_onWriteDescriptor = env->GetMethodID(clazz, "onWriteDescriptor", "(III)V");
+    method_onNotify = env->GetMethodID(clazz, "onNotify", "(ILjava/lang/String;IZ[B)V");
+    method_onRegisterForNotifications = env->GetMethodID(clazz, "onRegisterForNotifications", "(IIII)V");
     method_onReadRemoteRssi = env->GetMethodID(clazz, "onReadRemoteRssi", "(ILjava/lang/String;II)V");
     method_onConfigureMTU = env->GetMethodID(clazz, "onConfigureMTU", "(III)V");
     method_onAdvertiseCallback = env->GetMethodID(clazz, "onAdvertiseCallback", "(II)V");
@@ -1061,59 +1053,23 @@
 }
 
 static void gattClientReadCharacteristicNative(JNIEnv* env, jobject object,
-    jint conn_id, jint  service_type, jint  service_id_inst_id,
-    jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
-    jint  char_id_inst_id,
-    jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
-    jint authReq)
+    jint conn_id, jint handle, jint authReq)
 {
     if (!sGattIf) return;
 
-    btgatt_srvc_id_t srvc_id;
-    srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
-    srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
-    set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
-
-    btgatt_gatt_id_t char_id;
-    char_id.inst_id = (uint8_t) char_id_inst_id;
-    set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
-
-    sGattIf->client->read_characteristic(conn_id, &srvc_id, &char_id, authReq);
+    sGattIf->client->read_characteristic(conn_id, handle, authReq);
 }
 
 static void gattClientReadDescriptorNative(JNIEnv* env, jobject object,
-    jint conn_id, jint  service_type, jint  service_id_inst_id,
-    jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
-    jint  char_id_inst_id,
-    jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
-    jint descr_id_inst_id,
-    jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb,
-    jint authReq)
+    jint conn_id, jint  handle, jint authReq)
 {
     if (!sGattIf) return;
 
-    btgatt_srvc_id_t srvc_id;
-    srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
-    srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
-    set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
-
-    btgatt_gatt_id_t char_id;
-    char_id.inst_id = (uint8_t) char_id_inst_id;
-    set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
-
-    btgatt_gatt_id_t descr_id;
-    descr_id.inst_id = (uint8_t) descr_id_inst_id;
-    set_uuid(descr_id.uuid.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
-
-    sGattIf->client->read_descriptor(conn_id, &srvc_id, &char_id, &descr_id, authReq);
+    sGattIf->client->read_descriptor(conn_id, handle, authReq);
 }
 
 static void gattClientWriteCharacteristicNative(JNIEnv* env, jobject object,
-    jint conn_id, jint  service_type, jint  service_id_inst_id,
-    jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
-    jint  char_id_inst_id,
-    jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
-    jint write_type, jint auth_req, jbyteArray value)
+    jint conn_id, jint handle, jint write_type, jint auth_req, jbyteArray value)
 {
     if (!sGattIf) return;
 
@@ -1122,21 +1078,11 @@
         return;
     }
 
-    btgatt_srvc_id_t srvc_id;
-    srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
-    srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
-    set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
-
-    btgatt_gatt_id_t char_id;
-    char_id.inst_id = (uint8_t) char_id_inst_id;
-    set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
-
     uint16_t len = (uint16_t) env->GetArrayLength(value);
     jbyte *p_value = env->GetByteArrayElements(value, NULL);
     if (p_value == NULL) return;
 
-    sGattIf->client->write_characteristic(conn_id, &srvc_id, &char_id,
-                                    write_type, len, auth_req, (char*)p_value);
+    sGattIf->client->write_characteristic(conn_id, handle, write_type, len, auth_req, (char*)p_value);
     env->ReleaseByteArrayElements(value, p_value, 0);
 }
 
@@ -1148,13 +1094,7 @@
 }
 
 static void gattClientWriteDescriptorNative(JNIEnv* env, jobject object,
-    jint conn_id, jint  service_type, jint service_id_inst_id,
-    jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
-    jint char_id_inst_id,
-    jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
-    jint descr_id_inst_id,
-    jlong descr_id_uuid_lsb, jlong descr_id_uuid_msb,
-    jint write_type, jint auth_req, jbyteArray value)
+    jint conn_id, jint handle, jint write_type, jint auth_req, jbyteArray value)
 {
     if (!sGattIf) return;
 
@@ -1163,55 +1103,27 @@
         return;
     }
 
-    btgatt_srvc_id_t srvc_id;
-    srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
-    srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
-    set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
-
-    btgatt_gatt_id_t char_id;
-    char_id.inst_id = (uint8_t) char_id_inst_id;
-    set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
-
-    btgatt_gatt_id_t descr_id;
-    descr_id.inst_id = (uint8_t) descr_id_inst_id;
-    set_uuid(descr_id.uuid.uu, descr_id_uuid_msb, descr_id_uuid_lsb);
-
     uint16_t len = (uint16_t) env->GetArrayLength(value);
     jbyte *p_value = env->GetByteArrayElements(value, NULL);
     if (p_value == NULL) return;
 
-    sGattIf->client->write_descriptor(conn_id, &srvc_id, &char_id, &descr_id,
-                                    write_type, len, auth_req, (char*)p_value);
+    sGattIf->client->write_descriptor(conn_id, handle, write_type, len, auth_req, (char*)p_value);
     env->ReleaseByteArrayElements(value, p_value, 0);
 }
 
 static void gattClientRegisterForNotificationsNative(JNIEnv* env, jobject object,
-    jint clientIf, jstring address,
-    jint  service_type, jint service_id_inst_id,
-    jlong service_id_uuid_lsb, jlong service_id_uuid_msb,
-    jint char_id_inst_id,
-    jlong char_id_uuid_lsb, jlong char_id_uuid_msb,
-    jboolean enable)
+    jint clientIf, jstring address, jint handle, jboolean enable)
 {
     if (!sGattIf) return;
 
-    btgatt_srvc_id_t srvc_id;
-    srvc_id.id.inst_id = (uint8_t) service_id_inst_id;
-    srvc_id.is_primary = (service_type == BTGATT_SERVICE_TYPE_PRIMARY ? 1 : 0);
-    set_uuid(srvc_id.id.uuid.uu, service_id_uuid_msb, service_id_uuid_lsb);
-
-    btgatt_gatt_id_t char_id;
-    char_id.inst_id = (uint8_t) char_id_inst_id;
-    set_uuid(char_id.uuid.uu, char_id_uuid_msb, char_id_uuid_lsb);
-
     bt_bdaddr_t bd_addr;
     const char *c_address = env->GetStringUTFChars(address, NULL);
     bd_addr_str_to_addr(c_address, bd_addr.address);
 
     if (enable)
-        sGattIf->client->register_for_notification(clientIf, &bd_addr, &srvc_id, &char_id);
+        sGattIf->client->register_for_notification(clientIf, &bd_addr, handle);
     else
-        sGattIf->client->deregister_for_notification(clientIf, &bd_addr, &srvc_id, &char_id);
+        sGattIf->client->deregister_for_notification(clientIf, &bd_addr, handle);
 }
 
 static void gattClientReadRemoteRssiNative(JNIEnv* env, jobject object, jint clientif,
@@ -1785,12 +1697,12 @@
     {"gattClientRefreshNative", "(ILjava/lang/String;)V", (void *) gattClientRefreshNative},
     {"gattClientSearchServiceNative", "(IZJJ)V", (void *) gattClientSearchServiceNative},
     {"gattClientGetGattDbNative", "(I)V", (void *) gattClientGetGattDbNative},
-    {"gattClientReadCharacteristicNative", "(IIIJJIJJI)V", (void *) gattClientReadCharacteristicNative},
-    {"gattClientReadDescriptorNative", "(IIIJJIJJIJJI)V", (void *) gattClientReadDescriptorNative},
-    {"gattClientWriteCharacteristicNative", "(IIIJJIJJII[B)V", (void *) gattClientWriteCharacteristicNative},
-    {"gattClientWriteDescriptorNative", "(IIIJJIJJIJJII[B)V", (void *) gattClientWriteDescriptorNative},
+    {"gattClientReadCharacteristicNative", "(III)V", (void *) gattClientReadCharacteristicNative},
+    {"gattClientReadDescriptorNative", "(III)V", (void *) gattClientReadDescriptorNative},
+    {"gattClientWriteCharacteristicNative", "(IIII[B)V", (void *) gattClientWriteCharacteristicNative},
+    {"gattClientWriteDescriptorNative", "(IIII[B)V", (void *) gattClientWriteDescriptorNative},
     {"gattClientExecuteWriteNative", "(IZ)V", (void *) gattClientExecuteWriteNative},
-    {"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IIJJIJJZ)V", (void *) gattClientRegisterForNotificationsNative},
+    {"gattClientRegisterForNotificationsNative", "(ILjava/lang/String;IZ)V", (void *) gattClientRegisterForNotificationsNative},
     {"gattClientReadRemoteRssiNative", "(ILjava/lang/String;)V", (void *) gattClientReadRemoteRssiNative},
     {"gattClientConfigureMTUNative", "(II)V", (void *) gattClientConfigureMTUNative},
     {"gattConnectionParameterUpdateNative", "(ILjava/lang/String;IIII)V", (void *) gattConnectionParameterUpdateNative},
diff --git a/src/com/android/bluetooth/gatt/CallbackInfo.java b/src/com/android/bluetooth/gatt/CallbackInfo.java
index 25dfd4c..db70a53 100644
--- a/src/com/android/bluetooth/gatt/CallbackInfo.java
+++ b/src/com/android/bluetooth/gatt/CallbackInfo.java
@@ -27,21 +27,12 @@
 class CallbackInfo {
     String address;
     int status;
-    int srvcType;
-    int srvcInstId;
-    UUID srvcUuid;
-    int charInstId;
-    UUID charUuid;
+    int handle;
 
-    CallbackInfo(String address, int status, int srvcType, int srvcInstId,
-            UUID srvcUuid, int charInstId, UUID charUuid) {
+    CallbackInfo(String address, int status, int handle) {
         this.address = address;
         this.status = status;
-        this.srvcType = srvcType;
-        this.srvcInstId = srvcInstId;
-        this.srvcUuid = srvcUuid;
-        this.charInstId = charInstId;
-        this.charUuid = charUuid;
+        this.handle = handle;
     }
 
     CallbackInfo(String address, int status) {
diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java
index 804a0b6..949b233 100644
--- a/src/com/android/bluetooth/gatt/GattService.java
+++ b/src/com/android/bluetooth/gatt/GattService.java
@@ -132,6 +132,9 @@
     ArrayList<BluetoothProto.ScanEvent> mScanEvents =
         new ArrayList<BluetoothProto.ScanEvent>(NUM_SCAN_EVENTS_KEPT);
 
+    private Map<Integer, List<BluetoothGattService>> gattClientDatabases =
+            new HashMap<Integer, List<BluetoothGattService>>();
+
     private ServiceDeclaration addDeclaration() {
         synchronized (mServiceDeclarations) {
             mServiceDeclarations.add(new ServiceDeclaration());
@@ -216,6 +219,36 @@
         return true;
     }
 
+    boolean permissionCheck(int connId, int handle) {
+        List<BluetoothGattService> db = gattClientDatabases.get(connId);
+
+        for (BluetoothGattService service : db) {
+            for (BluetoothGattCharacteristic characteristic: service.getCharacteristics()) {
+                if (handle == characteristic.getInstanceId()) {
+                    if ((isRestrictedCharUuid(characteristic.getUuid()) ||
+                         isRestrictedSrvcUuid(service.getUuid())) &&
+                        (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)))
+                        return false;
+                    else
+                        return true;
+                }
+
+                for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) {
+                    if (handle == descriptor.getInstanceId()) {
+                        if ((isRestrictedCharUuid(characteristic.getUuid()) ||
+                             isRestrictedSrvcUuid(service.getUuid())) &&
+                            (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)))
+                            return false;
+                        else
+                            return true;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         if (GattDebugUtils.handleDebugAction(this, intent)) {
@@ -363,55 +396,30 @@
             service.discoverServices(clientIf, address);
         }
 
-        public void readCharacteristic(int clientIf, String address, int srvcType,
-                                       int srvcInstanceId, ParcelUuid srvcId,
-                                       int charInstanceId, ParcelUuid charId,
-                                       int authReq) {
+        public void readCharacteristic(int clientIf, String address, int handle, int authReq) {
             GattService service = getService();
             if (service == null) return;
-            service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId,
-                                       srvcId.getUuid(), charInstanceId,
-                                       charId.getUuid(), authReq);
+            service.readCharacteristic(clientIf, address, handle, authReq);
         }
 
-        public void writeCharacteristic(int clientIf, String address, int srvcType,
-                             int srvcInstanceId, ParcelUuid srvcId,
-                             int charInstanceId, ParcelUuid charId,
+        public void writeCharacteristic(int clientIf, String address, int handle,
                              int writeType, int authReq, byte[] value) {
             GattService service = getService();
             if (service == null) return;
-            service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId,
-                                       srvcId.getUuid(), charInstanceId,
-                                       charId.getUuid(), writeType, authReq,
-                                       value);
+            service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value);
         }
 
-        public void readDescriptor(int clientIf, String address, int srvcType,
-                            int srvcInstanceId, ParcelUuid srvcId,
-                            int charInstanceId, ParcelUuid charId,
-                            int descrInstanceId, ParcelUuid descrId,
-                            int authReq) {
+        public void readDescriptor(int clientIf, String address, int handle, int authReq) {
             GattService service = getService();
             if (service == null) return;
-            service.readDescriptor(clientIf, address, srvcType,
-                                   srvcInstanceId, srvcId.getUuid(),
-                                   charInstanceId, charId.getUuid(),
-                                   descrInstanceId, descrId.getUuid(),
-                                   authReq);
+            service.readDescriptor(clientIf, address, handle, authReq);
         }
 
-        public void writeDescriptor(int clientIf, String address, int srvcType,
-                            int srvcInstanceId, ParcelUuid srvcId,
-                            int charInstanceId, ParcelUuid charId,
-                            int descrInstanceId, ParcelUuid descrId,
-                            int writeType, int authReq, byte[] value) {
+        public void writeDescriptor(int clientIf, String address, int handle,
+                                    int writeType, int authReq, byte[] value) {
             GattService service = getService();
             if (service == null) return;
-            service.writeDescriptor(clientIf, address, srvcType,
-                                    srvcInstanceId, srvcId.getUuid(),
-                                    charInstanceId, charId.getUuid(),
-                                    descrInstanceId, descrId.getUuid(),
-                                    writeType, authReq, value);
+            service.writeDescriptor(clientIf, address, handle, writeType, authReq, value);
         }
 
         public void beginReliableWrite(int clientIf, String address) {
@@ -426,15 +434,10 @@
             service.endReliableWrite(clientIf, address, execute);
         }
 
-        public void registerForNotification(int clientIf, String address, int srvcType,
-                            int srvcInstanceId, ParcelUuid srvcId,
-                            int charInstanceId, ParcelUuid charId,
-                            boolean enable) {
+        public void registerForNotification(int clientIf, String address, int handle, boolean enable) {
             GattService service = getService();
             if (service == null) return;
-            service.registerForNotification(clientIf, address, srvcType, srvcInstanceId,
-                                       srvcId.getUuid(), charInstanceId,
-                                       charId.getUuid(), enable);
+            service.registerForNotification(clientIf, address, handle, enable);
         }
 
         public void readRemoteRssi(int clientIf, String address) {
@@ -779,53 +782,36 @@
         }
 
         // Search is complete when there was error, or nothing more to process
+        gattClientDatabases.put(connId, db_out);
         app.callback.onSearchComplete(address, db_out, 0 /* status */);
     }
 
-    void onRegisterForNotifications(int connId, int status, int registered, int srvcType,
-            int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
-            int charInstId, long charUuidLsb, long charUuidMsb) {
-        UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
-        UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
+    void onRegisterForNotifications(int connId, int status, int registered, int handle) {
         String address = mClientMap.addressByConnId(connId);
 
         if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address
             + ", status=" + status + ", registered=" + registered
-            + ", charUuid=" + charUuid);
+            + ", handle=" + handle);
     }
 
-    void onNotify(int connId, String address, int srvcType,
-            int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
-            int charInstId, long charUuidLsb, long charUuidMsb,
+    void onNotify(int connId, String address, int handle,
             boolean isNotify, byte[] data) throws RemoteException {
-        UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
-        UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
 
         if (VDBG) Log.d(TAG, "onNotify() - address=" + address
-            + ", charUuid=" + charUuid + ", length=" + data.length);
+            + ", handle=" + handle + ", length=" + data.length);
 
-
-        if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid) &&
-               (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))) {
+        if (!permissionCheck(connId, handle)) {
+            if (VDBG) Log.d(TAG, "onNotify() - permission check failed!");
             return;
         }
 
         ClientMap.App app = mClientMap.getByConnId(connId);
         if (app != null) {
-            app.callback.onNotify(address, srvcType,
-                        srvcInstId, new ParcelUuid(srvcUuid),
-                        charInstId, new ParcelUuid(charUuid),
-                        data);
+            app.callback.onNotify(address, handle, data);
         }
     }
 
-    void onReadCharacteristic(int connId, int status, int srvcType,
-            int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
-            int charInstId, long charUuidLsb, long charUuidMsb,
-            int charType, byte[] data) throws RemoteException {
-
-        UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
-        UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
+    void onReadCharacteristic(int connId, int status, int handle, byte[] data) throws RemoteException {
         String address = mClientMap.addressByConnId(connId);
 
         if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address
@@ -833,19 +819,12 @@
 
         ClientMap.App app = mClientMap.getByConnId(connId);
         if (app != null) {
-            app.callback.onCharacteristicRead(address, status, srvcType,
-                        srvcInstId, new ParcelUuid(srvcUuid),
-                        charInstId, new ParcelUuid(charUuid), data);
+            app.callback.onCharacteristicRead(address, status, handle, data);
         }
     }
 
-    void onWriteCharacteristic(int connId, int status, int srvcType,
-            int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
-            int charInstId, long charUuidLsb, long charUuidMsb)
+    void onWriteCharacteristic(int connId, int status, int handle)
             throws RemoteException {
-
-        UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
-        UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
         String address = mClientMap.addressByConnId(connId);
 
         if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address
@@ -855,15 +834,12 @@
         if (app == null) return;
 
         if (!app.isCongested) {
-            app.callback.onCharacteristicWrite(address, status, srvcType,
-                    srvcInstId, new ParcelUuid(srvcUuid),
-                    charInstId, new ParcelUuid(charUuid));
+            app.callback.onCharacteristicWrite(address, status, handle);
         } else {
             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                 status = BluetoothGatt.GATT_SUCCESS;
             }
-            CallbackInfo callbackInfo = new CallbackInfo(address, status, srvcType,
-                    srvcInstId, srvcUuid, charInstId, charUuid);
+            CallbackInfo callbackInfo = new CallbackInfo(address, status, handle);
             app.queueCallback(callbackInfo);
         }
     }
@@ -879,15 +855,7 @@
         }
     }
 
-    void onReadDescriptor(int connId, int status, int srvcType,
-            int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
-            int charInstId, long charUuidLsb, long charUuidMsb,
-            int descrInstId, long descrUuidLsb, long descrUuidMsb,
-            int charType, byte[] data) throws RemoteException {
-
-        UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
-        UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
-        UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb);
+    void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException {
         String address = mClientMap.addressByConnId(connId);
 
         if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address
@@ -895,21 +863,11 @@
 
         ClientMap.App app = mClientMap.getByConnId(connId);
         if (app != null) {
-            app.callback.onDescriptorRead(address, status, srvcType,
-                        srvcInstId, new ParcelUuid(srvcUuid),
-                        charInstId, new ParcelUuid(charUuid),
-                        descrInstId, new ParcelUuid(descrUuid), data);
+            app.callback.onDescriptorRead(address, status, handle, data);
         }
     }
 
-    void onWriteDescriptor(int connId, int status, int srvcType,
-            int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
-            int charInstId, long charUuidLsb, long charUuidMsb,
-            int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException {
-
-        UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
-        UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
-        UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb);
+    void onWriteDescriptor(int connId, int status, int handle) throws RemoteException {
         String address = mClientMap.addressByConnId(connId);
 
         if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address
@@ -917,10 +875,7 @@
 
         ClientMap.App app = mClientMap.getByConnId(connId);
         if (app != null) {
-            app.callback.onDescriptorWrite(address, status, srvcType,
-                        srvcInstId, new ParcelUuid(srvcUuid),
-                        charInstId, new ParcelUuid(charUuid),
-                        descrInstId, new ParcelUuid(descrUuid));
+            app.callback.onDescriptorWrite(address, status, handle);
         }
     }
 
@@ -1270,9 +1225,7 @@
                 CallbackInfo callbackInfo = app.popQueuedCallback();
                 if (callbackInfo == null)  return;
                 app.callback.onCharacteristicWrite(callbackInfo.address,
-                        callbackInfo.status, callbackInfo.srvcType,
-                        callbackInfo.srvcInstId, new ParcelUuid(callbackInfo.srvcUuid),
-                        callbackInfo.charInstId, new ParcelUuid(callbackInfo.charUuid));
+                        callbackInfo.status, callbackInfo.handle);
             }
         }
     }
@@ -1468,101 +1421,83 @@
             Log.e(TAG, "discoverServices() - No connection for " + address + "...");
     }
 
-    void readCharacteristic(int clientIf, String address, int srvcType,
-                            int srvcInstanceId, UUID srvcUuid,
-                            int charInstanceId, UUID charUuid, int authReq) {
+    void readCharacteristic(int clientIf, String address, int handle, int authReq) {
         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) {
-            enforcePrivilegedPermission();
-        }
 
         if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address);
 
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
-        if (connId != null)
-            gattClientReadCharacteristicNative(connId, srvcType,
-                srvcInstanceId, srvcUuid.getLeastSignificantBits(),
-                srvcUuid.getMostSignificantBits(), charInstanceId,
-                charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
-                authReq);
-        else
+        if (connId == null) {
             Log.e(TAG, "readCharacteristic() - No connection for " + address + "...");
+            return;
+        }
+
+        if (!permissionCheck(connId, handle)) {
+            if (VDBG) Log.d(TAG, "readCharacteristic() - permission check failed!");
+            return;
+        }
+
+        gattClientReadCharacteristicNative(connId, handle, authReq);
     }
 
-    void writeCharacteristic(int clientIf, String address, int srvcType,
-                             int srvcInstanceId, UUID srvcUuid,
-                             int charInstanceId, UUID charUuid, int writeType,
+    void writeCharacteristic(int clientIf, String address, int handle, int writeType,
                              int authReq, byte[] value) {
         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) {
-            enforcePrivilegedPermission();
-        }
 
         if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address);
 
         if (mReliableQueue.contains(address)) writeType = 3; // Prepared write
 
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
-        if (connId != null)
-            gattClientWriteCharacteristicNative(connId, srvcType,
-                srvcInstanceId, srvcUuid.getLeastSignificantBits(),
-                srvcUuid.getMostSignificantBits(), charInstanceId,
-                charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
-                writeType, authReq, value);
-        else
+        if (connId == null) {
             Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
+            return;
+        }
+
+        if (!permissionCheck(connId, handle)) {
+            if (VDBG) Log.d(TAG, "writeCharacteristic() - permission check failed!");
+            return;
+        }
+
+        gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
     }
 
-    void readDescriptor(int clientIf, String address, int srvcType,
-                            int srvcInstanceId, UUID srvcUuid,
-                            int charInstanceId, UUID charUuid,
-                            int descrInstanceId, UUID descrUuid,
-                            int authReq) {
+    void readDescriptor(int clientIf, String address, int handle, int authReq) {
         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) {
-            enforcePrivilegedPermission();
-        }
 
         if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address);
 
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
-        if (connId != null)
-            gattClientReadDescriptorNative(connId, srvcType,
-                srvcInstanceId,
-                srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(),
-                charInstanceId,
-                charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
-                descrInstanceId,
-                descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(),
-                authReq);
-        else
+        if (connId == null) {
             Log.e(TAG, "readDescriptor() - No connection for " + address + "...");
-    };
-
-    void writeDescriptor(int clientIf, String address, int srvcType,
-                            int srvcInstanceId, UUID srvcUuid,
-                            int charInstanceId, UUID charUuid,
-                            int descrInstanceId, UUID descrUuid,
-                            int writeType, int authReq, byte[] value) {
-        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) {
-            enforcePrivilegedPermission();
+            return;
         }
 
+        if (!permissionCheck(connId, handle)) {
+            if (VDBG) Log.d(TAG, "readDescriptor() - permission check failed!");
+            return;
+        }
+
+        gattClientReadDescriptorNative(connId, handle, authReq);
+    };
+
+    void writeDescriptor(int clientIf, String address, int handle,
+                            int writeType, int authReq, byte[] value) {
+        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
         if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address);
 
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
-        if (connId != null)
-            gattClientWriteDescriptorNative(connId, srvcType,
-                srvcInstanceId,
-                srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(),
-                charInstanceId,
-                charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
-                descrInstanceId,
-                descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(),
-                writeType, authReq, value);
-        else
+        if (connId == null) {
             Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
+            return;
+        }
+
+        if (!permissionCheck(connId, handle)) {
+            if (VDBG) Log.d(TAG, "writeDescriptor() - permission check failed!");
+            return;
+        }
+
+        gattClientWriteDescriptorNative(connId, handle, writeType, authReq, value);
     }
 
     void beginReliableWrite(int clientIf, String address) {
@@ -1583,27 +1518,23 @@
         if (connId != null) gattClientExecuteWriteNative(connId, execute);
     }
 
-    void registerForNotification(int clientIf, String address, int srvcType,
-                int srvcInstanceId, UUID srvcUuid,
-                int charInstanceId, UUID charUuid,
-                boolean enable) {
+    void registerForNotification(int clientIf, String address, int handle, boolean enable) {
         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) {
-            enforcePrivilegedPermission();
-        }
 
         if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
 
         Integer connId = mClientMap.connIdByAddress(clientIf, address);
         if (connId != null) {
-            gattClientRegisterForNotificationsNative(clientIf, address,
-                srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(),
-                srvcUuid.getMostSignificantBits(), charInstanceId,
-                charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
-                enable);
-        } else {
             Log.e(TAG, "registerForNotification() - No connection for " + address + "...");
+            return;
         }
+
+        if (!permissionCheck(connId, handle)) {
+            if (VDBG) Log.d(TAG, "writeDescriptor() - permission check failed!");
+            return;
+        }
+
+        gattClientRegisterForNotificationsNative(clientIf, address, handle, enable);
     }
 
     void readRemoteRssi(int clientIf, String address) {
@@ -2369,35 +2300,20 @@
 
     private native void gattClientGetGattDbNative(int conn_id);
 
-    private native void gattClientReadCharacteristicNative(int conn_id,
-            int service_type, int service_id_inst_id, long service_id_uuid_lsb,
-            long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb,
-            long char_id_uuid_msb, int authReq);
+    private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq);
 
-    private native void gattClientReadDescriptorNative(int conn_id, int service_type,
-            int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb,
-            int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
-            int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb,
-            int authReq);
+    private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq);
 
     private native void gattClientWriteCharacteristicNative(int conn_id,
-            int service_type, int service_id_inst_id, long service_id_uuid_lsb,
-            long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb,
-            long char_id_uuid_msb, int write_type, int auth_req, byte[] value);
+            int handle, int write_type, int auth_req, byte[] value);
 
-    private native void gattClientWriteDescriptorNative(int conn_id, int service_type,
-            int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb,
-            int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
-            int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb,
+    private native void gattClientWriteDescriptorNative(int conn_id, int handle,
             int write_type, int auth_req, byte[] value);
 
     private native void gattClientExecuteWriteNative(int conn_id, boolean execute);
 
     private native void gattClientRegisterForNotificationsNative(int clientIf,
-            String address, int service_type, int service_id_inst_id,
-            long service_id_uuid_lsb, long service_id_uuid_msb,
-            int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
-            boolean enable);
+            String address, int handle, boolean enable);
 
     private native void gattClientReadRemoteRssiNative(int clientIf,
             String address);