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