/*
 * Copyright (C) 2013 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 android.bluetooth;

import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Public API for the Bluetooth GATT Profile server role.
 *
 * <p>This class provides Bluetooth GATT server role functionality,
 * allowing applications to create Bluetooth Smart services and
 * characteristics.
 *
 * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
 * via IPC.  Use {@link BluetoothManager#openGattServer} to get an instance
 * of this class.
 */
public final class BluetoothGattServer implements BluetoothProfile {
    private static final String TAG = "BluetoothGattServer";
    private static final boolean DBG = true;
    private static final boolean VDBG = false;

    private BluetoothAdapter mAdapter;
    private IBluetoothGatt mService;
    private BluetoothGattServerCallback mCallback;

    private Object mServerIfLock = new Object();
    private int mServerIf;
    private int mTransport;
    private BluetoothGattService mPendingService;
    private List<BluetoothGattService> mServices;

    private static final int CALLBACK_REG_TIMEOUT = 10000;

    /**
     * Bluetooth GATT interface callbacks
     */
    private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
            new IBluetoothGattServerCallback.Stub() {
                /**
                 * Application interface registered - app is ready to go
                 * @hide
                 */
                @Override
                public void onServerRegistered(int status, int serverIf) {
                    if (DBG) {
                        Log.d(TAG, "onServerRegistered() - status=" + status
                                + " serverIf=" + serverIf);
                    }
                    synchronized (mServerIfLock) {
                        if (mCallback != null) {
                            mServerIf = serverIf;
                            mServerIfLock.notify();
                        } else {
                            // registration timeout
                            Log.e(TAG, "onServerRegistered: mCallback is null");
                        }
                    }
                }

                /**
                 * Server connection state changed
                 * @hide
                 */
                @Override
                public void onServerConnectionState(int status, int serverIf,
                        boolean connected, String address) {
                    if (DBG) {
                        Log.d(TAG, "onServerConnectionState() - status=" + status
                                + " serverIf=" + serverIf + " device=" + address);
                    }
                    try {
                        mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
                                connected ? BluetoothProfile.STATE_CONNECTED :
                                        BluetoothProfile.STATE_DISCONNECTED);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }
                }

                /**
                 * Service has been added
                 * @hide
                 */
                @Override
                public void onServiceAdded(int status, BluetoothGattService service) {
                    if (DBG) {
                        Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
                                + " uuid=" + service.getUuid() + " status=" + status);
                    }

                    if (mPendingService == null) {
                        return;
                    }

                    BluetoothGattService tmp = mPendingService;
                    mPendingService = null;

                    // Rewrite newly assigned handles to existing service.
                    tmp.setInstanceId(service.getInstanceId());
                    List<BluetoothGattCharacteristic> temp_chars = tmp.getCharacteristics();
                    List<BluetoothGattCharacteristic> svc_chars = service.getCharacteristics();
                    for (int i = 0; i < svc_chars.size(); i++) {
                        BluetoothGattCharacteristic temp_char = temp_chars.get(i);
                        BluetoothGattCharacteristic svc_char = svc_chars.get(i);

                        temp_char.setInstanceId(svc_char.getInstanceId());

                        List<BluetoothGattDescriptor> temp_descs = temp_char.getDescriptors();
                        List<BluetoothGattDescriptor> svc_descs = svc_char.getDescriptors();
                        for (int j = 0; j < svc_descs.size(); j++) {
                            temp_descs.get(j).setInstanceId(svc_descs.get(j).getInstanceId());
                        }
                    }

                    mServices.add(tmp);

