GattService.java revision 7c405bac41fc4ebb5c9cc7b5c896b023f7b1e9fc
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.BluetoothGatt; 23import android.bluetooth.BluetoothProfile; 24import android.bluetooth.IBluetoothGatt; 25import android.bluetooth.IBluetoothGattCallback; 26import android.bluetooth.IBluetoothGattServerCallback; 27import android.bluetooth.le.AdvertiseCallback; 28import android.bluetooth.le.AdvertiseData; 29import android.bluetooth.le.AdvertiseSettings; 30import android.bluetooth.le.ResultStorageDescriptor; 31import android.bluetooth.le.ScanFilter; 32import android.bluetooth.le.ScanRecord; 33import android.bluetooth.le.ScanResult; 34import android.bluetooth.le.ScanSettings; 35import android.content.Intent; 36import android.os.IBinder; 37import android.os.ParcelUuid; 38import android.os.RemoteException; 39import android.os.SystemClock; 40import android.util.Log; 41 42import com.android.bluetooth.Utils; 43import com.android.bluetooth.btservice.ProfileService; 44 45import java.util.ArrayList; 46import java.util.Arrays; 47import java.util.Collections; 48import java.util.HashMap; 49import java.util.HashSet; 50import java.util.List; 51import java.util.Map; 52import java.util.Set; 53import java.util.UUID; 54import java.util.concurrent.TimeUnit; 55 56/** 57 * Provides Bluetooth Gatt profile, as a service in 58 * the Bluetooth application. 59 * @hide 60 */ 61public class GattService extends ProfileService { 62 private static final boolean DBG = GattServiceConfig.DBG; 63 private static final boolean VDBG = GattServiceConfig.VDBG; 64 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 65 66 static final int SCAN_FILTER_ENABLED = 1; 67 static final int SCAN_FILTER_MODIFIED = 2; 68 69 private static final int MAC_ADDRESS_LENGTH = 6; 70 // Batch scan related constants. 71 private static final int TRUNCATED_RESULT_SIZE = 11; 72 private static final int TIME_STAMP_LENGTH = 2; 73 74 // onFoundLost related constants 75 private static final int ADVT_STATE_ONFOUND = 0; 76 private static final int ADVT_STATE_ONLOST = 1; 77 78 /** 79 * Search queue to serialize remote onbject inspection. 80 */ 81 SearchQueue mSearchQueue = new SearchQueue(); 82 83 /** 84 * List of our registered clients. 85 */ 86 87 class ClientMap extends ContextMap<IBluetoothGattCallback> {} 88 ClientMap mClientMap = new ClientMap(); 89 90 /** 91 * List of our registered server apps. 92 */ 93 class ServerMap extends ContextMap<IBluetoothGattServerCallback> {} 94 ServerMap mServerMap = new ServerMap(); 95 96 /** 97 * Server handle map. 98 */ 99 HandleMap mHandleMap = new HandleMap(); 100 private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); 101 102 private int mMaxScanFilters; 103 private Map<ScanClient, ScanResult> mOnFoundResults = new HashMap<ScanClient, ScanResult>(); 104 105 /** 106 * Pending service declaration queue 107 */ 108 private List<ServiceDeclaration> mServiceDeclarations = new ArrayList<ServiceDeclaration>(); 109 110 private ServiceDeclaration addDeclaration() { 111 synchronized (mServiceDeclarations) { 112 mServiceDeclarations.add(new ServiceDeclaration()); 113 } 114 return getActiveDeclaration(); 115 } 116 117 private ServiceDeclaration getActiveDeclaration() { 118 synchronized (mServiceDeclarations) { 119 if (mServiceDeclarations.size() > 0) 120 return mServiceDeclarations.get(mServiceDeclarations.size() - 1); 121 } 122 return null; 123 } 124 125 private ServiceDeclaration getPendingDeclaration() { 126 synchronized (mServiceDeclarations) { 127 if (mServiceDeclarations.size() > 0) 128 return mServiceDeclarations.get(0); 129 } 130 return null; 131 } 132 133 private void removePendingDeclaration() { 134 synchronized (mServiceDeclarations) { 135 if (mServiceDeclarations.size() > 0) 136 mServiceDeclarations.remove(0); 137 } 138 } 139 140 private AdvertiseManager mAdvertiseManager; 141 private ScanManager mScanManager; 142 143 /** 144 * Reliable write queue 145 */ 146 private Set<String> mReliableQueue = new HashSet<String>(); 147 148 static { 149 classInitNative(); 150 } 151 152 protected String getName() { 153 return TAG; 154 } 155 156 protected IProfileServiceBinder initBinder() { 157 return new BluetoothGattBinder(this); 158 } 159 160 protected boolean start() { 161 if (DBG) Log.d(TAG, "start()"); 162 initializeNative(); 163 mAdvertiseManager = new AdvertiseManager(this); 164 mAdvertiseManager.start(); 165 166 mScanManager = new ScanManager(this); 167 mScanManager.start(); 168 169 return true; 170 } 171 172 protected boolean stop() { 173 if (DBG) Log.d(TAG, "stop()"); 174 mClientMap.clear(); 175 mServerMap.clear(); 176 mSearchQueue.clear(); 177 mHandleMap.clear(); 178 mServiceDeclarations.clear(); 179 mReliableQueue.clear(); 180 if (mAdvertiseManager != null) mAdvertiseManager.cleanup(); 181 if (mScanManager != null) mScanManager.cleanup(); 182 return true; 183 } 184 185 protected boolean cleanup() { 186 if (DBG) Log.d(TAG, "cleanup()"); 187 cleanupNative(); 188 if (mAdvertiseManager != null) mAdvertiseManager.cleanup(); 189 if (mScanManager != null) mScanManager.cleanup(); 190 return true; 191 } 192 193 @Override 194 public int onStartCommand(Intent intent, int flags, int startId) { 195 if (GattDebugUtils.handleDebugAction(this, intent)) { 196 return Service.START_NOT_STICKY; 197 } 198 return super.onStartCommand(intent, flags, startId); 199 } 200 201 /** 202 * DeathReceipient handlers used to unregister applications that 203 * disconnect ungracefully (ie. crash or forced close). 204 */ 205 206 class ClientDeathRecipient implements IBinder.DeathRecipient { 207 int mAppIf; 208 209 public ClientDeathRecipient(int appIf) { 210 mAppIf = appIf; 211 } 212 213 @Override 214 public void binderDied() { 215 if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 216 217 if (isScanClient(mAppIf)) { 218 ScanClient client = new ScanClient(mAppIf, false); 219 client.appDied = true; 220 stopScan(client); 221 } else { 222 AdvertiseClient client = new AdvertiseClient(mAppIf); 223 client.appDied = true; 224 stopMultiAdvertising(client); 225 } 226 } 227 228 private boolean isScanClient(int clientIf) { 229 for (ScanClient client : mScanManager.getRegularScanQueue()) { 230 if (client.clientIf == clientIf) { 231 return true; 232 } 233 } 234 for (ScanClient client : mScanManager.getBatchScanQueue()) { 235 if (client.clientIf == clientIf) { 236 return true; 237 } 238 } 239 return false; 240 } 241 } 242 243 class ServerDeathRecipient implements IBinder.DeathRecipient { 244 int mAppIf; 245 246 public ServerDeathRecipient(int appIf) { 247 mAppIf = appIf; 248 } 249 250 public void binderDied() { 251 if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 252 unregisterServer(mAppIf); 253 } 254 } 255 256 /** 257 * Handlers for incoming service calls 258 */ 259 private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder { 260 private GattService mService; 261 262 public BluetoothGattBinder(GattService svc) { 263 mService = svc; 264 } 265 266 public boolean cleanup() { 267 mService = null; 268 return true; 269 } 270 271 private GattService getService() { 272 if (mService != null && mService.isAvailable()) return mService; 273 Log.e(TAG, "getService() - Service requested, but not available!"); 274 return null; 275 } 276 277 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 278 GattService service = getService(); 279 if (service == null) return new ArrayList<BluetoothDevice>(); 280 return service.getDevicesMatchingConnectionStates(states); 281 } 282 283 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 284 GattService service = getService(); 285 if (service == null) return; 286 service.registerClient(uuid.getUuid(), callback); 287 } 288 289 public void unregisterClient(int clientIf) { 290 GattService service = getService(); 291 if (service == null) return; 292 service.unregisterClient(clientIf); 293 } 294 295 @Override 296 public void startScan(int appIf, boolean isServer, ScanSettings settings, 297 List<ScanFilter> filters, List storages) { 298 GattService service = getService(); 299 if (service == null) return; 300 service.startScan(appIf, isServer, settings, filters, storages); 301 } 302 303 public void stopScan(int appIf, boolean isServer) { 304 GattService service = getService(); 305 if (service == null) return; 306 service.stopScan(new ScanClient(appIf, isServer)); 307 } 308 309 @Override 310 public void flushPendingBatchResults(int appIf, boolean isServer) { 311 GattService service = getService(); 312 if (service == null) return; 313 service.flushPendingBatchResults(appIf, isServer); 314 } 315 316 public void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 317 GattService service = getService(); 318 if (service == null) return; 319 service.clientConnect(clientIf, address, isDirect, transport); 320 } 321 322 public void clientDisconnect(int clientIf, String address) { 323 GattService service = getService(); 324 if (service == null) return; 325 service.clientDisconnect(clientIf, address); 326 } 327 328 public void refreshDevice(int clientIf, String address) { 329 GattService service = getService(); 330 if (service == null) return; 331 service.refreshDevice(clientIf, address); 332 } 333 334 public void discoverServices(int clientIf, String address) { 335 GattService service = getService(); 336 if (service == null) return; 337 service.discoverServices(clientIf, address); 338 } 339 340 public void readCharacteristic(int clientIf, String address, int srvcType, 341 int srvcInstanceId, ParcelUuid srvcId, 342 int charInstanceId, ParcelUuid charId, 343 int authReq) { 344 GattService service = getService(); 345 if (service == null) return; 346 service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId, 347 srvcId.getUuid(), charInstanceId, 348 charId.getUuid(), authReq); 349 } 350 351 public void writeCharacteristic(int clientIf, String address, int srvcType, 352 int srvcInstanceId, ParcelUuid srvcId, 353 int charInstanceId, ParcelUuid charId, 354 int writeType, int authReq, byte[] value) { 355 GattService service = getService(); 356 if (service == null) return; 357 service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId, 358 srvcId.getUuid(), charInstanceId, 359 charId.getUuid(), writeType, authReq, 360 value); 361 } 362 363 public void readDescriptor(int clientIf, String address, int srvcType, 364 int srvcInstanceId, ParcelUuid srvcId, 365 int charInstanceId, ParcelUuid charId, 366 int descrInstanceId, ParcelUuid descrId, 367 int authReq) { 368 GattService service = getService(); 369 if (service == null) return; 370 service.readDescriptor(clientIf, address, srvcType, 371 srvcInstanceId, srvcId.getUuid(), 372 charInstanceId, charId.getUuid(), 373 descrInstanceId, descrId.getUuid(), 374 authReq); 375 } 376 377 public void writeDescriptor(int clientIf, String address, int srvcType, 378 int srvcInstanceId, ParcelUuid srvcId, 379 int charInstanceId, ParcelUuid charId, 380 int descrInstanceId, ParcelUuid descrId, 381 int writeType, int authReq, byte[] value) { 382 GattService service = getService(); 383 if (service == null) return; 384 service.writeDescriptor(clientIf, address, srvcType, 385 srvcInstanceId, srvcId.getUuid(), 386 charInstanceId, charId.getUuid(), 387 descrInstanceId, descrId.getUuid(), 388 writeType, authReq, value); 389 } 390 391 public void beginReliableWrite(int clientIf, String address) { 392 GattService service = getService(); 393 if (service == null) return; 394 service.beginReliableWrite(clientIf, address); 395 } 396 397 public void endReliableWrite(int clientIf, String address, boolean execute) { 398 GattService service = getService(); 399 if (service == null) return; 400 service.endReliableWrite(clientIf, address, execute); 401 } 402 403 public void registerForNotification(int clientIf, String address, int srvcType, 404 int srvcInstanceId, ParcelUuid srvcId, 405 int charInstanceId, ParcelUuid charId, 406 boolean enable) { 407 GattService service = getService(); 408 if (service == null) return; 409 service.registerForNotification(clientIf, address, srvcType, srvcInstanceId, 410 srvcId.getUuid(), charInstanceId, 411 charId.getUuid(), enable); 412 } 413 414 public void readRemoteRssi(int clientIf, String address) { 415 GattService service = getService(); 416 if (service == null) return; 417 service.readRemoteRssi(clientIf, address); 418 } 419 420 public void configureMTU(int clientIf, String address, int mtu) { 421 GattService service = getService(); 422 if (service == null) return; 423 service.configureMTU(clientIf, address, mtu); 424 } 425 426 public void connectionParameterUpdate(int clientIf, String address, 427 int connectionPriority) { 428 GattService service = getService(); 429 if (service == null) return; 430 service.connectionParameterUpdate(clientIf, address, connectionPriority); 431 } 432 433 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 434 GattService service = getService(); 435 if (service == null) return; 436 service.registerServer(uuid.getUuid(), callback); 437 } 438 439 public void unregisterServer(int serverIf) { 440 GattService service = getService(); 441 if (service == null) return; 442 service.unregisterServer(serverIf); 443 } 444 445 public void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 446 GattService service = getService(); 447 if (service == null) return; 448 service.serverConnect(serverIf, address, isDirect, transport); 449 } 450 451 public void serverDisconnect(int serverIf, String address) { 452 GattService service = getService(); 453 if (service == null) return; 454 service.serverDisconnect(serverIf, address); 455 } 456 457 public void beginServiceDeclaration(int serverIf, int srvcType, 458 int srvcInstanceId, int minHandles, 459 ParcelUuid srvcId, boolean advertisePreferred) { 460 GattService service = getService(); 461 if (service == null) return; 462 service.beginServiceDeclaration(serverIf, srvcType, srvcInstanceId, 463 minHandles, srvcId.getUuid(), advertisePreferred); 464 } 465 466 public void addIncludedService(int serverIf, int srvcType, 467 int srvcInstanceId, ParcelUuid srvcId) { 468 GattService service = getService(); 469 if (service == null) return; 470 service.addIncludedService(serverIf, srvcType, srvcInstanceId, 471 srvcId.getUuid()); 472 } 473 474 public void addCharacteristic(int serverIf, ParcelUuid charId, 475 int properties, int permissions) { 476 GattService service = getService(); 477 if (service == null) return; 478 service.addCharacteristic(serverIf, charId.getUuid(), properties, 479 permissions); 480 } 481 482 public void addDescriptor(int serverIf, ParcelUuid descId, 483 int permissions) { 484 GattService service = getService(); 485 if (service == null) return; 486 service.addDescriptor(serverIf, descId.getUuid(), permissions); 487 } 488 489 public void endServiceDeclaration(int serverIf) { 490 GattService service = getService(); 491 if (service == null) return; 492 service.endServiceDeclaration(serverIf); 493 } 494 495 public void removeService(int serverIf, int srvcType, 496 int srvcInstanceId, ParcelUuid srvcId) { 497 GattService service = getService(); 498 if (service == null) return; 499 service.removeService(serverIf, srvcType, srvcInstanceId, 500 srvcId.getUuid()); 501 } 502 503 public void clearServices(int serverIf) { 504 GattService service = getService(); 505 if (service == null) return; 506 service.clearServices(serverIf); 507 } 508 509 public void sendResponse(int serverIf, String address, int requestId, 510 int status, int offset, byte[] value) { 511 GattService service = getService(); 512 if (service == null) return; 513 service.sendResponse(serverIf, address, requestId, status, offset, value); 514 } 515 516 public void sendNotification(int serverIf, String address, int srvcType, 517 int srvcInstanceId, ParcelUuid srvcId, 518 int charInstanceId, ParcelUuid charId, 519 boolean confirm, byte[] value) { 520 GattService service = getService(); 521 if (service == null) return; 522 service.sendNotification(serverIf, address, srvcType, srvcInstanceId, 523 srvcId.getUuid(), charInstanceId, charId.getUuid(), confirm, value); 524 } 525 526 @Override 527 public void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 528 AdvertiseData scanResponse, AdvertiseSettings settings) { 529 GattService service = getService(); 530 if (service == null) return; 531 service.startMultiAdvertising(clientIf, advertiseData, scanResponse, settings); 532 } 533 534 @Override 535 public void stopMultiAdvertising(int clientIf) { 536 GattService service = getService(); 537 if (service == null) return; 538 service.stopMultiAdvertising(new AdvertiseClient(clientIf)); 539 } 540 }; 541 542 /************************************************************************** 543 * Callback functions - CLIENT 544 *************************************************************************/ 545 546 void onScanResult(String address, int rssi, byte[] adv_data) { 547 if (VDBG) Log.d(TAG, "onScanResult() - address=" + address 548 + ", rssi=" + rssi); 549 ScanRecord record = ScanRecord.parseFromBytes(adv_data); 550 List<UUID> remoteUuids = parseUuids(adv_data); 551 for (ScanClient client : mScanManager.getRegularScanQueue()) { 552 if (client.uuids.length > 0) { 553 int matches = 0; 554 for (UUID search : client.uuids) { 555 for (UUID remote: remoteUuids) { 556 if (remote.equals(search)) { 557 ++matches; 558 break; // Only count 1st match in case of duplicates 559 } 560 } 561 } 562 563 if (matches < client.uuids.length) continue; 564 } 565 566 if (!client.isServer) { 567 ClientMap.App app = mClientMap.getById(client.clientIf); 568 if (app != null) { 569 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() 570 .getRemoteDevice(address); 571 ScanResult result = new ScanResult(device, ScanRecord.parseFromBytes(adv_data), 572 rssi, SystemClock.elapsedRealtimeNanos()); 573 if (matchesFilters(client, result)) { 574 try { 575 ScanSettings settings = client.settings; 576 // framework detects the first match, hw signal is 577 // used to detect the onlost 578 // ToDo: make scanClient+result, 1 to many when hw 579 // support is available 580 if ((settings.getCallbackType() & 581 ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0) { 582 synchronized (mOnFoundResults) { 583 mOnFoundResults.put(client, result); 584 } 585 app.callback.onFoundOrLost(true, result); 586 } 587 if ((settings.getCallbackType() & 588 ScanSettings.CALLBACK_TYPE_ALL_MATCHES) != 0) { 589 app.callback.onScanResult(result); 590 } 591 } catch (RemoteException e) { 592 Log.e(TAG, "Exception: " + e); 593 mClientMap.remove(client.clientIf); 594 mScanManager.stopScan(client); 595 } 596 } 597 } 598 } else { 599 ServerMap.App app = mServerMap.getById(client.clientIf); 600 if (app != null) { 601 try { 602 app.callback.onScanResult(address, rssi, adv_data); 603 } catch (RemoteException e) { 604 Log.e(TAG, "Exception: " + e); 605 mServerMap.remove(client.clientIf); 606 mScanManager.stopScan(client); 607 } 608 } 609 } 610 } 611 } 612 613 // Check if a scan record matches a specific filters. 614 private boolean matchesFilters(ScanClient client, ScanResult scanResult) { 615 if (client.filters == null || client.filters.isEmpty()) { 616 return true; 617 } 618 if (DBG) Log.d(TAG, "result: " + scanResult.toString()); 619 for (ScanFilter filter : client.filters) { 620 if (DBG) Log.d(TAG, "filter: " + filter.toString()); 621 if (filter.matches(scanResult)) { 622 return true; 623 } 624 } 625 return false; 626 } 627 628 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 629 throws RemoteException { 630 UUID uuid = new UUID(uuidMsb, uuidLsb); 631 if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 632 ClientMap.App app = mClientMap.getByUuid(uuid); 633 if (app != null) { 634 app.id = clientIf; 635 app.linkToDeath(new ClientDeathRecipient(clientIf)); 636 app.callback.onClientRegistered(status, clientIf); 637 } 638 } 639 640 void onConnected(int clientIf, int connId, int status, String address) 641 throws RemoteException { 642 if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 643 + ", connId=" + connId + ", address=" + address); 644 645 if (status == 0) mClientMap.addConnection(clientIf, connId, address); 646 ClientMap.App app = mClientMap.getById(clientIf); 647 if (app != null) { 648 app.callback.onClientConnectionState(status, clientIf, true, address); 649 } 650 } 651 652 void onDisconnected(int clientIf, int connId, int status, String address) 653 throws RemoteException { 654 if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 655 + ", connId=" + connId + ", address=" + address); 656 657 mClientMap.removeConnection(clientIf, connId); 658 mSearchQueue.removeConnId(connId); 659 ClientMap.App app = mClientMap.getById(clientIf); 660 if (app != null) { 661 app.callback.onClientConnectionState(status, clientIf, false, address); 662 } 663 } 664 665 void onSearchCompleted(int connId, int status) throws RemoteException { 666 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 667 // We got all services, now let's explore characteristics... 668 continueSearch(connId, status); 669 } 670 671 void onSearchResult(int connId, int srvcType, 672 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb) 673 throws RemoteException { 674 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 675 String address = mClientMap.addressByConnId(connId); 676 677 if (VDBG) Log.d(TAG, "onSearchResult() - address=" + address + ", uuid=" + uuid); 678 679 mSearchQueue.add(connId, srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb); 680 681 ClientMap.App app = mClientMap.getByConnId(connId); 682 if (app != null) { 683 app.callback.onGetService(address, srvcType, srvcInstId, 684 new ParcelUuid(uuid)); 685 } 686 } 687 688 void onGetCharacteristic(int connId, int status, int srvcType, 689 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 690 int charInstId, long charUuidLsb, long charUuidMsb, 691 int charProp) throws RemoteException { 692 693 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 694 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 695 String address = mClientMap.addressByConnId(connId); 696 697 if (VDBG) Log.d(TAG, "onGetCharacteristic() - address=" + address 698 + ", status=" + status + ", charUuid=" + charUuid + ", prop=" + charProp); 699 700 if (status == 0) { 701 mSearchQueue.add(connId, srvcType, 702 srvcInstId, srvcUuidLsb, srvcUuidMsb, 703 charInstId, charUuidLsb, charUuidMsb); 704 705 ClientMap.App app = mClientMap.getByConnId(connId); 706 if (app != null) { 707 app.callback.onGetCharacteristic(address, srvcType, 708 srvcInstId, new ParcelUuid(srvcUuid), 709 charInstId, new ParcelUuid(charUuid), charProp); 710 } 711 712 // Get next characteristic in the current service 713 gattClientGetCharacteristicNative(connId, srvcType, 714 srvcInstId, srvcUuidLsb, srvcUuidMsb, 715 charInstId, charUuidLsb, charUuidMsb); 716 } else { 717 // Check for included services next 718 gattClientGetIncludedServiceNative(connId, 719 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 720 0,0,0,0); 721 } 722 } 723 724 void onGetDescriptor(int connId, int status, int srvcType, 725 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 726 int charInstId, long charUuidLsb, long charUuidMsb, 727 int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 728 729 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 730 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 731 UUID descUuid = new UUID(descrUuidMsb, descrUuidLsb); 732 String address = mClientMap.addressByConnId(connId); 733 734 if (VDBG) Log.d(TAG, "onGetDescriptor() - address=" + address 735 + ", status=" + status + ", descUuid=" + descUuid); 736 737 if (status == 0) { 738 ClientMap.App app = mClientMap.getByConnId(connId); 739 if (app != null) { 740 app.callback.onGetDescriptor(address, srvcType, 741 srvcInstId, new ParcelUuid(srvcUuid), 742 charInstId, new ParcelUuid(charUuid), 743 descrInstId, new ParcelUuid(descUuid)); 744 } 745 746 // Get next descriptor for the current characteristic 747 gattClientGetDescriptorNative(connId, srvcType, 748 srvcInstId, srvcUuidLsb, srvcUuidMsb, 749 charInstId, charUuidLsb, charUuidMsb, 750 descrInstId, descrUuidLsb, descrUuidMsb); 751 } else { 752 // Explore the next service 753 continueSearch(connId, 0); 754 } 755 } 756 757 void onGetIncludedService(int connId, int status, int srvcType, 758 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType, 759 int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb) 760 throws RemoteException { 761 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 762 UUID inclSrvcUuid = new UUID(inclSrvcUuidMsb, inclSrvcUuidLsb); 763 String address = mClientMap.addressByConnId(connId); 764 765 if (VDBG) Log.d(TAG, "onGetIncludedService() - address=" + address 766 + ", status=" + status + ", uuid=" + srvcUuid 767 + ", inclUuid=" + inclSrvcUuid); 768 769 if (status == 0) { 770 ClientMap.App app = mClientMap.getByConnId(connId); 771 if (app != null) { 772 app.callback.onGetIncludedService(address, 773 srvcType, srvcInstId, new ParcelUuid(srvcUuid), 774 inclSrvcType, inclSrvcInstId, new ParcelUuid(inclSrvcUuid)); 775 } 776 777 // Find additional included services 778 gattClientGetIncludedServiceNative(connId, 779 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb, 780 inclSrvcType, inclSrvcInstId, inclSrvcUuidLsb, inclSrvcUuidMsb); 781 } else { 782 // Discover descriptors now 783 continueSearch(connId, 0); 784 } 785 } 786 787 void onRegisterForNotifications(int connId, int status, int registered, int srvcType, 788 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 789 int charInstId, long charUuidLsb, long charUuidMsb) { 790 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 791 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 792 String address = mClientMap.addressByConnId(connId); 793 794 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 795 + ", status=" + status + ", registered=" + registered 796 + ", charUuid=" + charUuid); 797 } 798 799 void onNotify(int connId, String address, int srvcType, 800 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 801 int charInstId, long charUuidLsb, long charUuidMsb, 802 boolean isNotify, byte[] data) throws RemoteException { 803 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 804 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 805 806 if (VDBG) Log.d(TAG, "onNotify() - address=" + address 807 + ", charUuid=" + charUuid + ", length=" + data.length); 808 809 ClientMap.App app = mClientMap.getByConnId(connId); 810 if (app != null) { 811 app.callback.onNotify(address, srvcType, 812 srvcInstId, new ParcelUuid(srvcUuid), 813 charInstId, new ParcelUuid(charUuid), 814 data); 815 } 816 } 817 818 void onReadCharacteristic(int connId, int status, int srvcType, 819 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 820 int charInstId, long charUuidLsb, long charUuidMsb, 821 int charType, byte[] data) throws RemoteException { 822 823 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 824 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 825 String address = mClientMap.addressByConnId(connId); 826 827 if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 828 + ", status=" + status + ", length=" + data.length); 829 830 ClientMap.App app = mClientMap.getByConnId(connId); 831 if (app != null) { 832 app.callback.onCharacteristicRead(address, status, srvcType, 833 srvcInstId, new ParcelUuid(srvcUuid), 834 charInstId, new ParcelUuid(charUuid), data); 835 } 836 } 837 838 void onWriteCharacteristic(int connId, int status, int srvcType, 839 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 840 int charInstId, long charUuidLsb, long charUuidMsb) 841 throws RemoteException { 842 843 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 844 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 845 String address = mClientMap.addressByConnId(connId); 846 847 if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 848 + ", status=" + status); 849 850 ClientMap.App app = mClientMap.getByConnId(connId); 851 if (app != null) { 852 app.callback.onCharacteristicWrite(address, status, srvcType, 853 srvcInstId, new ParcelUuid(srvcUuid), 854 charInstId, new ParcelUuid(charUuid)); 855 } 856 } 857 858 void onExecuteCompleted(int connId, int status) throws RemoteException { 859 String address = mClientMap.addressByConnId(connId); 860 if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 861 + ", status=" + status); 862 863 ClientMap.App app = mClientMap.getByConnId(connId); 864 if (app != null) { 865 app.callback.onExecuteWrite(address, status); 866 } 867 } 868 869 void onReadDescriptor(int connId, int status, int srvcType, 870 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 871 int charInstId, long charUuidLsb, long charUuidMsb, 872 int descrInstId, long descrUuidLsb, long descrUuidMsb, 873 int charType, byte[] data) throws RemoteException { 874 875 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 876 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 877 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 878 String address = mClientMap.addressByConnId(connId); 879 880 if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address 881 + ", status=" + status + ", length=" + data.length); 882 883 ClientMap.App app = mClientMap.getByConnId(connId); 884 if (app != null) { 885 app.callback.onDescriptorRead(address, status, srvcType, 886 srvcInstId, new ParcelUuid(srvcUuid), 887 charInstId, new ParcelUuid(charUuid), 888 descrInstId, new ParcelUuid(descrUuid), data); 889 } 890 } 891 892 void onWriteDescriptor(int connId, int status, int srvcType, 893 int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, 894 int charInstId, long charUuidLsb, long charUuidMsb, 895 int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException { 896 897 UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb); 898 UUID charUuid = new UUID(charUuidMsb, charUuidLsb); 899 UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb); 900 String address = mClientMap.addressByConnId(connId); 901 902 if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 903 + ", status=" + status); 904 905 ClientMap.App app = mClientMap.getByConnId(connId); 906 if (app != null) { 907 app.callback.onDescriptorWrite(address, status, srvcType, 908 srvcInstId, new ParcelUuid(srvcUuid), 909 charInstId, new ParcelUuid(charUuid), 910 descrInstId, new ParcelUuid(descrUuid)); 911 } 912 } 913 914 void onReadRemoteRssi(int clientIf, String address, 915 int rssi, int status) throws RemoteException{ 916 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 917 address + ", rssi=" + rssi + ", status=" + status); 918 919 ClientMap.App app = mClientMap.getById(clientIf); 920 if (app != null) { 921 app.callback.onReadRemoteRssi(address, rssi, status); 922 } 923 } 924 925 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 926 if (DBG) { 927 Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 928 + ", action=" + action); 929 } 930 mScanManager.callbackDone(clientIf, status); 931 } 932 933 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 934 if (DBG) { 935 Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf 936 + ", status=" + status + ", action=" + action 937 + ", availableSpace=" + availableSpace); 938 } 939 mScanManager.callbackDone(clientIf, status); 940 } 941 942 void onScanFilterConfig(int action, int status, int clientIf, int filterType, 943 int availableSpace) { 944 if (DBG) { 945 Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 946 + " status = " + status + ", filterType=" + filterType 947 + ", availableSpace=" + availableSpace); 948 } 949 950 mScanManager.callbackDone(clientIf, status); 951 } 952 953 void onBatchScanStorageConfigured(int status, int clientIf) { 954 if (DBG) { 955 Log.d(TAG, "onBatchScanStorageConfigured() - clientIf="+ clientIf + ", status=" + status); 956 } 957 mScanManager.callbackDone(clientIf, status); 958 } 959 960 // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. 961 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 962 if (DBG) { 963 Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf 964 + ", status=" + status + ", startStopAction=" + startStopAction); 965 } 966 mScanManager.callbackDone(clientIf, status); 967 } 968 969 void onBatchScanReports(int status, int clientIf, int reportType, int numRecords, 970 byte[] recordData) throws RemoteException { 971 if (DBG) { 972 Log.d(TAG, "onBatchScanReports() - clientIf=" + clientIf + ", status=" + status 973 + ", reportType=" + reportType + ", numRecords=" + numRecords); 974 } 975 mScanManager.callbackDone(clientIf, status); 976 Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 977 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 978 // We only support single client for truncated mode. 979 ClientMap.App app = mClientMap.getById(clientIf); 980 if (app == null) return; 981 app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); 982 } else { 983 for (ScanClient client : mScanManager.getBatchScanQueue()) { 984 // Deliver results for each client. 985 deliverBatchScan(client, results); 986 } 987 } 988 } 989 990 // Check and deliver scan results for different scan clients. 991 private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws 992 RemoteException { 993 ClientMap.App app = mClientMap.getById(client.clientIf); 994 if (app == null) return; 995 if (client.filters == null || client.filters.isEmpty()) { 996 app.callback.onBatchScanResults(new ArrayList<ScanResult>(allResults)); 997 } 998 // Reconstruct the scan results. 999 List<ScanResult> results = new ArrayList<ScanResult>(); 1000 for (ScanResult scanResult : allResults) { 1001 if (matchesFilters(client, scanResult)) { 1002 results.add(scanResult); 1003 } 1004 } 1005 app.callback.onBatchScanResults(results); 1006 } 1007 1008 private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 1009 byte[] batchRecord) { 1010 if (numRecords == 0) { 1011 return Collections.emptySet(); 1012 } 1013 if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 1014 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1015 return parseTruncatedResults(numRecords, batchRecord); 1016 } else { 1017 return parseFullResults(numRecords, batchRecord); 1018 } 1019 } 1020 1021 private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 1022 if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 1023 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1024 for (int i = 0; i < numRecords; ++i) { 1025 byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, 1026 TRUNCATED_RESULT_SIZE); 1027 byte[] address = extractBytes(record, 0, 6); 1028 // TODO: remove temp hack. 1029 reverse(address); 1030 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1031 int rssi = record[8]; 1032 // Timestamp is in every 50 ms. 1033 long timestampNanos = parseTimestampNanos(extractBytes(record, 9, 2)); 1034 results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), 1035 rssi, timestampNanos)); 1036 } 1037 return results; 1038 } 1039 1040 private long parseTimestampNanos(byte[] data) { 1041 long timestampUnit = data[1] & 0xFF << 8 + data[0]; 1042 long timestampNanos = SystemClock.elapsedRealtimeNanos() - 1043 TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 1044 return timestampNanos; 1045 } 1046 1047 private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 1048 Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 1049 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1050 int position = 0; 1051 while (position < batchRecord.length) { 1052 byte[] address = extractBytes(batchRecord, position, 6); 1053 // TODO: remove temp hack. 1054 reverse(address); 1055 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1056 position += 6; 1057 // Skip address type. 1058 position++; 1059 // Skip tx power level. 1060 position++; 1061 int rssi = batchRecord[position++]; 1062 long timestampNanos = parseTimestampNanos(extractBytes(batchRecord, position, 2)); 1063 position += 2; 1064 1065 // Combine advertise packet and scan response packet. 1066 int advertisePacketLen = batchRecord[position++]; 1067 byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 1068 position += advertisePacketLen; 1069 int scanResponsePacketLen = batchRecord[position++]; 1070 byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 1071 position += scanResponsePacketLen; 1072 byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 1073 System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 1074 System.arraycopy(scanResponseBytes, 0, scanRecord, 1075 advertisePacketLen, scanResponsePacketLen); 1076 Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 1077 results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), 1078 rssi, timestampNanos)); 1079 } 1080 return results; 1081 } 1082 1083 // Reverse byte array. 1084 private void reverse(byte[] address) { 1085 int len = address.length; 1086 for (int i = 0; i < len / 2; ++i) { 1087 byte b = address[i]; 1088 address[i] = address[len - 1 - i]; 1089 address[len - 1 - i] = b; 1090 } 1091 } 1092 1093 // Helper method to extract bytes from byte array. 1094 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 1095 byte[] bytes = new byte[length]; 1096 System.arraycopy(scanRecord, start, bytes, 0, length); 1097 return bytes; 1098 } 1099 1100 void onBatchScanThresholdCrossed(int clientIf) { 1101 if (DBG) { 1102 Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 1103 } 1104 boolean isServer = false; 1105 flushPendingBatchResults(clientIf, isServer); 1106 } 1107 1108 void onTrackAdvFoundLost(int filterIndex, int addrType, String address, int advState, 1109 int clientIf) throws RemoteException { 1110 if (DBG) Log.d(TAG, "onClientAdvertiserFoundLost() - clientIf=" 1111 + clientIf + "address = " + address + "adv_state = " 1112 + advState + "client_if = " + clientIf); 1113 ClientMap.App app = mClientMap.getById(clientIf); 1114 if (app == null || app.callback == null) { 1115 Log.e(TAG, "app or callback is null"); 1116 return; 1117 } 1118 1119 // use hw signal for only onlost reporting 1120 if (advState != ADVT_STATE_ONLOST) { 1121 return; 1122 } 1123 1124 for (ScanClient client : mScanManager.getRegularScanQueue()) { 1125 if (client.clientIf == clientIf) { 1126 ScanSettings settings = client.settings; 1127 if ((settings.getCallbackType() & 1128 ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { 1129 1130 while (!mOnFoundResults.isEmpty()) { 1131 ScanResult result = mOnFoundResults.get(client); 1132 app.callback.onFoundOrLost(false, result); 1133 synchronized (mOnFoundResults) { 1134 mOnFoundResults.remove(client); 1135 } 1136 } 1137 } 1138 } 1139 } 1140 } 1141 1142 // callback from AdvertiseManager for advertise status dispatch. 1143 void onMultipleAdvertiseCallback(int clientIf, int status, boolean isStart, 1144 AdvertiseSettings settings) throws RemoteException { 1145 ClientMap.App app = mClientMap.getById(clientIf); 1146 if (app == null || app.callback == null) { 1147 Log.e(TAG, "Advertise app or callback is null"); 1148 return; 1149 } 1150 app.callback.onMultiAdvertiseCallback(status, isStart, settings); 1151 } 1152 1153 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 1154 String address = mClientMap.addressByConnId(connId); 1155 1156 if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 1157 + status + ", mtu=" + mtu); 1158 1159 ClientMap.App app = mClientMap.getByConnId(connId); 1160 if (app != null) { 1161 app.callback.onConfigureMTU(address, mtu, status); 1162 } 1163 } 1164 1165 // Callback for standard advertising instance. 1166 void onAdvertiseCallback(int status, int clientIf) { 1167 if (DBG) Log.d(TAG, "onAdvertiseCallback,- clientIf=" + clientIf + ", status=" + status); 1168 } 1169 1170 // Followings are callbacks for Bluetooth LE Advertise operations. 1171 // Start advertising flow is 1172 // enable advertising instance -> onAdvertiseInstaceEnabled 1173 // -> set advertise data -> onAdvertiseDataSet 1174 // -> set scan response -> onAdvertiseDataSet 1175 1176 // Callback when advertise instance is enabled. 1177 void onAdvertiseInstanceEnabled(int status, int clientIf) { 1178 if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - " 1179 + "clientIf=" + clientIf + ", status=" + status); 1180 mAdvertiseManager.callbackDone(clientIf, status); 1181 } 1182 1183 // Not really used. 1184 void onAdvertiseDataUpdated(int status, int client_if) { 1185 if (DBG) Log.d(TAG, "onAdvertiseDataUpdated() - client_if=" + client_if 1186 + ", status=" + status); 1187 } 1188 1189 // Callback when advertise data or scan response is set. 1190 void onAdvertiseDataSet(int status, int clientIf) { 1191 if (DBG) Log.d(TAG, "onAdvertiseDataSet() - clientIf=" + clientIf 1192 + ", status=" + status); 1193 mAdvertiseManager.callbackDone(clientIf, status); 1194 } 1195 1196 // Callback when advertise instance is disabled 1197 void onAdvertiseInstanceDisabled(int status, int clientIf) throws RemoteException { 1198 if (DBG) Log.d(TAG, "onAdvertiseInstanceDisabled() - clientIf=" + clientIf 1199 + ", status=" + status); 1200 ClientMap.App app = mClientMap.getById(clientIf); 1201 if (app != null) { 1202 Log.d(TAG, "Client app is not null!"); 1203 boolean isStart = false; 1204 if (status == 0) { 1205 app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS, 1206 isStart, null); 1207 } else { 1208 app.callback.onMultiAdvertiseCallback( 1209 AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR, isStart, null); 1210 } 1211 } 1212 } 1213 1214 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1215 if (DBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1216 1217 ClientMap.App app = mClientMap.getByConnId(connId); 1218 if (app != null) { 1219 app.callback.onConnectionCongested(mClientMap.addressByConnId(connId), congested); 1220 } 1221 } 1222 1223 /************************************************************************** 1224 * GATT Service functions - Shared CLIENT/SERVER 1225 *************************************************************************/ 1226 1227 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1228 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1229 1230 final int DEVICE_TYPE_BREDR = 0x1; 1231 1232 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1233 Integer>(); 1234 1235 // Add paired LE devices 1236 1237 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1238 for (BluetoothDevice device : bondedDevices) { 1239 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1240 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1241 } 1242 } 1243 1244 // Add connected deviceStates 1245 1246 Set<String> connectedDevices = new HashSet<String>(); 1247 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1248 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1249 1250 for (String address : connectedDevices ) { 1251 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1252 if (device != null) { 1253 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1254 } 1255 } 1256 1257 // Create matching device sub-set 1258 1259 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1260 1261 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1262 for(int state : states) { 1263 if (entry.getValue() == state) { 1264 deviceList.add(entry.getKey()); 1265 } 1266 } 1267 } 1268 1269 return deviceList; 1270 } 1271 1272 void startScan(int appIf, boolean isServer, ScanSettings settings, 1273 List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages) { 1274 if (DBG) Log.d(TAG, "start scan with filters"); 1275 enforceAdminPermission(); 1276 mScanManager.startScan(new ScanClient(appIf, isServer, settings, filters, storages)); 1277 } 1278 1279 void flushPendingBatchResults(int clientIf, boolean isServer) { 1280 if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + 1281 ", isServer=" + isServer); 1282 mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); 1283 } 1284 1285 void stopScan(ScanClient client) { 1286 enforceAdminPermission(); 1287 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1288 mScanManager.getRegularScanQueue().size(); 1289 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1290 mScanManager.stopScan(client); 1291 } 1292 1293 /************************************************************************** 1294 * GATT Service functions - CLIENT 1295 *************************************************************************/ 1296 1297 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1298 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1299 1300 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1301 mClientMap.add(uuid, callback); 1302 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1303 uuid.getMostSignificantBits()); 1304 } 1305 1306 void unregisterClient(int clientIf) { 1307 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1308 1309 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1310 mClientMap.remove(clientIf); 1311 gattClientUnregisterAppNative(clientIf); 1312 } 1313 1314 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1315 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1316 1317 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1318 gattClientConnectNative(clientIf, address, isDirect, transport); 1319 } 1320 1321 void clientDisconnect(int clientIf, String address) { 1322 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1323 1324 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1325 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1326 1327 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1328 } 1329 1330 void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 1331 AdvertiseData scanResponse, AdvertiseSettings settings) { 1332 enforceAdminPermission(); 1333 mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData, 1334 scanResponse)); 1335 } 1336 1337 void stopMultiAdvertising(AdvertiseClient client) { 1338 enforceAdminPermission(); 1339 mAdvertiseManager.stopAdvertising(client); 1340 } 1341 1342 1343 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1344 Utils.enforceAdminPermission(this); 1345 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1346 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1347 serviceUuids.add(new ParcelUuid(entry.uuid)); 1348 } 1349 return serviceUuids; 1350 } 1351 1352 List<String> getConnectedDevices() { 1353 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1354 1355 Set<String> connectedDevAddress = new HashSet<String>(); 1356 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1357 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1358 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1359 return connectedDeviceList; 1360 } 1361 1362 void refreshDevice(int clientIf, String address) { 1363 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1364 1365 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1366 gattClientRefreshNative(clientIf, address); 1367 } 1368 1369 void discoverServices(int clientIf, String address) { 1370 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1371 1372 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1373 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1374 1375 if (connId != null) 1376 gattClientSearchServiceNative(connId, true, 0, 0); 1377 else 1378 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1379 } 1380 1381 void readCharacteristic(int clientIf, String address, int srvcType, 1382 int srvcInstanceId, UUID srvcUuid, 1383 int charInstanceId, UUID charUuid, int authReq) { 1384 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1385 1386 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1387 1388 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1389 if (connId != null) 1390 gattClientReadCharacteristicNative(connId, srvcType, 1391 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1392 srvcUuid.getMostSignificantBits(), charInstanceId, 1393 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1394 authReq); 1395 else 1396 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1397 } 1398 1399 void writeCharacteristic(int clientIf, String address, int srvcType, 1400 int srvcInstanceId, UUID srvcUuid, 1401 int charInstanceId, UUID charUuid, int writeType, 1402 int authReq, byte[] value) { 1403 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1404 1405 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1406 1407 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1408 1409 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1410 if (connId != null) 1411 gattClientWriteCharacteristicNative(connId, srvcType, 1412 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1413 srvcUuid.getMostSignificantBits(), charInstanceId, 1414 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1415 writeType, authReq, value); 1416 else 1417 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1418 } 1419 1420 void readDescriptor(int clientIf, String address, int srvcType, 1421 int srvcInstanceId, UUID srvcUuid, 1422 int charInstanceId, UUID charUuid, 1423 int descrInstanceId, UUID descrUuid, 1424 int authReq) { 1425 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1426 1427 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1428 1429 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1430 if (connId != null) 1431 gattClientReadDescriptorNative(connId, srvcType, 1432 srvcInstanceId, 1433 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1434 charInstanceId, 1435 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1436 descrInstanceId, 1437 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1438 authReq); 1439 else 1440 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1441 }; 1442 1443 void writeDescriptor(int clientIf, String address, int srvcType, 1444 int srvcInstanceId, UUID srvcUuid, 1445 int charInstanceId, UUID charUuid, 1446 int descrInstanceId, UUID descrUuid, 1447 int writeType, int authReq, byte[] value) { 1448 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1449 1450 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1451 1452 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1453 if (connId != null) 1454 gattClientWriteDescriptorNative(connId, srvcType, 1455 srvcInstanceId, 1456 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1457 charInstanceId, 1458 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1459 descrInstanceId, 1460 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1461 writeType, authReq, value); 1462 else 1463 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1464 } 1465 1466 void beginReliableWrite(int clientIf, String address) { 1467 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1468 1469 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1470 mReliableQueue.add(address); 1471 } 1472 1473 void endReliableWrite(int clientIf, String address, boolean execute) { 1474 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1475 1476 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1477 + " execute: " + execute); 1478 mReliableQueue.remove(address); 1479 1480 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1481 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1482 } 1483 1484 void registerForNotification(int clientIf, String address, int srvcType, 1485 int srvcInstanceId, UUID srvcUuid, 1486 int charInstanceId, UUID charUuid, 1487 boolean enable) { 1488 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1489 1490 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1491 1492 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1493 if (connId != null) { 1494 gattClientRegisterForNotificationsNative(clientIf, address, 1495 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1496 srvcUuid.getMostSignificantBits(), charInstanceId, 1497 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1498 enable); 1499 } else { 1500 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1501 } 1502 } 1503 1504 void readRemoteRssi(int clientIf, String address) { 1505 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1506 1507 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1508 gattClientReadRemoteRssiNative(clientIf, address); 1509 } 1510 1511 void configureMTU(int clientIf, String address, int mtu) { 1512 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1513 1514 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1515 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1516 if (connId != null) { 1517 gattClientConfigureMTUNative(connId, mtu); 1518 } else { 1519 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1520 } 1521 } 1522 1523 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1524 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1525 1526 // Default spec recommended interval is 30->50 ms 1527 int minInterval = 24; // 24 * 1.25ms = 30ms 1528 int maxInterval = 40; // 40 * 1.25ms = 50ms 1529 1530 // Slave latency 1531 int latency = 0; 1532 1533 // Link supervision timeout is measured in N * 10ms 1534 int timeout = 2000; // 20s 1535 1536 switch (connectionPriority) 1537 { 1538 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1539 minInterval = 6; // 7.5ms 1540 maxInterval = 8; // 10ms 1541 break; 1542 1543 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 1544 minInterval = 80; // 100ms 1545 maxInterval = 100; // 125ms 1546 latency = 2; 1547 break; 1548 } 1549 1550 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1551 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1552 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1553 latency, timeout); 1554 } 1555 1556 /************************************************************************** 1557 * Callback functions - SERVER 1558 *************************************************************************/ 1559 1560 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1561 throws RemoteException { 1562 1563 UUID uuid = new UUID(uuidMsb, uuidLsb); 1564 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1565 ServerMap.App app = mServerMap.getByUuid(uuid); 1566 if (app != null) { 1567 app.id = serverIf; 1568 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1569 app.callback.onServerRegistered(status, serverIf); 1570 } 1571 } 1572 1573 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1574 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1575 throws RemoteException { 1576 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1577 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1578 + ", handle=" + srvcHandle); 1579 if (status == 0) { 1580 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1581 mAdvertisingServiceUuids.remove(uuid)); 1582 } 1583 1584 continueServiceDeclaration(serverIf, status, srvcHandle); 1585 } 1586 1587 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1588 int includedSrvcHandle) throws RemoteException { 1589 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1590 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1591 continueServiceDeclaration(serverIf, status, srvcHandle); 1592 } 1593 1594 void onCharacteristicAdded(int status, int serverIf, 1595 long charUuidLsb, long charUuidMsb, 1596 int srvcHandle, int charHandle) 1597 throws RemoteException { 1598 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1599 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1600 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1601 if (status == 0) 1602 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1603 continueServiceDeclaration(serverIf, status, srvcHandle); 1604 } 1605 1606 void onDescriptorAdded(int status, int serverIf, 1607 long descrUuidLsb, long descrUuidMsb, 1608 int srvcHandle, int descrHandle) 1609 throws RemoteException { 1610 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1611 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1612 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1613 if (status == 0) 1614 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1615 continueServiceDeclaration(serverIf, status, srvcHandle); 1616 } 1617 1618 void onServiceStarted(int status, int serverIf, int srvcHandle) 1619 throws RemoteException { 1620 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1621 + ", status=" + status); 1622 if (status == 0) 1623 mHandleMap.setStarted(serverIf, srvcHandle, true); 1624 } 1625 1626 void onServiceStopped(int status, int serverIf, int srvcHandle) 1627 throws RemoteException { 1628 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1629 + ", status=" + status); 1630 if (status == 0) 1631 mHandleMap.setStarted(serverIf, srvcHandle, false); 1632 stopNextService(serverIf, status); 1633 } 1634 1635 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1636 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1637 + ", status=" + status); 1638 mHandleMap.deleteService(serverIf, srvcHandle); 1639 } 1640 1641 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1642 throws RemoteException { 1643 1644 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1645 + ", address=" + address + ", connected=" + connected); 1646 1647 ServerMap.App app = mServerMap.getById(serverIf); 1648 if (app == null) return; 1649 1650 if (connected) { 1651 mServerMap.addConnection(serverIf, connId, address); 1652 } else { 1653 mServerMap.removeConnection(serverIf, connId); 1654 } 1655 1656 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1657 } 1658 1659 void onAttributeRead(String address, int connId, int transId, 1660 int attrHandle, int offset, boolean isLong) 1661 throws RemoteException { 1662 if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1663 + ", address=" + address + ", handle=" + attrHandle 1664 + ", requestId=" + transId + ", offset=" + offset); 1665 1666 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1667 if (entry == null) return; 1668 1669 if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 1670 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1671 1672 mHandleMap.addRequest(transId, attrHandle); 1673 1674 ServerMap.App app = mServerMap.getById(entry.serverIf); 1675 if (app == null) return; 1676 1677 switch(entry.type) { 1678 case HandleMap.TYPE_CHARACTERISTIC: 1679 { 1680 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1681 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1682 serviceEntry.serviceType, serviceEntry.instance, 1683 new ParcelUuid(serviceEntry.uuid), entry.instance, 1684 new ParcelUuid(entry.uuid)); 1685 break; 1686 } 1687 1688 case HandleMap.TYPE_DESCRIPTOR: 1689 { 1690 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1691 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1692 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1693 serviceEntry.serviceType, serviceEntry.instance, 1694 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1695 new ParcelUuid(charEntry.uuid), 1696 new ParcelUuid(entry.uuid)); 1697 break; 1698 } 1699 1700 default: 1701 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1702 break; 1703 } 1704 } 1705 1706 void onAttributeWrite(String address, int connId, int transId, 1707 int attrHandle, int offset, int length, 1708 boolean needRsp, boolean isPrep, 1709 byte[] data) 1710 throws RemoteException { 1711 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1712 + ", address=" + address + ", handle=" + attrHandle 1713 + ", requestId=" + transId + ", isPrep=" + isPrep 1714 + ", offset=" + offset); 1715 1716 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1717 if (entry == null) return; 1718 1719 if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1720 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1721 1722 mHandleMap.addRequest(transId, attrHandle); 1723 1724 ServerMap.App app = mServerMap.getById(entry.serverIf); 1725 if (app == null) return; 1726 1727 switch(entry.type) { 1728 case HandleMap.TYPE_CHARACTERISTIC: 1729 { 1730 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1731 app.callback.onCharacteristicWriteRequest(address, transId, 1732 offset, length, isPrep, needRsp, 1733 serviceEntry.serviceType, serviceEntry.instance, 1734 new ParcelUuid(serviceEntry.uuid), entry.instance, 1735 new ParcelUuid(entry.uuid), data); 1736 break; 1737 } 1738 1739 case HandleMap.TYPE_DESCRIPTOR: 1740 { 1741 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1742 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1743 app.callback.onDescriptorWriteRequest(address, transId, 1744 offset, length, isPrep, needRsp, 1745 serviceEntry.serviceType, serviceEntry.instance, 1746 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1747 new ParcelUuid(charEntry.uuid), 1748 new ParcelUuid(entry.uuid), data); 1749 break; 1750 } 1751 1752 default: 1753 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1754 break; 1755 } 1756 } 1757 1758 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1759 throws RemoteException { 1760 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1761 + ", address=" + address + ", transId=" + transId); 1762 1763 ServerMap.App app = mServerMap.getByConnId(connId); 1764 if (app == null) return; 1765 1766 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1767 } 1768 1769 void onResponseSendCompleted(int status, int attrHandle) { 1770 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1771 } 1772 1773 void onNotificationSent(int connId, int status) throws RemoteException { 1774 if (DBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1775 1776 String address = mServerMap.addressByConnId(connId); 1777 if (address == null) return; 1778 1779 ServerMap.App app = mServerMap.getByConnId(connId); 1780 if (app == null) return; 1781 1782 app.callback.onNotificationSent(address, status); 1783 } 1784 1785 void onServerCongestion(int connId, boolean congested) throws RemoteException { 1786 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1787 1788 ServerMap.App app = mServerMap.getByConnId(connId); 1789 if (app != null) { 1790 app.callback.onConnectionCongested(mServerMap.addressByConnId(connId), congested); 1791 } 1792 } 1793 1794 /************************************************************************** 1795 * GATT Service functions - SERVER 1796 *************************************************************************/ 1797 1798 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1799 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1800 1801 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1802 mServerMap.add(uuid, callback); 1803 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1804 uuid.getMostSignificantBits()); 1805 } 1806 1807 void unregisterServer(int serverIf) { 1808 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1809 1810 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1811 1812 deleteServices(serverIf); 1813 1814 mServerMap.remove(serverIf); 1815 gattServerUnregisterAppNative(serverIf); 1816 } 1817 1818 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1819 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1820 1821 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1822 gattServerConnectNative(serverIf, address, isDirect,transport); 1823 } 1824 1825 void serverDisconnect(int serverIf, String address) { 1826 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1827 1828 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1829 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1830 1831 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1832 } 1833 1834 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1835 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1836 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1837 1838 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1839 ServiceDeclaration serviceDeclaration = addDeclaration(); 1840 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1841 advertisePreferred); 1842 } 1843 1844 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1845 UUID srvcUuid) { 1846 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1847 1848 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1849 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1850 } 1851 1852 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1853 int permissions) { 1854 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1855 1856 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1857 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1858 } 1859 1860 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1861 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1862 1863 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1864 getActiveDeclaration().addDescriptor(descUuid, permissions); 1865 } 1866 1867 void endServiceDeclaration(int serverIf) { 1868 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1869 1870 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1871 1872 if (getActiveDeclaration() == getPendingDeclaration()) { 1873 try { 1874 continueServiceDeclaration(serverIf, (byte)0, 0); 1875 } catch (RemoteException e) { 1876 Log.e(TAG,""+e); 1877 } 1878 } 1879 } 1880 1881 void removeService(int serverIf, int srvcType, 1882 int srvcInstanceId, UUID srvcUuid) { 1883 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1884 1885 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1886 1887 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1888 if (srvcHandle == 0) return; 1889 gattServerDeleteServiceNative(serverIf, srvcHandle); 1890 } 1891 1892 void clearServices(int serverIf) { 1893 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1894 1895 if (DBG) Log.d(TAG, "clearServices()"); 1896 deleteServices(serverIf); 1897 } 1898 1899 void sendResponse(int serverIf, String address, int requestId, 1900 int status, int offset, byte[] value) { 1901 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1902 1903 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 1904 1905 int handle = 0; 1906 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 1907 if (entry != null) handle = entry.handle; 1908 1909 int connId = mServerMap.connIdByAddress(serverIf, address); 1910 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 1911 handle, offset, value, (byte)0); 1912 mHandleMap.deleteRequest(requestId); 1913 } 1914 1915 void sendNotification(int serverIf, String address, int srvcType, 1916 int srvcInstanceId, UUID srvcUuid, 1917 int charInstanceId, UUID charUuid, 1918 boolean confirm, byte[] value) { 1919 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1920 1921 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address); 1922 1923 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1924 if (srvcHandle == 0) return; 1925 1926 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 1927 if (charHandle == 0) return; 1928 1929 int connId = mServerMap.connIdByAddress(serverIf, address); 1930 if (connId == 0) return; 1931 1932 if (confirm) { 1933 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 1934 } else { 1935 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 1936 } 1937 } 1938 1939 1940 /************************************************************************** 1941 * Private functions 1942 *************************************************************************/ 1943 1944 private int getDeviceType(BluetoothDevice device) { 1945 int type = gattClientGetDeviceTypeNative(device.getAddress()); 1946 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 1947 + ", type=" + type); 1948 return type; 1949 } 1950 1951 private void enforceAdminPermission() { 1952 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 1953 } 1954 1955 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 1956 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 1957 private void enforcePrivilegedPermission() { 1958 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1959 "Need BLUETOOTH_PRIVILEGED permission"); 1960 } 1961 1962 private void continueSearch(int connId, int status) throws RemoteException { 1963 if (status == 0 && !mSearchQueue.isEmpty()) { 1964 SearchQueue.Entry svc = mSearchQueue.pop(); 1965 1966 if (svc.charUuidLsb == 0) { 1967 // Characteristic is up next 1968 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 1969 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 1970 } else { 1971 // Descriptor is up next 1972 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 1973 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 1974 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 1975 } 1976 } else { 1977 ClientMap.App app = mClientMap.getByConnId(connId); 1978 if (app != null) { 1979 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 1980 } 1981 } 1982 } 1983 1984 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 1985 if (mServiceDeclarations.size() == 0) return; 1986 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 1987 1988 boolean finished = false; 1989 1990 ServiceDeclaration.Entry entry = null; 1991 if (status == 0) 1992 entry = getPendingDeclaration().getNext(); 1993 1994 if (entry != null) { 1995 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 1996 + entry.type); 1997 switch(entry.type) { 1998 case ServiceDeclaration.TYPE_SERVICE: 1999 if (entry.advertisePreferred) { 2000 mAdvertisingServiceUuids.add(entry.uuid); 2001 } 2002 gattServerAddServiceNative(serverIf, entry.serviceType, 2003 entry.instance, 2004 entry.uuid.getLeastSignificantBits(), 2005 entry.uuid.getMostSignificantBits(), 2006 getPendingDeclaration().getNumHandles()); 2007 break; 2008 2009 case ServiceDeclaration.TYPE_CHARACTERISTIC: 2010 gattServerAddCharacteristicNative(serverIf, srvcHandle, 2011 entry.uuid.getLeastSignificantBits(), 2012 entry.uuid.getMostSignificantBits(), 2013 entry.properties, entry.permissions); 2014 break; 2015 2016 case ServiceDeclaration.TYPE_DESCRIPTOR: 2017 gattServerAddDescriptorNative(serverIf, srvcHandle, 2018 entry.uuid.getLeastSignificantBits(), 2019 entry.uuid.getMostSignificantBits(), 2020 entry.permissions); 2021 break; 2022 2023 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2024 { 2025 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2026 entry.serviceType, entry.instance); 2027 if (inclSrvc != 0) { 2028 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2029 inclSrvc); 2030 } else { 2031 finished = true; 2032 } 2033 break; 2034 } 2035 } 2036 } else { 2037 gattServerStartServiceNative(serverIf, srvcHandle, 2038 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2039 finished = true; 2040 } 2041 2042 if (finished) { 2043 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2044 ServerMap.App app = mServerMap.getById(serverIf); 2045 if (app != null) { 2046 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2047 2048 if (serviceEntry != null) { 2049 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2050 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2051 } else { 2052 app.callback.onServiceAdded(status, 0, 0, null); 2053 } 2054 } 2055 removePendingDeclaration(); 2056 2057 if (getPendingDeclaration() != null) { 2058 continueServiceDeclaration(serverIf, (byte)0, 0); 2059 } 2060 } 2061 } 2062 2063 private void stopNextService(int serverIf, int status) throws RemoteException { 2064 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2065 + ", status=" + status); 2066 2067 if (status == 0) { 2068 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2069 for(HandleMap.Entry entry : entries) { 2070 if (entry.type != HandleMap.TYPE_SERVICE || 2071 entry.serverIf != serverIf || 2072 entry.started == false) 2073 continue; 2074 2075 gattServerStopServiceNative(serverIf, entry.handle); 2076 return; 2077 } 2078 } 2079 } 2080 2081 private void deleteServices(int serverIf) { 2082 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2083 2084 /* 2085 * Figure out which handles to delete. 2086 * The handles are copied into a new list to avoid race conditions. 2087 */ 2088 List<Integer> handleList = new ArrayList<Integer>(); 2089 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2090 for(HandleMap.Entry entry : entries) { 2091 if (entry.type != HandleMap.TYPE_SERVICE || 2092 entry.serverIf != serverIf) 2093 continue; 2094 handleList.add(entry.handle); 2095 } 2096 2097 /* Now actually delete the services.... */ 2098 for(Integer handle : handleList) { 2099 gattServerDeleteServiceNative(serverIf, handle); 2100 } 2101 } 2102 2103 private List<UUID> parseUuids(byte[] adv_data) { 2104 List<UUID> uuids = new ArrayList<UUID>(); 2105 2106 int offset = 0; 2107 while(offset < (adv_data.length-2)) { 2108 int len = adv_data[offset++]; 2109 if (len == 0) break; 2110 2111 int type = adv_data[offset++]; 2112 switch (type) { 2113 case 0x02: // Partial list of 16-bit UUIDs 2114 case 0x03: // Complete list of 16-bit UUIDs 2115 while (len > 1) { 2116 int uuid16 = adv_data[offset++]; 2117 uuid16 += (adv_data[offset++] << 8); 2118 len -= 2; 2119 uuids.add(UUID.fromString(String.format( 2120 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2121 } 2122 break; 2123 2124 default: 2125 offset += (len - 1); 2126 break; 2127 } 2128 } 2129 2130 return uuids; 2131 } 2132 2133 /************************************************************************** 2134 * GATT Test functions 2135 *************************************************************************/ 2136 2137 void gattTestCommand(int command, UUID uuid1, String bda1, 2138 int p1, int p2, int p3, int p4, int p5) { 2139 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2140 if (uuid1 != null) 2141 gattTestNative(command, uuid1.getLeastSignificantBits(), 2142 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2143 else 2144 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2145 } 2146 2147 private native void gattTestNative(int command, 2148 long uuid1_lsb, long uuid1_msb, String bda1, 2149 int p1, int p2, int p3, int p4, int p5); 2150 2151 /************************************************************************** 2152 * Native functions prototypes 2153 *************************************************************************/ 2154 2155 private native static void classInitNative(); 2156 private native void initializeNative(); 2157 private native void cleanupNative(); 2158 2159 private native int gattClientGetDeviceTypeNative(String address); 2160 2161 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2162 long app_uuid_msb); 2163 2164 private native void gattClientUnregisterAppNative(int clientIf); 2165 2166 private native void gattClientConnectNative(int clientIf, String address, 2167 boolean isDirect, int transport); 2168 2169 private native void gattClientDisconnectNative(int clientIf, String address, 2170 int conn_id); 2171 2172 private native void gattClientRefreshNative(int clientIf, String address); 2173 2174 private native void gattClientSearchServiceNative(int conn_id, 2175 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2176 2177 private native void gattClientGetCharacteristicNative(int conn_id, 2178 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2179 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2180 long char_id_uuid_msb); 2181 2182 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2183 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2184 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2185 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2186 2187 private native void gattClientGetIncludedServiceNative(int conn_id, 2188 int service_type, int service_id_inst_id, 2189 long service_id_uuid_lsb, long service_id_uuid_msb, 2190 int incl_service_id_inst_id, int incl_service_type, 2191 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2192 2193 private native void gattClientReadCharacteristicNative(int conn_id, 2194 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2195 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2196 long char_id_uuid_msb, int authReq); 2197 2198 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2199 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2200 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2201 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2202 int authReq); 2203 2204 private native void gattClientWriteCharacteristicNative(int conn_id, 2205 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2206 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2207 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2208 2209 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2210 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2211 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2212 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2213 int write_type, int auth_req, byte[] value); 2214 2215 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2216 2217 private native void gattClientRegisterForNotificationsNative(int clientIf, 2218 String address, int service_type, int service_id_inst_id, 2219 long service_id_uuid_lsb, long service_id_uuid_msb, 2220 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2221 boolean enable); 2222 2223 private native void gattClientReadRemoteRssiNative(int clientIf, 2224 String address); 2225 2226 private native void gattAdvertiseNative(int client_if, boolean start); 2227 2228 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2229 2230 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2231 int minInterval, int maxInterval, int latency, int timeout); 2232 2233 private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 2234 boolean inclTxPower, int minInterval, int maxInterval, 2235 int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid); 2236 2237 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2238 long app_uuid_msb); 2239 2240 private native void gattServerUnregisterAppNative(int serverIf); 2241 2242 private native void gattServerConnectNative(int server_if, String address, 2243 boolean is_direct, int transport); 2244 2245 private native void gattServerDisconnectNative(int serverIf, String address, 2246 int conn_id); 2247 2248 private native void gattServerAddServiceNative (int server_if, 2249 int service_type, int service_id_inst_id, 2250 long service_id_uuid_lsb, long service_id_uuid_msb, 2251 int num_handles); 2252 2253 private native void gattServerAddIncludedServiceNative (int server_if, 2254 int svc_handle, int included_svc_handle); 2255 2256 private native void gattServerAddCharacteristicNative (int server_if, 2257 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2258 int properties, int permissions); 2259 2260 private native void gattServerAddDescriptorNative (int server_if, 2261 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2262 int permissions); 2263 2264 private native void gattServerStartServiceNative (int server_if, 2265 int svc_handle, int transport ); 2266 2267 private native void gattServerStopServiceNative (int server_if, 2268 int svc_handle); 2269 2270 private native void gattServerDeleteServiceNative (int server_if, 2271 int svc_handle); 2272 2273 private native void gattServerSendIndicationNative (int server_if, 2274 int attr_handle, int conn_id, byte[] val); 2275 2276 private native void gattServerSendNotificationNative (int server_if, 2277 int attr_handle, int conn_id, byte[] val); 2278 2279 private native void gattServerSendResponseNative (int server_if, 2280 int conn_id, int trans_id, int status, int handle, int offset, 2281 byte[] val, int auth_req); 2282} 2283