Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.facade.bluetooth;
     18 
     19 import android.app.Service;
     20 import android.bluetooth.BluetoothAdapter;
     21 import android.bluetooth.BluetoothDevice;
     22 import android.bluetooth.BluetoothGatt;
     23 import android.bluetooth.IBluetoothGatt;
     24 import android.bluetooth.BluetoothGattCallback;
     25 import android.bluetooth.BluetoothGattCharacteristic;
     26 import android.bluetooth.BluetoothGattDescriptor;
     27 import android.bluetooth.BluetoothGattService;
     28 import android.bluetooth.BluetoothManager;
     29 import android.bluetooth.BluetoothProfile;
     30 import android.content.Context;
     31 import android.os.Bundle;
     32 
     33 import com.googlecode.android_scripting.Log;
     34 import com.googlecode.android_scripting.MainThread;
     35 import com.googlecode.android_scripting.facade.EventFacade;
     36 import com.googlecode.android_scripting.facade.FacadeManager;
     37 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
     38 import com.googlecode.android_scripting.rpc.Rpc;
     39 import com.googlecode.android_scripting.rpc.RpcParameter;
     40 import com.googlecode.android_scripting.rpc.RpcStopEvent;
     41 
     42 import java.lang.reflect.*;
     43 import java.util.ArrayList;
     44 import java.util.HashMap;
     45 import java.util.List;
     46 import java.util.concurrent.Callable;
     47 import java.util.UUID;
     48 
     49 public class GattClientFacade extends RpcReceiver {
     50     private final EventFacade mEventFacade;
     51     private BluetoothAdapter mBluetoothAdapter;
     52     private BluetoothManager mBluetoothManager;
     53     private final Service mService;
     54     private final Context mContext;
     55     private final HashMap<Integer, myBluetoothGattCallback> mGattCallbackList;
     56     private final HashMap<Integer, BluetoothGatt> mBluetoothGattList;
     57     private final HashMap<Integer, BluetoothGattCharacteristic> mCharacteristicList;
     58     private final HashMap<Integer, BluetoothGattDescriptor> mDescriptorList;
     59     private final HashMap<Integer, BluetoothGattService> mGattServiceList;
     60     private final HashMap<Integer, List<BluetoothGattService>> mBluetoothGattDiscoveredServicesList;
     61     private final HashMap<Integer, List<BluetoothDevice>> mGattServerDiscoveredDevicesList;
     62     private static int GattCallbackCount;
     63     private static int BluetoothGattDiscoveredServicesCount;
     64     private static int BluetoothGattCount;
     65     private static int CharacteristicCount;
     66     private static int DescriptorCount;
     67     private static int GattServerCallbackCount;
     68     private static int GattServerCount;
     69     private static int GattServiceCount;
     70 
     71     public GattClientFacade(FacadeManager manager) {
     72         super(manager);
     73         mService = manager.getService();
     74         mContext = mService.getApplicationContext();
     75         mBluetoothAdapter =
     76                 MainThread.run(
     77                         mService,
     78                         new Callable<BluetoothAdapter>() {
     79                             @Override
     80                             public BluetoothAdapter call() throws Exception {
     81                                 return BluetoothAdapter.getDefaultAdapter();
     82                             }
     83                         });
     84         mBluetoothManager = (BluetoothManager) mContext.getSystemService(Service.BLUETOOTH_SERVICE);
     85         mEventFacade = manager.getReceiver(EventFacade.class);
     86         mGattCallbackList = new HashMap<Integer, myBluetoothGattCallback>();
     87         mCharacteristicList = new HashMap<Integer, BluetoothGattCharacteristic>();
     88         mBluetoothGattList = new HashMap<Integer, BluetoothGatt>();
     89         mDescriptorList = new HashMap<Integer, BluetoothGattDescriptor>();
     90         mGattServiceList = new HashMap<Integer, BluetoothGattService>();
     91         mBluetoothGattDiscoveredServicesList = new HashMap<Integer, List<BluetoothGattService>>();
     92         mGattServerDiscoveredDevicesList = new HashMap<Integer, List<BluetoothDevice>>();
     93     }
     94 
     95     /**
     96      * Create a BluetoothGatt connection
     97      *
     98      * @param index of the callback to start a connection on
     99      * @param macAddress the mac address of the ble device
    100      * @param autoConnect Whether to directly connect to the remote device (false) or to
    101      *       automatically connect as soon as the remote device becomes available (true)
    102      * @param transport preferred transport for GATT connections to remote dual-mode devices
    103      *       TRANSPORT_AUTO or TRANSPORT_BREDR or TRANSPORT_LE
    104      * @return the index of the BluetoothGatt object
    105      * @throws Exception
    106      */
    107     @Rpc(description = "Create a gatt connection")
    108     public int gattClientConnectGatt(
    109             @RpcParameter(name = "index") Integer index,
    110             @RpcParameter(name = "macAddress") String macAddress,
    111             @RpcParameter(name = "autoConnect") Boolean autoConnect,
    112             @RpcParameter(name = "transport") Integer transport,
    113             @RpcParameter(name = "phy") Integer phy)
    114             throws Exception {
    115         if (mGattCallbackList.get(index) != null) {
    116             BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
    117             if (phy == null) phy = BluetoothDevice.PHY_LE_1M;
    118 
    119             BluetoothGatt mBluetoothGatt =
    120                     device.connectGatt(
    121                             mService.getApplicationContext(),
    122                             autoConnect,
    123                             mGattCallbackList.get(index),
    124                             transport,
    125                             phy);
    126             BluetoothGattCount += 1;
    127             mBluetoothGattList.put(BluetoothGattCount, mBluetoothGatt);
    128             return BluetoothGattCount;
    129         } else {
    130             throw new Exception("Invalid index input:" + Integer.toString(index));
    131         }
    132     }
    133 
    134     /**
    135      * Trigger discovering of services on the BluetoothGatt object
    136      *
    137      * @param index The BluetoothGatt object index
    138      * @return true, if the remote service discovery has been started
    139      * @throws Exception
    140      */
    141     @Rpc(description = "Trigger discovering of services on the BluetoothGatt object")
    142     public boolean gattClientDiscoverServices(@RpcParameter(name = "index") Integer index)
    143             throws Exception {
    144         if (mBluetoothGattList.get(index) != null) {
    145             return mBluetoothGattList.get(index).discoverServices();
    146         } else {
    147             throw new Exception("Invalid index input:" + Integer.toString(index));
    148         }
    149     }
    150 
    151     /**
    152      * Trigger discovering of services by UUID on the BluetoothGatt object
    153      *
    154      * @param index The BluetoothGatt object index
    155      * @param uuid service UUID
    156      * @return true, if the remote service discovery has been started
    157      * @throws Exception
    158      */
    159     @Rpc(description = "Trigger discovering of services on the BluetoothGatt object")
    160     public boolean gattClientDiscoverServiceByUuid(@RpcParameter(name = "index") Integer index,
    161             @RpcParameter(name = "uuid") String uuid) throws Exception {
    162         BluetoothGatt gatt = mBluetoothGattList.get(index);
    163         if (gatt != null) {
    164             Object ret = gatt.getClass().getMethod("discoverServiceByUuid", UUID.class)
    165                             .invoke(gatt, UUID.fromString(uuid));
    166             return (Boolean) ret;
    167         } else {
    168             throw new Exception("Invalid index input:" + Integer.toString(index));
    169         }
    170     }
    171 
    172 
    173     /**
    174      * Get the services from the BluetoothGatt object
    175      *
    176      * @param index The BluetoothGatt object index
    177      * @return a list of BluetoothGattServices
    178      * @throws Exception
    179      */
    180     @Rpc(description = "Get the services from the BluetoothGatt object")
    181     public List<BluetoothGattService> gattClientGetServices(
    182             @RpcParameter(name = "index") Integer index) throws Exception {
    183         if (mBluetoothGattList.get(index) != null) {
    184             return mBluetoothGattList.get(index).getServices();
    185         } else {
    186             throw new Exception("Invalid index input:" + Integer.toString(index));
    187         }
    188     }
    189 
    190     /**
    191      * Abort reliable write of a bluetooth gatt
    192      *
    193      * @param index the bluetooth gatt index
    194      * @throws Exception
    195      */
    196     @Rpc(description = "Abort reliable write of a bluetooth gatt")
    197     public void gattClientAbortReliableWrite(@RpcParameter(name = "index") Integer index)
    198             throws Exception {
    199         if (mBluetoothGattList.get(index) != null) {
    200             mBluetoothGattList.get(index).abortReliableWrite();
    201         } else {
    202             throw new Exception("Invalid index input:" + index);
    203         }
    204     }
    205 
    206     /**
    207      * Begin reliable write of a bluetooth gatt
    208      *
    209      * @param index the bluetooth gatt index
    210      * @return
    211      * @throws Exception
    212      */
    213     @Rpc(description = "Begin reliable write of a bluetooth gatt")
    214     public boolean gattClientBeginReliableWrite(@RpcParameter(name = "index") Integer index)
    215             throws Exception {
    216         if (mBluetoothGattList.get(index) != null) {
    217             return mBluetoothGattList.get(index).beginReliableWrite();
    218         } else {
    219             throw new Exception("Invalid index input:" + index);
    220         }
    221     }
    222 
    223     /**
    224      * Configure a bluetooth gatt's MTU
    225      *
    226      * @param index the bluetooth gatt index
    227      * @param mtu the MTU to set
    228      * @return
    229      * @throws Exception
    230      */
    231     @Rpc(description = "true, if the new MTU value has been requested successfully")
    232     public boolean gattClientRequestMtu(
    233             @RpcParameter(name = "index") Integer index, @RpcParameter(name = "mtu") Integer mtu)
    234             throws Exception {
    235         if (mBluetoothGattList.get(index) != null) {
    236             return mBluetoothGattList.get(index).requestMtu(mtu);
    237         } else {
    238             throw new Exception("Invalid index input:" + index);
    239         }
    240     }
    241 
    242     /**
    243      * Read the current transmitter PHY and receiver PHY of the connection.
    244      *
    245      * @param index the bluetooth gatt index
    246      * @throws Exception
    247      */
    248     @Rpc(description = "Read PHY")
    249     public void gattClientReadPhy(@RpcParameter(name = "index") Integer index) throws Exception {
    250         if (mBluetoothGattList.get(index) != null) {
    251             mBluetoothGattList.get(index).readPhy();
    252         } else {
    253             throw new Exception("Invalid index input:" + index);
    254         }
    255     }
    256 
    257     /**
    258      * Set the preferred connection PHY.
    259      *
    260      * @param index the bluetooth gatt index
    261      * @throws Exception
    262      */
    263     @Rpc(description = "Set the preferred connection PHY")
    264     public void gattClientSetPreferredPhy(@RpcParameter(name = "index") Integer index,
    265             @RpcParameter(name = "txPhy") Integer txPhy,
    266             @RpcParameter(name = "rxPhy") Integer rxPhy,
    267             @RpcParameter(name = "txPhy") Integer phyOptions) throws Exception {
    268         if (mBluetoothGattList.get(index) != null) {
    269             mBluetoothGattList.get(index).setPreferredPhy(txPhy, rxPhy, phyOptions);
    270         } else {
    271             throw new Exception("Invalid index input:" + index);
    272         }
    273     }
    274 
    275     /**
    276      * Disconnect a bluetooth gatt
    277      *
    278      * @param index the bluetooth gatt index
    279      * @throws Exception
    280      */
    281     @Rpc(description = "Disconnect a bluetooth gatt")
    282     @RpcStopEvent("GattConnect")
    283     public void gattClientDisconnect(@RpcParameter(name = "index") Integer index) throws Exception {
    284         if (mBluetoothGattList.get(index) != null) {
    285             mBluetoothGattList.get(index).disconnect();
    286         } else {
    287             throw new Exception("Invalid index input: " + index);
    288         }
    289     }
    290 
    291     /**
    292      * Close a bluetooth gatt object
    293      *
    294      * @param index the bluetooth gatt index
    295      * @throws Exception
    296      */
    297     @Rpc(description = "Close a Bluetooth GATT object")
    298     public void gattClientClose(@RpcParameter(name = "index") Integer index) throws Exception {
    299         if (mBluetoothGattList.get(index) != null) {
    300             mBluetoothGattList.get(index).close();
    301         } else {
    302             throw new Exception("Invalid index input: " + index);
    303         }
    304     }
    305 
    306     /**
    307      * Execute reliable write on a bluetooth gatt
    308      *
    309      * @param index the bluetooth gatt index
    310      * @return true, if the request to execute the transaction has been sent
    311      * @throws Exception
    312      */
    313     @Rpc(description = "Execute reliable write on a bluetooth gatt")
    314     public boolean gattExecuteReliableWrite(@RpcParameter(name = "index") Integer index)
    315             throws Exception {
    316         if (mBluetoothGattList.get(index) != null) {
    317             return mBluetoothGattList.get(index).executeReliableWrite();
    318         } else {
    319             throw new Exception("Invalid index input:" + index);
    320         }
    321     }
    322 
    323     /**
    324      * Get a list of Bluetooth Devices connnected to the bluetooth gatt
    325      *
    326      * @param index the bluetooth gatt index
    327      * @return List of BluetoothDevice Objects
    328      * @throws Exception
    329      */
    330     @Rpc(description = "Get a list of Bluetooth Devices connnected to the bluetooth gatt")
    331     public List<BluetoothDevice> gattClientGetConnectedDevices(
    332             @RpcParameter(name = "index") Integer index) throws Exception {
    333         if (mBluetoothGattList.get(index) != null) {
    334             return mBluetoothGattList.get(index).getConnectedDevices();
    335         } else {
    336             throw new Exception("Invalid index input:" + index);
    337         }
    338     }
    339 
    340     /**
    341      * Get the remote bluetooth device this GATT client targets to
    342      *
    343      * @param index the bluetooth gatt index
    344      * @return the remote bluetooth device this gatt client targets to
    345      * @throws Exception
    346      */
    347     @Rpc(description = "Get the remote bluetooth device this GATT client targets to")
    348     public BluetoothDevice gattGetDevice(@RpcParameter(name = "index") Integer index)
    349             throws Exception {
    350         if (mBluetoothGattList.get(index) != null) {
    351             return mBluetoothGattList.get(index).getDevice();
    352         } else {
    353             throw new Exception("Invalid index input:" + index);
    354         }
    355     }
    356 
    357     /**
    358      * Get the bluetooth devices matching input connection states
    359      *
    360      * @param index the bluetooth gatt index
    361      * @param states the list of states to match
    362      * @return The list of BluetoothDevice objects that match the states
    363      * @throws Exception
    364      */
    365     @Rpc(description = "Get the bluetooth devices matching input connection states")
    366     public List<BluetoothDevice> gattClientGetDevicesMatchingConnectionStates(
    367             @RpcParameter(name = "index") Integer index, @RpcParameter(
    368                 name = "states") int[] states)
    369             throws Exception {
    370         if (mBluetoothGattList.get(index) != null) {
    371             return mBluetoothGattList.get(index).getDevicesMatchingConnectionStates(states);
    372         } else {
    373             throw new Exception("Invalid index input:" + index);
    374         }
    375     }
    376 
    377     /**
    378      * Get the service from an input UUID
    379      *
    380      * @param index the bluetooth gatt index
    381      * @return BluetoothGattService related to the bluetooth gatt
    382      * @throws Exception
    383      */
    384     @Rpc(description = "Get the service from an input UUID")
    385     public ArrayList<String> gattClientGetServiceUuidList(
    386             @RpcParameter(name = "index") Integer index)
    387             throws Exception {
    388         if (mBluetoothGattList.get(index) != null) {
    389             ArrayList<String> serviceUuidList = new ArrayList<String>();
    390             for (BluetoothGattService service : mBluetoothGattList.get(index).getServices()) {
    391                 serviceUuidList.add(service.getUuid().toString());
    392             }
    393             return serviceUuidList;
    394         } else {
    395             throw new Exception("Invalid index input:" + index);
    396         }
    397     }
    398 
    399     /**
    400      * Reads the requested characteristic from the associated remote device.
    401      *
    402      * @deprecated Use {@link #gattClientReadCharacteristicByIndex(gattIndex,
    403      *     discoveredServiceListIndex, serviceIndex, characteristicIndex)} instead.
    404      * @param gattIndex the BluetoothGatt server accociated with the device
    405      * @param discoveredServiceListIndex the index returned from the discovered services callback
    406      * @param serviceIndex the service index of the discovered services
    407      * @param characteristicUuid the characteristic uuid to read
    408      * @return true, if the read operation was initiated successfully
    409      * @throws Exception
    410      */
    411     @Rpc(description = "Reads the requested characteristic from the associated remote device.")
    412     @Deprecated
    413     public boolean gattClientReadCharacteristic(
    414             @RpcParameter(name = "gattIndex") Integer gattIndex,
    415             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    416             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
    417             @RpcParameter(name = "characteristicUuid") String characteristicUuid) throws Exception {
    418         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    419         if (bluetoothGatt == null) {
    420             throw new Exception("Invalid gattIndex " + gattIndex);
    421         }
    422         List<BluetoothGattService> gattServiceList =
    423                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    424         if (gattServiceList == null) {
    425             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    426         }
    427         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
    428         if (gattService == null) {
    429             throw new Exception("Invalid serviceIndex " + serviceIndex);
    430         }
    431         UUID cUuid = UUID.fromString(characteristicUuid);
    432         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
    433         if (gattCharacteristic == null) {
    434             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
    435         }
    436         return bluetoothGatt.readCharacteristic(gattCharacteristic);
    437     }
    438 
    439     /**
    440      * Reads the characteristic from the associated remote device.
    441      *
    442      * @param gattIndex the BluetoothGatt server accociated with the device
    443      * @param uuid the characteristic uuid to read
    444      * @return true, if the read operation was initiated successfully
    445      * @throws Exception
    446      */
    447     @Rpc(description = "Reads the characteristic from the associated remote device.")
    448     public boolean gattClientReadUsingCharacteristicUuid(
    449             @RpcParameter(name = "gattIndex") Integer gattIndex,
    450             @RpcParameter(name = "uuid") String uuid,
    451             @RpcParameter(name = "startHandle") Integer startHandle,
    452             @RpcParameter(name = "endHandle") Integer endHandle) throws Exception {
    453         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    454         if (bluetoothGatt == null) {
    455             throw new Exception("Invalid gattIndex " + gattIndex);
    456         }
    457         UUID cUuid = UUID.fromString(uuid);
    458         return bluetoothGatt.readUsingCharacteristicUuid(cUuid, startHandle, endHandle);
    459     }
    460 
    461     /**
    462      * Reads the requested characteristic from the associated remote device.
    463      *
    464      * @param gattIndex the BluetoothGatt server accociated with the device
    465      * @param discoveredServiceListIndex the index returned from the discovered services callback
    466      * @param serviceIndex the service index of the discovered services
    467      * @param characteristicIndex the characteristic index
    468      * @return true, if the read operation was initiated successfully
    469      * @throws Exception
    470      */
    471     @Rpc(description = "Reads the requested characteristic from the associated remote device.")
    472     public boolean gattClientReadCharacteristicByIndex(
    473             @RpcParameter(name = "gattIndex") Integer gattIndex,
    474             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    475             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
    476             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
    477             throws Exception {
    478         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    479         if (bluetoothGatt == null) {
    480             throw new Exception("Invalid gattIndex " + gattIndex);
    481         }
    482         List<BluetoothGattService> gattServiceList =
    483                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    484         if (gattServiceList == null) {
    485             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    486         }
    487         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
    488         if (gattService == null) {
    489             throw new Exception("Invalid serviceIndex " + serviceIndex);
    490         }
    491         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
    492         if (charList.get(characteristicIndex) == null) {
    493             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
    494         }
    495         return bluetoothGatt.readCharacteristic(charList.get(characteristicIndex));
    496     }
    497 
    498     /**
    499      * Reads the requested characteristic from the associated remote device by instance id.
    500      *
    501      * @param gattIndex the BluetoothGatt server accociated with the device
    502      * @param discoveredServiceListIndex the index returned from the discovered services callback
    503      * @return true, if the read operation was initiated successfully
    504      * @throws Exception
    505      */
    506     @Rpc(description = "Reads the requested characteristic from the associated remote "
    507             + "device by instance id.")
    508     public boolean gattClientReadCharacteristicByInstanceId(
    509             @RpcParameter(name = "gattIndex") Integer gattIndex,
    510             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    511             @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)
    512             throws Exception {
    513         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    514         if (bluetoothGatt == null) {
    515             throw new Exception("Invalid gattIndex " + gattIndex);
    516         }
    517         List<BluetoothGattService> gattServiceList =
    518                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    519         if (gattServiceList == null) {
    520             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    521         }
    522         for (BluetoothGattService mGattService : gattServiceList) {
    523             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    524             for (BluetoothGattCharacteristic mGattChar : charList) {
    525                 if (mGattChar.getInstanceId() == characteristicInstanceId) {
    526                     Log.i("Found Characteristic to read. instanceId: "
    527                         + Integer.toString(characteristicInstanceId)
    528                         + " UUID: " + mGattChar.getUuid().toString());
    529                     return bluetoothGatt.readCharacteristic(mGattChar);
    530                 }
    531             }
    532         }
    533         Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
    534             characteristicInstanceId));
    535         return false;
    536     }
    537 
    538     /**
    539      * Writes the requested characteristic from the associated remote device by instance id.
    540      *
    541      * @param gattIndex the BluetoothGatt server accociated with the device
    542      * @param discoveredServiceListIndex the index returned from the discovered services callback
    543      * @param characteristicInstanceId the integer instance id of the Characteristic to write to
    544      * @param value the value to write to the characteristic
    545      * @return true, if the read operation was initiated successfully
    546      * @throws Exception
    547      */
    548     @Rpc(description = "Writes the requested characteristic from the associated remote "
    549             + "device by instance id.")
    550     public boolean gattClientWriteDescriptorByInstanceId(
    551             @RpcParameter(name = "gattIndex") Integer gattIndex,
    552             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    553             @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId,
    554             @RpcParameter(name = "value") byte[] value)
    555             throws Exception {
    556         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    557         if (bluetoothGatt == null) {
    558             throw new Exception("Invalid gattIndex " + gattIndex);
    559         }
    560         List<BluetoothGattService> gattServiceList =
    561                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    562         if (gattServiceList == null) {
    563             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    564         }
    565         for (BluetoothGattService mGattService : gattServiceList) {
    566             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    567             for (BluetoothGattCharacteristic mGattChar : charList) {
    568                 List<BluetoothGattDescriptor> descList = mGattChar.getDescriptors();
    569                 for (BluetoothGattDescriptor mGattDesc : descList) {
    570                     if (mGattDesc.getInstanceId() == descriptorInstanceId) {
    571                         mGattDesc.setValue(value);
    572                         Log.i("Found Descriptor to write. instanceId: "
    573                             + Integer.toString(descriptorInstanceId)
    574                             + " UUID: " + mGattDesc.getUuid().toString());
    575                         return bluetoothGatt.writeDescriptor(mGattDesc);
    576                     }
    577                 }
    578             }
    579         }
    580         Log.e("Failed to find Descriptor with instanceId: " + Integer.toString(
    581             descriptorInstanceId));
    582         return false;
    583     }
    584 
    585     /**
    586      * Writes the requested characteristic from the associated remote device by instance id.
    587      *
    588      * @param gattIndex the BluetoothGatt server accociated with the device
    589      * @param discoveredServiceListIndex the index returned from the discovered services callback
    590      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    591      * @param value the value to write to the characteristic
    592      * @return true, if the read operation was initiated successfully
    593      * @throws Exception
    594      */
    595     @Rpc(description = "Writes the requested characteristic from the associated remote "
    596             + "device by instance id.")
    597     public boolean gattClientWriteCharacteristicByInstanceId(
    598             @RpcParameter(name = "gattIndex") Integer gattIndex,
    599             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    600             @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId,
    601             @RpcParameter(name = "value") byte[] value)
    602             throws Exception {
    603         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    604         if (bluetoothGatt == null) {
    605             throw new Exception("Invalid gattIndex " + gattIndex);
    606         }
    607         List<BluetoothGattService> gattServiceList =
    608                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    609         if (gattServiceList == null) {
    610             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    611         }
    612         for (BluetoothGattService mGattService : gattServiceList) {
    613             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    614             for (BluetoothGattCharacteristic mGattChar : charList) {
    615                 if (mGattChar.getInstanceId() == characteristicInstanceId) {
    616                     mGattChar.setValue(value);
    617                     Log.i("Found Characteristic to write. instanceId: "
    618                         + Integer.toString(characteristicInstanceId)
    619                         + " UUID: " + mGattChar.getUuid().toString());
    620                     return bluetoothGatt.writeCharacteristic(mGattChar);
    621                 }
    622             }
    623         }
    624         Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
    625             characteristicInstanceId));
    626         return false;
    627     }
    628 
    629     /**
    630      * Writes the requested characteristic in which write is not permitted. For conformance tests
    631      * only.
    632      *
    633      * @param gattIndex the BluetoothGatt server accociated with the device
    634      * @param discoveredServiceListIndex the index returned from the discovered services callback
    635      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    636      * @param value the value to write to the characteristic
    637      * @return true, if the read operation was initiated successfully
    638      * @throws Exception
    639      */
    640     @Rpc(description = "Writes the requested characteristic from the associated remote "
    641             + "device by instance id.")
    642     public boolean gattClientModifyAccessAndWriteCharacteristicByInstanceId(
    643             @RpcParameter(name = "gattIndex") Integer gattIndex,
    644             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    645             @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId,
    646             @RpcParameter(name = "value") byte[] value)
    647             throws Exception {
    648         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    649         if (bluetoothGatt == null) {
    650             throw new Exception("Invalid gattIndex " + gattIndex);
    651         }
    652         List<BluetoothGattService> gattServiceList =
    653                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    654         if (gattServiceList == null) {
    655             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    656         }
    657         for (BluetoothGattService mGattService : gattServiceList) {
    658             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    659             for (BluetoothGattCharacteristic mGattChar : charList) {
    660                 if (mGattChar.getInstanceId() == characteristicInstanceId) {
    661                     Log.i("Found Characteristic to write. instanceId: "
    662                         + Integer.toString(characteristicInstanceId)
    663                         + " UUID: " + mGattChar.getUuid().toString());
    664                     BluetoothGattCharacteristic modChar = new BluetoothGattCharacteristic(
    665                         mGattChar.getUuid(), 0x08, 0x10);
    666                     modChar.setInstanceId(mGattChar.getInstanceId());
    667                     mGattService.addCharacteristic(modChar);
    668                     modChar.setValue(value);
    669                     return bluetoothGatt.writeCharacteristic(modChar);
    670                 }
    671             }
    672         }
    673         Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
    674             characteristicInstanceId));
    675         return false;
    676     }
    677 
    678     /**
    679      * Writes the requested descriptor in which write is not permitted. For conformance tests only.
    680      *
    681      * @param gattIndex the BluetoothGatt server accociated with the device
    682      * @param discoveredServiceListIndex the index returned from the discovered services callback
    683      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    684      * @param value the value to write to the characteristic
    685      * @return true, if the read operation was initiated successfully
    686      * @throws Exception
    687      */
    688     @Rpc(description = "Writes a Characteristic with an invalid instanceId to each service.")
    689     public boolean gattClientWriteInvalidCharacteristicByInstanceId(
    690             @RpcParameter(name = "gattIndex") Integer gattIndex,
    691             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    692             @RpcParameter(name = "instanceId") Integer instanceId,
    693             @RpcParameter(name = "value") byte[] value)
    694             throws Exception {
    695         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    696         if (bluetoothGatt == null) {
    697             throw new Exception("Invalid gattIndex " + gattIndex);
    698         }
    699         List<BluetoothGattService> gattServiceList =
    700                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    701         if (gattServiceList == null) {
    702             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    703         }
    704         for (BluetoothGattService mGattService : gattServiceList) {
    705             BluetoothGattCharacteristic invalidHandleChar = new BluetoothGattCharacteristic(
    706                 UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x08, 0x10);
    707             invalidHandleChar.setInstanceId(instanceId);
    708             mGattService.addCharacteristic(invalidHandleChar);
    709             invalidHandleChar.setValue(value);
    710             //todo: this used to be return bluetoothGatt. Retest with and without return
    711             bluetoothGatt.writeCharacteristic(invalidHandleChar);
    712         }
    713         return true;
    714     }
    715 
    716     /**
    717      * Writes the requested characteristic in which write is not permitted. For conformance tests
    718      * only.
    719      *
    720      * @param gattIndex the BluetoothGatt server accociated with the device
    721      * @param discoveredServiceListIndex the index returned from the discovered services callback
    722      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    723      * @param value the value to write to the characteristic
    724      * @return true, if the read operation was initiated successfully
    725      * @throws Exception
    726      */
    727     @Rpc(description = "Read the requested characteristic from the associated remote "
    728             + "device by instance id.")
    729     public boolean gattClientModifyAccessAndReadCharacteristicByInstanceId(
    730             @RpcParameter(name = "gattIndex") Integer gattIndex,
    731             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    732             @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)
    733             throws Exception {
    734         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    735         if (bluetoothGatt == null) {
    736             throw new Exception("Invalid gattIndex " + gattIndex);
    737         }
    738         List<BluetoothGattService> gattServiceList =
    739                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    740         if (gattServiceList == null) {
    741             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    742         }
    743         for (BluetoothGattService mGattService : gattServiceList) {
    744             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    745             for (BluetoothGattCharacteristic mGattChar : charList) {
    746                 if (mGattChar.getInstanceId() == characteristicInstanceId) {
    747                     Log.i("Found Characteristic to read. instanceId: "
    748                         + Integer.toString(characteristicInstanceId)
    749                         + " UUID: " + mGattChar.getUuid().toString());
    750                     BluetoothGattCharacteristic modChar = new BluetoothGattCharacteristic(
    751                         mGattChar.getUuid(), 0x02, 0x01);
    752                     modChar.setInstanceId(mGattChar.getInstanceId());
    753                     mGattService.addCharacteristic(modChar);
    754                     return bluetoothGatt.readCharacteristic(modChar);
    755                 }
    756             }
    757         }
    758         Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
    759             characteristicInstanceId));
    760         return false;
    761     }
    762 
    763     /**
    764      * Writes the requested descriptor in which write is not permitted. For conformance tests only.
    765      *
    766      * @param gattIndex the BluetoothGatt server accociated with the device
    767      * @param discoveredServiceListIndex the index returned from the discovered services callback
    768      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    769      * @param value the value to write to the characteristic
    770      * @return true, if the read operation was initiated successfully
    771      * @throws Exception
    772      */
    773     @Rpc(description = "Read a Characteristic with an invalid instanceId to each service.")
    774     public boolean gattClientReadInvalidCharacteristicByInstanceId(
    775             @RpcParameter(name = "gattIndex") Integer gattIndex,
    776             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    777             @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)
    778             throws Exception {
    779         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    780         if (bluetoothGatt == null) {
    781             throw new Exception("Invalid gattIndex " + gattIndex);
    782         }
    783         List<BluetoothGattService> gattServiceList =
    784                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    785         if (gattServiceList == null) {
    786             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    787         }
    788         for (BluetoothGattService mGattService : gattServiceList) {
    789             BluetoothGattCharacteristic invalidHandleChar = new BluetoothGattCharacteristic(
    790                 UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x02, 0x01);
    791             invalidHandleChar.setInstanceId(characteristicInstanceId);
    792             mGattService.addCharacteristic(invalidHandleChar);
    793             bluetoothGatt.readCharacteristic(invalidHandleChar);
    794         }
    795         return true;
    796     }
    797 
    798     /**
    799      * Writes the requested descriptor in which write is not permitted. For conformance tests
    800      * only.
    801      *
    802      * @param gattIndex the BluetoothGatt server accociated with the device
    803      * @param discoveredServiceListIndex the index returned from the discovered services callback
    804      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    805      * @param value the value to write to the characteristic
    806      * @return true, if the read operation was initiated successfully
    807      * @throws Exception
    808      */
    809     @Rpc(description = "Writes the requested descriptor from the associated remote "
    810             + "device by instance id.")
    811     public boolean gattClientModifyAccessAndWriteDescriptorByInstanceId(
    812             @RpcParameter(name = "gattIndex") Integer gattIndex,
    813             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    814             @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId,
    815             @RpcParameter(name = "value") byte[] value)
    816             throws Exception {
    817         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    818         if (bluetoothGatt == null) {
    819             throw new Exception("Invalid gattIndex " + gattIndex);
    820         }
    821         List<BluetoothGattService> gattServiceList =
    822                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    823         if (gattServiceList == null) {
    824             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    825         }
    826         for (BluetoothGattService mGattService : gattServiceList) {
    827             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    828             for (BluetoothGattCharacteristic mGattChar : charList) {
    829                 for (BluetoothGattDescriptor mGattDesc : mGattChar.getDescriptors()) {
    830                     if (mGattDesc.getInstanceId() == descriptorInstanceId) {
    831                         Log.i("Found Descriptor to write. instanceId: "
    832                             + Integer.toString(descriptorInstanceId)
    833                             + " UUID: " + mGattChar.getUuid().toString());
    834                         BluetoothGattDescriptor modDesc = new BluetoothGattDescriptor(
    835                             mGattDesc.getUuid(), 0x10);
    836                         modDesc.setInstanceId(descriptorInstanceId);
    837                         mGattChar.addDescriptor(modDesc);
    838                         modDesc.setValue(value);
    839                         return bluetoothGatt.writeDescriptor(modDesc);
    840                     }
    841                 }
    842             }
    843         }
    844         Log.e("Failed to find Descriptor with instanceId: " + Integer.toString(
    845             descriptorInstanceId));
    846         return false;
    847     }
    848 
    849     /**
    850      * Writes the requested descriptor in which write is not permitted. For conformance tests only.
    851      *
    852      * @param gattIndex the BluetoothGatt server accociated with the device
    853      * @param discoveredServiceListIndex the index returned from the discovered services callback
    854      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    855      * @param value the value to write to the characteristic
    856      * @return true, if the read operation was initiated successfully
    857      * @throws Exception
    858      */
    859     @Rpc(description = "Writes a Characteristic with an invalid instanceId to each service.")
    860     public boolean gattClientWriteInvalidDescriptorByInstanceId(
    861             @RpcParameter(name = "gattIndex") Integer gattIndex,
    862             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    863             @RpcParameter(name = "instanceId") Integer instanceId,
    864             @RpcParameter(name = "value") byte[] value)
    865             throws Exception {
    866         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    867         if (bluetoothGatt == null) {
    868             throw new Exception("Invalid gattIndex " + gattIndex);
    869         }
    870         List<BluetoothGattService> gattServiceList =
    871                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    872         if (gattServiceList == null) {
    873             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    874         }
    875         for (BluetoothGattService mGattService : gattServiceList) {
    876             for (BluetoothGattCharacteristic mGattChar : mGattService.getCharacteristics()) {
    877                 BluetoothGattDescriptor invalidHandleDesc = new BluetoothGattDescriptor(
    878                     UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x10);
    879                 invalidHandleDesc.setInstanceId(instanceId);
    880                 mGattChar.addDescriptor(invalidHandleDesc);
    881                 invalidHandleDesc.setValue(value);
    882                 bluetoothGatt.writeDescriptor(invalidHandleDesc);
    883             }
    884         }
    885         return true;
    886     }
    887 
    888     /**
    889      * Writes the requested descriptor in which write is not permitted. For conformance tests
    890      * only.
    891      *
    892      * @param gattIndex the BluetoothGatt server accociated with the device
    893      * @param discoveredServiceListIndex the index returned from the discovered services callback
    894      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    895      * @param value the value to write to the characteristic
    896      * @return true, if the read operation was initiated successfully
    897      * @throws Exception
    898      */
    899     @Rpc(description = "Read the requested descriptor from the associated remote "
    900             + "device by instance id.")
    901     public boolean gattClientModifyAccessAndReadDescriptorByInstanceId(
    902             @RpcParameter(name = "gattIndex") Integer gattIndex,
    903             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    904             @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId)
    905             throws Exception {
    906         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    907         if (bluetoothGatt == null) {
    908             throw new Exception("Invalid gattIndex " + gattIndex);
    909         }
    910         List<BluetoothGattService> gattServiceList =
    911                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    912         if (gattServiceList == null) {
    913             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    914         }
    915         for (BluetoothGattService mGattService : gattServiceList) {
    916             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
    917             for (BluetoothGattCharacteristic mGattChar : charList) {
    918                 for (BluetoothGattDescriptor mGattDesc : mGattChar.getDescriptors()) {
    919                     if (mGattDesc.getInstanceId() == descriptorInstanceId) {
    920                         Log.i("Found Descriptor to read. instanceId: "
    921                             + Integer.toString(descriptorInstanceId)
    922                             + " UUID: " + mGattDesc.getUuid().toString());
    923                         BluetoothGattDescriptor modDesc = new BluetoothGattDescriptor(
    924                             mGattDesc.getUuid(), 0x01);
    925                         modDesc.setInstanceId(descriptorInstanceId);
    926                         mGattChar.addDescriptor(modDesc);
    927                         return bluetoothGatt.readDescriptor(modDesc);
    928                     }
    929                 }
    930             }
    931         }
    932         Log.e("Failed to find Descriptor with instanceId: " + Integer.toString(
    933             descriptorInstanceId));
    934         return false;
    935     }
    936 
    937     /**
    938      * Writes the requested descriptor in which write is not permitted. For conformance tests only.
    939      *
    940      * @param gattIndex the BluetoothGatt server accociated with the device
    941      * @param discoveredServiceListIndex the index returned from the discovered services callback
    942      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    943      * @param value the value to write to the characteristic
    944      * @return true, if the read operation was initiated successfully
    945      * @throws Exception
    946      */
    947     @Rpc(description = "Read a Characteristic with an invalid instanceId to each service.")
    948     public boolean gattClientReadInvalidDescriptorByInstanceId(
    949             @RpcParameter(name = "gattIndex") Integer gattIndex,
    950             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    951             @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId)
    952             throws Exception {
    953         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    954         if (bluetoothGatt == null) {
    955             throw new Exception("Invalid gattIndex " + gattIndex);
    956         }
    957         List<BluetoothGattService> gattServiceList =
    958                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    959         if (gattServiceList == null) {
    960             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
    961         }
    962         for (BluetoothGattService mGattService : gattServiceList) {
    963             for (BluetoothGattCharacteristic mGattChar : mGattService.getCharacteristics()) {
    964                 BluetoothGattDescriptor invalidHandleDesc = new BluetoothGattDescriptor(
    965                     UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x01);
    966                 invalidHandleDesc.setInstanceId(descriptorInstanceId);
    967                 mGattChar.addDescriptor(invalidHandleDesc);
    968                 bluetoothGatt.readDescriptor(invalidHandleDesc);
    969             }
    970         }
    971         return true;
    972     }
    973 
    974     /**
    975      * Writes the requested characteristic in which write is not permitted. For conformance tests
    976      * only.
    977      *
    978      * @param gattIndex the BluetoothGatt server accociated with the device
    979      * @param discoveredServiceListIndex the index returned from the discovered services callback
    980      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
    981      * @param value the value to write to the characteristic
    982      * @return true, if the read operation was initiated successfully
    983      * @throws Exception
    984      */
    985     @Rpc(description = "Read the requested characteristic from the associated remote "
    986             + "device by uuid.")
    987     public boolean gattClientModifyAccessAndReadCharacteristicByUuidAndInstanceId(
    988             @RpcParameter(name = "gattIndex") Integer gattIndex,
    989             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
    990             @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId,
    991             @RpcParameter(name = "characteristicUuid") String characteristicUuid)
    992             throws Exception {
    993         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
    994         if (bluetoothGatt == null) {
    995             throw new Exception("Invalid gattIndex " + gattIndex);
    996         }
    997         List<BluetoothGattService> gattServiceList =
    998                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
    999         if (gattServiceList == null) {
   1000             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1001         }
   1002         for (BluetoothGattService mGattService : gattServiceList) {
   1003             List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
   1004             for (BluetoothGattCharacteristic mGattChar : charList) {
   1005                 if (mGattChar.getUuid().toString().equalsIgnoreCase(characteristicUuid) &&
   1006                         mGattChar.getInstanceId() == characteristicInstanceId) {
   1007                     Log.i("Found Characteristic to read. UUID: " + mGattChar.getUuid().toString());
   1008                     BluetoothGattCharacteristic modChar = new BluetoothGattCharacteristic(
   1009                         mGattChar.getUuid(), 0x02, 0x01);
   1010                     modChar.setInstanceId(characteristicInstanceId);
   1011                     mGattService.addCharacteristic(modChar);
   1012                     bluetoothGatt.readCharacteristic(modChar);
   1013                 }
   1014             }
   1015         }
   1016         return true;
   1017     }
   1018 
   1019     /**
   1020      * Writes the requested descriptor in which write is not permitted. For conformance tests only.
   1021      *
   1022      * @param gattIndex the BluetoothGatt server accociated with the device
   1023      * @param discoveredServiceListIndex the index returned from the discovered services callback
   1024      * @param descriptorInstanceId the integer instance id of the Characteristic to write to
   1025      * @param value the value to write to the characteristic
   1026      * @return true, if the read operation was initiated successfully
   1027      * @throws Exception
   1028      */
   1029     @Rpc(description = "Read a Characteristic with an invalid Uuid to each service.")
   1030     public boolean gattClientReadInvalidCharacteristicByUuidAndInstanceId(
   1031             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1032             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1033             @RpcParameter(name = "characteristicUuid") String characteristicUuid)
   1034             throws Exception {
   1035         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1036         if (bluetoothGatt == null) {
   1037             throw new Exception("Invalid gattIndex " + gattIndex);
   1038         }
   1039         List<BluetoothGattService> gattServiceList =
   1040                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1041         if (gattServiceList == null) {
   1042             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1043         }
   1044         for (BluetoothGattService mGattService : gattServiceList) {
   1045             BluetoothGattCharacteristic invalidHandleChar = new BluetoothGattCharacteristic(
   1046                 UUID.fromString(characteristicUuid), 0x02, 0x01);
   1047             mGattService.addCharacteristic(invalidHandleChar);
   1048             bluetoothGatt.readCharacteristic(invalidHandleChar);
   1049         }
   1050         return true;
   1051     }
   1052 
   1053     /**
   1054      * /** Reads the value for a given descriptor from the associated remote device
   1055      *
   1056      * @deprecated Use {@link #gattClientReadDescriptorByIndex(
   1057      * gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, descriptorIndex)}
   1058      * instead.
   1059      * @param gattIndex - the gatt index to use
   1060      * @param discoveredServiceListIndex - the discvered serivice list index
   1061      * @param serviceIndex - the servce index of the discoveredServiceListIndex
   1062      * @param characteristicUuid - the characteristic uuid in which the descriptor is
   1063      * @param descriptorUuid - the descriptor uuid to read
   1064      * @return
   1065      * @throws Exception
   1066      */
   1067     @Deprecated
   1068     @Rpc(description = "Reads the value for a given descriptor from the associated remote device")
   1069     public boolean gattClientReadDescriptor(
   1070             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1071             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1072             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1073             @RpcParameter(name = "characteristicUuid") String characteristicUuid,
   1074             @RpcParameter(name = "descriptorUuid") String descriptorUuid) throws Exception {
   1075         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1076         if (bluetoothGatt == null) {
   1077             throw new Exception("Invalid gattIndex " + gattIndex);
   1078         }
   1079         List<BluetoothGattService> gattServiceList = mBluetoothGattDiscoveredServicesList.get(
   1080                       discoveredServiceListIndex);
   1081         if (gattServiceList == null) {
   1082             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1083         }
   1084         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1085         if (gattService == null) {
   1086             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1087         }
   1088         UUID cUuid = UUID.fromString(characteristicUuid);
   1089         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
   1090         if (gattCharacteristic == null) {
   1091             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
   1092         }
   1093         UUID dUuid = UUID.fromString(descriptorUuid);
   1094         BluetoothGattDescriptor gattDescriptor = gattCharacteristic.getDescriptor(dUuid);
   1095         if (gattDescriptor == null) {
   1096             throw new Exception("Invalid descriptor uuid: " + descriptorUuid);
   1097         }
   1098         return bluetoothGatt.readDescriptor(gattDescriptor);
   1099     }
   1100 
   1101 
   1102     /**
   1103      * /** Reads the value for a given descriptor from the associated remote device
   1104      *
   1105      * @param gattIndex - the gatt index to use
   1106      * @param discoveredServiceListIndex - the discvered serivice list index
   1107      * @param serviceIndex - the servce index of the discoveredServiceListIndex
   1108      * @param characteristicIndex - the characteristic index
   1109      * @param descriptorIndex - the descriptor index to read
   1110      * @return
   1111      * @throws Exception
   1112      */
   1113     @Rpc(description = "Reads the value for a given descriptor from the associated remote device")
   1114     public boolean gattClientReadDescriptorByIndex(
   1115             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1116             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1117             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1118             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1119             @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)
   1120             throws Exception {
   1121         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1122         if (bluetoothGatt == null) {
   1123             throw new Exception("Invalid gattIndex " + gattIndex);
   1124         }
   1125         List<BluetoothGattService> gattServiceList =
   1126                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1127         if (gattServiceList == null) {
   1128             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1129         }
   1130         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1131         if (gattService == null) {
   1132             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1133         }
   1134         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1135         if (charList.get(characteristicIndex) == null) {
   1136             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
   1137         }
   1138         BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
   1139         List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
   1140         if (descList.get(descriptorIndex) == null) {
   1141             throw new Exception("Invalid descriptorIndex " + descriptorIndex);
   1142         }
   1143         return bluetoothGatt.readDescriptor(descList.get(descriptorIndex));
   1144     }
   1145 
   1146     /**
   1147      * Write the value of a given descriptor to the associated remote device
   1148      *
   1149      * @deprecated Use {@link #gattClientWriteDescriptorByIndex(
   1150      * gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, descriptorIndex)}
   1151      * instead.
   1152      * @param index the bluetooth gatt index
   1153      * @param serviceIndex the service index to write to
   1154      * @param characteristicUuid the uuid where the descriptor lives
   1155      * @param descriptorIndex the descriptor index
   1156      * @return true, if the write operation was initiated successfully
   1157      * @throws Exception
   1158      */
   1159     @Deprecated
   1160     @Rpc(description = "Write the value of a given descriptor to the associated remote device")
   1161     public boolean gattClientWriteDescriptor(
   1162             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1163             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1164             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1165             @RpcParameter(name = "characteristicUuid") String characteristicUuid,
   1166             @RpcParameter(name = "descriptorUuid") String descriptorUuid) throws Exception {
   1167         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1168         if (bluetoothGatt == null) {
   1169             throw new Exception("Invalid gattIndex " + gattIndex);
   1170         }
   1171         List<BluetoothGattService> discoveredServiceList =
   1172                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1173         if (discoveredServiceList == null) {
   1174             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1175         }
   1176         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1177         if (gattService == null) {
   1178             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1179         }
   1180         UUID cUuid = UUID.fromString(characteristicUuid);
   1181         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
   1182         if (gattCharacteristic == null) {
   1183             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
   1184         }
   1185         UUID dUuid = UUID.fromString(descriptorUuid);
   1186         BluetoothGattDescriptor gattDescriptor = gattCharacteristic.getDescriptor(dUuid);
   1187         if (gattDescriptor == null) {
   1188             throw new Exception("Invalid descriptor uuid: " + descriptorUuid);
   1189         }
   1190         return bluetoothGatt.writeDescriptor(gattDescriptor);
   1191     }
   1192 
   1193     /**
   1194      * Write the value of a given descriptor to the associated remote device
   1195      *
   1196      * @param index the bluetooth gatt index
   1197      * @param serviceIndex the service index to write to
   1198      * @param characteristicIndex the characteristic index to write to
   1199      * @param descriptorIndex the descriptor index to write to
   1200      * @return true, if the write operation was initiated successfully
   1201      * @throws Exception
   1202      */
   1203     @Rpc(description = "Write the value of a given descriptor to the associated remote device")
   1204     public boolean gattClientWriteDescriptorByIndex(
   1205             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1206             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1207             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1208             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1209             @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)
   1210             throws Exception {
   1211         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1212         if (bluetoothGatt == null) {
   1213             throw new Exception("Invalid gattIndex " + gattIndex);
   1214         }
   1215         List<BluetoothGattService> gattServiceList =
   1216                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1217         if (gattServiceList == null) {
   1218             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1219         }
   1220         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1221         if (gattService == null) {
   1222             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1223         }
   1224         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1225         if (charList.get(characteristicIndex) == null) {
   1226             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
   1227         }
   1228         BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
   1229         List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
   1230         if (descList.get(descriptorIndex) == null) {
   1231             throw new Exception("Invalid descriptorIndex " + descriptorIndex);
   1232         }
   1233         return bluetoothGatt.writeDescriptor(descList.get(descriptorIndex));
   1234     }
   1235 
   1236     /**
   1237      * Write the value to a discovered descriptor.
   1238      *
   1239      * @deprecated Use {@link #gattClientDescriptorSetValueByIndex(
   1240      *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, descriptorIndex,
   1241      *  value)} instead.
   1242      * @param gattIndex - the gatt index to use
   1243      * @param discoveredServiceListIndex - the discovered service list index
   1244      * @param serviceIndex - the service index of the discoveredServiceListIndex
   1245      * @param characteristicUuid - the characteristic uuid in which the descriptor is
   1246      * @param descriptorUuid - the descriptor uuid to read
   1247      * @param value - the value to set the descriptor to
   1248      * @return true is the value was set to the descriptor
   1249      * @throws Exception
   1250      */
   1251     @Deprecated
   1252     @Rpc(description = "Write the value of a given descriptor to the associated remote device")
   1253     public boolean gattClientDescriptorSetValue(
   1254             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1255             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1256             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1257             @RpcParameter(name = "characteristicUuid") String characteristicUuid,
   1258             @RpcParameter(name = "descriptorUuid") String descriptorUuid,
   1259             @RpcParameter(name = "value") byte[] value) throws Exception {
   1260         if (mBluetoothGattList.get(gattIndex) == null) {
   1261             throw new Exception("Invalid gattIndex " + gattIndex);
   1262         }
   1263         List<BluetoothGattService> discoveredServiceList =
   1264                   mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1265         if (discoveredServiceList == null) {
   1266             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1267         }
   1268         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1269         if (gattService == null) {
   1270             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1271         }
   1272         UUID cUuid = UUID.fromString(characteristicUuid);
   1273         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
   1274         if (gattCharacteristic == null) {
   1275             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
   1276         }
   1277         UUID dUuid = UUID.fromString(descriptorUuid);
   1278         BluetoothGattDescriptor gattDescriptor = gattCharacteristic.getDescriptor(dUuid);
   1279         if (gattDescriptor == null) {
   1280             throw new Exception("Invalid descriptor uuid: " + descriptorUuid);
   1281         }
   1282         return gattDescriptor.setValue(value);
   1283     }
   1284 
   1285     /**
   1286      * Write the value to a discovered descriptor.
   1287      *
   1288      * @param gattIndex - the gatt index to use
   1289      * @param discoveredServiceListIndex - the discovered service list index
   1290      * @param serviceIndex - the service index of the discoveredServiceListIndex
   1291      * @param characteristicIndex - the characteristic index
   1292      * @param descriptorIndex - the descriptor index to set
   1293      * @param value - the value to set the descriptor to
   1294      * @return true is the value was set to the descriptor
   1295      * @throws Exception
   1296      */
   1297     @Rpc(description = "Write the value of a given descriptor to the associated remote device")
   1298     public boolean gattClientDescriptorSetValueByIndex(
   1299             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1300             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1301             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1302             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1303             @RpcParameter(name = "descriptorIndex") Integer descriptorIndex,
   1304             @RpcParameter(name = "value") byte[] value)
   1305             throws Exception {
   1306         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1307         if (bluetoothGatt == null) {
   1308             throw new Exception("Invalid gattIndex " + gattIndex);
   1309         }
   1310         List<BluetoothGattService> gattServiceList =
   1311                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1312         if (gattServiceList == null) {
   1313             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1314         }
   1315         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1316         if (gattService == null) {
   1317             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1318         }
   1319         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1320         if (charList.get(characteristicIndex) == null) {
   1321             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
   1322         }
   1323         BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
   1324         List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
   1325         if (descList.get(descriptorIndex) == null) {
   1326             throw new Exception("Invalid descriptorIndex " + descriptorIndex);
   1327         }
   1328         return descList.get(descriptorIndex).setValue(value);
   1329     }
   1330 
   1331 
   1332     /**
   1333      * Write the value of a given characteristic to the associated remote device
   1334      *
   1335      * @deprecated Use {@link #gattClientWriteCharacteristicByIndex(
   1336      *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex)} instead.
   1337      * @param index the bluetooth gatt index
   1338      * @param serviceIndex the service where the characteristic lives
   1339      * @param characteristicUuid the characteristic uuid to write to
   1340      * @return true, if the write operation was successful
   1341      * @throws Exception
   1342      */
   1343     @Deprecated
   1344     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1345     public boolean gattClientWriteCharacteristic(
   1346             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1347             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1348             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1349             @RpcParameter(name = "characteristicUuid") String characteristicUuid) throws Exception {
   1350         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1351         if (bluetoothGatt == null) {
   1352             throw new Exception("Invalid gattIndex " + gattIndex);
   1353         }
   1354         List<BluetoothGattService> discoveredServiceList =
   1355                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1356         if (discoveredServiceList == null) {
   1357             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1358         }
   1359         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1360         if (gattService == null) {
   1361             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1362         }
   1363         UUID cUuid = UUID.fromString(characteristicUuid);
   1364         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
   1365         if (gattCharacteristic == null) {
   1366             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
   1367         }
   1368         return bluetoothGatt.writeCharacteristic(gattCharacteristic);
   1369     }
   1370 
   1371     /**
   1372      * Write the value of a given characteristic to the associated remote device
   1373      *
   1374      * @param index the bluetooth gatt index
   1375      * @param serviceIndex the service where the characteristic lives
   1376      * @param characteristicIndex the characteristic index
   1377      * @return true, if the write operation was successful
   1378      * @throws Exception
   1379      */
   1380     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1381     public boolean gattClientWriteCharacteristicByIndex(
   1382             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1383             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1384             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1385             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
   1386             throws Exception {
   1387         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1388         if (bluetoothGatt == null) {
   1389             throw new Exception("Invalid gattIndex " + gattIndex);
   1390         }
   1391         List<BluetoothGattService> gattServiceList =
   1392                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1393         if (gattServiceList == null) {
   1394             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1395         }
   1396         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1397         if (gattService == null) {
   1398             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1399         }
   1400         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1401         if (charList.get(characteristicIndex) == null) {
   1402             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
   1403         }
   1404         return bluetoothGatt.writeCharacteristic(charList.get(characteristicIndex));
   1405     }
   1406 
   1407     /**
   1408      * PTS HELPER... Write the value of a given characteristic to the associated remote device
   1409      *
   1410      * @param index the bluetooth gatt index
   1411      * @param serviceIndex the service where the characteristic lives
   1412      * @param characteristicIndex the characteristic index
   1413      * @return true, if the write operation was successful
   1414      * @throws Exception
   1415      */
   1416     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1417     public boolean gattClientReadInvalidCharacteristicInstanceId(
   1418             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1419             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1420             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1421             @RpcParameter(name = "instanceId") Integer instanceId)
   1422             throws Exception {
   1423         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1424         if (bluetoothGatt == null) {
   1425             throw new Exception("Invalid gattIndex " + gattIndex);
   1426         }
   1427         List<BluetoothGattService> gattServiceList =
   1428                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1429         if (gattServiceList == null) {
   1430             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1431         }
   1432         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1433         if (gattService == null) {
   1434             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1435         }
   1436         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1437         charList.get(0).setInstanceId(instanceId);
   1438         return bluetoothGatt.readCharacteristic(charList.get(0));
   1439     }
   1440 
   1441     /**
   1442      * Get the input Characteristic's instance ID.
   1443      *
   1444      * @param index the bluetooth gatt index
   1445      * @param serviceIndex the service where the characteristic lives
   1446      * @param characteristicIndex the characteristic index
   1447      * @return true, if the write operation was successful
   1448      * @throws Exception
   1449      */
   1450     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1451     public Integer gattClientGetCharacteristicInstanceId(
   1452             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1453             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1454             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1455             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
   1456             throws Exception {
   1457         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1458         if (bluetoothGatt == null) {
   1459             throw new Exception("Invalid gattIndex " + gattIndex);
   1460         }
   1461         List<BluetoothGattService> gattServiceList =
   1462                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1463         if (gattServiceList == null) {
   1464             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1465         }
   1466         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1467         if (gattService == null) {
   1468             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1469         }
   1470         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1471         if (charList.get(characteristicIndex) == null) {
   1472             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
   1473         }
   1474         return charList.get(characteristicIndex).getInstanceId();
   1475     }
   1476 
   1477     /**
   1478      * Get the input Descriptor's instance ID.
   1479      *
   1480      * @param index the bluetooth gatt index
   1481      * @param serviceIndex the service where the characteristic lives
   1482      * @param characteristicIndex the characteristic index
   1483      * @param descriptorIndex the descriptor index
   1484      * @return true, if the write operation was successful
   1485      * @throws Exception
   1486      */
   1487     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1488     public Integer gattClientGetDescriptorInstanceId(
   1489             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1490             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1491             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1492             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1493             @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)
   1494             throws Exception {
   1495         BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
   1496         if (bluetoothGatt == null) {
   1497             throw new Exception("Invalid gattIndex " + gattIndex);
   1498         }
   1499         List<BluetoothGattService> gattServiceList =
   1500                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1501         if (gattServiceList == null) {
   1502             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1503         }
   1504         BluetoothGattService gattService = gattServiceList.get(serviceIndex);
   1505         if (gattService == null) {
   1506             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1507         }
   1508         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1509         if (charList.get(characteristicIndex) == null) {
   1510             throw new Exception("Invalid characteristicIndex " + characteristicIndex);
   1511         }
   1512         BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
   1513         if (gattCharacteristic == null) {
   1514             throw new Exception("Invalid characteristicIndex " + serviceIndex);
   1515         }
   1516         List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
   1517         if (descList.get(descriptorIndex) == null) {
   1518             throw new Exception("Invalid descriptorIndex " + descriptorIndex);
   1519         }
   1520         return descList.get(descriptorIndex).getInstanceId();
   1521     }
   1522 
   1523     /**
   1524      * Write the value to a discovered characteristic.
   1525      *
   1526      * @deprecated Use {@link #gattClientCharacteristicSetValueByIndex(
   1527      *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, value)} instead.
   1528      * @param gattIndex - the gatt index to use
   1529      * @param discoveredServiceListIndex - the discovered service list index
   1530      * @param serviceIndex - the service index of the discoveredServiceListIndex
   1531      * @param characteristicUuid - the characteristic uuid in which the descriptor is
   1532      * @param value - the value to set the characteristic to
   1533      * @return true, if the value was set to the characteristic
   1534      * @throws Exception
   1535      */
   1536     @Deprecated
   1537     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1538     public boolean gattClientCharacteristicSetValue(
   1539             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1540             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1541             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1542             @RpcParameter(name = "characteristicUuid") String characteristicUuid,
   1543             @RpcParameter(name = "value") byte[] value) throws Exception {
   1544         if (mBluetoothGattList.get(gattIndex) == null) {
   1545             throw new Exception("Invalid gattIndex " + gattIndex);
   1546         }
   1547         List<BluetoothGattService> discoveredServiceList =
   1548                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1549         if (discoveredServiceList == null) {
   1550             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1551         }
   1552         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1553         if (gattService == null) {
   1554             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1555         }
   1556         UUID cUuid = UUID.fromString(characteristicUuid);
   1557         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
   1558         if (gattCharacteristic == null) {
   1559             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
   1560         }
   1561         return gattCharacteristic.setValue(value);
   1562     }
   1563 
   1564     /**
   1565      * Write the value to a discovered characteristic.
   1566      *
   1567      * @param gattIndex - the gatt index to use
   1568      * @param discoveredServiceListIndex - the discovered service list index
   1569      * @param serviceIndex - the service index of the discoveredServiceListIndex
   1570      * @param characteristicIndex - the characteristic index
   1571      * @param value - the value to set the characteristic to
   1572      * @return true, if the value was set to the characteristic
   1573      * @throws Exception
   1574      */
   1575     @Rpc(description = "Write the value of a given characteristic to the associated remote device")
   1576     public boolean gattClientCharacteristicSetValueByIndex(
   1577             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1578             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1579             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1580             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1581             @RpcParameter(name = "value") byte[] value)
   1582             throws Exception {
   1583         if (mBluetoothGattList.get(gattIndex) == null) {
   1584             throw new Exception("Invalid gattIndex " + gattIndex);
   1585         }
   1586         List<BluetoothGattService> discoveredServiceList =
   1587                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1588         if (discoveredServiceList == null) {
   1589             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1590         }
   1591         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1592         if (gattService == null) {
   1593             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1594         }
   1595         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1596         if (charList.get(characteristicIndex) == null) {
   1597             throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
   1598         }
   1599         return charList.get(characteristicIndex).setValue(value);
   1600     }
   1601 
   1602     /**
   1603      * Set write type to a discovered characteristic.
   1604      *
   1605      * @deprecated Use {@link #gattClientCharacteristicSetWriteTypeByIndex(
   1606      *  gattIndex, discoveredServiceListIndex, serviceIndex, ccharacteristicUuid, writeType)}
   1607      * instead.
   1608      * @param gattIndex - the gatt index to use
   1609      * @param discoveredServiceListIndex - the discovered service list index
   1610      * @param serviceIndex - the service index of the discoveredServiceListIndex
   1611      * @param characteristicUuid - the characteristic uuid in which the descriptor is
   1612      * @param writeType - the write type for characteristic
   1613      * @return true, if the value was set to the characteristic
   1614      * @throws Exception
   1615      */
   1616     @Deprecated
   1617     @Rpc(description = "Set write type of a given characteristic to the associated remote device")
   1618     public boolean gattClientCharacteristicSetWriteType(
   1619             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1620             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1621             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1622             @RpcParameter(name = "characteristicUuid") String characteristicUuid,
   1623             @RpcParameter(name = "writeType") Integer writeType) throws Exception {
   1624         if (mBluetoothGattList.get(gattIndex) == null) {
   1625             throw new Exception("Invalid gattIndex " + gattIndex);
   1626         }
   1627         List<BluetoothGattService> discoveredServiceList =
   1628                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1629         if (discoveredServiceList == null) {
   1630             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1631         }
   1632         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1633         if (gattService == null) {
   1634             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1635         }
   1636         UUID cUuid = UUID.fromString(characteristicUuid);
   1637         BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
   1638         if (gattCharacteristic == null) {
   1639             throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
   1640         }
   1641         gattCharacteristic.setWriteType(writeType);
   1642         return true;
   1643     }
   1644 
   1645     /**
   1646      * Set write type to a discovered characteristic.
   1647      *
   1648      * @param gattIndex - the gatt index to use
   1649      * @param discoveredServiceListIndex - the discovered service list index
   1650      * @param serviceIndex - the service index of the discoveredServiceListIndex
   1651      * @param characteristicIndex - the characteristic index
   1652      * @param writeType - the write type for characteristic
   1653      * @return true, if the value was set to the characteristic
   1654      * @throws Exception
   1655      */
   1656     @Rpc(description = "Set write type of a given characteristic to the associated remote device")
   1657     public void gattClientCharacteristicSetWriteTypeByIndex(
   1658             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1659             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1660             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1661             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1662             @RpcParameter(name = "writeType") Integer writeType)
   1663             throws Exception {
   1664         if (mBluetoothGattList.get(gattIndex) == null) {
   1665             throw new Exception("Invalid gattIndex " + gattIndex);
   1666         }
   1667         List<BluetoothGattService> discoveredServiceList =
   1668                 mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1669         if (discoveredServiceList == null) {
   1670             throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
   1671         }
   1672         BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
   1673         if (gattService == null) {
   1674             throw new Exception("Invalid serviceIndex " + serviceIndex);
   1675         }
   1676         List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
   1677         if (charList.get(characteristicIndex) == null) {
   1678             throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
   1679         }
   1680         charList.get(characteristicIndex).setWriteType(writeType);
   1681     }
   1682 
   1683     /**
   1684      * Read the RSSI for a connected remote device
   1685      *
   1686      * @param index the bluetooth gatt index
   1687      * @return true, if the RSSI value has been requested successfully
   1688      * @throws Exception
   1689      */
   1690     @Rpc(description = "Read the RSSI for a connected remote device")
   1691     public boolean gattClientReadRSSI(
   1692             @RpcParameter(name = "index") Integer index) throws Exception {
   1693         if (mBluetoothGattList.get(index) != null) {
   1694             return mBluetoothGattList.get(index).readRemoteRssi();
   1695         } else {
   1696             throw new Exception("Invalid index input:" + index);
   1697         }
   1698     }
   1699 
   1700     /**
   1701      * Clears the internal cache and forces a refresh of the services from the remote device
   1702      *
   1703      * @param index the bluetooth gatt index
   1704      * @return Clears the internal cache and forces a refresh of the services from the remote
   1705      *         device.
   1706      * @throws Exception
   1707      */
   1708     @Rpc(description = "Clears the internal cache and forces a refresh of the services from the "
   1709             + "remote device")
   1710     public boolean gattClientRefresh(@RpcParameter(name = "index") Integer index) throws Exception {
   1711         if (mBluetoothGattList.get(index) != null) {
   1712             return mBluetoothGattList.get(index).refresh();
   1713         } else {
   1714             throw new Exception("Invalid index input:" + index);
   1715         }
   1716     }
   1717 
   1718     /**
   1719      * Request a connection parameter update.
   1720      *
   1721      * @param index the bluetooth gatt index
   1722      * @param connectionPriority connection priority
   1723      * @return boolean True if successful False otherwise.
   1724      * @throws Exception
   1725      */
   1726     @Rpc(description = "Request a connection parameter update. from the Bluetooth Gatt")
   1727     public boolean gattClientRequestConnectionPriority(
   1728             @RpcParameter(name = "index") Integer index,
   1729             @RpcParameter(name = "connectionPriority") Integer connectionPriority)
   1730             throws Exception {
   1731         boolean result = false;
   1732         if (mBluetoothGattList.get(index) != null) {
   1733             result = mBluetoothGattList.get(index).requestConnectionPriority(connectionPriority);
   1734         } else {
   1735             throw new Exception("Invalid index input:" + index);
   1736         }
   1737         return result;
   1738     }
   1739 
   1740     /**
   1741      * Sets the characteristic notification of a bluetooth gatt
   1742      *
   1743      * @deprecated Use {@link #gattClientSetCharacteristicNotificationByIndex(
   1744      *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, enable)} instead.
   1745      * @param index the bluetooth gatt index
   1746      * @param characteristicIndex the characteristic index
   1747      * @param enable Enable or disable notifications/indications for a given characteristic
   1748      * @return true, if the requested notification status was set successfully
   1749      * @throws Exception
   1750      */
   1751     @Deprecated
   1752     @Rpc(description = "Sets the characteristic notification of a bluetooth gatt")
   1753     public boolean gattClientSetCharacteristicNotification(
   1754             @RpcParameter(name = "gattIndex")
   1755             Integer gattIndex,
   1756             @RpcParameter(name = "discoveredServiceListIndex")
   1757             Integer discoveredServiceListIndex,
   1758             @RpcParameter(name = "serviceIndex")
   1759             Integer serviceIndex,
   1760             @RpcParameter(name = "characteristicUuid")
   1761             String characteristicUuid,
   1762             @RpcParameter(name = "enable")
   1763             Boolean enable
   1764             ) throws Exception {
   1765         if (mBluetoothGattList.get(gattIndex) != null) {
   1766             if(mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex) != null) {
   1767                 List<BluetoothGattService> discoveredServiceList =
   1768                     mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1769                 if (discoveredServiceList.get(serviceIndex) != null) {
   1770                     UUID cUuid = UUID.fromString(characteristicUuid);
   1771                     if (discoveredServiceList.get(serviceIndex).getCharacteristic(cUuid) != null) {
   1772                         return mBluetoothGattList.get(gattIndex).setCharacteristicNotification(
   1773                                 discoveredServiceList.get(serviceIndex).getCharacteristic(cUuid), enable);
   1774                     } else {
   1775                         throw new Exception ("Invalid characteristic uuid: " + characteristicUuid);
   1776                     }
   1777                 } else {
   1778                     throw new Exception ("Invalid serviceIndex " + serviceIndex);
   1779                 }
   1780             } else {
   1781                 throw new Exception("Invalid discoveredServiceListIndex: " + discoveredServiceListIndex);
   1782             }
   1783         } else {
   1784             throw new Exception("Invalid gattIndex input: " + gattIndex);
   1785         }
   1786     }
   1787 
   1788     /**
   1789      * Sets the characteristic notification of a bluetooth gatt
   1790      *
   1791      * @param index the bluetooth gatt index
   1792      * @param characteristicIndex the characteristic index
   1793      * @param enable Enable or disable notifications/indications for a given characteristic
   1794      * @return true, if the requested notification status was set successfully
   1795      * @throws Exception
   1796      */
   1797     @Rpc(description = "Sets the characteristic notification of a bluetooth gatt")
   1798     public boolean gattClientSetCharacteristicNotificationByIndex(
   1799             @RpcParameter(name = "gattIndex") Integer gattIndex,
   1800             @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
   1801             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1802             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
   1803             @RpcParameter(name = "enable") Boolean enable)
   1804             throws Exception {
   1805         if (mBluetoothGattList.get(gattIndex) != null) {
   1806             if (mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex) != null) {
   1807                 List<BluetoothGattService> discoveredServiceList =
   1808                         mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
   1809                 if (discoveredServiceList.get(serviceIndex) != null) {
   1810                     List<BluetoothGattCharacteristic> charList =
   1811                             discoveredServiceList.get(serviceIndex).getCharacteristics();
   1812                     if (charList.get(characteristicIndex) != null) {
   1813                         return mBluetoothGattList
   1814                                 .get(gattIndex)
   1815                                 .setCharacteristicNotification(charList.get(characteristicIndex),
   1816                                     enable);
   1817                     } else {
   1818                         throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
   1819                     }
   1820                 } else {
   1821                     throw new Exception("Invalid serviceIndex " + serviceIndex);
   1822                 }
   1823             } else {
   1824                 throw new Exception(
   1825                     "Invalid discoveredServiceListIndex: " + discoveredServiceListIndex);
   1826             }
   1827         } else {
   1828             throw new Exception("Invalid gattIndex input: " + gattIndex);
   1829         }
   1830     }
   1831 
   1832     /**
   1833      * Create a new GattCallback object
   1834      *
   1835      * @return the index of the callback object
   1836      */
   1837     @Rpc(description = "Create a new GattCallback object")
   1838     public Integer gattCreateGattCallback() {
   1839         GattCallbackCount += 1;
   1840         int index = GattCallbackCount;
   1841         mGattCallbackList.put(index, new myBluetoothGattCallback(index));
   1842         return index;
   1843     }
   1844 
   1845     /**
   1846      * Returns the list of discovered Bluetooth Gatt Services.
   1847      *
   1848      * @throws Exception
   1849      */
   1850     @Rpc(description = "Get Bluetooth Gatt Services")
   1851     public int gattClientGetDiscoveredServicesCount(@RpcParameter(name = "index") Integer index)
   1852             throws Exception {
   1853         if (mBluetoothGattDiscoveredServicesList.get(index) != null) {
   1854             return mBluetoothGattDiscoveredServicesList.get(index).size();
   1855         } else {
   1856             throw new Exception("Invalid index input:" + index);
   1857         }
   1858     }
   1859 
   1860     /**
   1861      * Returns the discovered Bluetooth Gatt Service Uuid.
   1862      *
   1863      * @throws Exception
   1864      */
   1865     @Rpc(description = "Get Bluetooth Gatt Service Uuid")
   1866     public String gattClientGetDiscoveredServiceUuid(
   1867             @RpcParameter(name = "index") Integer index,
   1868             @RpcParameter(name = "serviceIndex") Integer serviceIndex)
   1869             throws Exception {
   1870         List<BluetoothGattService> mBluetoothServiceList =
   1871                 mBluetoothGattDiscoveredServicesList.get(index);
   1872         if (mBluetoothServiceList != null) {
   1873             return mBluetoothServiceList.get(serviceIndex).getUuid().toString();
   1874         } else {
   1875             throw new Exception("Invalid index input:" + index);
   1876         }
   1877     }
   1878 
   1879     /**
   1880      * Get discovered characteristic uuids from the pheripheral device.
   1881      *
   1882      * @param index the index of the bluetooth gatt discovered services list
   1883      * @param serviceIndex the service to get
   1884      * @return the list of characteristic uuids
   1885      * @throws Exception
   1886      */
   1887     @Rpc(description = "Get Bluetooth Gatt Services")
   1888     public ArrayList<String> gattClientGetDiscoveredCharacteristicUuids(
   1889             @RpcParameter(name = "index") Integer index,
   1890             @RpcParameter(name = "serviceIndex") Integer serviceIndex)
   1891             throws Exception {
   1892         if (mBluetoothGattDiscoveredServicesList.get(index) != null) {
   1893             if (mBluetoothGattDiscoveredServicesList.get(index).get(serviceIndex) != null) {
   1894                 ArrayList<String> uuidList = new ArrayList<String>();
   1895                 List<BluetoothGattCharacteristic> charList =
   1896                         mBluetoothGattDiscoveredServicesList.get(index).get(
   1897                             serviceIndex).getCharacteristics();
   1898                 for (BluetoothGattCharacteristic mChar : charList) {
   1899                     uuidList.add(mChar.getUuid().toString());
   1900                 }
   1901                 return uuidList;
   1902             } else {
   1903                 throw new Exception("Invalid serviceIndex input:" + index);
   1904             }
   1905         } else {
   1906             throw new Exception("Invalid index input:" + index);
   1907         }
   1908     }
   1909 
   1910     /**
   1911      * Get discovered descriptor uuids from the pheripheral device.
   1912      *
   1913      * @deprecated Use {@link #gattClientGetDiscoveredDescriptorUuidsByIndex(
   1914      *  index, serviceIndex, characteristicIndex)} instead.
   1915      * @param index the discovered services list index
   1916      * @param serviceIndex the service index of the discovered services list
   1917      * @param characteristicUuid the characteristicUuid to select from the
   1918      * discovered service which contains the list of descriptors.
   1919      * @return the list of descriptor uuids
   1920      * @throws Exception
   1921      */
   1922     @Deprecated
   1923     @Rpc(description = "Get Bluetooth Gatt Services")
   1924     public ArrayList<String> gattClientGetDiscoveredDescriptorUuids (
   1925             @RpcParameter(name = "index")
   1926             Integer index,
   1927             @RpcParameter(name = "serviceIndex")
   1928             Integer serviceIndex,
   1929             @RpcParameter(name = "characteristicUuid")
   1930             String characteristicUuid
   1931             ) throws Exception {
   1932         if (mBluetoothGattDiscoveredServicesList.get(index) != null) {
   1933             if (mBluetoothGattDiscoveredServicesList.get(index).get(serviceIndex) != null) {
   1934                 BluetoothGattService service = mBluetoothGattDiscoveredServicesList.get(
   1935                         index).get(serviceIndex);
   1936                 UUID cUuid = UUID.fromString(characteristicUuid);
   1937                 if (service.getCharacteristic(cUuid) != null) {
   1938                     ArrayList<String> uuidList = new ArrayList<String>();
   1939                     for (BluetoothGattDescriptor mDesc : service.getCharacteristic(
   1940                             cUuid).getDescriptors()) {
   1941                         uuidList.add(mDesc.getUuid().toString());
   1942                     }
   1943                     return uuidList;
   1944                 } else {
   1945                     throw new Exception("Invalid characeristicUuid : "
   1946                             + characteristicUuid);
   1947                 }
   1948             } else {
   1949                 throw new Exception("Invalid serviceIndex input:"
   1950                         + index);
   1951             }
   1952         } else {
   1953             throw new Exception("Invalid index input:"
   1954                     + index);
   1955         }
   1956     }
   1957 
   1958     /**
   1959      * Get discovered descriptor uuids from the pheripheral device.
   1960      *
   1961      * @param index the discovered services list index
   1962      * @param serviceIndex the service index of the discovered services list
   1963      * @param characteristicIndex the characteristicIndex to select from the discovered service
   1964      *       which contains the list of descriptors.
   1965      * @return the list of descriptor uuids
   1966      * @throws Exception
   1967      */
   1968     @Rpc(description = "Get Bluetooth Gatt Services")
   1969     public ArrayList<String> gattClientGetDiscoveredDescriptorUuidsByIndex(
   1970             @RpcParameter(name = "index") Integer index,
   1971             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
   1972             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
   1973             throws Exception {
   1974         if (mBluetoothGattDiscoveredServicesList.get(index) == null) {
   1975             throw new Exception("Invalid index: " + index);
   1976         }
   1977         if (mBluetoothGattDiscoveredServicesList.get(index).get(serviceIndex) == null) {
   1978             throw new Exception("Invalid serviceIndex: " + serviceIndex);
   1979         }
   1980         List<BluetoothGattCharacteristic> charList =
   1981                 mBluetoothGattDiscoveredServicesList.get(index).get(
   1982                     serviceIndex).getCharacteristics();
   1983         if (charList.get(characteristicIndex) == null) {
   1984             throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
   1985         }
   1986         List<BluetoothGattDescriptor> descList = charList.get(characteristicIndex).getDescriptors();
   1987         ArrayList<String> uuidList = new ArrayList<String>();
   1988         for (BluetoothGattDescriptor mDesc : descList) {
   1989             uuidList.add(mDesc.getUuid().toString());
   1990         }
   1991         return uuidList;
   1992     }
   1993 
   1994     private class myBluetoothGattCallback extends BluetoothGattCallback {
   1995         private final Bundle mResults;
   1996         private final int index;
   1997         private final String mEventType;
   1998 
   1999         public myBluetoothGattCallback(int idx) {
   2000             mResults = new Bundle();
   2001             mEventType = "GattConnect";
   2002             index = idx;
   2003         }
   2004 
   2005         @Override
   2006         public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
   2007             Log.d("gatt_connect change onConnectionStateChange " + mEventType + " " + index);
   2008             if (newState == BluetoothProfile.STATE_CONNECTED) {
   2009                 Log.d(
   2010                         "State Connected to mac address "
   2011                                 + gatt.getDevice().getAddress()
   2012                                 + " status "
   2013                                 + status);
   2014             } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
   2015                 Log.d(
   2016                         "State Disconnected from mac address "
   2017                                 + gatt.getDevice().getAddress()
   2018                                 + " status "
   2019                                 + status);
   2020             } else if (newState == BluetoothProfile.STATE_CONNECTING) {
   2021                 Log.d(
   2022                         "State Connecting to mac address "
   2023                                 + gatt.getDevice().getAddress()
   2024                                 + " status "
   2025                                 + status);
   2026             } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
   2027                 Log.d(
   2028                         "State Disconnecting from mac address "
   2029                                 + gatt.getDevice().getAddress()
   2030                                 + " status "
   2031                                 + status);
   2032             }
   2033             mResults.putInt("Status", status);
   2034             mResults.putInt("State", newState);
   2035             mEventFacade.postEvent(
   2036                     mEventType + index + "onConnectionStateChange", mResults.clone());
   2037             mResults.clear();
   2038         }
   2039 
   2040         @Override
   2041         public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
   2042             Log.d("gatt_connect change onPhyRead " + mEventType + " " + index);
   2043             mResults.putInt("TxPhy", txPhy);
   2044             mResults.putInt("RxPhy", rxPhy);
   2045             mResults.putInt("Status", status);
   2046             mEventFacade.postEvent(mEventType + index + "onPhyRead", mResults.clone());
   2047             mResults.clear();
   2048         }
   2049 
   2050         @Override
   2051         public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
   2052             Log.d("gatt_connect change onPhyUpdate " + mEventType + " " + index);
   2053             mResults.putInt("TxPhy", txPhy);
   2054             mResults.putInt("RxPhy", rxPhy);
   2055             mResults.putInt("Status", status);
   2056             mEventFacade.postEvent(mEventType + index + "onPhyUpdate", mResults.clone());
   2057             mResults.clear();
   2058         }
   2059 
   2060         @Override
   2061         public void onServicesDiscovered(BluetoothGatt gatt, int status) {
   2062             Log.d("gatt_connect change onServicesDiscovered " + mEventType + " " + index);
   2063             int idx = BluetoothGattDiscoveredServicesCount++;
   2064             mBluetoothGattDiscoveredServicesList.put(idx, gatt.getServices());
   2065             mResults.putInt("ServicesIndex", idx);
   2066             mResults.putInt("Status", status);
   2067             mEventFacade.postEvent(mEventType + index + "onServicesDiscovered", mResults.clone());
   2068             mResults.clear();
   2069         }
   2070 
   2071         @Override
   2072         public void onCharacteristicRead(
   2073                 BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
   2074             Log.d("gatt_connect change onCharacteristicRead " + mEventType + " " + index);
   2075             mResults.putInt("Status", status);
   2076             mResults.putString("CharacteristicUuid", characteristic.getUuid().toString());
   2077             mResults.putByteArray("CharacteristicValue", characteristic.getValue());
   2078             mEventFacade.postEvent(mEventType + index + "onCharacteristicRead", mResults.clone());
   2079             mResults.clear();
   2080         }
   2081 
   2082         @Override
   2083         public void onCharacteristicWrite(
   2084                 BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
   2085             Log.d("gatt_connect change onCharacteristicWrite " + mEventType + " " + index);
   2086             mResults.putInt("Status", status);
   2087             mResults.putString("CharacteristicUuid", characteristic.getUuid().toString());
   2088             mResults.putByteArray("CharacteristicValue", characteristic.getValue());
   2089             mEventFacade.postEvent(mEventType + index + "onCharacteristicWrite", mResults.clone());
   2090             mResults.clear();
   2091         }
   2092 
   2093         @Override
   2094         public void onCharacteristicChanged(
   2095                 BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
   2096             Log.d("gatt_connect change onCharacteristicChanged " + mEventType + " " + index);
   2097             mResults.putInt("ID", index);
   2098             mResults.putString("CharacteristicUuid", characteristic.getUuid().toString());
   2099             mResults.putByteArray("CharacteristicValue", characteristic.getValue());
   2100             mEventFacade.postEvent(
   2101                     mEventType + index + "onCharacteristicChanged", mResults.clone());
   2102             mResults.clear();
   2103         }
   2104 
   2105         @Override
   2106         public void onDescriptorRead(
   2107                 BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
   2108             Log.d("gatt_connect change onServicesDiscovered " + mEventType + " " + index);
   2109             mResults.putInt("Status", status);
   2110             mResults.putString("DescriptorUuid", descriptor.getUuid().toString());
   2111             mEventFacade.postEvent(mEventType + index + "onDescriptorRead", mResults.clone());
   2112             mResults.clear();
   2113         }
   2114 
   2115         @Override
   2116         public void onDescriptorWrite(
   2117                 BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
   2118             Log.d("gatt_connect change onDescriptorWrite " + mEventType + " " + index);
   2119             mResults.putInt("ID", index);
   2120             mResults.putInt("Status", status);
   2121             mResults.putString("DescriptorUuid", descriptor.getUuid().toString());
   2122             mEventFacade.postEvent(mEventType + index + "onDescriptorWrite", mResults.clone());
   2123             mResults.clear();
   2124         }
   2125 
   2126         @Override
   2127         public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
   2128             Log.d("gatt_connect change onReliableWriteCompleted " + mEventType + " " + index);
   2129             mResults.putInt("Status", status);
   2130             mEventFacade.postEvent(
   2131                     mEventType + index + "onReliableWriteCompleted", mResults.clone());
   2132             mResults.clear();
   2133         }
   2134 
   2135         @Override
   2136         public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
   2137             Log.d("gatt_connect change onReadRemoteRssi " + mEventType + " " + index);
   2138             mResults.putInt("Status", status);
   2139             mResults.putInt("Rssi", rssi);
   2140             mEventFacade.postEvent(mEventType + index + "onReadRemoteRssi", mResults.clone());
   2141             mResults.clear();
   2142         }
   2143 
   2144         @Override
   2145         public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
   2146             Log.d("gatt_connect change onMtuChanged " + mEventType + " " + index);
   2147             mResults.putInt("Status", status);
   2148             mResults.putInt("MTU", mtu);
   2149             mEventFacade.postEvent(mEventType + index + "onMtuChanged", mResults.clone());
   2150             mResults.clear();
   2151         }
   2152 
   2153         public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency,
   2154                                             int timeout, int status) {
   2155             Log.d("gatt_connect change onConnecitonUpdated " + mEventType + " " + index
   2156                     + ", interval: " + interval + ", latency: " + latency
   2157                     + ", timeout: " + timeout + ", status: " + status);
   2158 
   2159             mResults.putInt("Status", status);
   2160             mResults.putInt("Interval", interval);
   2161             mResults.putInt("Latency", latency);
   2162             mResults.putInt("Timeout", timeout);
   2163             mEventFacade.postEvent(mEventType + index + "onConnectionUpdated", mResults.clone());
   2164             mResults.clear();
   2165         }
   2166     }
   2167 
   2168     @Override
   2169     public void shutdown() {
   2170         if (!mBluetoothGattList.isEmpty()) {
   2171             if (mBluetoothGattList.values() != null) {
   2172                 for (BluetoothGatt mBluetoothGatt : mBluetoothGattList.values()) {
   2173                     mBluetoothGatt.close();
   2174                 }
   2175             }
   2176         }
   2177         mGattCallbackList.clear();
   2178     }
   2179 }
   2180