1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.bluetooth.gatt; 18 19 import android.app.Service; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.BluetoothDevice; 22 import android.bluetooth.BluetoothProfile; 23 import android.bluetooth.IBluetoothGatt; 24 import android.bluetooth.IBluetoothGattCallback; 25 import android.bluetooth.IBluetoothGattServerCallback; 26 import android.content.Intent; 27 import android.os.IBinder; 28 import android.os.IBinder.DeathRecipient; 29 import android.os.ParcelUuid; 30 import android.os.RemoteException; 31 import android.util.Log; 32 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.HashSet; 36 import java.util.Iterator; 37 import java.util.List; 38 import java.util.Map; 39 import java.util.Set; 40 import java.util.UUID; 41 42 import com.android.bluetooth.btservice.ProfileService; 43 import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder; 44 45 /** 46 * Provides Bluetooth Gatt profile, as a service in 47 * the Bluetooth application. 48 * @hide 49 */ 50 public class GattService extends ProfileService { 51 private static final boolean DBG = GattServiceConfig.DBG; 52 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 53 BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); 54 55 /** 56 * Search queue to serialize remote onbject inspection. 57 */ 58 SearchQueue mSearchQueue = new SearchQueue(); 59 60 /** 61 * List of our registered clients. 62 */ 63 64 class ClientMap extends ContextMap<IBluetoothGattCallback> {} 65 ClientMap mClientMap = new ClientMap(); 66 67 /** 68 * List of our registered server apps. 69 */ 70 class ServerMap extends ContextMap<IBluetoothGattServerCallback> {} 71 ServerMap mServerMap = new ServerMap(); 72 73 /** 74 * Server handle map. 75 */ 76 HandleMap mHandleMap = new HandleMap(); 77 78 /** 79 * Pending service declaration queue 80 */ 81 private List<ServiceDeclaration> mServiceDeclarations = new ArrayList<ServiceDeclaration>(); 82 83 private ServiceDeclaration addDeclaration() { 84 synchronized (mServiceDeclarations) { 85 mServiceDeclarations.add(new ServiceDeclaration()); 86 } 87 return getActiveDeclaration(); 88 } 89 90 private ServiceDeclaration getActiveDeclaration() { 91 synchronized (mServiceDeclarations) { 92 if (mServiceDeclarations.size() > 0) 93 return mServiceDeclarations.get(mServiceDeclarations.size() - 1); 94 } 95 return null; 96 } 97 98 private ServiceDeclaration getPendingDeclaration() { 99 synchronized (mServiceDeclarations) { 100 if (mServiceDeclarations.size() > 0) 101 return mServiceDeclarations.get(0); 102 } 103 return null; 104 } 105 106 private void removePendingDeclaration() { 107 synchronized (mServiceDeclarations) { 108 if (mServiceDeclarations.size() > 0) 109 mServiceDeclarations.remove(0); 110 } 111 } 112 113 /** 114 * List of clients intereste in scan results. 115 */ 116 private List<ScanClient> mScanQueue = new ArrayList<ScanClient>(); 117 118 private ScanClient getScanClient(int appIf, boolean isServer) { 119 for(ScanClient client : mScanQueue) { 120 if (client.appIf == appIf && client.isServer == isServer) { 121 return client; 122 } 123 } 124 return null; 125 } 126 127 private void removeScanClient(int appIf, boolean isServer) { 128 for(ScanClient client : mScanQueue) { 129 if (client.appIf == appIf && client.isServer == isServer) { 130 mScanQueue.remove(client); 131 break; 132 } 133 } 134 } 135 136 /** 137 * Reliable write queue 138 */ 139 private Set<String> mReliableQueue = new HashSet<String>(); 140 141 static { 142 classInitNative(); 143 } 144 145 protected String getName() { 146 return TAG; 147 } 148 149 protected IProfileServiceBinder initBinder() { 150 return new BluetoothGattBinder(this); 151 } 152 153 protected boolean start() { 154 if (DBG) Log.d(TAG, "start()"); 155 initializeNative(); 156 return true; 157 } 158 159 protected boolean stop() { 160 if (DBG) Log.d(TAG, "stop()"); 161 mClientMap.clear(); 162 mServerMap.clear(); 163 mSearchQueue.clear(); 164 mScanQueue.clear(); 165 mHandleMap.clear(); 166 mServiceDeclarations.clear(); 167 mReliableQueue.clear(); 168 return true; 169 } 170 171 protected boolean cleanup() { 172 if (DBG) Log.d(TAG, "cleanup()"); 173 cleanupNative(); 174 return true; 175 } 176 177 @Override 178 public int onStartCommand(Intent intent, int flags, int startId) { 179 if (GattDebugUtils.handleDebugAction(this, intent)) { 180 return Service.START_NOT_STICKY; 181 } 182 return super.onStartCommand(intent, flags, startId); 183 } 184 185 /** 186 * DeathReceipient handlers used to unregister applications that 187 * disconnect ungracefully (ie. crash or forced close). 188 */ 189 190 class ClientDeathRecipient implements IBinder.DeathRecipient { 191 int mAppIf; 192 193 public ClientDeathRecipient(int appIf) { 194 mAppIf = appIf; 195 } 196 197 public void binderDied() { 198 if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 199 unregisterClient(mAppIf); 200 } 201 } 202 203 class ServerDeathRecipient implements IBinder.DeathRecipient { 204 int mAppIf; 205 206 public ServerDeathRecipient(int appIf) { 207 mAppIf = appIf; 208 } 209 210 public void binderDied() { 211 if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 212 unregisterServer(mAppIf); 213 } 214 } 215 216 /** 217 * Handlers for incoming service calls 218 */ 219 private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder { 220 private GattService mService; 221 222 public BluetoothGattBinder(GattService svc) { 223 mService = svc; 224 } 225 226 public boolean cleanup() { 227 mService = null; 228 return true; 229 } 230 231 private GattService getService() { 232 if (mService != null && mService.isAvailable()) return mService; 233 Log.e(TAG, "getService() - Service requested, but not available!"); 234 return null; 235 } 236 237 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 238 GattService service = getService(); 239 if (service == null) return new ArrayList<BluetoothDevice>(); 240 return service.getDevicesMatchingConnectionStates(states); 241 } 242 243 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 244 GattService service = getService(); 245 if (service == null) return; 246 service.registerClient(uuid.getUuid(), callback); 247 } 248 249 public void unregisterClient(int clientIf) { 250 GattService service = getService(); 251 if (service == null) return; 252 service.unregisterClient(clientIf); 253 } 254 255 public void startScan(int appIf, boolean isServer) { 256 GattService service = getService(); 257 if (service == null) return; 258 service.startScan(appIf, isServer); 259 } 260 261 public void startScanWithUuids(int appIf, boolean isServer, ParcelUuid[] ids) { 262 GattService service = getService(); 263 if (service == null) return; 264 UUID[] uuids = new UUID[ids.length]; 265 for(int i = 0; i != ids.length; ++i) { 266 uuids[i] = ids[i].getUuid(); 267 } 268 service.startScanWithUuids(appIf, isServer, uuids); 269 } 270 271 public void stopScan(int appIf, boolean isServer) { 272 GattService service = getService(); 273 if (service == null) return; 274 service.stopScan(appIf, isServer); 275 } 276 277 public void clientConnect(int clientIf, String address, boolean isDirect) { 278 GattService service = getService(); 279 if (service == null) return; 280 service.clientConnect(clientIf, address, isDirect); 281 } 282 283 public void clientDisconnect(int clientIf, String address) { 284 GattService service = getService(); 285 if (service == null) return; 286 service.clientDisconnect(clientIf, address); 287 } 288 289 public void refreshDevice(int clientIf, String address) { 290 GattService service = getService(); 291 if (service == null) return; 292 service.refreshDevice(clientIf, address); 293 } 294 295 public void discoverServices(int clientIf, String address) { 296 GattService service = getService(); 297 if (service == null) return; 298 service.discoverServices(clientIf, address); 299 } 300 301 public void readCharacteristic(int clientIf, String address, int srvcType, 302 int srvcInstanceId, ParcelUuid srvcId, 303 int charInstanceId, ParcelUuid charId, 304 int authReq) { 305 GattService service = getService(); 306 if (service == null) return; 307 service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId, 308 srvcId.getUuid(), charInstanceId, 309 charId.getUuid(), authReq); 310 } 311 312 public void writeCharacteristic(int clientIf, String address, int srvcType, 313 int srvcInstanceId, ParcelUuid srvcId, 314 int charInstanceId, ParcelUuid charId, 315 int writeType, int authReq, byte[] value) { 316 GattService service = getService(); 317 if (service == null) return; 318 service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId, 319 srvcId.getUuid(), charInstanceId, 320 charId.getUuid(), writeType, authReq, 321 value); 322 } 323 324 public void readDescriptor(int clientIf, String address, int srvcType, 325 int srvcInstanceId, ParcelUuid srvcId, 326 int charInstanceId, ParcelUuid charId, 327 ParcelUuid descrId, int authReq) { 328 GattService service = getService(); 329 if (service == null) return; 330 service.readDescriptor(clientIf, address, srvcType, srvcInstanceId, 331 srvcId.getUuid(), charInstanceId, 332 charId.getUuid(), descrId.getUuid(), 333 authReq); 334 } 335 336 public void writeDescriptor(int clientIf, String address, int srvcType, 337 int srvcInstanceId, ParcelUuid srvcId, 338 int charInstanceId, ParcelUuid charId, 339 ParcelUuid descrId, int writeType, 340 int authReq, byte[] value) { 341 GattService service = getService(); 342 if (service == null) return; 343 service.writeDescriptor(clientIf, address, srvcType, srvcInstanceId, 344 srvcId.getUuid(), charInstanceId, 345 charId.getUuid(), descrId.getUuid(), 346 writeType, authReq, value); 347 } 348 349 public void beginReliableWrite(int clientIf, String address) { 350 GattService service = getService(); 351 if (service == null) return; 352 service.beginReliableWrite(clientIf, address); 353 } 354 355 public void endReliableWrite(int clientIf, String address, boolean execute) { 356 GattService service = getService(); 357 if (service == null) return; 358 service.endReliableWrite(clientIf, address, execute); 359 } 360 361 public void registerForNotification(int clientIf, String address, int srvcType, 362 int srvcInstanceId, ParcelUuid srvcId, 363 int charInstanceId, ParcelUuid charId, 364 boolean enable) { 365 GattService service = getService(); 366 if (service == null) return; 367 service.registerForNotification(clientIf, address, srvcType, srvcInstanceId, 368 srvcId.getUuid(), charInstanceId, 369 charId.getUuid(), enable); 370 } 371 372 public void readRemoteRssi(int clientIf, String address) { 373 GattService service = getService(); 374 if (service == null) return; 375 service.readRemoteRssi(clientIf, address); 376 } 377 378 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 379 GattService service = getService(); 380 if (service == null) return; 381 service.registerServer(uuid.getUuid(), callback); 382 } 383 384 public void unregisterServer(int serverIf) { 385 GattService service = getService(); 386 if (service == null) return; 387 service.unregisterServer(serverIf); 388 } 389 390 public void serverConnect(int serverIf, String address, boolean isDirect) { 391 GattService service = getService(); 392 if (service == null) return; 393 service.serverConnect(serverIf, address, isDirect); 394 } 395 396 public void serverDisconnect(int serverIf, String address) { 397 GattService service = getService(); 398 if (service == null) return; 399 service.serverDisconnect(serverIf, address); 400 } 401 402 public void beginServiceDeclaration(int serverIf, int srvcType, 403 int srvcInstanceId, int minHandles, 404 ParcelUuid srvcId) { 405 GattService service = getService(); 406 if (service == null) return; 407 service.beginServiceDeclaration(serverIf, srvcType, srvcInstanceId, 408 minHandles, srvcId.getUuid()); 409 } 410 411 public void addIncludedService(int serverIf, int srvcType, 412 int srvcInstanceId, ParcelUuid srvcId) { 413 GattService service = getService(); 414 if (service == null) return; 415 service.addIncludedService(serverIf, srvcType, srvcInstanceId, 416 srvcId.getUuid()); 417 } 418 419 public void addCharacteristic(int serverIf, ParcelUuid charId, 420 int properties, int permissions) { 421 GattService service = getService(); 422 if (service == null) return; 423 service.addCharacteristic(serverIf, charId.getUuid(), properties, 424 permissions); 425 } 426 427 public void addDescriptor(int serverIf, ParcelUuid descId, 428 int permissions) { 429 GattService service = getService(); 430 if (service == null) return; 431 service.addDescriptor(serverIf, descId.getUuid(), permissions); 432 } 433 434 public void endServiceDeclaration(int serverIf) { 435 GattService service = getService(); 436 if (service == null) return; 437 service.endServiceDeclaration(serverIf); 438 } 439 440 public void removeService(int serverIf, int srvcType, 441 int srvcInstanceId, ParcelUuid srvcId) { 442 GattService service = getService(); 443 if (service == null) return; 444 service.removeService(serverIf, srvcType, srvcInstanceId, 445 srvcId.getUuid()); 446 } 447 448 public void clearServices(int serverIf) { 449 GattService service = getService(); 450 if (service == null) return; 451 service.clearServices(serverIf); 452 } 453 454 public void sendResponse(int serverIf, String address, int requestId, 455 int status, int offset, byte[] value) { 456 GattService service = getService(); 457 if (service == null) return; 458 service.sendResponse(serverIf, address, requestId, status, offset, value); 459 } 460 461 public void sendNotification(int serverIf, String address, int srvcType, 462 int srvcInstanceId, ParcelUuid srvcId, 463 int charInstanceId, ParcelUuid charId, 464 boolean confirm, byte[] value) { 465 GattService service = getService(); 466 if (service == null) return; 467 service.sendNotification(serverIf, address, srvcType, srvcInstanceId, 468 srvcId.getUuid(), charInstanceId, charId.getUuid(), confirm, value); 469 } 470 471 }; 472 473 /************************************************************************** 474 * Callback functions - CLIENT 475 *************************************************************************/ 476 477 void onScanResult(String address, int rssi, byte[] adv_data) { 478 if (DBG) Log.d(TAG, "onScanResult() - address=" + address 479 + ", rssi=" + rssi); 480 481 List<UUID> remoteUuids = parseUuids(adv_data); 482 for (ScanClient client : mScanQueue) { 483 if (client.uuids.length > 0) { 484 int matches = 0; 485 for (UUID search : client.uuids) { 486 for (UUID remote: remoteUuids) { 487 if (remote.equals(search)) { 488 ++matches; 489 break; // Only count 1st match in case of duplicates 490 } 491 } 492 } 493 494 if (matches < client.uuids.length) continue; 495 } 496 497 if (!client.isServer) { 498 ClientMap.App app = mClientMap.getById(client.appIf); 499 if (app != null) { 500 try { 501 app.callback.onScanResult(address, rssi, adv_data); 502 } catch (RemoteException e) { 503 Log.e(TAG, "Exception: " + e); 504 mClientMap.remove(client.appIf); 505 mScanQueue.remove(client); 506 } 507 } 508 } else { 509 ServerMap.App app = mServerMap.getById(client.appIf); 510 if (app != null) { 511 try { 512 app.callback.onScanResult(address, rssi, adv_data); 513 } catch (RemoteException e) { 514 Log.e(TAG, "Exception: " + e); 515 mServerMap.remove(client.appIf); 516 mScanQueue.remove(client); 517 } 518 } 519 } 520 } 521 } 522 523 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 524 throws RemoteException { 525 UUID uuid = new UUID(uuidMsb, uuidLsb); 526 if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 527 ClientMap.App app = mClientMap.getByUuid(uuid); 528 if (app != null) { 529 app.id = clientIf; 530 app.linkToDeath(new ClientDeathRecipient(clientIf)); 531 app.callback.onClientRegistered(status, clientIf); 532 } 533 } 534 535 void onConnected(int clientIf, int connId, int status, String address) 536 throws RemoteException { 537 if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 538 + ", connId=" + connId + ", address=" + address); 539 540 if (status == 0) mClientMap.addConnection(clientIf, connId, address); 541 ClientMap.App app = mClientMap.getById(clientIf); 542 if (app != null) { 543 app.callback.onClientConnectionState(status, clientIf, true, address); 544 } 545 } 546 547 void onDisconnected(int clientIf, int connId, int status, String address) 548 throws RemoteException { 549 if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 550 + ", connId=" + connId + ", address=" + address); 551 552 mClientMap.removeConnection(clientIf, connId); 553 mSearchQueue.removeConnId(connId); 554 ClientMap.App app = mClientMap.getById(clientIf); 555 if (app != null) { 556 app.callback.onClientConnectionState(status, clientIf, false, address); 557 } 558 } 559 560 void onSearchCompleted(int connId, int status) throws RemoteException { 561 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 562 // We got all services, now let's explore characteristics... 563 continueSearch(connId, status); 564 } 565 566 void onSearchResult(int connId, int srvcType, 567 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb) 568 throws RemoteException { 569 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 570 String address = mClientMap.addressByConnId(connId); 571 572 if (DBG) Log.d(TAG, "onSearchResult() - address=" + address + ", uuid=" + uuid); 573 574 mSearchQueue.add(connId, srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb); 575 576 ClientMap.App app = mClientMap.getByConnId(connId); 577 if (app != null) { 578 app.callback.onGetService(address, srvcType, srvcInstId, 579 new ParcelUuid(uuid)); 580 } 581 } 582 583 void onGetCharacteristic(int connId, int status, int srvcType, 584 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 585 int charInstId, long charUuidLsb, long charUuidMsb, 586 int charProp) throws RemoteException { 587 588 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 589 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 590 String address = mClientMap.addressByConnId(connId); 591 592 if (DBG) Log.d(TAG, "onGetCharacteristic() - address=" + address 593 + ", status=" + status + ", charUuid=" + charUuid + ", prop=" + charProp); 594 595 if (status == 0) { 596 mSearchQueue.add(connId, srvcType, 597 srvcInstId, srvcUuidLsb, srvcUuidMsb, 598 charInstId, charUuidLsb, charUuidMsb); 599 600 ClientMap.App app = mClientMap.getByConnId(connId); 601 if (app != null) { 602 app.callback.onGetCharacteristic(address, srvcType, 603 srvcInstId, new ParcelUuid(srvcUuid), 604 charInstId, new ParcelUuid(charUuid), charProp); 605 } 606 607 // Get next characteristic in the current service 608 gattClientGetCharacteristicNative(connId, srvcType, 609 srvcInstId, srvcUuidLsb, srvcUuidMsb, 610 charInstId, charUuidLsb, charUuidMsb); 611 } else { 612 // Check for included services next 613 gattClientGetIncludedServiceNative(connId, 614 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 615 0,0,0,0); 616 } 617 } 618 619 void onGetDescriptor(int connId, int status, int srvcType, 620 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 621 int charInstId, long charUuidLsb, long charUuidMsb, 622 long descrUuidLsb, long descrUuidMsb) throws RemoteException { 623 624 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 625 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 626 UUID descUuid = new UUID(descrUuidMsb, descrUuidLsb); 627 String address = mClientMap.addressByConnId(connId); 628 629 if (DBG) Log.d(TAG, "onGetDescriptor() - address=" + address 630 + ", status=" + status + ", descUuid=" + descUuid); 631 632 if (status == 0) { 633 ClientMap.App app = mClientMap.getByConnId(connId); 634 if (app != null) { 635 app.callback.onGetDescriptor(address, srvcType, 636 srvcInstId, new ParcelUuid(srvcUuid), 637 charInstId, new ParcelUuid(charUuid), 638 new ParcelUuid(descUuid)); 639 } 640 641 // Get next descriptor for the current characteristic 642 gattClientGetDescriptorNative(connId, srvcType, 643 srvcInstId, srvcUuidLsb, srvcUuidMsb, 644 charInstId, charUuidLsb, charUuidMsb, 645 descrUuidLsb, descrUuidMsb); 646 } else { 647 // Explore the next service 648 continueSearch(connId, 0); 649 } 650 } 651 652 void onGetIncludedService(int connId, int status, int srvcType, 653 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType, 654 int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb) 655 throws RemoteException { 656 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 657 UUID inclSrvcUuid = new UUID(inclSrvcUuidMsb, inclSrvcUuidLsb); 658 String address = mClientMap.addressByConnId(connId); 659 660 if (DBG) Log.d(TAG, "onGetIncludedService() - address=" + address 661 + ", status=" + status + ", uuid=" + srvcUuid 662 + ", inclUuid=" + inclSrvcUuid); 663 664 if (status == 0) { 665 ClientMap.App app = mClientMap.getByConnId(connId); 666 if (app != null) { 667 app.callback.onGetIncludedService(address, 668 srvcType, srvcInstId, new ParcelUuid(srvcUuid), 669 inclSrvcType, inclSrvcInstId, new ParcelUuid(inclSrvcUuid)); 670 } 671 672 // Find additional included services 673 gattClientGetIncludedServiceNative(connId, 674 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 675 inclSrvcType, inclSrvcInstId, inclSrvcUuidLsb, inclSrvcUuidMsb); 676 } else { 677 // Discover descriptors now 678 continueSearch(connId, 0); 679 } 680 } 681 682 void onRegisterForNotifications(int connId, int status, int registered, int srvcType, 683 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 684 int charInstId, long charUuidLsb, long charUuidMsb) { 685 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 686 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 687 String address = mClientMap.addressByConnId(connId); 688 689 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 690 + ", status=" + status + ", registered=" + registered 691 + ", charUuid=" + charUuid); 692 } 693 694 void onNotify(int connId, String address, int srvcType, 695 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 696 int charInstId, long charUuidLsb, long charUuidMsb, 697 boolean isNotify, byte[] data) throws RemoteException { 698 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 699 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 700 701 if (DBG) Log.d(TAG, "onNotify() - address=" + address 702 + ", charUuid=" + charUuid + ", length=" + data.length); 703 704 ClientMap.App app = mClientMap.getByConnId(connId); 705 if (app != null) { 706 app.callback.onNotify(address, srvcType, 707 srvcInstId, new ParcelUuid(srvcUuid), 708 charInstId, new ParcelUuid(charUuid), 709 data); 710 } 711 } 712 713 void onReadCharacteristic(int connId, int status, int srvcType, 714 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 715 int charInstId, long charUuidLsb, long charUuidMsb, 716 int charType, byte[] data) throws RemoteException { 717 718 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 719 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 720 String address = mClientMap.addressByConnId(connId); 721 722 if (DBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 723 + ", status=" + status + ", length=" + data.length); 724 725 ClientMap.App app = mClientMap.getByConnId(connId); 726 if (app != null) { 727 app.callback.onCharacteristicRead(address, status, srvcType, 728 srvcInstId, new ParcelUuid(srvcUuid), 729 charInstId, new ParcelUuid(charUuid), data); 730 } 731 } 732 733 void onWriteCharacteristic(int connId, int status, int srvcType, 734 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 735 int charInstId, long charUuidLsb, long charUuidMsb) 736 throws RemoteException { 737 738 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 739 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 740 String address = mClientMap.addressByConnId(connId); 741 742 if (DBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 743 + ", status=" + status); 744 745 ClientMap.App app = mClientMap.getByConnId(connId); 746 if (app != null) { 747 app.callback.onCharacteristicWrite(address, status, srvcType, 748 srvcInstId, new ParcelUuid(srvcUuid), 749 charInstId, new ParcelUuid(charUuid)); 750 } 751 } 752 753 void onExecuteCompleted(int connId, int status) throws RemoteException { 754 String address = mClientMap.addressByConnId(connId); 755 if (DBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 756 + ", status=" + status); 757 758 ClientMap.App app = mClientMap.getByConnId(connId); 759 if (app != null) { 760 app.callback.onExecuteWrite(address, status); 761 } 762 } 763 764 void onReadDescriptor(int connId, int status, int srvcType, 765 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 766 int charInstId, long charUuidLsb, long charUuidMsb, 767 long descrUuidLsb, long descrUuidMsb, 768 int charType, byte[] data) throws RemoteException { 769 770 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 771 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 772 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 773 String address = mClientMap.addressByConnId(connId); 774 775 if (DBG) Log.d(TAG, "onReadDescriptor() - address=" + address 776 + ", status=" + status + ", length=" + data.length); 777 778 ClientMap.App app = mClientMap.getByConnId(connId); 779 if (app != null) { 780 app.callback.onDescriptorRead(address, status, srvcType, 781 srvcInstId, new ParcelUuid(srvcUuid), 782 charInstId, new ParcelUuid(charUuid), 783 new ParcelUuid(descrUuid), data); 784 } 785 } 786 787 void onWriteDescriptor(int connId, int status, int srvcType, 788 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 789 int charInstId, long charUuidLsb, long charUuidMsb, 790 long descrUuidLsb, long descrUuidMsb) throws RemoteException { 791 792 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 793 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 794 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 795 String address = mClientMap.addressByConnId(connId); 796 797 if (DBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 798 + ", status=" + status); 799 800 ClientMap.App app = mClientMap.getByConnId(connId); 801 if (app != null) { 802 app.callback.onDescriptorWrite(address, status, srvcType, 803 srvcInstId, new ParcelUuid(srvcUuid), 804 charInstId, new ParcelUuid(charUuid), 805 new ParcelUuid(descrUuid)); 806 } 807 } 808 809 void onReadRemoteRssi(int clientIf, String address, 810 int rssi, int status) throws RemoteException{ 811 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 812 address + ", rssi=" + rssi + ", status=" + status); 813 814 ClientMap.App app = mClientMap.getById(clientIf); 815 if (app != null) { 816 app.callback.onReadRemoteRssi(address, rssi, status); 817 } 818 } 819 820 /************************************************************************** 821 * GATT Service functions - Shared CLIENT/SERVER 822 *************************************************************************/ 823 824 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 825 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 826 827 final int DEVICE_TYPE_BREDR = 0x1; 828 829 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 830 Integer>(); 831 832 // Add paired LE devices 833 834 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 835 for (BluetoothDevice device : bondedDevices) { 836 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 837 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 838 } 839 } 840 841 // Add connected deviceStates 842 843 Set<String> connectedDevices = new HashSet<String>(); 844 connectedDevices.addAll(mClientMap.getConnectedDevices()); 845 connectedDevices.addAll(mServerMap.getConnectedDevices()); 846 847 for (String address : connectedDevices ) { 848 BluetoothDevice device = mAdapter.getRemoteDevice(address); 849 if (device != null) { 850 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 851 } 852 } 853 854 // Create matching device sub-set 855 856 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 857 858 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 859 for(int state : states) { 860 if (entry.getValue() == state) { 861 deviceList.add(entry.getKey()); 862 } 863 } 864 } 865 866 return deviceList; 867 } 868 869 void startScan(int appIf, boolean isServer) { 870 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 871 872 if (DBG) Log.d(TAG, "startScan() - queue=" + mScanQueue.size()); 873 874 if (getScanClient(appIf, isServer) == null) { 875 if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf); 876 mScanQueue.add(new ScanClient(appIf, isServer)); 877 } 878 879 gattClientScanNative(appIf, true); 880 } 881 882 void startScanWithUuids(int appIf, boolean isServer, UUID[] uuids) { 883 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 884 885 if (DBG) Log.d(TAG, "startScanWithUuids() - queue=" + mScanQueue.size()); 886 887 if (getScanClient(appIf, isServer) == null) { 888 if (DBG) Log.d(TAG, "startScanWithUuids() - adding client=" + appIf); 889 mScanQueue.add(new ScanClient(appIf, isServer, uuids)); 890 } 891 892 gattClientScanNative(appIf, true); 893 } 894 895 void stopScan(int appIf, boolean isServer) { 896 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH_ADMIN permission"); 897 898 if (DBG) Log.d(TAG, "stopScan() - queue=" + mScanQueue.size()); 899 removeScanClient(appIf, isServer); 900 901 if (mScanQueue.isEmpty()) { 902 if (DBG) Log.d(TAG, "stopScan() - queue empty; stopping scan"); 903 gattClientScanNative(appIf, false); 904 } 905 } 906 907 /************************************************************************** 908 * GATT Service functions - CLIENT 909 *************************************************************************/ 910 911 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 912 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 913 914 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 915 mClientMap.add(uuid, callback); 916 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 917 uuid.getMostSignificantBits()); 918 } 919 920 void unregisterClient(int clientIf) { 921 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 922 923 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 924 removeScanClient(clientIf, false); 925 mClientMap.remove(clientIf); 926 gattClientUnregisterAppNative(clientIf); 927 } 928 929 void clientConnect(int clientIf, String address, boolean isDirect) { 930 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 931 932 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 933 gattClientConnectNative(clientIf, address, isDirect); 934 } 935 936 void clientDisconnect(int clientIf, String address) { 937 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 938 939 Integer connId = mClientMap.connIdByAddress(clientIf, address); 940 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 941 942 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 943 } 944 945 List<String> getConnectedDevices() { 946 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 947 948 Set<String> connectedDevAddress = new HashSet<String>(); 949 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 950 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 951 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 952 return connectedDeviceList; 953 } 954 955 void refreshDevice(int clientIf, String address) { 956 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 957 958 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 959 gattClientRefreshNative(clientIf, address); 960 } 961 962 void discoverServices(int clientIf, String address) { 963 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 964 965 Integer connId = mClientMap.connIdByAddress(clientIf, address); 966 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 967 968 if (connId != null) 969 gattClientSearchServiceNative(connId, true, 0, 0); 970 else 971 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 972 } 973 974 void readCharacteristic(int clientIf, String address, int srvcType, 975 int srvcInstanceId, UUID srvcUuid, 976 int charInstanceId, UUID charUuid, int authReq) { 977 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 978 979 if (DBG) Log.d(TAG, "readCharacteristic() - address=" + address); 980 981 Integer connId = mClientMap.connIdByAddress(clientIf, address); 982 if (connId != null) 983 gattClientReadCharacteristicNative(connId, srvcType, 984 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 985 srvcUuid.getMostSignificantBits(), charInstanceId, 986 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 987 authReq); 988 else 989 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 990 } 991 992 void writeCharacteristic(int clientIf, String address, int srvcType, 993 int srvcInstanceId, UUID srvcUuid, 994 int charInstanceId, UUID charUuid, int writeType, 995 int authReq, byte[] value) { 996 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 997 998 if (DBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 999 1000 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1001 1002 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1003 if (connId != null) 1004 gattClientWriteCharacteristicNative(connId, srvcType, 1005 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1006 srvcUuid.getMostSignificantBits(), charInstanceId, 1007 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1008 writeType, authReq, value); 1009 else 1010 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1011 } 1012 1013 void readDescriptor(int clientIf, String address, int srvcType, 1014 int srvcInstanceId, UUID srvcUuid, 1015 int charInstanceId, UUID charUuid, 1016 UUID descrUuid, int authReq) { 1017 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1018 1019 if (DBG) Log.d(TAG, "readDescriptor() - address=" + address); 1020 1021 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1022 if (connId != null) 1023 gattClientReadDescriptorNative(connId, srvcType, 1024 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1025 srvcUuid.getMostSignificantBits(), charInstanceId, 1026 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1027 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1028 authReq); 1029 else 1030 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1031 }; 1032 1033 void writeDescriptor(int clientIf, String address, int srvcType, 1034 int srvcInstanceId, UUID srvcUuid, 1035 int charInstanceId, UUID charUuid, 1036 UUID descrUuid, int writeType, 1037 int authReq, byte[] value) { 1038 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1039 1040 if (DBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1041 1042 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1043 if (connId != null) 1044 gattClientWriteDescriptorNative(connId, srvcType, 1045 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1046 srvcUuid.getMostSignificantBits(), charInstanceId, 1047 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1048 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1049 writeType, authReq, value); 1050 else 1051 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1052 } 1053 1054 void beginReliableWrite(int clientIf, String address) { 1055 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1056 1057 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1058 mReliableQueue.add(address); 1059 } 1060 1061 void endReliableWrite(int clientIf, String address, boolean execute) { 1062 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1063 1064 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1065 + " execute: " + execute); 1066 mReliableQueue.remove(address); 1067 1068 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1069 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1070 } 1071 1072 void registerForNotification(int clientIf, String address, int srvcType, 1073 int srvcInstanceId, UUID srvcUuid, 1074 int charInstanceId, UUID charUuid, 1075 boolean enable) { 1076 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1077 1078 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1079 1080 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1081 if (connId != null) { 1082 gattClientRegisterForNotificationsNative(clientIf, address, 1083 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1084 srvcUuid.getMostSignificantBits(), charInstanceId, 1085 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1086 enable); 1087 } else { 1088 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1089 } 1090 } 1091 1092 void readRemoteRssi(int clientIf, String address) { 1093 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1094 1095 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1096 gattClientReadRemoteRssiNative(clientIf, address); 1097 } 1098 1099 /************************************************************************** 1100 * Callback functions - SERVER 1101 *************************************************************************/ 1102 1103 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1104 throws RemoteException { 1105 1106 UUID uuid = new UUID(uuidMsb, uuidLsb); 1107 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1108 ServerMap.App app = mServerMap.getByUuid(uuid); 1109 if (app != null) { 1110 app.id = serverIf; 1111 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1112 app.callback.onServerRegistered(status, serverIf); 1113 } 1114 } 1115 1116 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1117 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1118 throws RemoteException { 1119 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1120 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1121 + ", handle=" + srvcHandle); 1122 if (status == 0) 1123 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId); 1124 continueServiceDeclaration(serverIf, status, srvcHandle); 1125 } 1126 1127 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1128 int includedSrvcHandle) throws RemoteException { 1129 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1130 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1131 continueServiceDeclaration(serverIf, status, srvcHandle); 1132 } 1133 1134 void onCharacteristicAdded(int status, int serverIf, 1135 long charUuidLsb, long charUuidMsb, 1136 int srvcHandle, int charHandle) 1137 throws RemoteException { 1138 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1139 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1140 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1141 if (status == 0) 1142 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1143 continueServiceDeclaration(serverIf, status, srvcHandle); 1144 } 1145 1146 void onDescriptorAdded(int status, int serverIf, 1147 long descrUuidLsb, long descrUuidMsb, 1148 int srvcHandle, int descrHandle) 1149 throws RemoteException { 1150 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1151 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1152 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1153 if (status == 0) 1154 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1155 continueServiceDeclaration(serverIf, status, srvcHandle); 1156 } 1157 1158 void onServiceStarted(int status, int serverIf, int srvcHandle) 1159 throws RemoteException { 1160 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1161 + ", status=" + status); 1162 if (status == 0) 1163 mHandleMap.setStarted(serverIf, srvcHandle, true); 1164 } 1165 1166 void onServiceStopped(int status, int serverIf, int srvcHandle) 1167 throws RemoteException { 1168 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1169 + ", status=" + status); 1170 if (status == 0) 1171 mHandleMap.setStarted(serverIf, srvcHandle, false); 1172 stopNextService(serverIf, status); 1173 } 1174 1175 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1176 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1177 + ", status=" + status); 1178 mHandleMap.deleteService(serverIf, srvcHandle); 1179 } 1180 1181 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1182 throws RemoteException { 1183 1184 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1185 + ", address=" + address + ", connected=" + connected); 1186 1187 ServerMap.App app = mServerMap.getById(serverIf); 1188 if (app == null) return; 1189 1190 if (connected) { 1191 mServerMap.addConnection(serverIf, connId, address); 1192 } else { 1193 mServerMap.removeConnection(serverIf, connId); 1194 } 1195 1196 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1197 } 1198 1199 void onAttributeRead(String address, int connId, int transId, 1200 int attrHandle, int offset, boolean isLong) 1201 throws RemoteException { 1202 if (DBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1203 + ", address=" + address + ", handle=" + attrHandle 1204 + ", requestId=" + transId + ", offset=" + offset); 1205 1206 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1207 if (entry == null) return; 1208 1209 if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 1210 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1211 1212 mHandleMap.addRequest(transId, attrHandle); 1213 1214 ServerMap.App app = mServerMap.getById(entry.serverIf); 1215 if (app == null) return; 1216 1217 switch(entry.type) { 1218 case HandleMap.TYPE_CHARACTERISTIC: 1219 { 1220 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1221 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1222 serviceEntry.serviceType, serviceEntry.instance, 1223 new ParcelUuid(serviceEntry.uuid), entry.instance, 1224 new ParcelUuid(entry.uuid)); 1225 break; 1226 } 1227 1228 case HandleMap.TYPE_DESCRIPTOR: 1229 { 1230 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1231 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1232 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1233 serviceEntry.serviceType, serviceEntry.instance, 1234 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1235 new ParcelUuid(charEntry.uuid), 1236 new ParcelUuid(entry.uuid)); 1237 break; 1238 } 1239 1240 default: 1241 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1242 break; 1243 } 1244 } 1245 1246 void onAttributeWrite(String address, int connId, int transId, 1247 int attrHandle, int offset, int length, 1248 boolean needRsp, boolean isPrep, 1249 byte[] data) 1250 throws RemoteException { 1251 if (DBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1252 + ", address=" + address + ", handle=" + attrHandle 1253 + ", requestId=" + transId + ", isPrep=" + isPrep 1254 + ", offset=" + offset); 1255 1256 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1257 if (entry == null) return; 1258 1259 if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1260 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1261 1262 mHandleMap.addRequest(transId, attrHandle); 1263 1264 ServerMap.App app = mServerMap.getById(entry.serverIf); 1265 if (app == null) return; 1266 1267 switch(entry.type) { 1268 case HandleMap.TYPE_CHARACTERISTIC: 1269 { 1270 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1271 app.callback.onCharacteristicWriteRequest(address, transId, 1272 offset, length, isPrep, needRsp, 1273 serviceEntry.serviceType, serviceEntry.instance, 1274 new ParcelUuid(serviceEntry.uuid), entry.instance, 1275 new ParcelUuid(entry.uuid), data); 1276 break; 1277 } 1278 1279 case HandleMap.TYPE_DESCRIPTOR: 1280 { 1281 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1282 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1283 app.callback.onDescriptorWriteRequest(address, transId, 1284 offset, length, isPrep, needRsp, 1285 serviceEntry.serviceType, serviceEntry.instance, 1286 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1287 new ParcelUuid(charEntry.uuid), 1288 new ParcelUuid(entry.uuid), data); 1289 break; 1290 } 1291 1292 default: 1293 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1294 break; 1295 } 1296 } 1297 1298 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1299 throws RemoteException { 1300 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1301 + ", address=" + address + ", transId=" + transId); 1302 1303 ServerMap.App app = mServerMap.getByConnId(connId); 1304 if (app == null) return; 1305 1306 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1307 } 1308 1309 void onResponseSendCompleted(int status, int attrHandle) { 1310 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1311 } 1312 1313 /************************************************************************** 1314 * GATT Service functions - SERVER 1315 *************************************************************************/ 1316 1317 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1318 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1319 1320 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1321 mServerMap.add(uuid, callback); 1322 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1323 uuid.getMostSignificantBits()); 1324 } 1325 1326 void unregisterServer(int serverIf) { 1327 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1328 1329 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1330 1331 deleteServices(serverIf); 1332 1333 mServerMap.remove(serverIf); 1334 gattServerUnregisterAppNative(serverIf); 1335 } 1336 1337 void serverConnect(int serverIf, String address, boolean isDirect) { 1338 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1339 1340 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1341 gattServerConnectNative(serverIf, address, isDirect); 1342 } 1343 1344 void serverDisconnect(int serverIf, String address) { 1345 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1346 1347 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1348 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1349 1350 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1351 } 1352 1353 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1354 int minHandles, UUID srvcUuid) { 1355 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1356 1357 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1358 ServiceDeclaration serviceDeclaration = addDeclaration(); 1359 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles); 1360 } 1361 1362 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1363 UUID srvcUuid) { 1364 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1365 1366 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1367 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1368 } 1369 1370 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1371 int permissions) { 1372 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1373 1374 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1375 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1376 } 1377 1378 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1379 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1380 1381 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1382 getActiveDeclaration().addDescriptor(descUuid, permissions); 1383 } 1384 1385 void endServiceDeclaration(int serverIf) { 1386 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1387 1388 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1389 1390 if (getActiveDeclaration() == getPendingDeclaration()) { 1391 try { 1392 continueServiceDeclaration(serverIf, (byte)0, 0); 1393 } catch (RemoteException e) { 1394 Log.e(TAG,""+e); 1395 } 1396 } 1397 } 1398 1399 void removeService(int serverIf, int srvcType, 1400 int srvcInstanceId, UUID srvcUuid) { 1401 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1402 1403 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1404 1405 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1406 if (srvcHandle == 0) return; 1407 gattServerDeleteServiceNative(serverIf, srvcHandle); 1408 } 1409 1410 void clearServices(int serverIf) { 1411 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1412 1413 if (DBG) Log.d(TAG, "clearServices()"); 1414 deleteServices(serverIf); 1415 } 1416 1417 void sendResponse(int serverIf, String address, int requestId, 1418 int status, int offset, byte[] value) { 1419 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1420 1421 if (DBG) Log.d(TAG, "sendResponse() - address=" + address); 1422 1423 int handle = 0; 1424 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 1425 if (entry != null) handle = entry.handle; 1426 1427 int connId = mServerMap.connIdByAddress(serverIf, address); 1428 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 1429 handle, offset, value, (byte)0); 1430 mHandleMap.deleteRequest(requestId); 1431 } 1432 1433 void sendNotification(int serverIf, String address, int srvcType, 1434 int srvcInstanceId, UUID srvcUuid, 1435 int charInstanceId, UUID charUuid, 1436 boolean confirm, byte[] value) { 1437 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1438 1439 if (DBG) Log.d(TAG, "sendNotification() - address=" + address); 1440 1441 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1442 if (srvcHandle == 0) return; 1443 1444 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 1445 if (charHandle == 0) return; 1446 1447 int connId = mServerMap.connIdByAddress(serverIf, address); 1448 if (connId == 0) return; 1449 1450 if (confirm) { 1451 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 1452 } else { 1453 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 1454 } 1455 } 1456 1457 /************************************************************************** 1458 * Private functions 1459 *************************************************************************/ 1460 1461 private int getDeviceType(BluetoothDevice device) { 1462 int type = gattClientGetDeviceTypeNative(device.getAddress()); 1463 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 1464 + ", type=" + type); 1465 return type; 1466 } 1467 1468 private void continueSearch(int connId, int status) throws RemoteException { 1469 if (status == 0 && !mSearchQueue.isEmpty()) { 1470 SearchQueue.Entry svc = mSearchQueue.pop(); 1471 1472 if (svc.charUuidLsb == 0) { 1473 // Characteristic is up next 1474 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 1475 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 1476 } else { 1477 // Descriptor is up next 1478 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 1479 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 1480 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0,0); 1481 } 1482 } else { 1483 ClientMap.App app = mClientMap.getByConnId(connId); 1484 if (app != null) { 1485 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 1486 } 1487 } 1488 } 1489 1490 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 1491 if (mServiceDeclarations.size() == 0) return; 1492 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 1493 1494 boolean finished = false; 1495 1496 ServiceDeclaration.Entry entry = null; 1497 if (status == 0) 1498 entry = getPendingDeclaration().getNext(); 1499 1500 if (entry != null) { 1501 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 1502 + entry.type); 1503 switch(entry.type) { 1504 case ServiceDeclaration.TYPE_SERVICE: 1505 gattServerAddServiceNative(serverIf, entry.serviceType, 1506 entry.instance, 1507 entry.uuid.getLeastSignificantBits(), 1508 entry.uuid.getMostSignificantBits(), 1509 getPendingDeclaration().getNumHandles()); 1510 break; 1511 1512 case ServiceDeclaration.TYPE_CHARACTERISTIC: 1513 gattServerAddCharacteristicNative(serverIf, srvcHandle, 1514 entry.uuid.getLeastSignificantBits(), 1515 entry.uuid.getMostSignificantBits(), 1516 entry.properties, entry.permissions); 1517 break; 1518 1519 case ServiceDeclaration.TYPE_DESCRIPTOR: 1520 gattServerAddDescriptorNative(serverIf, srvcHandle, 1521 entry.uuid.getLeastSignificantBits(), 1522 entry.uuid.getMostSignificantBits(), 1523 entry.permissions); 1524 break; 1525 1526 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 1527 { 1528 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 1529 entry.serviceType, entry.instance); 1530 if (inclSrvc != 0) { 1531 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 1532 inclSrvc); 1533 } else { 1534 finished = true; 1535 } 1536 break; 1537 } 1538 } 1539 } else { 1540 gattServerStartServiceNative(serverIf, srvcHandle, (byte)2 /*BREDR/LE*/); 1541 finished = true; 1542 } 1543 1544 if (finished) { 1545 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 1546 ServerMap.App app = mServerMap.getById(serverIf); 1547 if (app != null) { 1548 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 1549 if (serviceEntry != null) { 1550 app.callback.onServiceAdded(status, serviceEntry.serviceType, 1551 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 1552 } else { 1553 app.callback.onServiceAdded(status, 0, 0, null); 1554 } 1555 } 1556 removePendingDeclaration(); 1557 1558 if (getPendingDeclaration() != null) { 1559 continueServiceDeclaration(serverIf, (byte)0, 0); 1560 } 1561 } 1562 } 1563 1564 private void stopNextService(int serverIf, int status) throws RemoteException { 1565 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 1566 + ", status=" + status); 1567 1568 if (status == 0) { 1569 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 1570 for(HandleMap.Entry entry : entries) { 1571 if (entry.type != HandleMap.TYPE_SERVICE || 1572 entry.serverIf != serverIf || 1573 entry.started == false) 1574 continue; 1575 1576 gattServerStopServiceNative(serverIf, entry.handle); 1577 return; 1578 } 1579 } 1580 } 1581 1582 private void deleteServices(int serverIf) { 1583 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 1584 1585 /* 1586 * Figure out which handles to delete. 1587 * The handles are copied into a new list to avoid race conditions. 1588 */ 1589 List<Integer> handleList = new ArrayList<Integer>(); 1590 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 1591 for(HandleMap.Entry entry : entries) { 1592 if (entry.type != HandleMap.TYPE_SERVICE || 1593 entry.serverIf != serverIf) 1594 continue; 1595 handleList.add(entry.handle); 1596 } 1597 1598 /* Now actually delete the services.... */ 1599 for(Integer handle : handleList) { 1600 gattServerDeleteServiceNative(serverIf, handle); 1601 } 1602 } 1603 1604 private List<UUID> parseUuids(byte[] adv_data) { 1605 List<UUID> uuids = new ArrayList<UUID>(); 1606 1607 int offset = 0; 1608 while(offset < (adv_data.length-2)) { 1609 int len = adv_data[offset++]; 1610 if (len == 0) break; 1611 1612 int type = adv_data[offset++]; 1613 switch (type) { 1614 case 0x02: // Partial list of 16-bit UUIDs 1615 case 0x03: // Complete list of 16-bit UUIDs 1616 while (len > 1) { 1617 int uuid16 = adv_data[offset++]; 1618 uuid16 += (adv_data[offset++] << 8); 1619 len -= 2; 1620 uuids.add(UUID.fromString(String.format( 1621 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 1622 } 1623 break; 1624 1625 default: 1626 offset += (len - 1); 1627 break; 1628 } 1629 } 1630 1631 return uuids; 1632 } 1633 1634 /************************************************************************** 1635 * GATT Test functions 1636 *************************************************************************/ 1637 1638 void gattTestCommand(int command, UUID uuid1, String bda1, 1639 int p1, int p2, int p3, int p4, int p5) { 1640 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 1641 if (uuid1 != null) 1642 gattTestNative(command, uuid1.getLeastSignificantBits(), 1643 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 1644 else 1645 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 1646 } 1647 1648 private native void gattTestNative(int command, 1649 long uuid1_lsb, long uuid1_msb, String bda1, 1650 int p1, int p2, int p3, int p4, int p5); 1651 1652 /************************************************************************** 1653 * Native functions prototypes 1654 *************************************************************************/ 1655 1656 private native static void classInitNative(); 1657 private native void initializeNative(); 1658 private native void cleanupNative(); 1659 1660 private native int gattClientGetDeviceTypeNative(String address); 1661 1662 private native void gattClientRegisterAppNative(long app_uuid_lsb, 1663 long app_uuid_msb); 1664 1665 private native void gattClientUnregisterAppNative(int clientIf); 1666 1667 private native void gattClientScanNative(int clientIf, boolean start); 1668 1669 private native void gattClientConnectNative(int clientIf, String address, 1670 boolean isDirect); 1671 1672 private native void gattClientDisconnectNative(int clientIf, String address, 1673 int conn_id); 1674 1675 private native void gattClientRefreshNative(int clientIf, String address); 1676 1677 private native void gattClientSearchServiceNative(int conn_id, 1678 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 1679 1680 private native void gattClientGetCharacteristicNative(int conn_id, 1681 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1682 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1683 long char_id_uuid_msb); 1684 1685 private native void gattClientGetDescriptorNative(int conn_id, 1686 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1687 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1688 long char_id_uuid_msb, long descr_id_uuid_lsb, long descr_id_uuid_msb); 1689 1690 private native void gattClientGetIncludedServiceNative(int conn_id, 1691 int service_type, int service_id_inst_id, 1692 long service_id_uuid_lsb, long service_id_uuid_msb, 1693 int incl_service_id_inst_id, int incl_service_type, 1694 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 1695 1696 private native void gattClientReadCharacteristicNative(int conn_id, 1697 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1698 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1699 long char_id_uuid_msb, int authReq); 1700 1701 private native void gattClientReadDescriptorNative(int conn_id, 1702 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1703 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1704 long char_id_uuid_msb, long descr_id_uuid_lsb, long descr_id_uuid_msb, 1705 int authReq); 1706 1707 private native void gattClientWriteCharacteristicNative(int conn_id, 1708 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1709 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1710 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 1711 1712 private native void gattClientWriteDescriptorNative(int conn_id, 1713 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 1714 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 1715 long char_id_uuid_msb, long descr_id_uuid_lsb, long descr_id_uuid_msb, 1716 int write_type, int auth_req, byte[] value); 1717 1718 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 1719 1720 private native void gattClientRegisterForNotificationsNative(int clientIf, 1721 String address, int service_type, int service_id_inst_id, 1722 long service_id_uuid_lsb, long service_id_uuid_msb, 1723 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 1724 boolean enable); 1725 1726 private native void gattClientReadRemoteRssiNative(int clientIf, 1727 String address); 1728 1729 private native void gattServerRegisterAppNative(long app_uuid_lsb, 1730 long app_uuid_msb); 1731 1732 private native void gattServerUnregisterAppNative(int serverIf); 1733 1734 private native void gattServerConnectNative(int server_if, String address, 1735 boolean is_direct); 1736 1737 private native void gattServerDisconnectNative(int serverIf, String address, 1738 int conn_id); 1739 1740 private native void gattServerAddServiceNative (int server_if, 1741 int service_type, int service_id_inst_id, 1742 long service_id_uuid_lsb, long service_id_uuid_msb, 1743 int num_handles); 1744 1745 private native void gattServerAddIncludedServiceNative (int server_if, 1746 int svc_handle, int included_svc_handle); 1747 1748 private native void gattServerAddCharacteristicNative (int server_if, 1749 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 1750 int properties, int permissions); 1751 1752 private native void gattServerAddDescriptorNative (int server_if, 1753 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 1754 int permissions); 1755 1756 private native void gattServerStartServiceNative (int server_if, 1757 int svc_handle, int transport ); 1758 1759 private native void gattServerStopServiceNative (int server_if, 1760 int svc_handle); 1761 1762 private native void gattServerDeleteServiceNative (int server_if, 1763 int svc_handle); 1764 1765 private native void gattServerSendIndicationNative (int server_if, 1766 int attr_handle, int conn_id, byte[] val); 1767 1768 private native void gattServerSendNotificationNative (int server_if, 1769 int attr_handle, int conn_id, byte[] val); 1770 1771 private native void gattServerSendResponseNative (int server_if, 1772 int conn_id, int trans_id, int status, int handle, int offset, 1773 byte[] val, int auth_req); 1774 } 1775