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.content.Context; 239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.ParcelUuid; 249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.os.RemoteException; 259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport android.util.Log; 269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.ArrayList; 289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.List; 299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battaimport java.util.UUID; 309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta/** 32ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Public API for the Bluetooth GATT Profile server role. 339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 34ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>This class provides Bluetooth GATT server role functionality, 35061cfd0049b1f44af9469a3e6db71b6cbc049413Andre Eisenbach * allowing applications to create Bluetooth Smart services and 36061cfd0049b1f44af9469a3e6db71b6cbc049413Andre Eisenbach * characteristics. 379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service 39061cfd0049b1f44af9469a3e6db71b6cbc049413Andre Eisenbach * via IPC. Use {@link BluetoothManager#openGattServer} to get an instance 40061cfd0049b1f44af9469a3e6db71b6cbc049413Andre Eisenbach * of this class. 419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Battapublic final class BluetoothGattServer implements BluetoothProfile { 439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private static final String TAG = "BluetoothGattServer"; 449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private static final boolean DBG = true; 4555d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach private static final boolean VDBG = false; 469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 47ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private final Context mContext; 489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private BluetoothAdapter mAdapter; 499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private IBluetoothGatt mService; 509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private BluetoothGattServerCallback mCallback; 519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 52ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private Object mServerIfLock = new Object(); 53ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private int mServerIf; 54b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta private int mTransport; 559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private List<BluetoothGattService> mServices; 569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 57ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private static final int CALLBACK_REG_TIMEOUT = 10000; 589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Bluetooth GATT interface callbacks 619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta private final IBluetoothGattServerCallback mBluetoothGattServerCallback = 639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta new IBluetoothGattServerCallback.Stub() { 649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Application interface registered - app is ready to go 669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onServerRegistered(int status, int serverIf) { 699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status 709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + " serverIf=" + serverIf); 71ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mServerIfLock) { 72ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mCallback != null) { 73ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mServerIf = serverIf; 74ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mServerIfLock.notify(); 75ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 76ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // registration timeout 77ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "onServerRegistered: mCallback is null"); 78ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Callback reporting an LE scan result. 849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onScanResult(String address, int rssi, byte[] advData) { 8755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi); 88ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie // no op 899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Server connection state changed 939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onServerConnectionState(int status, int serverIf, 969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta boolean connected, String address) { 979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status 989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + " serverIf=" + serverIf + " device=" + address); 999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status, 1019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta connected ? BluetoothProfile.STATE_CONNECTED : 1029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothProfile.STATE_DISCONNECTED); 1039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 1040998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 1059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Service has been added 1109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onServiceAdded(int status, int srvcType, 1139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int srvcInstId, ParcelUuid srvcId) { 1149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID srvcUuid = srvcId.getUuid(); 1159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onServiceAdded() - service=" + srvcUuid 1169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "status=" + status); 1179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 1199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return; 1209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onServiceAdded((int)status, service); 1239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 1240998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 1259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote client characteristic read request. 1309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onCharacteristicReadRequest(String address, int transId, 1339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int offset, boolean isLong, int srvcType, int srvcInstId, 1349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta ParcelUuid srvcId, int charInstId, ParcelUuid charId) { 1359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID srvcUuid = srvcId.getUuid(); 1369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID charUuid = charId.getUuid(); 13755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - " 1389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "service=" + srvcUuid + ", characteristic=" + charUuid); 1399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = mAdapter.getRemoteDevice(address); 1419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 1429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return; 1439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 144ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 1459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return; 1469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onCharacteristicReadRequest(device, transId, offset, characteristic); 1499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 1500998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 1519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote client descriptor read request. 1569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onDescriptorReadRequest(String address, int transId, 1599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int offset, boolean isLong, int srvcType, int srvcInstId, 1609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta ParcelUuid srvcId, int charInstId, ParcelUuid charId, 1619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta ParcelUuid descrId) { 1629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID srvcUuid = srvcId.getUuid(); 1639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID charUuid = charId.getUuid(); 1649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID descrUuid = descrId.getUuid(); 16555d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - " 1669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "service=" + srvcUuid + ", characteristic=" + charUuid 1679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "descriptor=" + descrUuid); 1689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = mAdapter.getRemoteDevice(address); 1709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 1719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return; 1729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 1749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return; 1759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid); 1779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (descriptor == null) return; 1789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 1809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onDescriptorReadRequest(device, transId, offset, descriptor); 1819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 1820998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 1839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 1859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 1879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote client characteristic write request. 1889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 1899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 1909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onCharacteristicWriteRequest(String address, int transId, 1919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int offset, int length, boolean isPrep, boolean needRsp, 1929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int srvcType, int srvcInstId, ParcelUuid srvcId, 1939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int charInstId, ParcelUuid charId, byte[] value) { 1949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID srvcUuid = srvcId.getUuid(); 1959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID charUuid = charId.getUuid(); 19655d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onCharacteristicWriteRequest() - " 1979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "service=" + srvcUuid + ", characteristic=" + charUuid); 1989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 1999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = mAdapter.getRemoteDevice(address); 2009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 2019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return; 2029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 2049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return; 2059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 2079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onCharacteristicWriteRequest(device, transId, characteristic, 2089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta isPrep, needRsp, offset, value); 2099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 2100998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 2119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 2129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 2149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 2169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Remote client descriptor write request. 2179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 2189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 2199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onDescriptorWriteRequest(String address, int transId, 2209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int offset, int length, boolean isPrep, boolean needRsp, 2219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int srvcType, int srvcInstId, ParcelUuid srvcId, 2229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int charInstId, ParcelUuid charId, ParcelUuid descrId, 2239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta byte[] value) { 2249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID srvcUuid = srvcId.getUuid(); 2259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID charUuid = charId.getUuid(); 2269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta UUID descrUuid = descrId.getUuid(); 22755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - " 2289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "service=" + srvcUuid + ", characteristic=" + charUuid 2299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "descriptor=" + descrUuid); 2309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = mAdapter.getRemoteDevice(address); 2329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType); 2349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return; 2359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid); 2379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (characteristic == null) return; 2389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattDescriptor descriptor = characteristic.getDescriptor(descrUuid); 2409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (descriptor == null) return; 2419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 2439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onDescriptorWriteRequest(device, transId, descriptor, 2449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta isPrep, needRsp, offset, value); 2459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 2460998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 2479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 2489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 2499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 2519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Execute pending writes. 2529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @hide 2539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 2549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void onExecuteWrite(String address, int transId, 2559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta boolean execWrite) { 2569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "onExecuteWrite() - " 2579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "device=" + address + ", transId=" + transId 2589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + "execWrite=" + execWrite); 2599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothDevice device = mAdapter.getRemoteDevice(address); 2619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (device == null) return; 2629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 2639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 2649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback.onExecuteWrite(device, transId, execWrite); 2659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (Exception ex) { 2660998ff13498ed004956d1de428eb0c4dcd33c1fbMike Lockwood Log.w(TAG, "Unhandled exception in callback", ex); 2679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 2689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 269dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach 270dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach /** 271dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach * A notification/indication has been sent. 272dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach * @hide 273dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach */ 274dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach public void onNotificationSent(String address, int status) { 27555d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "onNotificationSent() - " 276dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach + "device=" + address + ", status=" + status); 277dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach 278dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach BluetoothDevice device = mAdapter.getRemoteDevice(address); 279dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach if (device == null) return; 280dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach 281dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach try { 282dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach mCallback.onNotificationSent(device, status); 283dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach } catch (Exception ex) { 284dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach Log.w(TAG, "Unhandled exception: " + ex); 285dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach } 286dadefdad8ef424991feb45f02f923a2f8224285bAndre Eisenbach } 28716bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach 28816bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach /** 28916bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach * The MTU for a connection has changed 29016bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach * @hide 29116bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach */ 29216bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach public void onMtuChanged(String address, int mtu) { 29316bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach if (DBG) Log.d(TAG, "onMtuChanged() - " 29416bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach + "device=" + address + ", mtu=" + mtu); 29516bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach 29616bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach BluetoothDevice device = mAdapter.getRemoteDevice(address); 29716bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach if (device == null) return; 29816bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach 29916bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach try { 30016bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach mCallback.onMtuChanged(device, mtu); 30116bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach } catch (Exception ex) { 30216bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach Log.w(TAG, "Unhandled exception: " + ex); 30316bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach } 30416bf846990293e1f19f042eed8e2ce5e7348ac5aAndre Eisenbach } 3059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta }; 3069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 3089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Create a BluetoothGattServer proxy object. 3099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 310b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt, int transport) { 3119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mContext = context; 312ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService = iGatt; 3139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mAdapter = BluetoothAdapter.getDefaultAdapter(); 314ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mCallback = null; 315ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mServerIf = 0; 316b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta mTransport = transport; 3179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServices = new ArrayList<BluetoothGattService>(); 3189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 3213b64f38a167dd755977b01a339cb7724e05efbeaAndre Eisenbach * Close this GATT server instance. 322b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie * 323b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie * Application should call this method as early as possible after it is done with 324b30f91e38c19f6728d836293446d4b9c76705e7fMatthew Xie * this GATT server. 3259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 3263b64f38a167dd755977b01a339cb7724e05efbeaAndre Eisenbach public void close() { 3279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "close()"); 328ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie unregisterCallback(); 3299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 332ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Register an application callback to start using GattServer. 3339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 3349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This is an asynchronous call. The callback is used to notify 3359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * success or failure if the function returns true. 3369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 3379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 3389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 339ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @param callback GATT callback handler that will receive asynchronous 340ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * callbacks. 341ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @return true, the callback will be called to notify success or failure, 342ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * false on immediate error 3439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 344ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) { 345ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "registerCallback()"); 346ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mService == null) { 347ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "GATT service not available"); 3489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 3499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 350ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie UUID uuid = UUID.randomUUID(); 351ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid); 3529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 353ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie synchronized(mServerIfLock) { 354ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mCallback != null) { 355ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "App can register callback only once"); 356ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return false; 357ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 358ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 359ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mCallback = callback; 360ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie try { 361ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback); 362ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } catch (RemoteException e) { 363ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG,"",e); 364ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mCallback = null; 365ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return false; 366ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 367ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 368ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie try { 369ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mServerIfLock.wait(CALLBACK_REG_TIMEOUT); 370ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } catch (InterruptedException e) { 371ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie Log.e(TAG, "" + e); 372ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mCallback = null; 373ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 374ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 375ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (mServerIf == 0) { 376ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie mCallback = null; 377ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return false; 378ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } else { 379ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return true; 380ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 381ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie } 3829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 3859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Unregister the current application and callbacks. 3869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 387ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie private void unregisterCallback() { 388ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf); 3899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return; 3909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 3919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 3929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mCallback = null; 3939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.unregisterServer(mServerIf); 3949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServerIf = 0; 3959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 3969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 3979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 3999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 401ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Returns a service by UUID, instance and type. 402ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @hide 4039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 404ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie /*package*/ BluetoothGattService getService(UUID uuid, int instanceId, int type) { 405ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie for(BluetoothGattService svc : mServices) { 406ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie if (svc.getType() == type && 407ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie svc.getInstanceId() == instanceId && 408ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie svc.getUuid().equals(uuid)) { 409ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return svc; 4109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 412ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie return null; 4139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 416ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Initiate a connection to a Bluetooth GATT capable device. 4179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>The connection may not be established right away, but will be 4199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * completed when the remote device is available. A 4203f36660a60ce065b71f6d5eb24911012b6d66fddAndre Eisenbach * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be 4219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * invoked when the connection state changes as a result of this function. 4229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>The autoConnect paramter determines whether to actively connect to 4249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * the remote device, or rather passively scan and finalize the connection 4259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * when the remote device is in range/available. Generally, the first ever 4269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * connection to a device should be direct (autoConnect set to false) and 4279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * subsequent connections to known devices should be invoked with the 428ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * autoConnect parameter set to true. 4299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 4319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param autoConnect Whether to directly connect to the remote device (false) 4339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * or to automatically connect as soon as the remote 4349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * device becomes available (true). 4359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the connection attempt was initiated successfully 4369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 4379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean connect(BluetoothDevice device, boolean autoConnect) { 4383f36660a60ce065b71f6d5eb24911012b6d66fddAndre Eisenbach if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect); 4399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return false; 4409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 4429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.serverConnect(mServerIf, device.getAddress(), 443b88fa824ab6337684de9aa8437c4952df4f1a75eGanesh Ganapathi Batta autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect" 4449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 4459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 4469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 4479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 4509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 4539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Disconnects an established connection, or cancels a connection attempt 4549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * currently in progress. 4559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 4579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param device Remote device 4599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 4609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void cancelConnection(BluetoothDevice device) { 4619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "cancelConnection() - device: " + device.getAddress()); 4629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return; 4639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 4659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.serverDisconnect(mServerIf, device.getAddress()); 4669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 4679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 4689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 4709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 4729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Send a response to a read or write request to a remote device. 4739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>This function must be invoked in when a remote read/write request 475ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * is received by one of these callback methods: 4769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <ul> 4789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest} 4799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest} 4809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest} 4819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest} 4829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * </ul> 4839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 4859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 4869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param device The remote device to send this response to 4879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param requestId The ID of the request that was received with the callback 4889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param status The status of the request to be sent to the remote devices 4899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param offset Value offset for partial read/write response 4909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param value The value of the attribute that was read/written (optional) 4919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 4929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean sendResponse(BluetoothDevice device, int requestId, 4939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int status, int offset, byte[] value) { 49455d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "sendResponse() - device: " + device.getAddress()); 4959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return false; 4969908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 4979908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 4989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.sendResponse(mServerIf, device.getAddress(), requestId, 4999908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta status, offset, value); 5009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 5019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 5029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 5039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 5059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 5089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Send a notification or indication that a local characteristic has been 5099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * updated. 5109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 5119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>A notification or indication is sent to the remote device to signal 5129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * that the characteristic has been updated. This function should be invoked 5139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * for every client that requests notifications/indications by writing 5149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * to the "Client Configuration" descriptor for the given characteristic. 5159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 5169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 5179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 5189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param device The remote device to receive the notification/indication 5199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param characteristic The local characteristic that has been updated 5209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param confirm true to request confirmation from the client (indication), 5219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * false to send a notification 522ee3cc8bf177c03ea571a87a73d9ada83201afa63Prerepa Viswanadham * @throws IllegalArgumentException 5239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the notification has been triggered successfully 5249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 5259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean notifyCharacteristicChanged(BluetoothDevice device, 5269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattCharacteristic characteristic, boolean confirm) { 52755d19e495e2b3cd744724f2d12c399217e3c565cAndre Eisenbach if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress()); 5289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return false; 5299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService service = characteristic.getService(); 5319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service == null) return false; 5329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 533ee3cc8bf177c03ea571a87a73d9ada83201afa63Prerepa Viswanadham if (characteristic.getValue() == null) { 534ee3cc8bf177c03ea571a87a73d9ada83201afa63Prerepa Viswanadham throw new IllegalArgumentException("Chracteristic value is empty. Use " 535ee3cc8bf177c03ea571a87a73d9ada83201afa63Prerepa Viswanadham + "BluetoothGattCharacteristic#setvalue to update"); 536ee3cc8bf177c03ea571a87a73d9ada83201afa63Prerepa Viswanadham } 537ee3cc8bf177c03ea571a87a73d9ada83201afa63Prerepa Viswanadham 5389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 5399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.sendNotification(mServerIf, device.getAddress(), 5409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta service.getType(), service.getInstanceId(), 5419908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta new ParcelUuid(service.getUuid()), characteristic.getInstanceId(), 5429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta new ParcelUuid(characteristic.getUuid()), confirm, 5439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta characteristic.getValue()); 5449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 5459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 5469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 5479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 5509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 553ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Add a service to the list of services to be hosted. 5549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 555061cfd0049b1f44af9469a3e6db71b6cbc049413Andre Eisenbach * <p>Once a service has been addded to the the list, the service and its 556ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * included characteristics will be provided by the local device. 5579908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 558ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * <p>If the local device has already exposed services when this function 5599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * is called, a service update notification will be sent to all clients. 5609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 5619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 5629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 563ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @param service Service to be added to the list of services provided 5649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * by this device. 5659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the service has been added successfully 5669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 5679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean addService(BluetoothGattService service) { 5689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid()); 5699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return false; 5709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServices.add(service); 5729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 5749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.beginServiceDeclaration(mServerIf, service.getType(), 5759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta service.getInstanceId(), service.getHandles(), 57618c76934f62410d1499e2eb63635b5dd8da5013aWei Wang new ParcelUuid(service.getUuid()), service.isAdvertisePreferred()); 5779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta List<BluetoothGattService> includedServices = service.getIncludedServices(); 5799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for (BluetoothGattService includedService : includedServices) { 5809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.addIncludedService(mServerIf, 5819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta includedService.getType(), 5829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta includedService.getInstanceId(), 5839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta new ParcelUuid(includedService.getUuid())); 5849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 5859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics(); 5879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for (BluetoothGattCharacteristic characteristic : characteristics) { 5889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta int permission = ((characteristic.getKeySize() - 7) << 12) 5899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta + characteristic.getPermissions(); 5909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.addCharacteristic(mServerIf, 5919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta new ParcelUuid(characteristic.getUuid()), 5929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta characteristic.getProperties(), permission); 5939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 5949908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors(); 5959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for (BluetoothGattDescriptor descriptor: descriptors) { 5966f0ed128e46d723c82a2be1d5a45beaf302a2cb1Andre Eisenbach permission = ((characteristic.getKeySize() - 7) << 12) 5976f0ed128e46d723c82a2be1d5a45beaf302a2cb1Andre Eisenbach + descriptor.getPermissions(); 5989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.addDescriptor(mServerIf, 5996f0ed128e46d723c82a2be1d5a45beaf302a2cb1Andre Eisenbach new ParcelUuid(descriptor.getUuid()), permission); 6009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6039908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.endServiceDeclaration(mServerIf); 6049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 6059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 6069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 6079908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6089908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 6109908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 613ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Removes a service from the list of services to be provided. 6149908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6159908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 6169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 617ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @param service Service to be removed. 6189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return true, if the service has been removed 6199908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 6209908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public boolean removeService(BluetoothGattService service) { 6219908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "removeService() - service: " + service.getUuid()); 6229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return false; 6239908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta BluetoothGattService intService = getService(service.getUuid(), 6259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta service.getInstanceId(), service.getType()); 6269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (intService == null) return false; 6279908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6289908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 6299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.removeService(mServerIf, service.getType(), 6309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta service.getInstanceId(), new ParcelUuid(service.getUuid())); 6319908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServices.remove(intService); 6329908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 6339908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 6349908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return false; 6359908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6369908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6379908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return true; 6389908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6399908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6409908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 641ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Remove all services from the list of provided services. 6429908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 6439908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 6449908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public void clearServices() { 6459908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (DBG) Log.d(TAG, "clearServices()"); 6469908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (mService == null || mServerIf == 0) return; 6479908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6489908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta try { 6499908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mService.clearServices(mServerIf); 6509908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta mServices.clear(); 6519908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } catch (RemoteException e) { 6529908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta Log.e(TAG,"",e); 6539908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6549908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6559908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6569908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 657ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Returns a list of GATT services offered by this device. 6589908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6599908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>An application must call {@link #addService} to add a serice to the 6609908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * list of services offered by this device. 6619908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6629908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 6639908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6649908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return List of services. Returns an empty list 6659908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * if no services have been added yet. 6669908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 6679908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public List<BluetoothGattService> getServices() { 6689908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return mServices; 6699908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6709908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6719908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 6729908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * Returns a {@link BluetoothGattService} from the list of services offered 6739908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * by this device. 6749908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6759908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>If multiple instances of the same service (as identified by UUID) 6769908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * exist, the first instance of the service is returned. 6779908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6789908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. 6799908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 6809908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @param uuid UUID of the requested service 6819908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * @return BluetoothGattService if supported, or null if the requested 6829908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * service is not offered by this device. 6839908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 6849908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public BluetoothGattService getService(UUID uuid) { 6859908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta for (BluetoothGattService service : mServices) { 6869908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta if (service.getUuid().equals(uuid)) { 6879908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return service; 6889908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6899908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6909908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 6919908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta return null; 6929908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 6939908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 694ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie 6959908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 696ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} 697ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * with {@link BluetoothProfile#GATT} as argument 6989908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 699ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @throws UnsupportedOperationException 7009908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 7019908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta @Override 7029908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public int getConnectionState(BluetoothDevice device) { 703ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead."); 7049908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7059908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7069908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 707ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} 708ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * with {@link BluetoothProfile#GATT} as argument 7099908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 710ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @throws UnsupportedOperationException 7119908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 7129908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta @Override 7139908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public List<BluetoothDevice> getConnectedDevices() { 714ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new UnsupportedOperationException 715ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie ("Use BluetoothManager#getConnectedDevices instead."); 7169908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7179908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta 7189908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta /** 719ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * Not supported - please use 720ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])} 721ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * with {@link BluetoothProfile#GATT} as first argument 7229908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta * 723ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie * @throws UnsupportedOperationException 7249908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta */ 7259908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta @Override 7269908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 727ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie throw new UnsupportedOperationException 728ddf7e4756c31d0ed90802f98abeaa79df6d16b2aMatthew Xie ("Use BluetoothManager#getDevicesMatchingConnectionStates instead."); 7299908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta } 7309908112fd085d8b0d91e0562d32eebd1884f09a5Ganesh Ganapathi Batta} 731