/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.android_scripting.facade.bluetooth;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Bundle;

import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.MainThread;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcParameter;
import com.googlecode.android_scripting.rpc.RpcStopEvent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;

public class GattClientFacade extends RpcReceiver {
    private final EventFacade mEventFacade;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager mBluetoothManager;
    private final Service mService;
    private final Context mContext;
    private final HashMap<Integer, myBluetoothGattCallback> mGattCallbackList;
    private final HashMap<Integer, BluetoothGatt> mBluetoothGattList;
    private final HashMap<Integer, BluetoothGattCharacteristic> mCharacteristicList;
    private final HashMap<Integer, BluetoothGattDescriptor> mDescriptorList;
    private final HashMap<Integer, BluetoothGattService> mGattServiceList;
    private final HashMap<Integer, List<BluetoothGattService>> mBluetoothGattDiscoveredServicesList;
    private final HashMap<Integer, List<BluetoothDevice>> mGattServerDiscoveredDevicesList;
    private static int GattCallbackCount;
    private static int BluetoothGattDiscoveredServicesCount;
    private static int BluetoothGattCount;
    private static int CharacteristicCount;
    private static int DescriptorCount;
    private static int GattServerCallbackCount;
    private static int GattServerCount;
    private static int GattServiceCount;

    public GattClientFacade(FacadeManager manager) {
        super(manager);
        mService = manager.getService();
        mContext = mService.getApplicationContext();
        mBluetoothAdapter =
                MainThread.run(
                        mService,
                        new Callable<BluetoothAdapter>() {
                            @Override
                            public BluetoothAdapter call() throws Exception {
                                return BluetoothAdapter.getDefaultAdapter();
                            }
                        });
        mBluetoothManager = (BluetoothManager) mContext.getSystemService(Service.BLUETOOTH_SERVICE);
        mEventFacade = manager.getReceiver(EventFacade.class);
        mGattCallbackList = new HashMap<Integer, myBluetoothGattCallback>();
        mCharacteristicList = new HashMap<Integer, BluetoothGattCharacteristic>();
        mBluetoothGattList = new HashMap<Integer, BluetoothGatt>();
        mDescriptorList = new HashMap<Integer, BluetoothGattDescriptor>();
        mGattServiceList = new HashMap<Integer, BluetoothGattService>();
        mBluetoothGattDiscoveredServicesList = new HashMap<Integer, List<BluetoothGattService>>();
        mGattServerDiscoveredDevicesList = new HashMap<Integer, List<BluetoothDevice>>();
    }

