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