LE: Add instance ID to descriptors (1/4)

If a remote devices offers multiple descriptors with the same UUID, the
instance ID is used to differentiate between them.

Change-Id: I0c36494c980c86abd23f9647196af8d59ef663e9
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1ea13e1..74d85c3 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1704,7 +1704,7 @@
         public void onGetDescriptor(String address, int srvcType,
                                     int srvcInstId, ParcelUuid srvcUuid,
                                     int charInstId, ParcelUuid charUuid,
-                                    ParcelUuid descUuid) {
+                                    int descInstId, ParcelUuid descUuid) {
             // no op
         }
 
@@ -1734,14 +1734,14 @@
         public void onDescriptorRead(String address, int status, int srvcType,
                                      int srvcInstId, ParcelUuid srvcUuid,
                                      int charInstId, ParcelUuid charUuid,
-                                     ParcelUuid descrUuid, byte[] value) {
+                                     int descInstId, ParcelUuid descrUuid, byte[] value) {
             // no op
         }
 
         public void onDescriptorWrite(String address, int status, int srvcType,
                                       int srvcInstId, ParcelUuid srvcUuid,
                                       int charInstId, ParcelUuid charUuid,
-                                      ParcelUuid descrUuid) {
+                                      int descInstId, ParcelUuid descrUuid) {
             // no op
         }
 
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index df3ec1a..1ad7bf2 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -261,7 +261,7 @@
             public void onGetDescriptor(String address, int srvcType,
                              int srvcInstId, ParcelUuid srvcUuid,
                              int charInstId, ParcelUuid charUuid,
-                             ParcelUuid descUuid) {
+                             int descrInstId, ParcelUuid descUuid) {
                 if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
 
                 if (!address.equals(mDevice.getAddress())) {
@@ -276,7 +276,7 @@
                 if (characteristic == null) return;
 
                 characteristic.addDescriptor(new BluetoothGattDescriptor(
-                    characteristic, descUuid.getUuid(), 0));
+                    characteristic, descUuid.getUuid(), descrInstId, 0));
             }
 
             /**
@@ -429,7 +429,8 @@
             public void onDescriptorRead(String address, int status, int srvcType,
                              int srvcInstId, ParcelUuid srvcUuid,
                              int charInstId, ParcelUuid charUuid,
-                             ParcelUuid descrUuid, byte[] value) {
+                             int descrInstId, ParcelUuid descrUuid,
+                             byte[] value) {
                 if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
 
                 if (!address.equals(mDevice.getAddress())) {
@@ -444,7 +445,7 @@
                 if (characteristic == null) return;
 
                 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
-                        descrUuid.getUuid());
+                        descrUuid.getUuid(), descrInstId);
                 if (descriptor == null) return;
 
                 if (status == 0) descriptor.setValue(value);
@@ -456,7 +457,7 @@
                         mAuthRetry = true;
                         mService.readDescriptor(mClientIf, address,
                             srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
-                            descrUuid, AUTHENTICATION_MITM);
+                            descrInstId, descrUuid, AUTHENTICATION_MITM);
                     } catch (RemoteException e) {
                         Log.e(TAG,"",e);
                     }
@@ -478,7 +479,7 @@
             public void onDescriptorWrite(String address, int status, int srvcType,
                              int srvcInstId, ParcelUuid srvcUuid,
                              int charInstId, ParcelUuid charUuid,
-                             ParcelUuid descrUuid) {
+                             int descrInstId, ParcelUuid descrUuid) {
                 if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
 
                 if (!address.equals(mDevice.getAddress())) {
@@ -493,7 +494,7 @@
                 if (characteristic == null) return;
 
                 BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
-                        descrUuid.getUuid());
+                        descrUuid.getUuid(), descrInstId);
                 if (descriptor == null) return;
 
                 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
@@ -503,7 +504,7 @@
                         mAuthRetry = true;
                         mService.writeDescriptor(mClientIf, address,
                             srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
-                            descrUuid, characteristic.getWriteType(),
+                            descrInstId, descrUuid, characteristic.getWriteType(),
                             AUTHENTICATION_MITM, descriptor.getValue());
                     } catch (RemoteException e) {
                         Log.e(TAG,"",e);
@@ -915,11 +916,11 @@
         if (device == null) return false;
 
         try {
-            mService.readDescriptor(mClientIf, device.getAddress(),
-                service.getType(), service.getInstanceId(),
-                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
-                new ParcelUuid(characteristic.getUuid()),
-                new ParcelUuid(descriptor.getUuid()), AUTHENTICATION_NONE);
+            mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
+                service.getInstanceId(), new ParcelUuid(service.getUuid()),
+                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
+                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
+                AUTHENTICATION_NONE);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
             return false;
@@ -953,11 +954,10 @@
         if (device == null) return false;
 
         try {
-            mService.writeDescriptor(mClientIf, device.getAddress(),
-                service.getType(), service.getInstanceId(),
-                new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
-                new ParcelUuid(characteristic.getUuid()),
-                new ParcelUuid(descriptor.getUuid()),
+            mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
+                service.getInstanceId(), new ParcelUuid(service.getUuid()),
+                characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
+                descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
                 characteristic.getWriteType(), AUTHENTICATION_NONE,
                 descriptor.getValue());
         } catch (RemoteException e) {
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 033f079..f0ecbb4 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -283,6 +283,20 @@
     }
 
     /**
+     * Get a descriptor by UUID and isntance id.
+     * @hide
+     */
+    /*package*/  BluetoothGattDescriptor getDescriptor(UUID uuid, int instanceId) {
+        for(BluetoothGattDescriptor descriptor : mDescriptors) {
+            if (descriptor.getUuid().equals(uuid)
+             && descriptor.getInstanceId() == instanceId) {
+                return descriptor;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Returns the service this characteristic belongs to.
      * @return The asscociated service
      */
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 1cd6878..5f525dc 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -91,6 +91,12 @@
     protected UUID mUuid;
 
     /**
+     * Instance ID for this descriptor.
+     * @hide
+     */
+    protected int mInstance;
+
+    /**
      * Permissions for this descriptor
      * @hide
      */
@@ -116,7 +122,7 @@
      * @param permissions Permissions for this descriptor
      */
     public BluetoothGattDescriptor(UUID uuid, int permissions) {
-        initDescriptor(null, uuid, permissions);
+        initDescriptor(null, uuid, 0, permissions);
     }
 
     /**
@@ -128,14 +134,15 @@
      * @param permissions Permissions for this descriptor
      */
     /*package*/ BluetoothGattDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
-                                    int permissions) {
-        initDescriptor(characteristic, uuid, permissions);
+                                    int instance, int permissions) {
+        initDescriptor(characteristic, uuid, instance, permissions);
     }
 
     private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
-                                int permissions) {
+                                int instance, int permissions) {
         mCharacteristic = characteristic;
         mUuid = uuid;
+        mInstance = instance;
         mPermissions = permissions;
     }
 
@@ -165,6 +172,21 @@
     }
 
     /**
+     * Returns the instance ID for this descriptor.
+     *
+     * <p>If a remote device offers multiple descriptors with the same UUID,
+     * the instance ID is used to distuinguish between descriptors.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @return Instance ID of this descriptor
+     * @hide
+     */
+    public int getInstanceId() {
+        return mInstance;
+    }
+
+    /**
      * Returns the permissions for this descriptor.
      *
      * @return Permissions of this descriptor
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 39a435b..1e66369 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -152,8 +152,8 @@
      */
     /*package*/ BluetoothGattCharacteristic getCharacteristic(UUID uuid, int instanceId) {
         for(BluetoothGattCharacteristic characteristic : mCharacteristics) {
-            if (uuid.equals(characteristic.getUuid()) &&
-                    mInstanceId == instanceId)
+            if (uuid.equals(characteristic.getUuid())
+             && characteristic.getInstanceId() == instanceId)
                 return characteristic;
         }
         return null;
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index c89d132..b58b847 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -50,12 +50,13 @@
     void readDescriptor(in int clientIf, in String address, in int srvcType,
                             in int srvcInstanceId, in ParcelUuid srvcId,
                             in int charInstanceId, in ParcelUuid charId,
-                            in ParcelUuid descrUuid, in int authReq);
+                            in int descrInstanceId, in ParcelUuid descrUuid,
+                            in int authReq);
     void writeDescriptor(in int clientIf, in String address, in int srvcType,
                             in int srvcInstanceId, in ParcelUuid srvcId,
                             in int charInstanceId, in ParcelUuid charId,
-                            in ParcelUuid descrId, in int writeType,
-                            in int authReq, in byte[] value);
+                            in int descrInstanceId, in ParcelUuid descrId,
+                            in int writeType, in int authReq, in byte[] value);
     void registerForNotification(in int clientIf, in String address, in int srvcType,
                             in int srvcInstanceId, in ParcelUuid srvcId,
                             in int charInstanceId, in ParcelUuid charId,
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index fc52172..e3563fc 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -39,7 +39,7 @@
     void onGetDescriptor(in String address, in int srvcType,
                              in int srvcInstId, in ParcelUuid srvcUuid,
                              in int charInstId, in ParcelUuid charUuid,
-                             in ParcelUuid descrUuid);
+                             in int descrInstId, in ParcelUuid descrUuid);
     void onSearchComplete(in String address, in int status);
     void onCharacteristicRead(in String address, in int status, in int srvcType,
                              in int srvcInstId, in ParcelUuid srvcUuid,
@@ -52,11 +52,12 @@
     void onDescriptorRead(in String address, in int status, in int srvcType,
                              in int srvcInstId, in ParcelUuid srvcUuid,
                              in int charInstId, in ParcelUuid charUuid,
-                             in ParcelUuid descrUuid, in byte[] value);
+                             in int descrInstId, in ParcelUuid descrUuid,
+                             in byte[] value);
     void onDescriptorWrite(in String address, in int status, in int srvcType,
                              in int srvcInstId, in ParcelUuid srvcUuid,
                              in int charInstId, in ParcelUuid charUuid,
-                             in ParcelUuid descrUuid);
+                             in int descrInstId, in ParcelUuid descrUuid);
     void onNotify(in String address, in int srvcType,
                              in int srvcInstId, in ParcelUuid srvcUuid,
                              in int charInstId, in ParcelUuid charUuid,