    /**
     * Create a BluetoothGatt connection
     *
     * @param index of the callback to start a connection on
     * @param macAddress the mac address of the ble device
     * @param autoConnect Whether to directly connect to the remote device (false) or to
     *       automatically connect as soon as the remote device becomes available (true)
     * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
     *                      does not hold a GATT connection. It automatically disconnects when no
     *                      other GATT connections are active for the remote device.
     * @param transport preferred transport for GATT connections to remote dual-mode devices
     *       TRANSPORT_AUTO or TRANSPORT_BREDR or TRANSPORT_LE
     * @return the index of the BluetoothGatt object
     * @throws Exception
     */
    @Rpc(description = "Create a gatt connection")
    public int gattClientConnectGatt(
            @RpcParameter(name = "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)
            throws Exception {
        if (mGattCallbackList.get(index) != null) {
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
            if (phy == null) phy = BluetoothDevice.PHY_LE_1M;

            BluetoothGatt mBluetoothGatt = device.connectGatt(mService.getApplicationContext(),
                    autoConnect, mGattCallbackList.get(index), transport, opportunistic, phy, null);
            BluetoothGattCount += 1;
            mBluetoothGattList.put(BluetoothGattCount, mBluetoothGatt);
            return BluetoothGattCount;
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Trigger discovering of services on the BluetoothGatt object
     *
     * @param index The BluetoothGatt object index
     * @return true, if the remote service discovery has been started
     * @throws Exception
     */
    @Rpc(description = "Trigger discovering of services on the BluetoothGatt object")
    public boolean gattClientDiscoverServices(@RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).discoverServices();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Trigger discovering of services by UUID on the BluetoothGatt object
     *
     * @param index The BluetoothGatt object index
     * @param uuid service UUID
     * @return true, if the remote service discovery has been started
     * @throws Exception
     */
    @Rpc(description = "Trigger discovering of services on the BluetoothGatt object")
    public boolean gattClientDiscoverServiceByUuid(@RpcParameter(name = "index") Integer index,
            @RpcParameter(name = "uuid") String uuid) throws Exception {
        BluetoothGatt gatt = mBluetoothGattList.get(index);
        if (gatt != null) {
            Object ret = gatt.getClass().getMethod("discoverServiceByUuid", UUID.class)
                            .invoke(gatt, UUID.fromString(uuid));
            return (Boolean) ret;
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }


    /**
     * Get the services from the BluetoothGatt object
     *
     * @param index The BluetoothGatt object index
     * @return a list of BluetoothGattServices
     * @throws Exception
     */
    @Rpc(description = "Get the services from the BluetoothGatt object")
    public List<BluetoothGattService> gattClientGetServices(
            @RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).getServices();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Abort reliable write of a bluetooth gatt
     *
     * @param index the bluetooth gatt index
     * @throws Exception
     */
    @Rpc(description = "Abort reliable write of a bluetooth gatt")
    public void gattClientAbortReliableWrite(@RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            mBluetoothGattList.get(index).abortReliableWrite();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Begin reliable write of a bluetooth gatt
     *
     * @param index the bluetooth gatt index
     * @return
     * @throws Exception
     */
    @Rpc(description = "Begin reliable write of a bluetooth gatt")
    public boolean gattClientBeginReliableWrite(@RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).beginReliableWrite();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Configure a bluetooth gatt's MTU
     *
     * @param index the bluetooth gatt index
     * @param mtu the MTU to set
     * @return
     * @throws Exception
     */
    @Rpc(description = "true, if the new MTU value has been requested successfully")
    public boolean gattClientRequestMtu(
            @RpcParameter(name = "index") Integer index, @RpcParameter(name = "mtu") Integer mtu)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).requestMtu(mtu);
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Read the current transmitter PHY and receiver PHY of the connection.
     *
     * @param index the bluetooth gatt index
     * @throws Exception
     */
    @Rpc(description = "Read PHY")
    public void gattClientReadPhy(@RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            mBluetoothGattList.get(index).readPhy();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Set the preferred connection PHY.
     *
     * @param index the bluetooth gatt index
     * @throws Exception
     */
    @Rpc(description = "Set the preferred connection PHY")
    public void gattClientSetPreferredPhy(@RpcParameter(name = "index") Integer index,
            @RpcParameter(name = "txPhy") Integer txPhy,
            @RpcParameter(name = "rxPhy") Integer rxPhy,
            @RpcParameter(name = "txPhy") Integer phyOptions) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            mBluetoothGattList.get(index).setPreferredPhy(txPhy, rxPhy, phyOptions);
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Disconnect a bluetooth gatt
     *
     * @param index the bluetooth gatt index
     * @throws Exception
     */
    @Rpc(description = "Disconnect a bluetooth gatt")
    @RpcStopEvent("GattConnect")
    public void gattClientDisconnect(@RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            mBluetoothGattList.get(index).disconnect();
        } else {
            throw new Exception("Invalid index input: " + index);
        }
    }

    /**
     * Close a bluetooth gatt object
     *
     * @param index the bluetooth gatt index
     * @throws Exception
     */
    @Rpc(description = "Close a Bluetooth GATT object")
    public void gattClientClose(@RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            mBluetoothGattList.get(index).close();
        } else {
            throw new Exception("Invalid index input: " + index);
        }
    }

    /**
     * Execute reliable write on a bluetooth gatt
     *
     * @param index the bluetooth gatt index
     * @return true, if the request to execute the transaction has been sent
     * @throws Exception
     */
    @Rpc(description = "Execute reliable write on a bluetooth gatt")
    public boolean gattExecuteReliableWrite(@RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).executeReliableWrite();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Get a list of Bluetooth Devices connnected to the bluetooth gatt
     *
     * @param index the bluetooth gatt index
     * @return List of BluetoothDevice Objects
     * @throws Exception
     */
    @Rpc(description = "Get a list of Bluetooth Devices connnected to the bluetooth gatt")
    public List<BluetoothDevice> gattClientGetConnectedDevices(
            @RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).getConnectedDevices();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Get the remote bluetooth device this GATT client targets to
     *
     * @param index the bluetooth gatt index
     * @return the remote bluetooth device this gatt client targets to
     * @throws Exception
     */
    @Rpc(description = "Get the remote bluetooth device this GATT client targets to")
    public BluetoothDevice gattGetDevice(@RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).getDevice();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Get the bluetooth devices matching input connection states
     *
     * @param index the bluetooth gatt index
     * @param states the list of states to match
     * @return The list of BluetoothDevice objects that match the states
     * @throws Exception
     */
    @Rpc(description = "Get the bluetooth devices matching input connection states")
    public List<BluetoothDevice> gattClientGetDevicesMatchingConnectionStates(
            @RpcParameter(name = "index") Integer index, @RpcParameter(
                name = "states") int[] states)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).getDevicesMatchingConnectionStates(states);
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Get the service from an input UUID
     *
     * @param index the bluetooth gatt index
     * @return BluetoothGattService related to the bluetooth gatt
     * @throws Exception
     */
    @Rpc(description = "Get the service from an input UUID")
    public ArrayList<String> gattClientGetServiceUuidList(
            @RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            ArrayList<String> serviceUuidList = new ArrayList<String>();
            for (BluetoothGattService service : mBluetoothGattList.get(index).getServices()) {
                serviceUuidList.add(service.getUuid().toString());
            }
            return serviceUuidList;
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Reads the requested characteristic from the associated remote device.
     *
     * @deprecated Use {@link #gattClientReadCharacteristicByIndex(gattIndex,
     *     discoveredServiceListIndex, serviceIndex, characteristicIndex)} instead.
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param serviceIndex the service index of the discovered services
     * @param characteristicUuid the characteristic uuid to read
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Reads the requested characteristic from the associated remote device.")
    @Deprecated
    public boolean gattClientReadCharacteristic(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid) throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        return bluetoothGatt.readCharacteristic(gattCharacteristic);
    }

    /**
     * Reads the characteristic from the associated remote device.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param uuid the characteristic uuid to read
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Reads the characteristic from the associated remote device.")
    public boolean gattClientReadUsingCharacteristicUuid(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "uuid") String uuid,
            @RpcParameter(name = "startHandle") Integer startHandle,
            @RpcParameter(name = "endHandle") Integer endHandle) throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        UUID cUuid = UUID.fromString(uuid);
        return bluetoothGatt.readUsingCharacteristicUuid(cUuid, startHandle, endHandle);
    }

    /**
     * Reads the requested characteristic from the associated remote device.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param serviceIndex the service index of the discovered services
     * @param characteristicIndex the characteristic index
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Reads the requested characteristic from the associated remote device.")
    public boolean gattClientReadCharacteristicByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        return bluetoothGatt.readCharacteristic(charList.get(characteristicIndex));
    }

    /**
     * Reads the requested characteristic from the associated remote device by instance id.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Reads the requested characteristic from the associated remote "
            + "device by instance id.")
    public boolean gattClientReadCharacteristicByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                if (mGattChar.getInstanceId() == characteristicInstanceId) {
                    Log.i("Found Characteristic to read. instanceId: "
                        + Integer.toString(characteristicInstanceId)
                        + " UUID: " + mGattChar.getUuid().toString());
                    return bluetoothGatt.readCharacteristic(mGattChar);
                }
            }
        }
        Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
            characteristicInstanceId));
        return false;
    }

    /**
     * Writes the requested characteristic from the associated remote device by instance id.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param characteristicInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Writes the requested characteristic from the associated remote "
            + "device by instance id.")
    public boolean gattClientWriteDescriptorByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                List<BluetoothGattDescriptor> descList = mGattChar.getDescriptors();
                for (BluetoothGattDescriptor mGattDesc : descList) {
                    if (mGattDesc.getInstanceId() == descriptorInstanceId) {
                        mGattDesc.setValue(value);
                        Log.i("Found Descriptor to write. instanceId: "
                            + Integer.toString(descriptorInstanceId)
                            + " UUID: " + mGattDesc.getUuid().toString());
                        return bluetoothGatt.writeDescriptor(mGattDesc);
                    }
                }
            }
        }
        Log.e("Failed to find Descriptor with instanceId: " + Integer.toString(
            descriptorInstanceId));
        return false;
    }

    /**
     * Writes the requested characteristic from the associated remote device by instance id.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Writes the requested characteristic from the associated remote "
            + "device by instance id.")
    public boolean gattClientWriteCharacteristicByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                if (mGattChar.getInstanceId() == characteristicInstanceId) {
                    mGattChar.setValue(value);
                    Log.i("Found Characteristic to write. instanceId: "
                        + Integer.toString(characteristicInstanceId)
                        + " UUID: " + mGattChar.getUuid().toString());
                    return bluetoothGatt.writeCharacteristic(mGattChar);
                }
            }
        }
        Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
            characteristicInstanceId));
        return false;
    }

    /**
     * Writes the requested characteristic in which write is not permitted. For conformance tests
     * only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Writes the requested characteristic from the associated remote "
            + "device by instance id.")
    public boolean gattClientModifyAccessAndWriteCharacteristicByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                if (mGattChar.getInstanceId() == characteristicInstanceId) {
                    Log.i("Found Characteristic to write. instanceId: "
                        + Integer.toString(characteristicInstanceId)
                        + " UUID: " + mGattChar.getUuid().toString());
                    BluetoothGattCharacteristic modChar = new BluetoothGattCharacteristic(
                        mGattChar.getUuid(), 0x08, 0x10);
                    modChar.setInstanceId(mGattChar.getInstanceId());
                    mGattService.addCharacteristic(modChar);
                    modChar.setValue(value);
                    return bluetoothGatt.writeCharacteristic(modChar);
                }
            }
        }
        Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
            characteristicInstanceId));
        return false;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Writes a Characteristic with an invalid instanceId to each service.")
    public boolean gattClientWriteInvalidCharacteristicByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "instanceId") Integer instanceId,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            BluetoothGattCharacteristic invalidHandleChar = new BluetoothGattCharacteristic(
                UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x08, 0x10);
            invalidHandleChar.setInstanceId(instanceId);
            mGattService.addCharacteristic(invalidHandleChar);
            invalidHandleChar.setValue(value);
            //todo: this used to be return bluetoothGatt. Retest with and without return
            bluetoothGatt.writeCharacteristic(invalidHandleChar);
        }
        return true;
    }

    /**
     * Writes the requested characteristic in which write is not permitted. For conformance tests
     * only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Read the requested characteristic from the associated remote "
            + "device by instance id.")
    public boolean gattClientModifyAccessAndReadCharacteristicByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                if (mGattChar.getInstanceId() == characteristicInstanceId) {
                    Log.i("Found Characteristic to read. instanceId: "
                        + Integer.toString(characteristicInstanceId)
                        + " UUID: " + mGattChar.getUuid().toString());
                    BluetoothGattCharacteristic modChar = new BluetoothGattCharacteristic(
                        mGattChar.getUuid(), 0x02, 0x01);
                    modChar.setInstanceId(mGattChar.getInstanceId());
                    mGattService.addCharacteristic(modChar);
                    return bluetoothGatt.readCharacteristic(modChar);
                }
            }
        }
        Log.e("Failed to find Characteristic with instanceId: " + Integer.toString(
            characteristicInstanceId));
        return false;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Read a Characteristic with an invalid instanceId to each service.")
    public boolean gattClientReadInvalidCharacteristicByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            BluetoothGattCharacteristic invalidHandleChar = new BluetoothGattCharacteristic(
                UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x02, 0x01);
            invalidHandleChar.setInstanceId(characteristicInstanceId);
            mGattService.addCharacteristic(invalidHandleChar);
            bluetoothGatt.readCharacteristic(invalidHandleChar);
        }
        return true;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests
     * only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Writes the requested descriptor from the associated remote "
            + "device by instance id.")
    public boolean gattClientModifyAccessAndWriteDescriptorByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                for (BluetoothGattDescriptor mGattDesc : mGattChar.getDescriptors()) {
                    if (mGattDesc.getInstanceId() == descriptorInstanceId) {
                        Log.i("Found Descriptor to write. instanceId: "
                            + Integer.toString(descriptorInstanceId)
                            + " UUID: " + mGattChar.getUuid().toString());
                        BluetoothGattDescriptor modDesc = new BluetoothGattDescriptor(
                            mGattDesc.getUuid(), 0x10);
                        modDesc.setInstanceId(descriptorInstanceId);
                        mGattChar.addDescriptor(modDesc);
                        modDesc.setValue(value);
                        return bluetoothGatt.writeDescriptor(modDesc);
                    }
                }
            }
        }
        Log.e("Failed to find Descriptor with instanceId: " + Integer.toString(
            descriptorInstanceId));
        return false;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Writes a Characteristic with an invalid instanceId to each service.")
    public boolean gattClientWriteInvalidDescriptorByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "instanceId") Integer instanceId,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            for (BluetoothGattCharacteristic mGattChar : mGattService.getCharacteristics()) {
                BluetoothGattDescriptor invalidHandleDesc = new BluetoothGattDescriptor(
                    UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x10);
                invalidHandleDesc.setInstanceId(instanceId);
                mGattChar.addDescriptor(invalidHandleDesc);
                invalidHandleDesc.setValue(value);
                bluetoothGatt.writeDescriptor(invalidHandleDesc);
            }
        }
        return true;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests
     * only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Read the requested descriptor from the associated remote "
            + "device by instance id.")
    public boolean gattClientModifyAccessAndReadDescriptorByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                for (BluetoothGattDescriptor mGattDesc : mGattChar.getDescriptors()) {
                    if (mGattDesc.getInstanceId() == descriptorInstanceId) {
                        Log.i("Found Descriptor to read. instanceId: "
                            + Integer.toString(descriptorInstanceId)
                            + " UUID: " + mGattDesc.getUuid().toString());
                        BluetoothGattDescriptor modDesc = new BluetoothGattDescriptor(
                            mGattDesc.getUuid(), 0x01);
                        modDesc.setInstanceId(descriptorInstanceId);
                        mGattChar.addDescriptor(modDesc);
                        return bluetoothGatt.readDescriptor(modDesc);
                    }
                }
            }
        }
        Log.e("Failed to find Descriptor with instanceId: " + Integer.toString(
            descriptorInstanceId));
        return false;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Read a Characteristic with an invalid instanceId to each service.")
    public boolean gattClientReadInvalidDescriptorByInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "descriptorInstanceId") Integer descriptorInstanceId)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            for (BluetoothGattCharacteristic mGattChar : mGattService.getCharacteristics()) {
                BluetoothGattDescriptor invalidHandleDesc = new BluetoothGattDescriptor(
                    UUID.fromString("aa7edd5a-4d1d-4f0e-883a-d145616a1630"), 0x01);
                invalidHandleDesc.setInstanceId(descriptorInstanceId);
                mGattChar.addDescriptor(invalidHandleDesc);
                bluetoothGatt.readDescriptor(invalidHandleDesc);
            }
        }
        return true;
    }

    /**
     * Writes the requested characteristic in which write is not permitted. For conformance tests
     * only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Read the requested characteristic from the associated remote "
            + "device by uuid.")
    public boolean gattClientModifyAccessAndReadCharacteristicByUuidAndInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicInstanceId") Integer characteristicInstanceId,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            List<BluetoothGattCharacteristic> charList = mGattService.getCharacteristics();
            for (BluetoothGattCharacteristic mGattChar : charList) {
                if (mGattChar.getUuid().toString().equalsIgnoreCase(characteristicUuid) &&
                        mGattChar.getInstanceId() == characteristicInstanceId) {
                    Log.i("Found Characteristic to read. UUID: " + mGattChar.getUuid().toString());
                    BluetoothGattCharacteristic modChar = new BluetoothGattCharacteristic(
                        mGattChar.getUuid(), 0x02, 0x01);
                    modChar.setInstanceId(characteristicInstanceId);
                    mGattService.addCharacteristic(modChar);
                    bluetoothGatt.readCharacteristic(modChar);
                }
            }
        }
        return true;
    }

    /**
     * Writes the requested descriptor in which write is not permitted. For conformance tests only.
     *
     * @param gattIndex the BluetoothGatt server accociated with the device
     * @param discoveredServiceListIndex the index returned from the discovered services callback
     * @param descriptorInstanceId the integer instance id of the Characteristic to write to
     * @param value the value to write to the characteristic
     * @return true, if the read operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Read a Characteristic with an invalid Uuid to each service.")
    public boolean gattClientReadInvalidCharacteristicByUuidAndInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        for (BluetoothGattService mGattService : gattServiceList) {
            BluetoothGattCharacteristic invalidHandleChar = new BluetoothGattCharacteristic(
                UUID.fromString(characteristicUuid), 0x02, 0x01);
            mGattService.addCharacteristic(invalidHandleChar);
            bluetoothGatt.readCharacteristic(invalidHandleChar);
        }
        return true;
    }

    /**
     * /** Reads the value for a given descriptor from the associated remote device
     *
     * @deprecated Use {@link #gattClientReadDescriptorByIndex(
     * gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, descriptorIndex)}
     * instead.
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discvered serivice list index
     * @param serviceIndex - the servce index of the discoveredServiceListIndex
     * @param characteristicUuid - the characteristic uuid in which the descriptor is
     * @param descriptorUuid - the descriptor uuid to read
     * @return
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Reads the value for a given descriptor from the associated remote device")
    public boolean gattClientReadDescriptor(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid,
            @RpcParameter(name = "descriptorUuid") String descriptorUuid) throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList = mBluetoothGattDiscoveredServicesList.get(
                      discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        UUID dUuid = UUID.fromString(descriptorUuid);
        BluetoothGattDescriptor gattDescriptor = gattCharacteristic.getDescriptor(dUuid);
        if (gattDescriptor == null) {
            throw new Exception("Invalid descriptor uuid: " + descriptorUuid);
        }
        return bluetoothGatt.readDescriptor(gattDescriptor);
    }


    /**
     * /** Reads the value for a given descriptor from the associated remote device
     *
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discvered serivice list index
     * @param serviceIndex - the servce index of the discoveredServiceListIndex
     * @param characteristicIndex - the characteristic index
     * @param descriptorIndex - the descriptor index to read
     * @return
     * @throws Exception
     */
    @Rpc(description = "Reads the value for a given descriptor from the associated remote device")
    public boolean gattClientReadDescriptorByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
            @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
        List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
        if (descList.get(descriptorIndex) == null) {
            throw new Exception("Invalid descriptorIndex " + descriptorIndex);
        }
        return bluetoothGatt.readDescriptor(descList.get(descriptorIndex));
    }

    /**
     * Write the value of a given descriptor to the associated remote device
     *
     * @deprecated Use {@link #gattClientWriteDescriptorByIndex(
     * gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, descriptorIndex)}
     * instead.
     * @param index the bluetooth gatt index
     * @param serviceIndex the service index to write to
     * @param characteristicUuid the uuid where the descriptor lives
     * @param descriptorIndex the descriptor index
     * @return true, if the write operation was initiated successfully
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Write the value of a given descriptor to the associated remote device")
    public boolean gattClientWriteDescriptor(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid,
            @RpcParameter(name = "descriptorUuid") String descriptorUuid) throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        UUID dUuid = UUID.fromString(descriptorUuid);
        BluetoothGattDescriptor gattDescriptor = gattCharacteristic.getDescriptor(dUuid);
        if (gattDescriptor == null) {
            throw new Exception("Invalid descriptor uuid: " + descriptorUuid);
        }
        return bluetoothGatt.writeDescriptor(gattDescriptor);
    }

    /**
     * Write the value of a given descriptor to the associated remote device
     *
     * @param index the bluetooth gatt index
     * @param serviceIndex the service index to write to
     * @param characteristicIndex the characteristic index to write to
     * @param descriptorIndex the descriptor index to write to
     * @return true, if the write operation was initiated successfully
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given descriptor to the associated remote device")
    public boolean gattClientWriteDescriptorByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
            @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
        List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
        if (descList.get(descriptorIndex) == null) {
            throw new Exception("Invalid descriptorIndex " + descriptorIndex);
        }
        return bluetoothGatt.writeDescriptor(descList.get(descriptorIndex));
    }

    /**
     * Write the value to a discovered descriptor.
     *
     * @deprecated Use {@link #gattClientDescriptorSetValueByIndex(
     *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, descriptorIndex,
     *  value)} instead.
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discovered service list index
     * @param serviceIndex - the service index of the discoveredServiceListIndex
     * @param characteristicUuid - the characteristic uuid in which the descriptor is
     * @param descriptorUuid - the descriptor uuid to read
     * @param value - the value to set the descriptor to
     * @return true is the value was set to the descriptor
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Write the value of a given descriptor to the associated remote device")
    public boolean gattClientDescriptorSetValue(
            @RpcParameter(name = "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) throws Exception {
        if (mBluetoothGattList.get(gattIndex) == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                  mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        UUID dUuid = UUID.fromString(descriptorUuid);
        BluetoothGattDescriptor gattDescriptor = gattCharacteristic.getDescriptor(dUuid);
        if (gattDescriptor == null) {
            throw new Exception("Invalid descriptor uuid: " + descriptorUuid);
        }
        return gattDescriptor.setValue(value);
    }

    /**
     * Write the value to a discovered descriptor.
     *
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discovered service list index
     * @param serviceIndex - the service index of the discoveredServiceListIndex
     * @param characteristicIndex - the characteristic index
     * @param descriptorIndex - the descriptor index to set
     * @param value - the value to set the descriptor to
     * @return true is the value was set to the descriptor
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given descriptor to the associated remote device")
    public boolean gattClientDescriptorSetValueByIndex(
            @RpcParameter(name = "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)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
        List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
        if (descList.get(descriptorIndex) == null) {
            throw new Exception("Invalid descriptorIndex " + descriptorIndex);
        }
        return descList.get(descriptorIndex).setValue(value);
    }


    /**
     * Write the value of a given characteristic to the associated remote device
     *
     * @deprecated Use {@link #gattClientWriteCharacteristicByIndex(
     *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex)} instead.
     * @param index the bluetooth gatt index
     * @param serviceIndex the service where the characteristic lives
     * @param characteristicUuid the characteristic uuid to write to
     * @return true, if the write operation was successful
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public boolean gattClientWriteCharacteristic(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid) throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        return bluetoothGatt.writeCharacteristic(gattCharacteristic);
    }

    /**
     * Write the value of a given characteristic to the associated remote device
     *
     * @param index the bluetooth gatt index
     * @param serviceIndex the service where the characteristic lives
     * @param characteristicIndex the characteristic index
     * @return true, if the write operation was successful
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public boolean gattClientWriteCharacteristicByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        return bluetoothGatt.writeCharacteristic(charList.get(characteristicIndex));
    }

    /**
     * PTS HELPER... Write the value of a given characteristic to the associated remote device
     *
     * @param index the bluetooth gatt index
     * @param serviceIndex the service where the characteristic lives
     * @param characteristicIndex the characteristic index
     * @return true, if the write operation was successful
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public boolean gattClientReadInvalidCharacteristicInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "instanceId") Integer instanceId)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        charList.get(0).setInstanceId(instanceId);
        return bluetoothGatt.readCharacteristic(charList.get(0));
    }

    /**
     * Get the input Characteristic's instance ID.
     *
     * @param index the bluetooth gatt index
     * @param serviceIndex the service where the characteristic lives
     * @param characteristicIndex the characteristic index
     * @return true, if the write operation was successful
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public Integer gattClientGetCharacteristicInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        return charList.get(characteristicIndex).getInstanceId();
    }

    /**
     * Get the input Descriptor's instance ID.
     *
     * @param index the bluetooth gatt index
     * @param serviceIndex the service where the characteristic lives
     * @param characteristicIndex the characteristic index
     * @param descriptorIndex the descriptor index
     * @return true, if the write operation was successful
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public Integer gattClientGetDescriptorInstanceId(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
            @RpcParameter(name = "descriptorIndex") Integer descriptorIndex)
            throws Exception {
        BluetoothGatt bluetoothGatt = mBluetoothGattList.get(gattIndex);
        if (bluetoothGatt == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> gattServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (gattServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = gattServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex " + characteristicIndex);
        }
        BluetoothGattCharacteristic gattCharacteristic = charList.get(characteristicIndex);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristicIndex " + serviceIndex);
        }
        List<BluetoothGattDescriptor> descList = gattCharacteristic.getDescriptors();
        if (descList.get(descriptorIndex) == null) {
            throw new Exception("Invalid descriptorIndex " + descriptorIndex);
        }
        return descList.get(descriptorIndex).getInstanceId();
    }

    /**
     * Write the value to a discovered characteristic.
     *
     * @deprecated Use {@link #gattClientCharacteristicSetValueByIndex(
     *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, value)} instead.
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discovered service list index
     * @param serviceIndex - the service index of the discoveredServiceListIndex
     * @param characteristicUuid - the characteristic uuid in which the descriptor is
     * @param value - the value to set the characteristic to
     * @return true, if the value was set to the characteristic
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public boolean gattClientCharacteristicSetValue(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid,
            @RpcParameter(name = "value") byte[] value) throws Exception {
        if (mBluetoothGattList.get(gattIndex) == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        return gattCharacteristic.setValue(value);
    }

    /**
     * Write the value to a discovered characteristic.
     *
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discovered service list index
     * @param serviceIndex - the service index of the discoveredServiceListIndex
     * @param characteristicIndex - the characteristic index
     * @param value - the value to set the characteristic to
     * @return true, if the value was set to the characteristic
     * @throws Exception
     */
    @Rpc(description = "Write the value of a given characteristic to the associated remote device")
    public boolean gattClientCharacteristicSetValueByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
            @RpcParameter(name = "value") byte[] value)
            throws Exception {
        if (mBluetoothGattList.get(gattIndex) == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
        }
        return charList.get(characteristicIndex).setValue(value);
    }

