• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GattClientFacade(FacadeManager manager)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")
gattClientConnectGatt( @pcParametername = "index") Integer index, @RpcParameter(name = "macAddress") String macAddress, @RpcParameter(name = "autoConnect") Boolean autoConnect, @RpcParameter(name = "transport") Integer transport, @RpcParameter(name = "phy") Integer phy)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")
gattClientDiscoverServices(@pcParametername = "index") Integer index)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")
gattClientDiscoverServiceByUuid(@pcParametername = "index") Integer index, @RpcParameter(name = "uuid") String uuid)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")
gattClientGetServices( @pcParametername = "index") Integer index)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")
gattClientAbortReliableWrite(@pcParametername = "index") Integer index)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")
gattClientBeginReliableWrite(@pcParametername = "index") Integer index)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")
gattClientRequestMtu( @pcParametername = "index") Integer index, @RpcParameter(name = "mtu") Integer mtu)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")
gattClientReadPhy(@pcParametername = "index") Integer index)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")
gattClientSetPreferredPhy(@pcParametername = "index") Integer index, @RpcParameter(name = "txPhy") Integer txPhy, @RpcParameter(name = "rxPhy") Integer rxPhy, @RpcParameter(name = "txPhy") Integer phyOptions)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")
gattClientDisconnect(@pcParametername = "index") Integer index)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")
gattClientClose(@pcParametername = "index") Integer index)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")
gattExecuteReliableWrite(@pcParametername = "index") Integer index)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")
gattClientGetConnectedDevices( @pcParametername = "index") Integer index)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")
gattGetDevice(@pcParametername = "index") Integer index)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")
gattClientGetDevicesMatchingConnectionStates( @pcParametername = "index") Integer index, @RpcParameter( name = "states") int[] 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")
gattClientGetServiceUuidList( @pcParametername = "index") Integer index)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
gattClientReadCharacteristic( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid)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.")
gattClientReadUsingCharacteristicUuid( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "uuid") String uuid, @RpcParameter(name = "startHandle") Integer startHandle, @RpcParameter(name = "endHandle") Integer endHandle)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.")
gattClientReadCharacteristicByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)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.")
gattClientReadCharacteristicByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)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.")
gattClientWriteDescriptorByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId, @RpcParameter(name = "value") byte[] value)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.")
gattClientWriteCharacteristicByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId, @RpcParameter(name = "value") byte[] value)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.")
gattClientModifyAccessAndWriteCharacteristicByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId, @RpcParameter(name = "value") byte[] value)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.")
gattClientWriteInvalidCharacteristicByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "instanceId") Integer instanceId, @RpcParameter(name = "value") byte[] value)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.")
gattClientModifyAccessAndReadCharacteristicByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)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.")
gattClientReadInvalidCharacteristicByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)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.")
gattClientModifyAccessAndWriteDescriptorByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId, @RpcParameter(name = "value") byte[] value)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.")
gattClientWriteInvalidDescriptorByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "instanceId") Integer instanceId, @RpcParameter(name = "value") byte[] value)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.")
gattClientModifyAccessAndReadDescriptorByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId)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.")
gattClientReadInvalidDescriptorByInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId)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.")
gattClientModifyAccessAndReadCharacteristicByUuidAndInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId, @RpcParameter(name = "characteristicUuid") String characteristicUuid)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.")
gattClientReadInvalidCharacteristicByUuidAndInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid)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")
gattClientReadDescriptor( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid, @RpcParameter(name = "descriptorUuid") String descriptorUuid)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")
gattClientReadDescriptorByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)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")
gattClientWriteDescriptor( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid, @RpcParameter(name = "descriptorUuid") String descriptorUuid)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")
gattClientWriteDescriptorByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)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")
gattClientDescriptorSetValue( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid, @RpcParameter(name = "descriptorUuid") String descriptorUuid, @RpcParameter(name = "value") byte[] value)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")
gattClientDescriptorSetValueByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "descriptorIndex") Integer descriptorIndex, @RpcParameter(name = "value") byte[] value)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")
gattClientWriteCharacteristic( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid)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")
gattClientWriteCharacteristicByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)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")
gattClientReadInvalidCharacteristicInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "instanceId") Integer instanceId)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")
gattClientGetCharacteristicInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)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")
gattClientGetDescriptorInstanceId( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)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")
gattClientCharacteristicSetValue( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid, @RpcParameter(name = "value") byte[] value)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")
gattClientCharacteristicSetValueByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "value") byte[] value)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")
gattClientCharacteristicSetWriteType( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid, @RpcParameter(name = "writeType") Integer writeType)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")
gattClientCharacteristicSetWriteTypeByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "writeType") Integer writeType)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")
gattClientReadRSSI( @pcParametername = "index") Integer index)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")
gattClientRefresh(@pcParametername = "index") Integer index)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")
gattClientRequestConnectionPriority( @pcParametername = "index") Integer index, @RpcParameter(name = "connectionPriority") Integer connectionPriority)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")
gattClientSetCharacteristicNotification( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid, @RpcParameter(name = "enable") Boolean enable )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")
gattClientSetCharacteristicNotificationByIndex( @pcParametername = "gattIndex") Integer gattIndex, @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex, @RpcParameter(name = "enable") Boolean enable)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")
gattCreateGattCallback()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")
gattClientGetDiscoveredServicesCount(@pcParametername = "index") Integer index)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")
gattClientGetDiscoveredServiceUuid( @pcParametername = "index") Integer index, @RpcParameter(name = "serviceIndex") Integer serviceIndex)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")
gattClientGetDiscoveredCharacteristicUuids( @pcParametername = "index") Integer index, @RpcParameter(name = "serviceIndex") Integer serviceIndex)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")
gattClientGetDiscoveredDescriptorUuids( @pcParametername = "index") Integer index, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicUuid") String characteristicUuid )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")
gattClientGetDiscoveredDescriptorUuidsByIndex( @pcParametername = "index") Integer index, @RpcParameter(name = "serviceIndex") Integer serviceIndex, @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)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 
myBluetoothGattCallback(int idx)1999         public myBluetoothGattCallback(int idx) {
2000             mResults = new Bundle();
2001             mEventType = "GattConnect";
2002             index = idx;
2003         }
2004 
2005         @Override
onConnectionStateChange(BluetoothGatt gatt, int status, int newState)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
onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status)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
onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status)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
onServicesDiscovered(BluetoothGatt gatt, int status)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
onCharacteristicRead( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)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
onCharacteristicWrite( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status)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
onCharacteristicChanged( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)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
onDescriptorRead( BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)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
onDescriptorWrite( BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status)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
onReliableWriteCompleted(BluetoothGatt gatt, int status)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
onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)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
onMtuChanged(BluetoothGatt gatt, int mtu, int status)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 
onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout, int status)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
shutdown()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