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