    /**
     * Set write type to a discovered characteristic.
     *
     * @deprecated Use {@link #gattClientCharacteristicSetWriteTypeByIndex(
     *  gattIndex, discoveredServiceListIndex, serviceIndex, ccharacteristicUuid, writeType)}
     * instead.
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discovered service list index
     * @param serviceIndex - the service index of the discoveredServiceListIndex
     * @param characteristicUuid - the characteristic uuid in which the descriptor is
     * @param writeType - the write type for characteristic
     * @return true, if the value was set to the characteristic
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Set write type of a given characteristic to the associated remote device")
    public boolean gattClientCharacteristicSetWriteType(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid") String characteristicUuid,
            @RpcParameter(name = "writeType") Integer writeType) throws Exception {
        if (mBluetoothGattList.get(gattIndex) == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        UUID cUuid = UUID.fromString(characteristicUuid);
        BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(cUuid);
        if (gattCharacteristic == null) {
            throw new Exception("Invalid characteristic uuid: " + characteristicUuid);
        }
        gattCharacteristic.setWriteType(writeType);
        return true;
    }

    /**
     * Set write type to a discovered characteristic.
     *
     * @param gattIndex - the gatt index to use
     * @param discoveredServiceListIndex - the discovered service list index
     * @param serviceIndex - the service index of the discoveredServiceListIndex
     * @param characteristicIndex - the characteristic index
     * @param writeType - the write type for characteristic
     * @return true, if the value was set to the characteristic
     * @throws Exception
     */
    @Rpc(description = "Set write type of a given characteristic to the associated remote device")
    public void gattClientCharacteristicSetWriteTypeByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
            @RpcParameter(name = "writeType") Integer writeType)
            throws Exception {
        if (mBluetoothGattList.get(gattIndex) == null) {
            throw new Exception("Invalid gattIndex " + gattIndex);
        }
        List<BluetoothGattService> discoveredServiceList =
                mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
        if (discoveredServiceList == null) {
            throw new Exception("Invalid discoveredServiceListIndex " + discoveredServiceListIndex);
        }
        BluetoothGattService gattService = discoveredServiceList.get(serviceIndex);
        if (gattService == null) {
            throw new Exception("Invalid serviceIndex " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList = gattService.getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
        }
        charList.get(characteristicIndex).setWriteType(writeType);
    }

    /**
     * Read the RSSI for a connected remote device
     *
     * @param index the bluetooth gatt index
     * @return true, if the RSSI value has been requested successfully
     * @throws Exception
     */
    @Rpc(description = "Read the RSSI for a connected remote device")
    public boolean gattClientReadRSSI(
            @RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).readRemoteRssi();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Clears the internal cache and forces a refresh of the services from the remote device
     *
     * @param index the bluetooth gatt index
     * @return Clears the internal cache and forces a refresh of the services from the remote
     *         device.
     * @throws Exception
     */
    @Rpc(description = "Clears the internal cache and forces a refresh of the services from the "
            + "remote device")
    public boolean gattClientRefresh(@RpcParameter(name = "index") Integer index) throws Exception {
        if (mBluetoothGattList.get(index) != null) {
            return mBluetoothGattList.get(index).refresh();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Request a connection parameter update.
     *
     * @param index the bluetooth gatt index
     * @param connectionPriority connection priority
     * @return boolean True if successful False otherwise.
     * @throws Exception
     */
    @Rpc(description = "Request a connection parameter update. from the Bluetooth Gatt")
    public boolean gattClientRequestConnectionPriority(
            @RpcParameter(name = "index") Integer index,
            @RpcParameter(name = "connectionPriority") Integer connectionPriority)
            throws Exception {
        boolean result = false;
        if (mBluetoothGattList.get(index) != null) {
            result = mBluetoothGattList.get(index).requestConnectionPriority(connectionPriority);
        } else {
            throw new Exception("Invalid index input:" + index);
        }
        return result;
    }

    /**
     * Request a connection parameter update for Connection Interval.
     *
     * @param index the bluetooth gatt index
     * @param minConnectionInterval minimum connection interval
     * @param maxConnectionInterval maximum connection interval
     * @param peripheralLatency maximum peripheral latency
     * @param supervisionTimeout supervision timeout
     * @return boolean True if successful False otherwise.
     * @throws Exception
     */
    @Rpc(description = "Request an LE connection parameters update.")
    public boolean gattClientRequestLeConnectionParameters(
            @RpcParameter(name = "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)
            throws Exception {
        boolean result = false;
        if (mBluetoothGattList.get(index) != null) {
            result = mBluetoothGattList.get(index).requestLeConnectionUpdate(
                minConnectionInterval, maxConnectionInterval, peripheralLatency, supervisionTimeout,
                minConnectionEventLen, maxConnectionEventLen);
        } else {
            throw new Exception("Invalid index input:" + index);
        }
        return result;
    }

    /**
     * Sets the characteristic notification of a bluetooth gatt
     *
     * @deprecated Use {@link #gattClientSetCharacteristicNotificationByIndex(
     *  gattIndex, discoveredServiceListIndex, serviceIndex, characteristicIndex, enable)} instead.
     * @param index the bluetooth gatt index
     * @param characteristicIndex the characteristic index
     * @param enable Enable or disable notifications/indications for a given characteristic
     * @return true, if the requested notification status was set successfully
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Sets the characteristic notification of a bluetooth gatt")
    public boolean gattClientSetCharacteristicNotification(
            @RpcParameter(name = "gattIndex")
            Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex")
            Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex")
            Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid")
            String characteristicUuid,
            @RpcParameter(name = "enable")
            Boolean enable
            ) throws Exception {
        if (mBluetoothGattList.get(gattIndex) != null) {
            if(mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex) != null) {
                List<BluetoothGattService> discoveredServiceList =
                    mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
                if (discoveredServiceList.get(serviceIndex) != null) {
                    UUID cUuid = UUID.fromString(characteristicUuid);
                    if (discoveredServiceList.get(serviceIndex).getCharacteristic(cUuid) != null) {
                        return mBluetoothGattList.get(gattIndex).setCharacteristicNotification(
                                discoveredServiceList.get(serviceIndex).getCharacteristic(cUuid), enable);
                    } else {
                        throw new Exception ("Invalid characteristic uuid: " + characteristicUuid);
                    }
                } else {
                    throw new Exception ("Invalid serviceIndex " + serviceIndex);
                }
            } else {
                throw new Exception("Invalid discoveredServiceListIndex: " + discoveredServiceListIndex);
            }
        } else {
            throw new Exception("Invalid gattIndex input: " + gattIndex);
        }
    }

    /**
     * Sets the characteristic notification of a bluetooth gatt
     *
     * @param gattIndex the bluetooth gatt index
     * @param characteristicIndex the characteristic index
     * @param enable Enable or disable notifications/indications for a given characteristic
     * @return true, if the requested notification status was set successfully
     * @throws Exception
     */
    @Rpc(description = "Sets the characteristic notification of a bluetooth gatt")
    public boolean gattClientSetCharacteristicNotificationByIndex(
            @RpcParameter(name = "gattIndex") Integer gattIndex,
            @RpcParameter(name = "discoveredServiceListIndex") Integer discoveredServiceListIndex,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
            @RpcParameter(name = "enable") Boolean enable)
            throws Exception {
        if (mBluetoothGattList.get(gattIndex) != null) {
            if (mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex) != null) {
                List<BluetoothGattService> discoveredServiceList =
                        mBluetoothGattDiscoveredServicesList.get(discoveredServiceListIndex);
                if (discoveredServiceList.get(serviceIndex) != null) {
                    List<BluetoothGattCharacteristic> charList =
                            discoveredServiceList.get(serviceIndex).getCharacteristics();
                    if (charList.get(characteristicIndex) != null) {
                        return mBluetoothGattList
                                .get(gattIndex)
                                .setCharacteristicNotification(charList.get(characteristicIndex),
                                    enable);
                    } else {
                        throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
                    }
                } else {
                    throw new Exception("Invalid serviceIndex " + serviceIndex);
                }
            } else {
                throw new Exception(
                    "Invalid discoveredServiceListIndex: " + discoveredServiceListIndex);
            }
        } else {
            throw new Exception("Invalid gattIndex input: " + gattIndex);
        }
    }

    /**
     * Create a new GattCallback object
     *
     * @return the index of the callback object
     */
    @Rpc(description = "Create a new GattCallback object")
    public Integer gattCreateGattCallback() {
        GattCallbackCount += 1;
        int index = GattCallbackCount;
        mGattCallbackList.put(index, new myBluetoothGattCallback(index));
        return index;
    }

    /**
     * Returns the list of discovered Bluetooth Gatt Services.
     *
     * @throws Exception
     */
    @Rpc(description = "Get Bluetooth Gatt Services")
    public int gattClientGetDiscoveredServicesCount(@RpcParameter(name = "index") Integer index)
            throws Exception {
        if (mBluetoothGattDiscoveredServicesList.get(index) != null) {
            return mBluetoothGattDiscoveredServicesList.get(index).size();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Returns the discovered Bluetooth Gatt Service Uuid.
     *
     * @throws Exception
     */
    @Rpc(description = "Get Bluetooth Gatt Service Uuid")
    public String gattClientGetDiscoveredServiceUuid(
            @RpcParameter(name = "index") Integer index,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex)
            throws Exception {
        List<BluetoothGattService> mBluetoothServiceList =
                mBluetoothGattDiscoveredServicesList.get(index);
        if (mBluetoothServiceList != null) {
            return mBluetoothServiceList.get(serviceIndex).getUuid().toString();
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Get discovered characteristic uuids from the pheripheral device.
     *
     * @param index the index of the bluetooth gatt discovered services list
     * @param serviceIndex the service to get
     * @return the list of characteristic uuids
     * @throws Exception
     */
    @Rpc(description = "Get Bluetooth Gatt Services")
    public ArrayList<String> gattClientGetDiscoveredCharacteristicUuids(
            @RpcParameter(name = "index") Integer index,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex)
            throws Exception {
        if (mBluetoothGattDiscoveredServicesList.get(index) != null) {
            if (mBluetoothGattDiscoveredServicesList.get(index).get(serviceIndex) != null) {
                ArrayList<String> uuidList = new ArrayList<String>();
                List<BluetoothGattCharacteristic> charList =
                        mBluetoothGattDiscoveredServicesList.get(index).get(
                            serviceIndex).getCharacteristics();
                for (BluetoothGattCharacteristic mChar : charList) {
                    uuidList.add(mChar.getUuid().toString());
                }
                return uuidList;
            } else {
                throw new Exception("Invalid serviceIndex input:" + index);
            }
        } else {
            throw new Exception("Invalid index input:" + index);
        }
    }

    /**
     * Get discovered descriptor uuids from the pheripheral device.
     *
     * @deprecated Use {@link #gattClientGetDiscoveredDescriptorUuidsByIndex(
     *  index, serviceIndex, characteristicIndex)} instead.
     * @param index the discovered services list index
     * @param serviceIndex the service index of the discovered services list
     * @param characteristicUuid the characteristicUuid to select from the
     * discovered service which contains the list of descriptors.
     * @return the list of descriptor uuids
     * @throws Exception
     */
    @Deprecated
    @Rpc(description = "Get Bluetooth Gatt Services")
    public ArrayList<String> gattClientGetDiscoveredDescriptorUuids (
            @RpcParameter(name = "index")
            Integer index,
            @RpcParameter(name = "serviceIndex")
            Integer serviceIndex,
            @RpcParameter(name = "characteristicUuid")
            String characteristicUuid
            ) throws Exception {
        if (mBluetoothGattDiscoveredServicesList.get(index) != null) {
            if (mBluetoothGattDiscoveredServicesList.get(index).get(serviceIndex) != null) {
                BluetoothGattService service = mBluetoothGattDiscoveredServicesList.get(
                        index).get(serviceIndex);
                UUID cUuid = UUID.fromString(characteristicUuid);
                if (service.getCharacteristic(cUuid) != null) {
                    ArrayList<String> uuidList = new ArrayList<String>();
                    for (BluetoothGattDescriptor mDesc : service.getCharacteristic(
                            cUuid).getDescriptors()) {
                        uuidList.add(mDesc.getUuid().toString());
                    }
                    return uuidList;
                } else {
                    throw new Exception("Invalid characeristicUuid : "
                            + characteristicUuid);
                }
            } else {
                throw new Exception("Invalid serviceIndex input:"
                        + index);
            }
        } else {
            throw new Exception("Invalid index input:"
                    + index);
        }
    }

    /**
     * Get discovered descriptor uuids from the pheripheral device.
     *
     * @param index the discovered services list index
     * @param serviceIndex the service index of the discovered services list
     * @param characteristicIndex the characteristicIndex to select from the discovered service
     *       which contains the list of descriptors.
     * @return the list of descriptor uuids
     * @throws Exception
     */
    @Rpc(description = "Get Bluetooth Gatt Services")
    public ArrayList<String> gattClientGetDiscoveredDescriptorUuidsByIndex(
            @RpcParameter(name = "index") Integer index,
            @RpcParameter(name = "serviceIndex") Integer serviceIndex,
            @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
            throws Exception {
        if (mBluetoothGattDiscoveredServicesList.get(index) == null) {
            throw new Exception("Invalid index: " + index);
        }
        if (mBluetoothGattDiscoveredServicesList.get(index).get(serviceIndex) == null) {
            throw new Exception("Invalid serviceIndex: " + serviceIndex);
        }
        List<BluetoothGattCharacteristic> charList =
                mBluetoothGattDiscoveredServicesList.get(index).get(
                    serviceIndex).getCharacteristics();
        if (charList.get(characteristicIndex) == null) {
            throw new Exception("Invalid characteristicIndex: " + characteristicIndex);
        }
        List<BluetoothGattDescriptor> descList = charList.get(characteristicIndex).getDescriptors();
        ArrayList<String> uuidList = new ArrayList<String>();
        for (BluetoothGattDescriptor mDesc : descList) {
            uuidList.add(mDesc.getUuid().toString());
        }
        return uuidList;
    }

    private class myBluetoothGattCallback extends BluetoothGattCallback {
        private final Bundle mResults;
        private final int index;
        private final String mEventType;

        public myBluetoothGattCallback(int idx) {
            mResults = new Bundle();
            mEventType = "GattConnect";
            index = idx;
        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.d("gatt_connect change onConnectionStateChange " + mEventType + " " + index);
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.d(
                        "State Connected to mac address "
                                + gatt.getDevice().getAddress()
                                + " status "
                                + status);
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d(
                        "State Disconnected from mac address "
                                + gatt.getDevice().getAddress()
                                + " status "
                                + status);
            } else if (newState == BluetoothProfile.STATE_CONNECTING) {
                Log.d(
                        "State Connecting to mac address "
                                + gatt.getDevice().getAddress()
                                + " status "
                                + status);
            } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                Log.d(
                        "State Disconnecting from mac address "
                                + gatt.getDevice().getAddress()
                                + " status "
                                + status);
            }
            mResults.putInt("Status", status);
            mResults.putInt("State", newState);
            mEventFacade.postEvent(
                    mEventType + index + "onConnectionStateChange", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            Log.d("gatt_connect change onPhyRead " + mEventType + " " + index);
            mResults.putInt("TxPhy", txPhy);
            mResults.putInt("RxPhy", rxPhy);
            mResults.putInt("Status", status);
            mEventFacade.postEvent(mEventType + index + "onPhyRead", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
            Log.d("gatt_connect change onPhyUpdate " + mEventType + " " + index);
            mResults.putInt("TxPhy", txPhy);
            mResults.putInt("RxPhy", rxPhy);
            mResults.putInt("Status", status);
            mEventFacade.postEvent(mEventType + index + "onPhyUpdate", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.d("gatt_connect change onServicesDiscovered " + mEventType + " " + index);
            int idx = BluetoothGattDiscoveredServicesCount++;
            mBluetoothGattDiscoveredServicesList.put(idx, gatt.getServices());
            mResults.putInt("ServicesIndex", idx);
            mResults.putInt("Status", status);
            mEventFacade.postEvent(mEventType + index + "onServicesDiscovered", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onCharacteristicRead(
                BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.d("gatt_connect change onCharacteristicRead " + mEventType + " " + index);
            mResults.putInt("Status", status);
            mResults.putString("CharacteristicUuid", characteristic.getUuid().toString());
            mResults.putByteArray("CharacteristicValue", characteristic.getValue());
            mEventFacade.postEvent(mEventType + index + "onCharacteristicRead", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onCharacteristicWrite(
                BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.d("gatt_connect change onCharacteristicWrite " + mEventType + " " + index);
            mResults.putInt("Status", status);
            mResults.putString("CharacteristicUuid", characteristic.getUuid().toString());
            mResults.putByteArray("CharacteristicValue", characteristic.getValue());
            mEventFacade.postEvent(mEventType + index + "onCharacteristicWrite", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onCharacteristicChanged(
                BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            Log.d("gatt_connect change onCharacteristicChanged " + mEventType + " " + index);
            mResults.putInt("ID", index);
            mResults.putString("CharacteristicUuid", characteristic.getUuid().toString());
            mResults.putByteArray("CharacteristicValue", characteristic.getValue());
            mEventFacade.postEvent(
                    mEventType + index + "onCharacteristicChanged", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onDescriptorRead(
                BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            Log.d("gatt_connect change onServicesDiscovered " + mEventType + " " + index);
            mResults.putInt("Status", status);
            mResults.putString("DescriptorUuid", descriptor.getUuid().toString());
            mEventFacade.postEvent(mEventType + index + "onDescriptorRead", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onDescriptorWrite(
                BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            Log.d("gatt_connect change onDescriptorWrite " + mEventType + " " + index);
            mResults.putInt("ID", index);
            mResults.putInt("Status", status);
            mResults.putString("DescriptorUuid", descriptor.getUuid().toString());
            mEventFacade.postEvent(mEventType + index + "onDescriptorWrite", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            Log.d("gatt_connect change onReliableWriteCompleted " + mEventType + " " + index);
            mResults.putInt("Status", status);
            mEventFacade.postEvent(
                    mEventType + index + "onReliableWriteCompleted", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            Log.d("gatt_connect change onReadRemoteRssi " + mEventType + " " + index);
            mResults.putInt("Status", status);
            mResults.putInt("Rssi", rssi);
            mEventFacade.postEvent(mEventType + index + "onReadRemoteRssi", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            Log.d("gatt_connect change onMtuChanged " + mEventType + " " + index);
            mResults.putInt("Status", status);
            mResults.putInt("MTU", mtu);
            mEventFacade.postEvent(mEventType + index + "onMtuChanged", mResults.clone());
            mResults.clear();
        }

        public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency,
                                            int timeout, int status) {
            Log.d("gatt_connect change onConnectionUpdated " + mEventType + " " + index
                    + ", interval: " + interval + ", latency: " + latency
                    + ", timeout: " + timeout + ", status: " + status);

            mResults.putInt("Status", status);
            mResults.putInt("Interval", interval);
            mResults.putInt("Latency", latency);
            mResults.putInt("Timeout", timeout);
            mEventFacade.postEvent(mEventType + index + "onConnectionUpdated", mResults.clone());
            mResults.clear();
        }
    }

    @Override
    public void shutdown() {
        if (!mBluetoothGattList.isEmpty()) {
            if (mBluetoothGattList.values() != null) {
                for (BluetoothGatt mBluetoothGatt : mBluetoothGattList.values()) {
                    mBluetoothGatt.close();
                }
            }
        }
        mGattCallbackList.clear();
    }
}
