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