BluetoothGattServer.java revision ddf7e4756c31d0ed90802f98abeaa79df6d16b2a
19908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/*
29908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Copyright (C) 2013 The Android Open Source Project
39908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
49908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Licensed under the Apache License, Version 2.0 (the "License");
59908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * you may not use this file except in compliance with the License.
69908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * You may obtain a copy of the License at
79908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
89908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *      http://www.apache.org/licenses/LICENSE-2.0
99908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unless required by applicable law or agreed to in writing, software
119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * distributed under the License is distributed on an "AS IS" BASIS,
129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * See the License for the specific language governing permissions and
149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * limitations under the License.
159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapackage android.bluetooth;
189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothAdapter;
209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothDevice;
219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothProfile;
229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.BluetoothProfile.ServiceListener;
239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.IBluetoothManager;
249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.bluetooth.IBluetoothStateChangeCallback;
259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.ComponentName;
279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Context;
289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.Intent;
299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.content.ServiceConnection;
309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.IBinder;
319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid;
329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException;
339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ServiceManager;
349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log;
359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList;
379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List;
389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID;
399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/**
41ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile server role.
429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
43ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT server role functionality,
449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * allowing applications to create and advertise Bluetooth Smart services
459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * and characteristics.
469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta *
479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * via IPC.  Use {@link BluetoothAdapter#getProfileProxy} to get the
499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * BluetoothGatt proxy object.
509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */
519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGattServer implements BluetoothProfile {
529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final String TAG = "BluetoothGattServer";
539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private static final boolean DBG = true;
549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
55ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private final Context mContext;
569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private BluetoothAdapter mAdapter;
579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private IBluetoothGatt mService;
589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private BluetoothGattServerCallback mCallback;
599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
60ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private Object mServerIfLock = new Object();
61ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private int mServerIf;
629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private List<BluetoothGattService> mServices;
639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
64ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private static final int CALLBACK_REG_TIMEOUT = 10000;
659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Bluetooth GATT interface callbacks
689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        new IBluetoothGattServerCallback.Stub() {
719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Application interface registered - app is ready to go
739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onServerRegistered(int status, int serverIf) {
769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status
779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " serverIf=" + serverIf);
78ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                synchronized(mServerIfLock) {
79ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    if (mCallback != null) {
80ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mServerIf = serverIf;
81ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        mServerIfLock.notify();
82ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    } else {
83ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        // registration timeout
84ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                        Log.e(TAG, "onServerRegistered: mCallback is null");
85ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                    }
869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Callback reporting an LE scan result.
919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onScanResult(String address, int rssi, byte[] advData) {
949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
95ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                // no op
969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Server connection state changed
1009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onServerConnectionState(int status, int serverIf,
1039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                boolean connected, String address) {
1049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status
1059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + " serverIf=" + serverIf + " device=" + address);
1069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
1079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
1089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                      connected ? BluetoothProfile.STATE_CONNECTED :
1099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                      BluetoothProfile.STATE_DISCONNECTED);
1109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
1129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Service has been added
1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onServiceAdded(int status, int srvcType,
1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                       int srvcInstId, ParcelUuid srvcId) {
1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID srvcUuid = srvcId.getUuid();
1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onServiceAdded() - service=" + srvcUuid
1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "status=" + status);
1249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onServiceAdded((int)status, service);
1309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
1329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote client characteristic read request.
1379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicReadRequest(String address, int transId,
1409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int offset, boolean isLong, int srvcType, int srvcInstId,
1419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            ParcelUuid srvcId, int charInstId, ParcelUuid charId) {
1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID srvcUuid = srvcId.getUuid();
1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID charUuid = charId.getUuid();
1449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicReadRequest() - "
1459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "service=" + srvcUuid + ", characteristic=" + charUuid);
1469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothDevice device = mAdapter.getRemoteDevice(address);
1489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
1499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
1509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
151ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
1529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
1539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
1559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onCharacteristicReadRequest(device, transId, offset, characteristic);
1569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
1589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote client descriptor read request.
1639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorReadRequest(String address, int transId,
1669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int offset, boolean isLong, int srvcType, int srvcInstId,
1679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            ParcelUuid srvcId, int charInstId, ParcelUuid charId,
1689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            ParcelUuid descrId) {
1699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID srvcUuid = srvcId.getUuid();
1709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID charUuid = charId.getUuid();
1719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID descrUuid = descrId.getUuid();
1729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicReadRequest() - "
1739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "service=" + srvcUuid + ", characteristic=" + charUuid
1749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "descriptor=" + descrUuid);
1759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothDevice device = mAdapter.getRemoteDevice(address);
1779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
1789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
1799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
1829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid);
1849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
1859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
1879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onDescriptorReadRequest(device, transId, offset, descriptor);
1889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
1899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
1909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
1919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
1929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
1939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
1949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote client characteristic write request.
1959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
1969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
1979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onCharacteristicWriteRequest(String address, int transId,
1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int offset, int length, boolean isPrep, boolean needRsp,
1999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int srvcType, int srvcInstId, ParcelUuid srvcId,
2009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int charInstId, ParcelUuid charId, byte[] value) {
2019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID srvcUuid = srvcId.getUuid();
2029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID charUuid = charId.getUuid();
2039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onCharacteristicWriteRequest() - "
2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "service=" + srvcUuid + ", characteristic=" + charUuid);
2059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothDevice device = mAdapter.getRemoteDevice(address);
2079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
2089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
2119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
2149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onCharacteristicWriteRequest(device, transId, characteristic,
2159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                           isPrep, needRsp, offset, value);
2169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
2179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
2189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Remote client descriptor write request.
2249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onDescriptorWriteRequest(String address, int transId,
2279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int offset, int length, boolean isPrep, boolean needRsp,
2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int srvcType, int srvcInstId, ParcelUuid srvcId,
2299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            int charInstId, ParcelUuid charId, ParcelUuid descrId,
2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                            byte[] value) {
2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID srvcUuid = srvcId.getUuid();
2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID charUuid = charId.getUuid();
2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                UUID descrUuid = descrId.getUuid();
2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onDescriptorWriteRequest() - "
2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "service=" + srvcUuid + ", characteristic=" + charUuid
2369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "descriptor=" + descrUuid);
2379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothDevice device = mAdapter.getRemoteDevice(address);
2399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
2419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (service == null) return;
2429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
2449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (characteristic == null) return;
2459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid);
2479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (descriptor == null) return;
2489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
2509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onDescriptorWriteRequest(device, transId, descriptor,
2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                                       isPrep, needRsp, offset, value);
2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            /**
2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * Execute pending writes.
2599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             * @hide
2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta             */
2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            public void onExecuteWrite(String address, int transId,
2629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                       boolean execWrite) {
2639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (DBG) Log.d(TAG, "onExecuteWrite() - "
2649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "device=" + address + ", transId=" + transId
2659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    + "execWrite=" + execWrite);
2669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                BluetoothDevice device = mAdapter.getRemoteDevice(address);
2689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                if (device == null) return;
2699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                try {
2719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mCallback.onExecuteWrite(device, transId, execWrite);
2729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                } catch (Exception ex) {
2739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    Log.w(TAG, "Unhandled exception: " + ex);
2749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
2759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
2769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        };
2779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
2799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Create a BluetoothGattServer proxy object.
2809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
281ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt) {
2829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mContext = context;
283ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mService = iGatt;
2849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mAdapter = BluetoothAdapter.getDefaultAdapter();
285ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mCallback = null;
286ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        mServerIf = 0;
2879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices = new ArrayList<BluetoothGattService>();
2889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
2899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
2919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Close the connection to the gatt service.
2929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
2939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /*package*/ void close() {
2949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "close()");
295ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        unregisterCallback();
2969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
2979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
2989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
299ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Register an application callback to start using GattServer.
3009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
3019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This is an asynchronous call. The callback is used to notify
3029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * success or failure if the function returns true.
3039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
3049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
306ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param callback GATT callback handler that will receive asynchronous
307ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *                 callbacks.
308ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @return true, the callback will be called to notify success or failure,
309ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     *         false on immediate error
3109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
311ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
312ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "registerCallback()");
313ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (mService == null) {
314ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            Log.e(TAG, "GATT service not available");
3159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
3169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
317ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        UUID uuid = UUID.randomUUID();
318ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
3199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
320ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        synchronized(mServerIfLock) {
321ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mCallback != null) {
322ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                Log.e(TAG, "App can register callback only once");
323ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return false;
324ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
325ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
326ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            mCallback = callback;
327ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            try {
328ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
329ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            } catch (RemoteException e) {
330ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                Log.e(TAG,"",e);
331ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mCallback = null;
332ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return false;
333ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
334ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
335ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            try {
336ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
337ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            } catch (InterruptedException e) {
338ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                Log.e(TAG, "" + e);
339ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mCallback = null;
340ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
341ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
342ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (mServerIf == 0) {
343ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                mCallback = null;
344ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return false;
345ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            } else {
346ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return true;
347ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            }
348ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        }
3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
3509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Unregister the current application and callbacks.
3539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
354ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    private void unregisterCallback() {
355ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
3569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return;
3579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
3599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mCallback = null;
3609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.unregisterServer(mServerIf);
3619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mServerIf = 0;
3629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
3639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
3649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
3659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
3669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
368ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Returns a service by UUID, instance and type.
369ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @hide
3709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
371ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie    /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) {
372ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        for(BluetoothGattService svc : mServices) {
373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            if (svc.getType() == type &&
374ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                svc.getInstanceId() == instanceId &&
375ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                svc.getUuid().equals(uuid)) {
376ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie                return svc;
3779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
3789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
379ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        return null;
3809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
3819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
383ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Initiate a connection to a Bluetooth GATT capable device.
3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The connection may not be established right away, but will be
3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * completed when the remote device is available. A
3873f36660a60ce065b71f6d5eb24911012b6d66fddAndre Eisenbach     * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
3889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * invoked when the connection state changes as a result of this function.
3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
3909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>The autoConnect paramter determines whether to actively connect to
3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * the remote device, or rather passively scan and finalize the connection
3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * when the remote device is in range/available. Generally, the first ever
3939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * connection to a device should be direct (autoConnect set to false) and
3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * subsequent connections to known devices should be invoked with the
395ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * autoConnect parameter set to true.
3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param autoConnect Whether to directly connect to the remote device (false)
4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    or to automatically connect as soon as the remote
4019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                    device becomes available (true).
4029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the connection attempt was initiated successfully
4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
4049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean connect(BluetoothDevice device, boolean autoConnect) {
4053f36660a60ce065b71f6d5eb24911012b6d66fddAndre Eisenbach        if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
4069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return false;
4079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
4099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.serverConnect(mServerIf, device.getAddress(),
4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                               autoConnect ? false : true); // autoConnect is inverse of "isDirect"
4119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
4129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
4189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
4209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Disconnects an established connection, or cancels a connection attempt
4219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * currently in progress.
4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
4249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device Remote device
4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public void cancelConnection(BluetoothDevice device) {
4289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress());
4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return;
4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
4329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.serverDisconnect(mServerIf, device.getAddress());
4339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
4349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
4359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
4369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
4379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
4399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Send a response to a read or write request to a remote device.
4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>This function must be invoked in when a remote read/write request
442ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * is received by one of these callback methods:
4439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <ul>
4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *      <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *      <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
4479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *      <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
4489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *      <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
4499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * </ul>
4509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
4529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device The remote device to send this response to
4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param requestId The ID of the request that was received with the callback
4559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param status The status of the request to be sent to the remote devices
4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param offset Value offset for partial read/write response
4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param value The value of the attribute that was read/written (optional)
4589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean sendResponse(BluetoothDevice device, int requestId,
4609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                int status, int offset, byte[] value) {
4619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress());
4629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return false;
4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
4659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.sendResponse(mServerIf, device.getAddress(), requestId,
4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                  status, offset, value);
4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
4699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
4709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
4719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
4759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Send a notification or indication that a local characteristic has been
4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * updated.
4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>A notification or indication is sent to the remote device to signal
4799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * that the characteristic has been updated. This function should be invoked
4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * for every client that requests notifications/indications by writing
4819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * to the "Client Configuration" descriptor for the given characteristic.
4829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
4849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
4859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param device The remote device to receive the notification/indication
4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param characteristic The local characteristic that has been updated
4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param confirm true to request confirmation from the client (indication),
4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                false to send a notification
4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the notification has been triggered successfully
4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean notifyCharacteristicChanged(BluetoothDevice device,
4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    BluetoothGattCharacteristic characteristic, boolean confirm) {
4939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
4949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return false;
4959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService service = characteristic.getService();
4979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (service == null) return false;
4989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.sendNotification(mServerIf, device.getAddress(),
5019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    service.getType(), service.getInstanceId(),
5029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
5039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    new ParcelUuid(characteristic.getUuid()), confirm,
5049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    characteristic.getValue());
5059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
5079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
5089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
5129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
514ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Add a service to the list of services to be hosted.
5159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
5169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Once a service has been addded to the the list, the service and it's
517ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * included characteristics will be provided by the local device.
5189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
519ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * <p>If the local device has already exposed services when this function
5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * is called, a service update notification will be sent to all clients.
5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
5229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
5239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
524ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param service Service to be added to the list of services provided
5259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *                by this device.
5269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the service has been added successfully
5279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
5289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean addService(BluetoothGattService service) {
5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
5309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return false;
5319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        mServices.add(service);
5339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
5359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.beginServiceDeclaration(mServerIf, service.getType(),
5369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getInstanceId(), service.getHandles(),
5379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                new ParcelUuid(service.getUuid()));
5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            List<BluetoothGattService> includedServices = service.getIncludedServices();
5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            for (BluetoothGattService includedService : includedServices) {
5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mService.addIncludedService(mServerIf,
5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    includedService.getType(),
5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    includedService.getInstanceId(),
5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    new ParcelUuid(includedService.getUuid()));
5459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
5489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            for (BluetoothGattCharacteristic characteristic : characteristics) {
5499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                int permission = ((characteristic.getKeySize() - 7) << 12)
5509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                    + characteristic.getPermissions();
5519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                mService.addCharacteristic(mServerIf,
5529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    new ParcelUuid(characteristic.getUuid()),
5539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    characteristic.getProperties(), permission);
5549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors();
5569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                for (BluetoothGattDescriptor descriptor: descriptors) {
5579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                    mService.addDescriptor(mServerIf,
5589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        new ParcelUuid(descriptor.getUuid()),
5599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                        descriptor.getPermissions());
5609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                }
5619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
5629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.endServiceDeclaration(mServerIf);
5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
5659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
5669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
5679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
5689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
5709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
5719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
573ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Removes a service from the list of services to be provided.
5749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
5759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
5769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
577ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @param service Service to be removed.
5789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return true, if the service has been removed
5799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public boolean removeService(BluetoothGattService service) {
5819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid());
5829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return false;
5839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        BluetoothGattService intService = getService(service.getUuid(),
5859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                                service.getInstanceId(), service.getType());
5869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (intService == null) return false;
5879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
5899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.removeService(mServerIf, service.getType(),
5909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                service.getInstanceId(), new ParcelUuid(service.getUuid()));
5919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mServices.remove(intService);
5929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
5939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
5949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            return false;
5959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
5969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
5979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return true;
5989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
5999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
601ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Remove all services from the list of provided services.
6029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public void clearServices() {
6059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (DBG) Log.d(TAG, "clearServices()");
6069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        if (mService == null || mServerIf == 0) return;
6079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        try {
6099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mService.clearServices(mServerIf);
6109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            mServices.clear();
6119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        } catch (RemoteException e) {
6129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            Log.e(TAG,"",e);
6139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
617ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Returns a list of GATT services offered by this device.
6189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>An application must call {@link #addService} to add a serice to the
6209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * list of services offered by this device.
6219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return List of services. Returns an empty list
6259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         if no services have been added yet.
6269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothGattService> getServices() {
6289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return mServices;
6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
6329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * Returns a {@link BluetoothGattService} from the list of services offered
6339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * by this device.
6349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>If multiple instances of the same service (as identified by UUID)
6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * exist, the first instance of the service is returned.
6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
6399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @param uuid UUID of the requested service
6419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     * @return BluetoothGattService if supported, or null if the requested
6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *         service is not offered by this device.
6439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public BluetoothGattService getService(UUID uuid) {
6459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        for (BluetoothGattService service : mServices) {
6469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            if (service.getUuid().equals(uuid)) {
6479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta                return service;
6489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta            }
6499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        }
6509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta        return null;
6529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
654ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie
6559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
656ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
657ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
6589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
659ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public int getConnectionState(BluetoothDevice device) {
663ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
667ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
668ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as argument
6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
670ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getConnectedDevices() {
674ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
675ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getConnectedDevices instead.");
6769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta
6789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    /**
679ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * Not supported - please use
680ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
681ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * with {@link BluetoothProfile#GATT} as first argument
6829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     *
683ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie     * @throws UnsupportedOperationException
6849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta     */
6859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    @Override
6869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
687ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie        throw new UnsupportedOperationException
688ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie            ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta    }
6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta}
691