                    try {
                        mCallback.onServiceAdded((int) status, tmp);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }
                }

                /**
                 * Remote client characteristic read request.
                 * @hide
                 */
                @Override
                public void onCharacteristicReadRequest(String address, int transId,
                        int offset, boolean isLong, int handle) {
                    if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
                    if (characteristic == null) {
                        Log.w(TAG, "onCharacteristicReadRequest() no char for handle " + handle);
                        return;
                    }

                    try {
                        mCallback.onCharacteristicReadRequest(device, transId, offset,
                                characteristic);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }
                }

                /**
                 * Remote client descriptor read request.
                 * @hide
                 */
                @Override
                public void onDescriptorReadRequest(String address, int transId,
                        int offset, boolean isLong, int handle) {
                    if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
                    if (descriptor == null) {
                        Log.w(TAG, "onDescriptorReadRequest() no desc for handle " + handle);
                        return;
                    }

                    try {
                        mCallback.onDescriptorReadRequest(device, transId, offset, descriptor);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }
                }

                /**
                 * Remote client characteristic write request.
                 * @hide
                 */
                @Override
                public void onCharacteristicWriteRequest(String address, int transId,
                        int offset, int length, boolean isPrep, boolean needRsp,
                        int handle, byte[] value) {
                    if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - handle=" + handle);

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    BluetoothGattCharacteristic characteristic = getCharacteristicByHandle(handle);
                    if (characteristic == null) {
                        Log.w(TAG, "onCharacteristicWriteRequest() no char for handle " + handle);
                        return;
                    }

                    try {
                        mCallback.onCharacteristicWriteRequest(device, transId, characteristic,
                                isPrep, needRsp, offset, value);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }

                }

                /**
                 * Remote client descriptor write request.
                 * @hide
                 */
                @Override
                public void onDescriptorWriteRequest(String address, int transId, int offset,
                        int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
                    if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    BluetoothGattDescriptor descriptor = getDescriptorByHandle(handle);
                    if (descriptor == null) {
                        Log.w(TAG, "onDescriptorWriteRequest() no desc for handle " + handle);
                        return;
                    }

                    try {
                        mCallback.onDescriptorWriteRequest(device, transId, descriptor,
                                isPrep, needRsp, offset, value);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }
                }

                /**
                 * Execute pending writes.
                 * @hide
                 */
                @Override
                public void onExecuteWrite(String address, int transId,
                        boolean execWrite) {
                    if (DBG) {
                        Log.d(TAG, "onExecuteWrite() - "
                                + "device=" + address + ", transId=" + transId
                                + "execWrite=" + execWrite);
                    }

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    if (device == null) return;

                    try {
                        mCallback.onExecuteWrite(device, transId, execWrite);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception in callback", ex);
                    }
                }

                /**
                 * A notification/indication has been sent.
                 * @hide
                 */
                @Override
                public void onNotificationSent(String address, int status) {
                    if (VDBG) {
                        Log.d(TAG, "onNotificationSent() - "
                                + "device=" + address + ", status=" + status);
                    }

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    if (device == null) return;

                    try {
                        mCallback.onNotificationSent(device, status);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception: " + ex);
                    }
                }

                /**
                 * The MTU for a connection has changed
                 * @hide
                 */
                @Override
                public void onMtuChanged(String address, int mtu) {
                    if (DBG) {
                        Log.d(TAG, "onMtuChanged() - "
                                + "device=" + address + ", mtu=" + mtu);
                    }

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    if (device == null) return;

                    try {
                        mCallback.onMtuChanged(device, mtu);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception: " + ex);
                    }
                }

                /**
                 * The PHY for a connection was updated
                 * @hide
                 */
                @Override
                public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
                    if (DBG) {
                        Log.d(TAG,
                                "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
                                        + ", rxPHy=" + rxPhy);
                    }

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    if (device == null) return;

                    try {
                        mCallback.onPhyUpdate(device, txPhy, rxPhy, status);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception: " + ex);
                    }
                }

                /**
                 * The PHY for a connection was read
                 * @hide
                 */
                @Override
                public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
                    if (DBG) {
                        Log.d(TAG,
                                "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
                                        + ", rxPHy=" + rxPhy);
                    }

                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    if (device == null) return;

                    try {
                        mCallback.onPhyRead(device, txPhy, rxPhy, status);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception: " + ex);
                    }
                }

                /**
                 * Callback invoked when the given connection is updated
                 * @hide
                 */
                @Override
                public void onConnectionUpdated(String address, int interval, int latency,
                        int timeout, int status) {
                    if (DBG) {
                        Log.d(TAG, "onConnectionUpdated() - Device=" + address
                                + " interval=" + interval + " latency=" + latency
                                + " timeout=" + timeout + " status=" + status);
                    }
                    BluetoothDevice device = mAdapter.getRemoteDevice(address);
                    if (device == null) return;

                    try {
                        mCallback.onConnectionUpdated(device, interval, latency,
                                timeout, status);
                    } catch (Exception ex) {
                        Log.w(TAG, "Unhandled exception: " + ex);
                    }
                }

            };

    /**
     * Create a BluetoothGattServer proxy object.
     */
    /*package*/ BluetoothGattServer(IBluetoothGatt iGatt, int transport) {
        mService = iGatt;
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mCallback = null;
        mServerIf = 0;
        mTransport = transport;
        mServices = new ArrayList<BluetoothGattService>();
    }

    /**
     * Returns a characteristic with given handle.
     *
     * @hide
     */
    /*package*/ BluetoothGattCharacteristic getCharacteristicByHandle(int handle) {
        for (BluetoothGattService svc : mServices) {
            for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
                if (charac.getInstanceId() == handle) {
                    return charac;
                }
            }
        }
        return null;
    }

    /**
     * Returns a descriptor with given handle.
     *
     * @hide
     */
    /*package*/ BluetoothGattDescriptor getDescriptorByHandle(int handle) {
        for (BluetoothGattService svc : mServices) {
            for (BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
                for (BluetoothGattDescriptor desc : charac.getDescriptors()) {
                    if (desc.getInstanceId() == handle) {
                        return desc;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Close this GATT server instance.
     *
     * Application should call this method as early as possible after it is done with
     * this GATT server.
     */
    public void close() {
        if (DBG) Log.d(TAG, "close()");
        unregisterCallback();
    }

    /**
     * Register an application callback to start using GattServer.
     *
     * <p>This is an asynchronous call. The callback is used to notify
     * success or failure if the function returns true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param callback GATT callback handler that will receive asynchronous callbacks.
     * @return true, the callback will be called to notify success or failure, false on immediate
     * error
     */
    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
        if (DBG) Log.d(TAG, "registerCallback()");
        if (mService == null) {
            Log.e(TAG, "GATT service not available");
            return false;
        }
        UUID uuid = UUID.randomUUID();
        if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);

        synchronized (mServerIfLock) {
            if (mCallback != null) {
                Log.e(TAG, "App can register callback only once");
                return false;
            }

            mCallback = callback;
            try {
                mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
            } catch (RemoteException e) {
                Log.e(TAG, "", e);
                mCallback = null;
                return false;
            }

            try {
                mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
            } catch (InterruptedException e) {
                Log.e(TAG, "" + e);
                mCallback = null;
            }

            if (mServerIf == 0) {
                mCallback = null;
                return false;
            } else {
                return true;
            }
        }
    }

    /**
     * Unregister the current application and callbacks.
     */
    private void unregisterCallback() {
        if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
        if (mService == null || mServerIf == 0) return;

        try {
            mCallback = null;
            mService.unregisterServer(mServerIf);
            mServerIf = 0;
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
    }

    /**
     * Returns a service by UUID, instance and type.
     *
     * @hide
     */
    /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) {
        for (BluetoothGattService svc : mServices) {
            if (svc.getType() == type
                    && svc.getInstanceId() == instanceId
                    && svc.getUuid().equals(uuid)) {
                return svc;
            }
        }
        return null;
    }

    /**
     * Initiate a connection to a Bluetooth GATT capable device.
     *
     * <p>The connection may not be established right away, but will be
     * completed when the remote device is available. A
     * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
     * invoked when the connection state changes as a result of this function.
     *
     * <p>The autoConnect paramter determines whether to actively connect to
     * the remote device, or rather passively scan and finalize the connection
     * when the remote device is in range/available. Generally, the first ever
     * connection to a device should be direct (autoConnect set to false) and
     * subsequent connections to known devices should be invoked with the
     * autoConnect parameter set to true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param autoConnect Whether to directly connect to the remote device (false) or to
     * automatically connect as soon as the remote device becomes available (true).
     * @return true, if the connection attempt was initiated successfully
     */
    public boolean connect(BluetoothDevice device, boolean autoConnect) {
        if (DBG) {
            Log.d(TAG,
                    "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
        }
        if (mService == null || mServerIf == 0) return false;

        try {
            // autoConnect is inverse of "isDirect"
            mService.serverConnect(mServerIf, device.getAddress(), !autoConnect, mTransport);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }

        return true;
    }

    /**
     * Disconnects an established connection, or cancels a connection attempt
     * currently in progress.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device Remote device
     */
    public void cancelConnection(BluetoothDevice device) {
        if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return;

        try {
            mService.serverDisconnect(mServerIf, device.getAddress());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
    }

    /**
     * Set the preferred connection PHY for this app. Please note that this is just a
     * recommendation, whether the PHY change will happen depends on other applications peferences,
     * local and remote controller capabilities. Controller can override these settings. <p> {@link
     * BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even if
     * no PHY change happens. It is also triggered when remote device updates the PHY.
     *
     * @param device The remote device to send this response to
     * @param txPhy preferred transmitter PHY. Bitwise OR of any of {@link
     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
     * BluetoothDevice#PHY_LE_CODED_MASK}.
     * @param rxPhy preferred receiver PHY. Bitwise OR of any of {@link
     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
     * BluetoothDevice#PHY_LE_CODED_MASK}.
     * @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
     * of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
     * {@link BluetoothDevice#PHY_OPTION_S8}
     */
    public void setPreferredPhy(BluetoothDevice device, int txPhy, int rxPhy, int phyOptions) {
        try {
            mService.serverSetPreferredPhy(mServerIf, device.getAddress(), txPhy, rxPhy,
                    phyOptions);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
    }

    /**
     * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
     * in {@link BluetoothGattServerCallback#onPhyRead}
     *
     * @param device The remote device to send this response to
     */
    public void readPhy(BluetoothDevice device) {
        try {
            mService.serverReadPhy(mServerIf, device.getAddress());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
    }

    /**
     * Send a response to a read or write request to a remote device.
     *
     * <p>This function must be invoked in when a remote read/write request
     * is received by one of these callback methods:
     *
     * <ul>
     * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
     * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
     * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
     * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
     * </ul>
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device The remote device to send this response to
     * @param requestId The ID of the request that was received with the callback
     * @param status The status of the request to be sent to the remote devices
     * @param offset Value offset for partial read/write response
     * @param value The value of the attribute that was read/written (optional)
     */
    public boolean sendResponse(BluetoothDevice device, int requestId,
            int status, int offset, byte[] value) {
        if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return false;

        try {
            mService.sendResponse(mServerIf, device.getAddress(), requestId,
                    status, offset, value);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }
        return true;
    }

    /**
     * Send a notification or indication that a local characteristic has been
     * updated.
     *
     * <p>A notification or indication is sent to the remote device to signal
     * that the characteristic has been updated. This function should be invoked
     * for every client that requests notifications/indications by writing
     * to the "Client Configuration" descriptor for the given characteristic.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device The remote device to receive the notification/indication
     * @param characteristic The local characteristic that has been updated
     * @param confirm true to request confirmation from the client (indication), false to send a
     * notification
     * @return true, if the notification has been triggered successfully
     * @throws IllegalArgumentException
     */
    public boolean notifyCharacteristicChanged(BluetoothDevice device,
            BluetoothGattCharacteristic characteristic, boolean confirm) {
        if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return false;

        BluetoothGattService service = characteristic.getService();
        if (service == null) return false;

        if (characteristic.getValue() == null) {
            throw new IllegalArgumentException("Chracteristic value is empty. Use "
                    + "BluetoothGattCharacteristic#setvalue to update");
        }

        try {
            mService.sendNotification(mServerIf, device.getAddress(),
                    characteristic.getInstanceId(), confirm,
                    characteristic.getValue());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }

        return true;
    }

    /**
     * Add a service to the list of services to be hosted.
     *
     * <p>Once a service has been addded to the the list, the service and its
     * included characteristics will be provided by the local device.
     *
     * <p>If the local device has already exposed services when this function
     * is called, a service update notification will be sent to all clients.
     *
     * <p>The {@link BluetoothGattServerCallback#onServiceAdded} callback will indicate
     * whether this service has been added successfully. Do not add another service
     * before this callback.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param service Service to be added to the list of services provided by this device.
     * @return true, if the request to add service has been initiated
     */
    public boolean addService(BluetoothGattService service) {
        if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
        if (mService == null || mServerIf == 0) return false;

        mPendingService = service;

        try {
            mService.addService(mServerIf, service);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }

        return true;
    }

    /**
     * Removes a service from the list of services to be provided.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param service Service to be removed.
     * @return true, if the service has been removed
     */
    public boolean removeService(BluetoothGattService service) {
        if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid());
        if (mService == null || mServerIf == 0) return false;

        BluetoothGattService intService = getService(service.getUuid(),
                service.getInstanceId(), service.getType());
        if (intService == null) return false;

        try {
            mService.removeService(mServerIf, service.getInstanceId());
            mServices.remove(intService);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
        }

        return true;
    }

    /**
     * Remove all services from the list of provided services.
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     */
    public void clearServices() {
        if (DBG) Log.d(TAG, "clearServices()");
        if (mService == null || mServerIf == 0) return;

        try {
            mService.clearServices(mServerIf);
            mServices.clear();
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
    }

    /**
     * Returns a list of GATT services offered by this device.
     *
     * <p>An application must call {@link #addService} to add a serice to the
     * list of services offered by this device.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @return List of services. Returns an empty list if no services have been added yet.
     */
    public List<BluetoothGattService> getServices() {
        return mServices;
    }

    /**
     * Returns a {@link BluetoothGattService} from the list of services offered
     * by this device.
     *
     * <p>If multiple instances of the same service (as identified by UUID)
     * exist, the first instance of the service is returned.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param uuid UUID of the requested service
     * @return BluetoothGattService if supported, or null if the requested service is not offered by
     * this device.
     */
    public BluetoothGattService getService(UUID uuid) {
        for (BluetoothGattService service : mServices) {
            if (service.getUuid().equals(uuid)) {
                return service;
            }
        }

        return null;
    }


    /**
     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
     * with {@link BluetoothProfile#GATT} as argument
     *
     * @throws UnsupportedOperationException
     */
    @Override
    public int getConnectionState(BluetoothDevice device) {
        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
    }

    /**
     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
     * with {@link BluetoothProfile#GATT} as argument
     *
     * @throws UnsupportedOperationException
     */
    @Override
    public List<BluetoothDevice> getConnectedDevices() {
        throw new UnsupportedOperationException(
                "Use BluetoothManager#getConnectedDevices instead.");
    }

    /**
     * Not supported - please use
     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
     * with {@link BluetoothProfile#GATT} as first argument
     *
     * @throws UnsupportedOperationException
     */
    @Override
    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        throw new UnsupportedOperationException(
                "Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
    }
}
