GattService.java revision b7461b17cad5476a7a528cbf2a0b9c9706c6faef
1/* 2 * Copyright (C) 2017 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.AppOpsManager; 20import android.app.PendingIntent; 21import android.app.Service; 22import android.bluetooth.BluetoothAdapter; 23import android.bluetooth.BluetoothDevice; 24import android.bluetooth.BluetoothGatt; 25import android.bluetooth.BluetoothGattCharacteristic; 26import android.bluetooth.BluetoothGattDescriptor; 27import android.bluetooth.BluetoothGattService; 28import android.bluetooth.BluetoothProfile; 29import android.bluetooth.IBluetoothGatt; 30import android.bluetooth.IBluetoothGattCallback; 31import android.bluetooth.IBluetoothGattServerCallback; 32import android.bluetooth.le.AdvertiseData; 33import android.bluetooth.le.AdvertisingSetParameters; 34import android.bluetooth.le.BluetoothLeScanner; 35import android.bluetooth.le.IAdvertisingSetCallback; 36import android.bluetooth.le.IPeriodicAdvertisingCallback; 37import android.bluetooth.le.IScannerCallback; 38import android.bluetooth.le.PeriodicAdvertisingParameters; 39import android.bluetooth.le.ResultStorageDescriptor; 40import android.bluetooth.le.ScanCallback; 41import android.bluetooth.le.ScanFilter; 42import android.bluetooth.le.ScanRecord; 43import android.bluetooth.le.ScanResult; 44import android.bluetooth.le.ScanSettings; 45import android.content.Intent; 46import android.os.Binder; 47import android.os.IBinder; 48import android.os.ParcelUuid; 49import android.os.RemoteException; 50import android.os.SystemClock; 51import android.os.WorkSource; 52import android.provider.Settings; 53import android.util.Log; 54 55import com.android.bluetooth.R; 56import com.android.bluetooth.Utils; 57import com.android.bluetooth.btservice.AdapterService; 58import com.android.bluetooth.btservice.BluetoothProto; 59import com.android.bluetooth.btservice.ProfileService; 60import com.android.bluetooth.util.NumberUtils; 61import com.android.internal.annotations.VisibleForTesting; 62 63import java.util.ArrayList; 64import java.util.Arrays; 65import java.util.Collections; 66import java.util.HashMap; 67import java.util.HashSet; 68import java.util.List; 69import java.util.Map; 70import java.util.Set; 71import java.util.UUID; 72import java.util.concurrent.TimeUnit; 73 74import static android.content.pm.PackageManager.PERMISSION_GRANTED; 75/** 76 * Provides Bluetooth Gatt profile, as a service in 77 * the Bluetooth application. 78 * @hide 79 */ 80public class GattService extends ProfileService { 81 private static final boolean DBG = GattServiceConfig.DBG; 82 private static final boolean VDBG = GattServiceConfig.VDBG; 83 private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService"; 84 85 static final int SCAN_FILTER_ENABLED = 1; 86 static final int SCAN_FILTER_MODIFIED = 2; 87 88 private static final int MAC_ADDRESS_LENGTH = 6; 89 // Batch scan related constants. 90 private static final int TRUNCATED_RESULT_SIZE = 11; 91 private static final int TIME_STAMP_LENGTH = 2; 92 93 // onFoundLost related constants 94 private static final int ADVT_STATE_ONFOUND = 0; 95 private static final int ADVT_STATE_ONLOST = 1; 96 97 private static final int ET_LEGACY_MASK = 0x10; 98 99 private static final UUID[] HID_UUIDS = { 100 UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"), 101 UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"), 102 UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"), 103 UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB") 104 }; 105 106 private static final UUID[] FIDO_UUIDS = { 107 UUID.fromString("0000FFFD-0000-1000-8000-00805F9B34FB") // U2F 108 }; 109 110 /** 111 * Keep the arguments passed in for the PendingIntent. 112 */ 113 class PendingIntentInfo { 114 PendingIntent intent; 115 ScanSettings settings; 116 List<ScanFilter> filters; 117 String callingPackage; 118 119 @Override 120 public boolean equals(Object other) { 121 if (!(other instanceof PendingIntentInfo)) return false; 122 return intent.equals(((PendingIntentInfo) other).intent); 123 } 124 } 125 126 /** 127 * List of our registered scanners. 128 */ 129 class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {} 130 ScannerMap mScannerMap = new ScannerMap(); 131 132 /** 133 * List of our registered clients. 134 */ 135 class ClientMap extends ContextMap<IBluetoothGattCallback, Void> {} 136 ClientMap mClientMap = new ClientMap(); 137 138 /** 139 * List of our registered server apps. 140 */ 141 class ServerMap extends ContextMap<IBluetoothGattServerCallback, Void> {} 142 ServerMap mServerMap = new ServerMap(); 143 144 /** 145 * Server handle map. 146 */ 147 HandleMap mHandleMap = new HandleMap(); 148 private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); 149 150 private int mMaxScanFilters; 151 152 static final int NUM_SCAN_EVENTS_KEPT = 20; 153 /** 154 * Internal list of scan events to use with the proto 155 */ 156 ArrayList<BluetoothProto.ScanEvent> mScanEvents = 157 new ArrayList<BluetoothProto.ScanEvent>(NUM_SCAN_EVENTS_KEPT); 158 159 private Map<Integer, List<BluetoothGattService>> gattClientDatabases = 160 new HashMap<Integer, List<BluetoothGattService>>(); 161 162 private AdvertiseManager mAdvertiseManager; 163 private PeriodicScanManager mPeriodicScanManager; 164 private ScanManager mScanManager; 165 private AppOpsManager mAppOps; 166 167 /** 168 * Reliable write queue 169 */ 170 private Set<String> mReliableQueue = new HashSet<String>(); 171 172 static { 173 classInitNative(); 174 } 175 176 @Override 177 protected String getName() { 178 return TAG; 179 } 180 181 @Override 182 protected IProfileServiceBinder initBinder() { 183 return new BluetoothGattBinder(this); 184 } 185 186 @Override 187 protected boolean start() { 188 if (DBG) Log.d(TAG, "start()"); 189 initializeNative(); 190 mAppOps = getSystemService(AppOpsManager.class); 191 mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService()); 192 mAdvertiseManager.start(); 193 194 mScanManager = new ScanManager(this); 195 mScanManager.start(); 196 197 mPeriodicScanManager = new PeriodicScanManager(AdapterService.getAdapterService()); 198 mPeriodicScanManager.start(); 199 200 return true; 201 } 202 203 @Override 204 protected boolean stop() { 205 if (DBG) Log.d(TAG, "stop()"); 206 mScannerMap.clear(); 207 mClientMap.clear(); 208 mServerMap.clear(); 209 mHandleMap.clear(); 210 mReliableQueue.clear(); 211 if (mAdvertiseManager != null) mAdvertiseManager.cleanup(); 212 if (mScanManager != null) mScanManager.cleanup(); 213 if (mPeriodicScanManager != null) mPeriodicScanManager.cleanup(); 214 return true; 215 } 216 217 @Override 218 protected boolean cleanup() { 219 if (DBG) Log.d(TAG, "cleanup()"); 220 cleanupNative(); 221 if (mAdvertiseManager != null) mAdvertiseManager.cleanup(); 222 if (mScanManager != null) mScanManager.cleanup(); 223 if (mPeriodicScanManager != null) mPeriodicScanManager.cleanup(); 224 return true; 225 } 226 227 boolean permissionCheck(UUID uuid) { 228 if (isRestrictedCharUuid(uuid) && (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))) 229 return false; 230 else 231 return true; 232 } 233 234 boolean permissionCheck(int connId, int handle) { 235 List<BluetoothGattService> db = gattClientDatabases.get(connId); 236 if (db == null) return true; 237 238 for (BluetoothGattService service : db) { 239 for (BluetoothGattCharacteristic characteristic: service.getCharacteristics()) { 240 if (handle == characteristic.getInstanceId()) { 241 if ((isRestrictedCharUuid(characteristic.getUuid()) || 242 isRestrictedSrvcUuid(service.getUuid())) && 243 (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))) 244 return false; 245 else 246 return true; 247 } 248 249 for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) { 250 if (handle == descriptor.getInstanceId()) { 251 if ((isRestrictedCharUuid(characteristic.getUuid()) || 252 isRestrictedSrvcUuid(service.getUuid())) && 253 (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))) 254 return false; 255 else 256 return true; 257 } 258 } 259 } 260 } 261 262 return true; 263 } 264 265 @Override 266 public int onStartCommand(Intent intent, int flags, int startId) { 267 if (GattDebugUtils.handleDebugAction(this, intent)) { 268 return Service.START_NOT_STICKY; 269 } 270 return super.onStartCommand(intent, flags, startId); 271 } 272 273 /** 274 * DeathReceipient handlers used to unregister applications that 275 * disconnect ungracefully (ie. crash or forced close). 276 */ 277 278 class ScannerDeathRecipient implements IBinder.DeathRecipient { 279 int mScannerId; 280 281 public ScannerDeathRecipient(int scannerId) { 282 mScannerId = scannerId; 283 } 284 285 @Override 286 public void binderDied() { 287 if (DBG) Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!"); 288 289 if (isScanClient(mScannerId)) { 290 ScanClient client = new ScanClient(mScannerId); 291 client.appDied = true; 292 stopScan(client); 293 } 294 } 295 296 private boolean isScanClient(int clientIf) { 297 for (ScanClient client : mScanManager.getRegularScanQueue()) { 298 if (client.scannerId == clientIf) { 299 return true; 300 } 301 } 302 for (ScanClient client : mScanManager.getBatchScanQueue()) { 303 if (client.scannerId == clientIf) { 304 return true; 305 } 306 } 307 return false; 308 } 309 } 310 311 class ServerDeathRecipient implements IBinder.DeathRecipient { 312 int mAppIf; 313 314 public ServerDeathRecipient(int appIf) { 315 mAppIf = appIf; 316 } 317 318 @Override 319 public void binderDied() { 320 if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!"); 321 unregisterServer(mAppIf); 322 } 323 } 324 325 class ClientDeathRecipient implements IBinder.DeathRecipient { 326 int mAppIf; 327 328 public ClientDeathRecipient(int appIf) { 329 mAppIf = appIf; 330 } 331 332 @Override 333 public void binderDied() { 334 if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!"); 335 unregisterClient(mAppIf); 336 } 337 } 338 339 /** 340 * Handlers for incoming service calls 341 */ 342 private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder { 343 private GattService mService; 344 345 public BluetoothGattBinder(GattService svc) { 346 mService = svc; 347 } 348 349 @Override 350 public boolean cleanup() { 351 mService = null; 352 return true; 353 } 354 355 private GattService getService() { 356 if (mService != null && mService.isAvailable()) return mService; 357 Log.e(TAG, "getService() - Service requested, but not available!"); 358 return null; 359 } 360 361 @Override 362 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 363 GattService service = getService(); 364 if (service == null) return new ArrayList<BluetoothDevice>(); 365 return service.getDevicesMatchingConnectionStates(states); 366 } 367 368 @Override 369 public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) { 370 GattService service = getService(); 371 if (service == null) return; 372 service.registerClient(uuid.getUuid(), callback); 373 } 374 375 @Override 376 public void unregisterClient(int clientIf) { 377 GattService service = getService(); 378 if (service == null) return; 379 service.unregisterClient(clientIf); 380 } 381 382 @Override 383 public void registerScanner(IScannerCallback callback, WorkSource workSource) 384 throws RemoteException { 385 GattService service = getService(); 386 if (service == null) return; 387 service.registerScanner(callback, workSource); 388 } 389 390 @Override 391 public void unregisterScanner(int scannerId) { 392 GattService service = getService(); 393 if (service == null) return; 394 service.unregisterScanner(scannerId); 395 } 396 397 @Override 398 public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 399 List storages, String callingPackage) { 400 GattService service = getService(); 401 if (service == null) return; 402 service.startScan(scannerId, settings, filters, storages, callingPackage); 403 } 404 405 @Override 406 public void startScanForIntent(PendingIntent intent, ScanSettings settings, 407 List<ScanFilter> filters, String callingPackage) throws RemoteException { 408 GattService service = getService(); 409 if (service == null) return; 410 service.registerPiAndStartScan(intent, settings, filters, callingPackage); 411 } 412 413 @Override 414 public void stopScanForIntent(PendingIntent intent, String callingPackage) 415 throws RemoteException { 416 GattService service = getService(); 417 if (service == null) return; 418 service.stopScan(intent, callingPackage); 419 } 420 421 @Override 422 public void stopScan(int scannerId) { 423 GattService service = getService(); 424 if (service == null) return; 425 service.stopScan(new ScanClient(scannerId)); 426 } 427 428 @Override 429 public void flushPendingBatchResults(int scannerId) { 430 GattService service = getService(); 431 if (service == null) return; 432 service.flushPendingBatchResults(scannerId); 433 } 434 435 @Override 436 public void clientConnect(int clientIf, String address, boolean isDirect, int transport, 437 boolean opportunistic, int phy) { 438 GattService service = getService(); 439 if (service == null) return; 440 service.clientConnect(clientIf, address, isDirect, transport, opportunistic, phy); 441 } 442 443 @Override 444 public void clientDisconnect(int clientIf, String address) { 445 GattService service = getService(); 446 if (service == null) return; 447 service.clientDisconnect(clientIf, address); 448 } 449 450 @Override 451 public void clientSetPreferredPhy( 452 int clientIf, String address, int txPhy, int rxPhy, int phyOptions) { 453 GattService service = getService(); 454 if (service == null) return; 455 service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions); 456 } 457 458 @Override 459 public void clientReadPhy(int clientIf, String address) { 460 GattService service = getService(); 461 if (service == null) return; 462 service.clientReadPhy(clientIf, address); 463 } 464 465 @Override 466 public void refreshDevice(int clientIf, String address) { 467 GattService service = getService(); 468 if (service == null) return; 469 service.refreshDevice(clientIf, address); 470 } 471 472 @Override 473 public void discoverServices(int clientIf, String address) { 474 GattService service = getService(); 475 if (service == null) return; 476 service.discoverServices(clientIf, address); 477 } 478 479 @Override 480 public void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid) { 481 GattService service = getService(); 482 if (service == null) return; 483 service.discoverServiceByUuid(clientIf, address, uuid.getUuid()); 484 } 485 486 @Override 487 public void readCharacteristic(int clientIf, String address, int handle, int authReq) { 488 GattService service = getService(); 489 if (service == null) return; 490 service.readCharacteristic(clientIf, address, handle, authReq); 491 } 492 493 @Override 494 public void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, 495 int startHandle, int endHandle, int authReq) { 496 GattService service = getService(); 497 if (service == null) return; 498 service.readUsingCharacteristicUuid( 499 clientIf, address, uuid.getUuid(), startHandle, endHandle, authReq); 500 } 501 502 @Override 503 public void writeCharacteristic(int clientIf, String address, int handle, 504 int writeType, int authReq, byte[] value) { 505 GattService service = getService(); 506 if (service == null) return; 507 service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value); 508 } 509 510 @Override 511 public void readDescriptor(int clientIf, String address, int handle, int authReq) { 512 GattService service = getService(); 513 if (service == null) return; 514 service.readDescriptor(clientIf, address, handle, authReq); 515 } 516 517 @Override 518 public void writeDescriptor(int clientIf, String address, int handle, 519 int authReq, byte[] value) { 520 GattService service = getService(); 521 if (service == null) return; 522 service.writeDescriptor(clientIf, address, handle, authReq, value); 523 } 524 525 @Override 526 public void beginReliableWrite(int clientIf, String address) { 527 GattService service = getService(); 528 if (service == null) return; 529 service.beginReliableWrite(clientIf, address); 530 } 531 532 @Override 533 public void endReliableWrite(int clientIf, String address, boolean execute) { 534 GattService service = getService(); 535 if (service == null) return; 536 service.endReliableWrite(clientIf, address, execute); 537 } 538 539 @Override 540 public void registerForNotification(int clientIf, String address, int handle, boolean enable) { 541 GattService service = getService(); 542 if (service == null) return; 543 service.registerForNotification(clientIf, address, handle, enable); 544 } 545 546 @Override 547 public void readRemoteRssi(int clientIf, String address) { 548 GattService service = getService(); 549 if (service == null) return; 550 service.readRemoteRssi(clientIf, address); 551 } 552 553 @Override 554 public void configureMTU(int clientIf, String address, int mtu) { 555 GattService service = getService(); 556 if (service == null) return; 557 service.configureMTU(clientIf, address, mtu); 558 } 559 560 @Override 561 public void connectionParameterUpdate(int clientIf, String address, 562 int connectionPriority) { 563 GattService service = getService(); 564 if (service == null) return; 565 service.connectionParameterUpdate(clientIf, address, connectionPriority); 566 } 567 568 @Override 569 public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) { 570 GattService service = getService(); 571 if (service == null) return; 572 service.registerServer(uuid.getUuid(), callback); 573 } 574 575 @Override 576 public void unregisterServer(int serverIf) { 577 GattService service = getService(); 578 if (service == null) return; 579 service.unregisterServer(serverIf); 580 } 581 582 @Override 583 public void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 584 GattService service = getService(); 585 if (service == null) return; 586 service.serverConnect(serverIf, address, isDirect, transport); 587 } 588 589 @Override 590 public void serverDisconnect(int serverIf, String address) { 591 GattService service = getService(); 592 if (service == null) return; 593 service.serverDisconnect(serverIf, address); 594 } 595 596 @Override 597 public void serverSetPreferredPhy( 598 int serverIf, String address, int txPhy, int rxPhy, int phyOptions) { 599 GattService service = getService(); 600 if (service == null) return; 601 service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions); 602 } 603 604 @Override 605 public void serverReadPhy(int clientIf, String address) { 606 GattService service = getService(); 607 if (service == null) return; 608 service.serverReadPhy(clientIf, address); 609 } 610 611 @Override 612 public void addService(int serverIf, BluetoothGattService svc) { 613 GattService service = getService(); 614 if (service == null) return; 615 616 service.addService(serverIf, svc); 617 } 618 619 @Override 620 public void removeService(int serverIf, int handle) { 621 GattService service = getService(); 622 if (service == null) return; 623 service.removeService(serverIf, handle); 624 } 625 626 @Override 627 public void clearServices(int serverIf) { 628 GattService service = getService(); 629 if (service == null) return; 630 service.clearServices(serverIf); 631 } 632 633 @Override 634 public void sendResponse(int serverIf, String address, int requestId, 635 int status, int offset, byte[] value) { 636 GattService service = getService(); 637 if (service == null) return; 638 service.sendResponse(serverIf, address, requestId, status, offset, value); 639 } 640 641 @Override 642 public void sendNotification(int serverIf, String address, int handle, 643 boolean confirm, byte[] value) { 644 GattService service = getService(); 645 if (service == null) return; 646 service.sendNotification(serverIf, address, handle, confirm, value); 647 } 648 649 @Override 650 public void startAdvertisingSet(AdvertisingSetParameters parameters, 651 AdvertiseData advertiseData, AdvertiseData scanResponse, 652 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, 653 int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback) { 654 GattService service = getService(); 655 if (service == null) return; 656 service.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 657 periodicData, duration, maxExtAdvEvents, callback); 658 } 659 660 @Override 661 public void stopAdvertisingSet(IAdvertisingSetCallback callback) { 662 GattService service = getService(); 663 if (service == null) return; 664 service.stopAdvertisingSet(callback); 665 } 666 667 @Override 668 public void getOwnAddress(int advertiserId) { 669 GattService service = getService(); 670 if (service == null) return; 671 service.getOwnAddress(advertiserId); 672 } 673 674 @Override 675 public void enableAdvertisingSet( 676 int advertiserId, boolean enable, int duration, int maxExtAdvEvents) { 677 GattService service = getService(); 678 if (service == null) return; 679 service.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 680 } 681 682 @Override 683 public void setAdvertisingData(int advertiserId, AdvertiseData data) { 684 GattService service = getService(); 685 if (service == null) return; 686 service.setAdvertisingData(advertiserId, data); 687 } 688 689 @Override 690 public void setScanResponseData(int advertiserId, AdvertiseData data) { 691 GattService service = getService(); 692 if (service == null) return; 693 service.setScanResponseData(advertiserId, data); 694 } 695 696 @Override 697 public void setAdvertisingParameters( 698 int advertiserId, AdvertisingSetParameters parameters) { 699 GattService service = getService(); 700 if (service == null) return; 701 service.setAdvertisingParameters(advertiserId, parameters); 702 } 703 704 @Override 705 public void setPeriodicAdvertisingParameters( 706 int advertiserId, PeriodicAdvertisingParameters parameters) { 707 GattService service = getService(); 708 if (service == null) return; 709 service.setPeriodicAdvertisingParameters(advertiserId, parameters); 710 } 711 712 @Override 713 public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 714 GattService service = getService(); 715 if (service == null) return; 716 service.setPeriodicAdvertisingData(advertiserId, data); 717 } 718 719 @Override 720 public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 721 GattService service = getService(); 722 if (service == null) return; 723 service.setPeriodicAdvertisingEnable(advertiserId, enable); 724 } 725 726 @Override 727 public void registerSync(ScanResult scanResult, int skip, int timeout, 728 IPeriodicAdvertisingCallback callback) { 729 GattService service = getService(); 730 if (service == null) return; 731 service.registerSync(scanResult, skip, timeout, callback); 732 } 733 734 @Override 735 public void unregisterSync(IPeriodicAdvertisingCallback callback) { 736 GattService service = getService(); 737 if (service == null) return; 738 service.unregisterSync(callback); 739 } 740 741 @Override 742 public void disconnectAll() { 743 GattService service = getService(); 744 if (service == null) return; 745 service.disconnectAll(); 746 } 747 748 @Override 749 public void unregAll() { 750 GattService service = getService(); 751 if (service == null) return; 752 service.unregAll(); 753 } 754 755 @Override 756 public int numHwTrackFiltersAvailable() { 757 GattService service = getService(); 758 if (service == null) return 0; 759 return service.numHwTrackFiltersAvailable(); 760 } 761 }; 762 763 /************************************************************************** 764 * Callback functions - CLIENT 765 *************************************************************************/ 766 767 void onScanResult(int eventType, int addressType, String address, int primaryPhy, 768 int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, 769 byte[] advData) { 770 if (VDBG) { 771 Log.d(TAG, "onScanResult() - eventType=0x" + Integer.toHexString(eventType) 772 + ", addressType=" + addressType + ", address=" + address 773 + ", primaryPhy=" + primaryPhy + ", secondaryPhy=" + secondaryPhy 774 + ", advertisingSid=0x" + Integer.toHexString(advertisingSid) 775 + ", txPower=" + txPower + ", rssi=" + rssi + ", periodicAdvInt=0x" 776 + Integer.toHexString(periodicAdvInt)); 777 } 778 List<UUID> remoteUuids = parseUuids(advData); 779 addScanResult(); 780 781 byte[] legacy_adv_data = Arrays.copyOfRange(advData, 0, 62); 782 783 for (ScanClient client : mScanManager.getRegularScanQueue()) { 784 if (client.uuids.length > 0) { 785 int matches = 0; 786 for (UUID search : client.uuids) { 787 for (UUID remote: remoteUuids) { 788 if (remote.equals(search)) { 789 ++matches; 790 break; // Only count 1st match in case of duplicates 791 } 792 } 793 } 794 795 if (matches < client.uuids.length) continue; 796 } 797 798 ScannerMap.App app = mScannerMap.getById(client.scannerId); 799 if (app == null) { 800 continue; 801 } 802 803 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 804 805 ScanSettings settings = client.settings; 806 byte[] scan_record_data; 807 // This is for compability with applications that assume fixed size scan data. 808 if (settings.getLegacy()) { 809 if ((eventType & ET_LEGACY_MASK) == 0) { 810 // If this is legacy scan, but nonlegacy result - skip. 811 continue; 812 } else { 813 // Some apps are used to fixed-size advertise data. 814 scan_record_data = legacy_adv_data; 815 } 816 } else { 817 scan_record_data = advData; 818 } 819 820 ScanResult result = new ScanResult(device, eventType, primaryPhy, secondaryPhy, 821 advertisingSid, txPower, rssi, periodicAdvInt, 822 ScanRecord.parseFromBytes(scan_record_data), 823 SystemClock.elapsedRealtimeNanos()); 824 // Do no report if location mode is OFF or the client has no location permission 825 // PEERS_MAC_ADDRESS permission holders always get results 826 if (!hasScanResultPermission(client) || !matchesFilters(client, result)) { 827 continue; 828 } 829 830 if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) { 831 continue; 832 } 833 834 try { 835 app.appScanStats.addResult(client.scannerId); 836 if (app.callback != null) { 837 app.callback.onScanResult(result); 838 } else { 839 // Send the PendingIntent 840 ArrayList<ScanResult> results = new ArrayList<>(); 841 results.add(result); 842 sendResultsByPendingIntent(app.info, results, 843 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 844 } 845 } catch (RemoteException | PendingIntent.CanceledException e) { 846 Log.e(TAG, "Exception: " + e); 847 mScannerMap.remove(client.scannerId); 848 mScanManager.stopScan(client); 849 } 850 } 851 } 852 853 private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, 854 int callbackType, ScanClient client) { 855 ArrayList<ScanResult> results = new ArrayList<>(); 856 results.add(result); 857 try { 858 sendResultsByPendingIntent(pii, results, callbackType); 859 } catch (PendingIntent.CanceledException e) { 860 stopScan(client); 861 unregisterScanner(client.scannerId); 862 } 863 } 864 865 private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, 866 int callbackType) throws PendingIntent.CanceledException { 867 Intent extrasIntent = new Intent(); 868 extrasIntent.putParcelableArrayListExtra( 869 BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, results); 870 extrasIntent.putExtra( 871 BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); 872 pii.intent.send(this, 0, extrasIntent); 873 } 874 875 private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) 876 throws PendingIntent.CanceledException { 877 Intent extrasIntent = new Intent(); 878 extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); 879 pii.intent.send(this, 0, extrasIntent); 880 } 881 882 void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) 883 throws RemoteException { 884 UUID uuid = new UUID(uuidMsb, uuidLsb); 885 if (DBG) Log.d(TAG, "onScannerRegistered() - UUID=" + uuid 886 + ", scannerId=" + scannerId + ", status=" + status); 887 888 // First check the callback map 889 ScannerMap.App cbApp = mScannerMap.getByUuid(uuid); 890 if (cbApp != null) { 891 if (status == 0) { 892 cbApp.id = scannerId; 893 // If app is callback based, setup a death recipient. App will initiate the start. 894 // Otherwise, if PendingIntent based, start the scan directly. 895 if (cbApp.callback != null) { 896 cbApp.linkToDeath(new ScannerDeathRecipient(scannerId)); 897 } else { 898 continuePiStartScan(scannerId, cbApp.info); 899 } 900 } else { 901 mScannerMap.remove(scannerId); 902 } 903 if (cbApp.callback != null) { 904 cbApp.callback.onScannerRegistered(status, scannerId); 905 } 906 } 907 } 908 909 /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ 910 private boolean hasScanResultPermission(final ScanClient client) { 911 final boolean requiresLocationEnabled = 912 getResources().getBoolean(R.bool.strict_location_check); 913 final boolean locationEnabledSetting = Settings.Secure.getInt(getContentResolver(), 914 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 915 != Settings.Secure.LOCATION_MODE_OFF; 916 final boolean locationEnabled = !requiresLocationEnabled || locationEnabledSetting 917 || client.legacyForegroundApp; 918 return (client.hasPeersMacAddressPermission 919 || (client.hasLocationPermission && locationEnabled)); 920 } 921 922 // Check if a scan record matches a specific filters. 923 private boolean matchesFilters(ScanClient client, ScanResult scanResult) { 924 if (client.filters == null || client.filters.isEmpty()) { 925 return true; 926 } 927 for (ScanFilter filter : client.filters) { 928 if (filter.matches(scanResult)) { 929 return true; 930 } 931 } 932 return false; 933 } 934 935 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 936 throws RemoteException { 937 UUID uuid = new UUID(uuidMsb, uuidLsb); 938 if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 939 ClientMap.App app = mClientMap.getByUuid(uuid); 940 if (app != null) { 941 if (status == 0) { 942 app.id = clientIf; 943 app.linkToDeath(new ClientDeathRecipient(clientIf)); 944 } else { 945 mClientMap.remove(uuid); 946 } 947 app.callback.onClientRegistered(status, clientIf); 948 } 949 } 950 951 void onConnected(int clientIf, int connId, int status, String address) 952 throws RemoteException { 953 if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 954 + ", connId=" + connId + ", address=" + address); 955 956 if (status == 0) mClientMap.addConnection(clientIf, connId, address); 957 ClientMap.App app = mClientMap.getById(clientIf); 958 if (app != null) { 959 app.callback.onClientConnectionState(status, clientIf, 960 (status==BluetoothGatt.GATT_SUCCESS), address); 961 } 962 } 963 964 void onDisconnected(int clientIf, int connId, int status, String address) 965 throws RemoteException { 966 if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 967 + ", connId=" + connId + ", address=" + address); 968 969 mClientMap.removeConnection(clientIf, connId); 970 ClientMap.App app = mClientMap.getById(clientIf); 971 if (app != null) { 972 app.callback.onClientConnectionState(status, clientIf, false, address); 973 } 974 } 975 976 void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 977 if (DBG) Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status); 978 979 String address = mClientMap.addressByConnId(connId); 980 if (address == null) return; 981 982 ClientMap.App app = mClientMap.getByConnId(connId); 983 if (app == null) return; 984 985 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 986 } 987 988 void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status) 989 throws RemoteException { 990 if (DBG) 991 Log.d(TAG, "onClientPhyRead() - address=" + address + ", status=" + status 992 + ", clientIf=" + clientIf); 993 994 Integer connId = mClientMap.connIdByAddress(clientIf, address); 995 if (connId == null) { 996 Log.d(TAG, "onClientPhyRead() - no connection to " + address); 997 return; 998 } 999 1000 ClientMap.App app = mClientMap.getByConnId(connId); 1001 if (app == null) return; 1002 1003 app.callback.onPhyRead(address, txPhy, rxPhy, status); 1004 } 1005 1006 void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) 1007 throws RemoteException { 1008 if (DBG) Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status); 1009 1010 String address = mClientMap.addressByConnId(connId); 1011 if (address == null) return; 1012 1013 ClientMap.App app = mClientMap.getByConnId(connId); 1014 if (app == null) return; 1015 1016 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 1017 } 1018 1019 void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 1020 if (DBG) Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status); 1021 1022 String address = mServerMap.addressByConnId(connId); 1023 if (address == null) return; 1024 1025 ServerMap.App app = mServerMap.getByConnId(connId); 1026 if (app == null) return; 1027 1028 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 1029 } 1030 1031 void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) 1032 throws RemoteException { 1033 if (DBG) Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status); 1034 1035 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1036 if (connId == null) { 1037 Log.d(TAG, "onServerPhyRead() - no connection to " + address); 1038 return; 1039 } 1040 1041 ServerMap.App app = mServerMap.getByConnId(connId); 1042 if (app == null) return; 1043 1044 app.callback.onPhyRead(address, txPhy, rxPhy, status); 1045 } 1046 1047 void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) 1048 throws RemoteException { 1049 if (DBG) Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status); 1050 1051 String address = mServerMap.addressByConnId(connId); 1052 if (address == null) return; 1053 1054 ServerMap.App app = mServerMap.getByConnId(connId); 1055 if (app == null) return; 1056 1057 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 1058 } 1059 1060 void onSearchCompleted(int connId, int status) throws RemoteException { 1061 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 1062 // Gatt DB is ready! 1063 1064 // This callback was called from the jni_workqueue thread. If we make request to the stack 1065 // on the same thread, it might cause deadlock. Schedule request on a new thread instead. 1066 Thread t = new Thread(new Runnable() { 1067 @Override 1068 public void run() { 1069 gattClientGetGattDbNative(connId); 1070 } 1071 }); 1072 t.start(); 1073 } 1074 1075 GattDbElement GetSampleGattDbElement() { 1076 return new GattDbElement(); 1077 } 1078 1079 void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException { 1080 String address = mClientMap.addressByConnId(connId); 1081 1082 if (DBG) Log.d(TAG, "onGetGattDb() - address=" + address); 1083 1084 ClientMap.App app = mClientMap.getByConnId(connId); 1085 if (app == null || app.callback == null) { 1086 Log.e(TAG, "app or callback is null"); 1087 return; 1088 } 1089 1090 List<BluetoothGattService> db_out = new ArrayList<BluetoothGattService>(); 1091 1092 BluetoothGattService currSrvc = null; 1093 BluetoothGattCharacteristic currChar = null; 1094 1095 for (GattDbElement el: db) { 1096 switch (el.type) 1097 { 1098 case GattDbElement.TYPE_PRIMARY_SERVICE: 1099 case GattDbElement.TYPE_SECONDARY_SERVICE: 1100 if (DBG) Log.d(TAG, "got service with UUID=" + el.uuid + " id: " + el.id); 1101 1102 currSrvc = new BluetoothGattService(el.uuid, el.id, el.type); 1103 db_out.add(currSrvc); 1104 break; 1105 1106 case GattDbElement.TYPE_CHARACTERISTIC: 1107 if (DBG) 1108 Log.d(TAG, "got characteristic with UUID=" + el.uuid + " id: " + el.id); 1109 1110 currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0); 1111 currSrvc.addCharacteristic(currChar); 1112 break; 1113 1114 case GattDbElement.TYPE_DESCRIPTOR: 1115 if (DBG) Log.d(TAG, "got descriptor with UUID=" + el.uuid + " id: " + el.id); 1116 1117 currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0)); 1118 break; 1119 1120 case GattDbElement.TYPE_INCLUDED_SERVICE: 1121 if (DBG) 1122 Log.d(TAG, 1123 "got included service with UUID=" + el.uuid + " id: " + el.id 1124 + " startHandle: " + el.startHandle); 1125 1126 currSrvc.addIncludedService( 1127 new BluetoothGattService(el.uuid, el.startHandle, el.type)); 1128 break; 1129 1130 default: 1131 Log.e(TAG, 1132 "got unknown element with type=" + el.type + " and UUID=" + el.uuid 1133 + " id: " + el.id); 1134 } 1135 } 1136 1137 // Search is complete when there was error, or nothing more to process 1138 gattClientDatabases.put(connId, db_out); 1139 app.callback.onSearchComplete(address, db_out, 0 /* status */); 1140 } 1141 1142 void onRegisterForNotifications(int connId, int status, int registered, int handle) { 1143 String address = mClientMap.addressByConnId(connId); 1144 1145 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 1146 + ", status=" + status + ", registered=" + registered 1147 + ", handle=" + handle); 1148 } 1149 1150 void onNotify(int connId, String address, int handle, 1151 boolean isNotify, byte[] data) throws RemoteException { 1152 1153 if (VDBG) Log.d(TAG, "onNotify() - address=" + address 1154 + ", handle=" + handle + ", length=" + data.length); 1155 1156 if (!permissionCheck(connId, handle)) { 1157 Log.w(TAG, "onNotify() - permission check failed!"); 1158 return; 1159 } 1160 1161 ClientMap.App app = mClientMap.getByConnId(connId); 1162 if (app != null) { 1163 app.callback.onNotify(address, handle, data); 1164 } 1165 } 1166 1167 void onReadCharacteristic(int connId, int status, int handle, byte[] data) throws RemoteException { 1168 String address = mClientMap.addressByConnId(connId); 1169 1170 if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 1171 + ", status=" + status + ", length=" + data.length); 1172 1173 ClientMap.App app = mClientMap.getByConnId(connId); 1174 if (app != null) { 1175 app.callback.onCharacteristicRead(address, status, handle, data); 1176 } 1177 } 1178 1179 void onWriteCharacteristic(int connId, int status, int handle) 1180 throws RemoteException { 1181 String address = mClientMap.addressByConnId(connId); 1182 1183 if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 1184 + ", status=" + status); 1185 1186 ClientMap.App app = mClientMap.getByConnId(connId); 1187 if (app == null) return; 1188 1189 if (!app.isCongested) { 1190 app.callback.onCharacteristicWrite(address, status, handle); 1191 } else { 1192 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1193 status = BluetoothGatt.GATT_SUCCESS; 1194 } 1195 CallbackInfo callbackInfo = new CallbackInfo(address, status, handle); 1196 app.queueCallback(callbackInfo); 1197 } 1198 } 1199 1200 void onExecuteCompleted(int connId, int status) throws RemoteException { 1201 String address = mClientMap.addressByConnId(connId); 1202 if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 1203 + ", status=" + status); 1204 1205 ClientMap.App app = mClientMap.getByConnId(connId); 1206 if (app != null) { 1207 app.callback.onExecuteWrite(address, status); 1208 } 1209 } 1210 1211 void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { 1212 String address = mClientMap.addressByConnId(connId); 1213 1214 if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address 1215 + ", status=" + status + ", length=" + data.length); 1216 1217 ClientMap.App app = mClientMap.getByConnId(connId); 1218 if (app != null) { 1219 app.callback.onDescriptorRead(address, status, handle, data); 1220 } 1221 } 1222 1223 void onWriteDescriptor(int connId, int status, int handle) throws RemoteException { 1224 String address = mClientMap.addressByConnId(connId); 1225 1226 if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 1227 + ", status=" + status); 1228 1229 ClientMap.App app = mClientMap.getByConnId(connId); 1230 if (app != null) { 1231 app.callback.onDescriptorWrite(address, status, handle); 1232 } 1233 } 1234 1235 void onReadRemoteRssi(int clientIf, String address, 1236 int rssi, int status) throws RemoteException{ 1237 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 1238 address + ", rssi=" + rssi + ", status=" + status); 1239 1240 ClientMap.App app = mClientMap.getById(clientIf); 1241 if (app != null) { 1242 app.callback.onReadRemoteRssi(address, rssi, status); 1243 } 1244 } 1245 1246 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 1247 if (DBG) { 1248 Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 1249 + ", action=" + action); 1250 } 1251 mScanManager.callbackDone(clientIf, status); 1252 } 1253 1254 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 1255 if (DBG) { 1256 Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf 1257 + ", status=" + status + ", action=" + action 1258 + ", availableSpace=" + availableSpace); 1259 } 1260 mScanManager.callbackDone(clientIf, status); 1261 } 1262 1263 void onScanFilterConfig(int action, int status, int clientIf, int filterType, 1264 int availableSpace) { 1265 if (DBG) { 1266 Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 1267 + " status = " + status + ", filterType=" + filterType 1268 + ", availableSpace=" + availableSpace); 1269 } 1270 1271 mScanManager.callbackDone(clientIf, status); 1272 } 1273 1274 void onBatchScanStorageConfigured(int status, int clientIf) { 1275 if (DBG) { 1276 Log.d(TAG, 1277 "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); 1278 } 1279 mScanManager.callbackDone(clientIf, status); 1280 } 1281 1282 // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. 1283 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 1284 if (DBG) { 1285 Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf 1286 + ", status=" + status + ", startStopAction=" + startStopAction); 1287 } 1288 mScanManager.callbackDone(clientIf, status); 1289 } 1290 1291 void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, 1292 byte[] recordData) throws RemoteException { 1293 if (DBG) { 1294 Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status 1295 + ", reportType=" + reportType + ", numRecords=" + numRecords); 1296 } 1297 mScanManager.callbackDone(scannerId, status); 1298 Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 1299 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1300 // We only support single client for truncated mode. 1301 ScannerMap.App app = mScannerMap.getById(scannerId); 1302 if (app == null) return; 1303 if (app.callback != null) { 1304 app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); 1305 } else { 1306 // PendingIntent based 1307 try { 1308 sendResultsByPendingIntent(app.info, new ArrayList<ScanResult>(results), 1309 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1310 } catch (PendingIntent.CanceledException e) { 1311 } 1312 } 1313 } else { 1314 for (ScanClient client : mScanManager.getFullBatchScanQueue()) { 1315 // Deliver results for each client. 1316 deliverBatchScan(client, results); 1317 } 1318 } 1319 } 1320 1321 private void sendBatchScanResults( 1322 ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results) { 1323 try { 1324 if (app.callback != null) { 1325 app.callback.onBatchScanResults(results); 1326 } else { 1327 sendResultsByPendingIntent(app.info, results, 1328 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1329 } 1330 } catch (RemoteException | PendingIntent.CanceledException e) { 1331 Log.e(TAG, "Exception: " + e); 1332 mScannerMap.remove(client.scannerId); 1333 mScanManager.stopScan(client); 1334 } 1335 } 1336 1337 // Check and deliver scan results for different scan clients. 1338 private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws 1339 RemoteException { 1340 ScannerMap.App app = mScannerMap.getById(client.scannerId); 1341 if (app == null) return; 1342 if (client.filters == null || client.filters.isEmpty()) { 1343 sendBatchScanResults(app, client, new ArrayList<ScanResult>(allResults)); 1344 // TODO: Question to reviewer: Shouldn't there be a return here? 1345 } 1346 // Reconstruct the scan results. 1347 ArrayList<ScanResult> results = new ArrayList<ScanResult>(); 1348 for (ScanResult scanResult : allResults) { 1349 if (matchesFilters(client, scanResult)) { 1350 results.add(scanResult); 1351 } 1352 } 1353 sendBatchScanResults(app, client, results); 1354 } 1355 1356 private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 1357 byte[] batchRecord) { 1358 if (numRecords == 0) { 1359 return Collections.emptySet(); 1360 } 1361 if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 1362 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1363 return parseTruncatedResults(numRecords, batchRecord); 1364 } else { 1365 return parseFullResults(numRecords, batchRecord); 1366 } 1367 } 1368 1369 private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 1370 if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 1371 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1372 long now = SystemClock.elapsedRealtimeNanos(); 1373 for (int i = 0; i < numRecords; ++i) { 1374 byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, 1375 TRUNCATED_RESULT_SIZE); 1376 byte[] address = extractBytes(record, 0, 6); 1377 reverse(address); 1378 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1379 int rssi = record[8]; 1380 long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); 1381 results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), 1382 rssi, timestampNanos)); 1383 } 1384 return results; 1385 } 1386 1387 @VisibleForTesting 1388 long parseTimestampNanos(byte[] data) { 1389 long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); 1390 // Timestamp is in every 50 ms. 1391 return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 1392 } 1393 1394 private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 1395 if (DBG) Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 1396 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1397 int position = 0; 1398 long now = SystemClock.elapsedRealtimeNanos(); 1399 while (position < batchRecord.length) { 1400 byte[] address = extractBytes(batchRecord, position, 6); 1401 // TODO: remove temp hack. 1402 reverse(address); 1403 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1404 position += 6; 1405 // Skip address type. 1406 position++; 1407 // Skip tx power level. 1408 position++; 1409 int rssi = batchRecord[position++]; 1410 long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); 1411 position += 2; 1412 1413 // Combine advertise packet and scan response packet. 1414 int advertisePacketLen = batchRecord[position++]; 1415 byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 1416 position += advertisePacketLen; 1417 int scanResponsePacketLen = batchRecord[position++]; 1418 byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 1419 position += scanResponsePacketLen; 1420 byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 1421 System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 1422 System.arraycopy(scanResponseBytes, 0, scanRecord, 1423 advertisePacketLen, scanResponsePacketLen); 1424 if (DBG) Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 1425 results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), 1426 rssi, timestampNanos)); 1427 } 1428 return results; 1429 } 1430 1431 // Reverse byte array. 1432 private void reverse(byte[] address) { 1433 int len = address.length; 1434 for (int i = 0; i < len / 2; ++i) { 1435 byte b = address[i]; 1436 address[i] = address[len - 1 - i]; 1437 address[len - 1 - i] = b; 1438 } 1439 } 1440 1441 // Helper method to extract bytes from byte array. 1442 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 1443 byte[] bytes = new byte[length]; 1444 System.arraycopy(scanRecord, start, bytes, 0, length); 1445 return bytes; 1446 } 1447 1448 void onBatchScanThresholdCrossed(int clientIf) { 1449 if (DBG) { 1450 Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 1451 } 1452 flushPendingBatchResults(clientIf); 1453 } 1454 1455 AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int clientIf, int advPktLen, 1456 byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState, 1457 int advInfoPresent, String address, int addrType, int txPower, int rssiValue, 1458 int timeStamp) { 1459 1460 return new AdvtFilterOnFoundOnLostInfo(clientIf, advPktLen, advPkt, 1461 scanRspLen, scanRsp, filtIndex, advState, 1462 advInfoPresent, address, addrType, txPower, 1463 rssiValue, timeStamp); 1464 } 1465 1466 void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { 1467 if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() 1468 + " address = " + trackingInfo.getAddress() 1469 + " adv_state = " + trackingInfo.getAdvState()); 1470 1471 ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); 1472 if (app == null || (app.callback == null && app.info == null)) { 1473 Log.e(TAG, "app or callback is null"); 1474 return; 1475 } 1476 1477 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() 1478 .getRemoteDevice(trackingInfo.getAddress()); 1479 int advertiserState = trackingInfo.getAdvState(); 1480 ScanResult result = new ScanResult(device, 1481 ScanRecord.parseFromBytes(trackingInfo.getResult()), 1482 trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); 1483 1484 for (ScanClient client : mScanManager.getRegularScanQueue()) { 1485 if (client.scannerId == trackingInfo.getClientIf()) { 1486 ScanSettings settings = client.settings; 1487 if ((advertiserState == ADVT_STATE_ONFOUND) 1488 && ((settings.getCallbackType() 1489 & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0)) { 1490 if (app.callback != null) { 1491 app.callback.onFoundOrLost(true, result); 1492 } else { 1493 sendResultByPendingIntent(app.info, result, 1494 ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); 1495 } 1496 } else if ((advertiserState == ADVT_STATE_ONLOST) 1497 && ((settings.getCallbackType() 1498 & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0)) { 1499 if (app.callback != null) { 1500 app.callback.onFoundOrLost(false, result); 1501 } else { 1502 sendResultByPendingIntent(app.info, result, 1503 ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); 1504 } 1505 } else { 1506 if (DBG) { 1507 Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState 1508 + " scannerId = " + client.scannerId + " callbackType " 1509 + settings.getCallbackType()); 1510 } 1511 } 1512 } 1513 } 1514 } 1515 1516 void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { 1517 ScannerMap.App app = mScannerMap.getById(scannerId); 1518 if (app == null || app.callback == null) { 1519 Log.e(TAG, "Advertise app or callback is null"); 1520 return; 1521 } 1522 if (DBG) Log.d(TAG, "onScanParamSetupCompleted : " + status); 1523 } 1524 1525 // callback from ScanManager for dispatch of errors apps. 1526 void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { 1527 ScannerMap.App app = mScannerMap.getById(scannerId); 1528 if (app == null || (app.callback == null && app.info == null)) { 1529 Log.e(TAG, "App or callback is null"); 1530 return; 1531 } 1532 if (app.callback != null) { 1533 app.callback.onScanManagerErrorCallback(errorCode); 1534 } else { 1535 try { 1536 sendErrorByPendingIntent(app.info, errorCode); 1537 } catch (PendingIntent.CanceledException e) { 1538 Log.e(TAG, "Error sending error code via PendingIntent:" + e); 1539 } 1540 } 1541 } 1542 1543 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 1544 String address = mClientMap.addressByConnId(connId); 1545 1546 if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 1547 + status + ", mtu=" + mtu); 1548 1549 ClientMap.App app = mClientMap.getByConnId(connId); 1550 if (app != null) { 1551 app.callback.onConfigureMTU(address, mtu, status); 1552 } 1553 } 1554 1555 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1556 if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1557 1558 ClientMap.App app = mClientMap.getByConnId(connId); 1559 1560 if (app != null) { 1561 app.isCongested = congested; 1562 while(!app.isCongested) { 1563 CallbackInfo callbackInfo = app.popQueuedCallback(); 1564 if (callbackInfo == null) return; 1565 app.callback.onCharacteristicWrite(callbackInfo.address, 1566 callbackInfo.status, callbackInfo.handle); 1567 } 1568 } 1569 } 1570 1571 /************************************************************************** 1572 * GATT Service functions - Shared CLIENT/SERVER 1573 *************************************************************************/ 1574 1575 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1576 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1577 1578 final int DEVICE_TYPE_BREDR = 0x1; 1579 1580 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1581 Integer>(); 1582 1583 // Add paired LE devices 1584 1585 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1586 for (BluetoothDevice device : bondedDevices) { 1587 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1588 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1589 } 1590 } 1591 1592 // Add connected deviceStates 1593 1594 Set<String> connectedDevices = new HashSet<String>(); 1595 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1596 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1597 1598 for (String address : connectedDevices ) { 1599 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1600 if (device != null) { 1601 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1602 } 1603 } 1604 1605 // Create matching device sub-set 1606 1607 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1608 1609 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1610 for(int state : states) { 1611 if (entry.getValue() == state) { 1612 deviceList.add(entry.getKey()); 1613 } 1614 } 1615 } 1616 1617 return deviceList; 1618 } 1619 1620 void registerScanner(IScannerCallback callback, WorkSource workSource) throws RemoteException { 1621 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1622 1623 UUID uuid = UUID.randomUUID(); 1624 if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid); 1625 1626 if (workSource != null) { 1627 enforceImpersonatationPermission(); 1628 } 1629 1630 AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid()); 1631 if (app != null && app.isScanningTooFrequently() 1632 && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) { 1633 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 1634 callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); 1635 return; 1636 } 1637 1638 mScannerMap.add(uuid, workSource, callback, null, this); 1639 mScanManager.registerScanner(uuid); 1640 } 1641 1642 void unregisterScanner(int scannerId) { 1643 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1644 1645 if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); 1646 mScannerMap.remove(scannerId); 1647 mScanManager.unregisterScanner(scannerId); 1648 } 1649 1650 void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 1651 List<List<ResultStorageDescriptor>> storages, String callingPackage) { 1652 if (DBG) Log.d(TAG, "start scan with filters"); 1653 enforceAdminPermission(); 1654 if (needsPrivilegedPermissionForScan(settings)) { 1655 enforcePrivilegedPermission(); 1656 } 1657 final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages); 1658 scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps, 1659 callingPackage); 1660 scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission( 1661 this); 1662 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); 1663 1664 AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); 1665 if (app != null) { 1666 scanClient.stats = app; 1667 boolean isFilteredScan = (filters != null) && !filters.isEmpty(); 1668 app.recordScanStart(settings, isFilteredScan, scannerId); 1669 } 1670 1671 mScanManager.startScan(scanClient); 1672 } 1673 1674 void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, 1675 List<ScanFilter> filters, String callingPackage) { 1676 if (DBG) Log.d(TAG, "start scan with filters, for PendingIntent"); 1677 enforceAdminPermission(); 1678 if (needsPrivilegedPermissionForScan(settings)) { 1679 enforcePrivilegedPermission(); 1680 } 1681 1682 UUID uuid = UUID.randomUUID(); 1683 if (DBG) Log.d(TAG, "startScan(PI) - UUID=" + uuid); 1684 PendingIntentInfo piInfo = new PendingIntentInfo(); 1685 piInfo.intent = pendingIntent; 1686 piInfo.settings = settings; 1687 piInfo.filters = filters; 1688 piInfo.callingPackage = callingPackage; 1689 mScannerMap.add(uuid, null, null, piInfo, this); 1690 mScanManager.registerScanner(uuid); 1691 } 1692 1693 void continuePiStartScan(int scannerId, PendingIntentInfo piInfo) { 1694 final ScanClient scanClient = 1695 new ScanClient(scannerId, piInfo.settings, piInfo.filters, null); 1696 scanClient.hasLocationPermission = 1697 true; // Utils.checkCallerHasLocationPermission(this, mAppOps, 1698 // piInfo.callingPackage); 1699 scanClient.hasPeersMacAddressPermission = 1700 true; // Utils.checkCallerHasPeersMacAddressPermission( 1701 // this); 1702 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, piInfo.callingPackage); 1703 1704 AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); 1705 if (app != null) { 1706 scanClient.stats = app; 1707 boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); 1708 app.recordScanStart(piInfo.settings, isFilteredScan, scannerId); 1709 } 1710 1711 mScanManager.startScan(scanClient); 1712 } 1713 1714 void flushPendingBatchResults(int scannerId) { 1715 if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); 1716 mScanManager.flushBatchScanResults(new ScanClient(scannerId)); 1717 } 1718 1719 void stopScan(ScanClient client) { 1720 enforceAdminPermission(); 1721 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1722 mScanManager.getRegularScanQueue().size(); 1723 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1724 1725 AppScanStats app = null; 1726 app = mScannerMap.getAppScanStatsById(client.scannerId); 1727 if (app != null) app.recordScanStop(client.scannerId); 1728 1729 mScanManager.stopScan(client); 1730 } 1731 1732 void stopScan(PendingIntent intent, String callingPackage) { 1733 enforceAdminPermission(); 1734 PendingIntentInfo pii = new PendingIntentInfo(); 1735 pii.intent = intent; 1736 ScannerMap.App app = mScannerMap.getByContextInfo(pii); 1737 if (VDBG) Log.d(TAG, "stopScan(PendingIntent): app found = " + app); 1738 if (app != null) { 1739 final int scannerId = app.id; 1740 stopScan(new ScanClient(scannerId)); 1741 // Also unregister the scanner 1742 unregisterScanner(scannerId); 1743 } 1744 } 1745 1746 void disconnectAll() { 1747 if (DBG) Log.d(TAG, "disconnectAll()"); 1748 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 1749 for(Map.Entry<Integer, String> entry:connMap.entrySet()){ 1750 if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue()); 1751 clientDisconnect(entry.getKey(), entry.getValue()); 1752 //clientDisconnect(int clientIf, String address) 1753 } 1754 } 1755 1756 void unregAll() { 1757 for (Integer appId : mClientMap.getAllAppsIds()) { 1758 if (DBG) Log.d(TAG, "unreg:" + appId); 1759 unregisterClient(appId); 1760 } 1761 } 1762 1763 /************************************************************************** 1764 * PERIODIC SCANNING 1765 *************************************************************************/ 1766 void registerSync( 1767 ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback) { 1768 enforceAdminPermission(); 1769 mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); 1770 } 1771 1772 void unregisterSync(IPeriodicAdvertisingCallback callback) { 1773 enforceAdminPermission(); 1774 mPeriodicScanManager.stopSync(callback); 1775 } 1776 1777 /************************************************************************** 1778 * ADVERTISING SET 1779 *************************************************************************/ 1780 void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, 1781 AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, 1782 AdvertiseData periodicData, int duration, int maxExtAdvEvents, 1783 IAdvertisingSetCallback callback) { 1784 enforceAdminPermission(); 1785 mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse, 1786 periodicParameters, periodicData, duration, maxExtAdvEvents, callback); 1787 } 1788 1789 void stopAdvertisingSet(IAdvertisingSetCallback callback) { 1790 enforceAdminPermission(); 1791 mAdvertiseManager.stopAdvertisingSet(callback); 1792 } 1793 1794 void getOwnAddress(int advertiserId) { 1795 enforcePrivilegedPermission(); 1796 mAdvertiseManager.getOwnAddress(advertiserId); 1797 } 1798 1799 void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) { 1800 enforceAdminPermission(); 1801 mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 1802 } 1803 1804 void setAdvertisingData(int advertiserId, AdvertiseData data) { 1805 enforceAdminPermission(); 1806 mAdvertiseManager.setAdvertisingData(advertiserId, data); 1807 } 1808 1809 void setScanResponseData(int advertiserId, AdvertiseData data) { 1810 enforceAdminPermission(); 1811 mAdvertiseManager.setScanResponseData(advertiserId, data); 1812 } 1813 1814 void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) { 1815 enforceAdminPermission(); 1816 mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters); 1817 } 1818 1819 void setPeriodicAdvertisingParameters( 1820 int advertiserId, PeriodicAdvertisingParameters parameters) { 1821 enforceAdminPermission(); 1822 mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters); 1823 } 1824 1825 void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 1826 enforceAdminPermission(); 1827 mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data); 1828 } 1829 1830 void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 1831 enforceAdminPermission(); 1832 mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable); 1833 } 1834 1835 /************************************************************************** 1836 * GATT Service functions - CLIENT 1837 *************************************************************************/ 1838 1839 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1840 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1841 1842 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1843 mClientMap.add(uuid, null, callback, null, this); 1844 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1845 uuid.getMostSignificantBits()); 1846 } 1847 1848 void unregisterClient(int clientIf) { 1849 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1850 1851 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1852 mClientMap.remove(clientIf); 1853 gattClientUnregisterAppNative(clientIf); 1854 } 1855 1856 void clientConnect(int clientIf, String address, boolean isDirect, int transport, 1857 boolean opportunistic, int phy) { 1858 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1859 1860 if (DBG) { 1861 Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect + 1862 ", opportunistic=" + opportunistic + ", phy=" + phy); 1863 } 1864 gattClientConnectNative(clientIf, address, isDirect, transport, opportunistic, phy); 1865 } 1866 1867 void clientDisconnect(int clientIf, String address) { 1868 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1869 1870 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1871 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1872 1873 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1874 } 1875 1876 void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions) { 1877 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1878 1879 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1880 if (connId == null) { 1881 if (DBG) Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address); 1882 return; 1883 } 1884 1885 if (DBG) Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId); 1886 gattClientSetPreferredPhyNative(clientIf, address, txPhy, rxPhy, phyOptions); 1887 } 1888 1889 void clientReadPhy(int clientIf, String address) { 1890 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1891 1892 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1893 if (connId == null) { 1894 if (DBG) Log.d(TAG, "clientReadPhy() - no connection to " + address); 1895 return; 1896 } 1897 1898 if (DBG) Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId); 1899 gattClientReadPhyNative(clientIf, address); 1900 } 1901 1902 int numHwTrackFiltersAvailable() { 1903 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 1904 - mScanManager.getCurrentUsedTrackingAdvertisement()); 1905 } 1906 1907 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1908 Utils.enforceAdminPermission(this); 1909 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1910 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1911 serviceUuids.add(new ParcelUuid(entry.uuid)); 1912 } 1913 return serviceUuids; 1914 } 1915 1916 List<String> getConnectedDevices() { 1917 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1918 1919 Set<String> connectedDevAddress = new HashSet<String>(); 1920 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1921 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1922 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1923 return connectedDeviceList; 1924 } 1925 1926 void refreshDevice(int clientIf, String address) { 1927 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1928 1929 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1930 gattClientRefreshNative(clientIf, address); 1931 } 1932 1933 void discoverServices(int clientIf, String address) { 1934 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1935 1936 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1937 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1938 1939 if (connId != null) 1940 gattClientSearchServiceNative(connId, true, 0, 0); 1941 else 1942 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1943 } 1944 1945 void discoverServiceByUuid(int clientIf, String address, UUID uuid) { 1946 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1947 1948 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1949 if (connId != null) 1950 gattClientDiscoverServiceByUuidNative( 1951 connId, uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); 1952 else 1953 Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "..."); 1954 } 1955 1956 void readCharacteristic(int clientIf, String address, int handle, int authReq) { 1957 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1958 1959 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1960 1961 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1962 if (connId == null) { 1963 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1964 return; 1965 } 1966 1967 if (!permissionCheck(connId, handle)) { 1968 Log.w(TAG, "readCharacteristic() - permission check failed!"); 1969 return; 1970 } 1971 1972 gattClientReadCharacteristicNative(connId, handle, authReq); 1973 } 1974 1975 void readUsingCharacteristicUuid( 1976 int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq) { 1977 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1978 1979 if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address); 1980 1981 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1982 if (connId == null) { 1983 Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "..."); 1984 return; 1985 } 1986 1987 if (!permissionCheck(uuid)) { 1988 Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); 1989 return; 1990 } 1991 1992 gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(), 1993 uuid.getMostSignificantBits(), startHandle, endHandle, authReq); 1994 } 1995 1996 void writeCharacteristic(int clientIf, String address, int handle, int writeType, 1997 int authReq, byte[] value) { 1998 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1999 2000 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 2001 2002 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 2003 2004 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2005 if (connId == null) { 2006 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 2007 return; 2008 } 2009 2010 if (!permissionCheck(connId, handle)) { 2011 Log.w(TAG, "writeCharacteristic() - permission check failed!"); 2012 return; 2013 } 2014 2015 gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value); 2016 } 2017 2018 void readDescriptor(int clientIf, String address, int handle, int authReq) { 2019 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2020 2021 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 2022 2023 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2024 if (connId == null) { 2025 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 2026 return; 2027 } 2028 2029 if (!permissionCheck(connId, handle)) { 2030 Log.w(TAG, "readDescriptor() - permission check failed!"); 2031 return; 2032 } 2033 2034 gattClientReadDescriptorNative(connId, handle, authReq); 2035 }; 2036 2037 void writeDescriptor(int clientIf, String address, int handle, 2038 int authReq, byte[] value) { 2039 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2040 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 2041 2042 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2043 if (connId == null) { 2044 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 2045 return; 2046 } 2047 2048 if (!permissionCheck(connId, handle)) { 2049 Log.w(TAG, "writeDescriptor() - permission check failed!"); 2050 return; 2051 } 2052 2053 gattClientWriteDescriptorNative(connId, handle, authReq, value); 2054 } 2055 2056 void beginReliableWrite(int clientIf, String address) { 2057 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2058 2059 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 2060 mReliableQueue.add(address); 2061 } 2062 2063 void endReliableWrite(int clientIf, String address, boolean execute) { 2064 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2065 2066 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 2067 + " execute: " + execute); 2068 mReliableQueue.remove(address); 2069 2070 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2071 if (connId != null) gattClientExecuteWriteNative(connId, execute); 2072 } 2073 2074 void registerForNotification(int clientIf, String address, int handle, boolean enable) { 2075 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2076 2077 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 2078 2079 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2080 if (connId == null) { 2081 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 2082 return; 2083 } 2084 2085 if (!permissionCheck(connId, handle)) { 2086 Log.w(TAG, "registerForNotification() - permission check failed!"); 2087 return; 2088 } 2089 2090 gattClientRegisterForNotificationsNative(clientIf, address, handle, enable); 2091 } 2092 2093 void readRemoteRssi(int clientIf, String address) { 2094 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2095 2096 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 2097 gattClientReadRemoteRssiNative(clientIf, address); 2098 } 2099 2100 void configureMTU(int clientIf, String address, int mtu) { 2101 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2102 2103 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 2104 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2105 if (connId != null) { 2106 gattClientConfigureMTUNative(connId, mtu); 2107 } else { 2108 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 2109 } 2110 } 2111 2112 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 2113 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2114 2115 int minInterval; 2116 int maxInterval; 2117 2118 // Slave latency 2119 int latency; 2120 2121 // Link supervision timeout is measured in N * 10ms 2122 int timeout = 2000; // 20s 2123 2124 switch (connectionPriority) 2125 { 2126 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 2127 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 2128 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 2129 latency = getResources().getInteger(R.integer.gatt_high_priority_latency); 2130 break; 2131 2132 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 2133 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval); 2134 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval); 2135 latency = getResources().getInteger(R.integer.gatt_low_power_latency); 2136 break; 2137 2138 default: 2139 // Using the values for CONNECTION_PRIORITY_BALANCED. 2140 minInterval = 2141 getResources().getInteger(R.integer.gatt_balanced_priority_min_interval); 2142 maxInterval = 2143 getResources().getInteger(R.integer.gatt_balanced_priority_max_interval); 2144 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency); 2145 break; 2146 } 2147 2148 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 2149 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 2150 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 2151 latency, timeout); 2152 } 2153 2154 /************************************************************************** 2155 * Callback functions - SERVER 2156 *************************************************************************/ 2157 2158 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 2159 throws RemoteException { 2160 2161 UUID uuid = new UUID(uuidMsb, uuidLsb); 2162 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 2163 ServerMap.App app = mServerMap.getByUuid(uuid); 2164 if (app != null) { 2165 app.id = serverIf; 2166 app.linkToDeath(new ServerDeathRecipient(serverIf)); 2167 app.callback.onServerRegistered(status, serverIf); 2168 } 2169 } 2170 2171 void onServiceAdded(int status, int serverIf, List<GattDbElement> service) 2172 throws RemoteException { 2173 if (DBG) Log.d(TAG, "onServiceAdded(), status=" + status); 2174 2175 if (status != 0) { 2176 return; 2177 } 2178 2179 GattDbElement svcEl = service.get(0); 2180 int srvcHandle = svcEl.attributeHandle; 2181 2182 BluetoothGattService svc = null; 2183 2184 for (GattDbElement el : service) { 2185 if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) { 2186 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 2187 BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false); 2188 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 2189 BluetoothGattService.SERVICE_TYPE_PRIMARY); 2190 } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) { 2191 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 2192 BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false); 2193 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 2194 BluetoothGattService.SERVICE_TYPE_SECONDARY); 2195 } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) { 2196 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle); 2197 svc.addCharacteristic(new BluetoothGattCharacteristic(el.uuid, 2198 el.attributeHandle, el.properties, el.permissions)); 2199 } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) { 2200 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle); 2201 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics(); 2202 chars.get(chars.size()-1).addDescriptor( 2203 new BluetoothGattDescriptor(el.uuid, el.attributeHandle, el.permissions)); 2204 } 2205 } 2206 mHandleMap.setStarted(serverIf, srvcHandle, true); 2207 2208 ServerMap.App app = mServerMap.getById(serverIf); 2209 if (app != null) { 2210 app.callback.onServiceAdded(status, svc); 2211 } 2212 } 2213 2214 void onServiceStopped(int status, int serverIf, int srvcHandle) 2215 throws RemoteException { 2216 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 2217 + ", status=" + status); 2218 if (status == 0) 2219 mHandleMap.setStarted(serverIf, srvcHandle, false); 2220 stopNextService(serverIf, status); 2221 } 2222 2223 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 2224 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 2225 + ", status=" + status); 2226 mHandleMap.deleteService(serverIf, srvcHandle); 2227 } 2228 2229 void onClientConnected(String address, boolean connected, int connId, int serverIf) 2230 throws RemoteException { 2231 2232 if (DBG) Log.d(TAG, "onClientConnected() connId=" + connId 2233 + ", address=" + address + ", connected=" + connected); 2234 2235 ServerMap.App app = mServerMap.getById(serverIf); 2236 if (app == null) return; 2237 2238 if (connected) { 2239 mServerMap.addConnection(serverIf, connId, address); 2240 } else { 2241 mServerMap.removeConnection(serverIf, connId); 2242 } 2243 2244 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 2245 } 2246 2247 void onServerReadCharacteristic(String address, int connId, int transId, 2248 int handle, int offset, boolean isLong) 2249 throws RemoteException { 2250 if (VDBG) Log.d(TAG, "onServerReadCharacteristic() connId=" + connId 2251 + ", address=" + address + ", handle=" + handle 2252 + ", requestId=" + transId + ", offset=" + offset); 2253 2254 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2255 if (entry == null) return; 2256 2257 mHandleMap.addRequest(transId, handle); 2258 2259 ServerMap.App app = mServerMap.getById(entry.serverIf); 2260 if (app == null) return; 2261 2262 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); 2263 } 2264 2265 void onServerReadDescriptor(String address, int connId, int transId, 2266 int handle, int offset, boolean isLong) 2267 throws RemoteException { 2268 if (VDBG) Log.d(TAG, "onServerReadDescriptor() connId=" + connId 2269 + ", address=" + address + ", handle=" + handle 2270 + ", requestId=" + transId + ", offset=" + offset); 2271 2272 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2273 if (entry == null) return; 2274 2275 mHandleMap.addRequest(transId, handle); 2276 2277 ServerMap.App app = mServerMap.getById(entry.serverIf); 2278 if (app == null) return; 2279 2280 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); 2281 } 2282 2283 void onServerWriteCharacteristic(String address, int connId, int transId, 2284 int handle, int offset, int length, 2285 boolean needRsp, boolean isPrep, 2286 byte[] data) 2287 throws RemoteException { 2288 if (VDBG) Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId 2289 + ", address=" + address + ", handle=" + handle 2290 + ", requestId=" + transId + ", isPrep=" + isPrep 2291 + ", offset=" + offset); 2292 2293 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2294 if (entry == null) return; 2295 2296 mHandleMap.addRequest(transId, handle); 2297 2298 ServerMap.App app = mServerMap.getById(entry.serverIf); 2299 if (app == null) return; 2300 2301 app.callback.onCharacteristicWriteRequest(address, transId, 2302 offset, length, isPrep, needRsp, handle, data); 2303 } 2304 2305 void onServerWriteDescriptor(String address, int connId, int transId, 2306 int handle, int offset, int length, 2307 boolean needRsp, boolean isPrep, 2308 byte[] data) 2309 throws RemoteException { 2310 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 2311 + ", address=" + address + ", handle=" + handle 2312 + ", requestId=" + transId + ", isPrep=" + isPrep 2313 + ", offset=" + offset); 2314 2315 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2316 if (entry == null) return; 2317 2318 mHandleMap.addRequest(transId, handle); 2319 2320 ServerMap.App app = mServerMap.getById(entry.serverIf); 2321 if (app == null) return; 2322 2323 app.callback.onDescriptorWriteRequest(address, transId, 2324 offset, length, isPrep, needRsp, handle, data); 2325 } 2326 2327 void onExecuteWrite(String address, int connId, int transId, int execWrite) 2328 throws RemoteException { 2329 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 2330 + ", address=" + address + ", transId=" + transId); 2331 2332 ServerMap.App app = mServerMap.getByConnId(connId); 2333 if (app == null) return; 2334 2335 app.callback.onExecuteWrite(address, transId, execWrite == 1); 2336 } 2337 2338 void onResponseSendCompleted(int status, int attrHandle) { 2339 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 2340 } 2341 2342 void onNotificationSent(int connId, int status) throws RemoteException { 2343 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 2344 2345 String address = mServerMap.addressByConnId(connId); 2346 if (address == null) return; 2347 2348 ServerMap.App app = mServerMap.getByConnId(connId); 2349 if (app == null) return; 2350 2351 if (!app.isCongested) { 2352 app.callback.onNotificationSent(address, status); 2353 } else { 2354 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 2355 status = BluetoothGatt.GATT_SUCCESS; 2356 } 2357 app.queueCallback(new CallbackInfo(address, status)); 2358 } 2359 } 2360 2361 void onServerCongestion(int connId, boolean congested) throws RemoteException { 2362 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 2363 2364 ServerMap.App app = mServerMap.getByConnId(connId); 2365 if (app == null) return; 2366 2367 app.isCongested = congested; 2368 while(!app.isCongested) { 2369 CallbackInfo callbackInfo = app.popQueuedCallback(); 2370 if (callbackInfo == null) return; 2371 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 2372 } 2373 } 2374 2375 void onMtuChanged(int connId, int mtu) throws RemoteException { 2376 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 2377 2378 String address = mServerMap.addressByConnId(connId); 2379 if (address == null) return; 2380 2381 ServerMap.App app = mServerMap.getByConnId(connId); 2382 if (app == null) return; 2383 2384 app.callback.onMtuChanged(address, mtu); 2385 } 2386 2387 /************************************************************************** 2388 * GATT Service functions - SERVER 2389 *************************************************************************/ 2390 2391 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 2392 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2393 2394 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 2395 mServerMap.add(uuid, null, callback, null, this); 2396 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 2397 uuid.getMostSignificantBits()); 2398 } 2399 2400 void unregisterServer(int serverIf) { 2401 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2402 2403 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 2404 2405 deleteServices(serverIf); 2406 2407 mServerMap.remove(serverIf); 2408 gattServerUnregisterAppNative(serverIf); 2409 } 2410 2411 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 2412 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2413 2414 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 2415 gattServerConnectNative(serverIf, address, isDirect,transport); 2416 } 2417 2418 void serverDisconnect(int serverIf, String address) { 2419 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2420 2421 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2422 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 2423 2424 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 2425 } 2426 2427 void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions) { 2428 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2429 2430 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2431 if (connId == null) { 2432 if (DBG) Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address); 2433 return; 2434 } 2435 2436 if (DBG) Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId); 2437 gattServerSetPreferredPhyNative(serverIf, address, txPhy, rxPhy, phyOptions); 2438 } 2439 2440 void serverReadPhy(int serverIf, String address) { 2441 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2442 2443 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2444 if (connId == null) { 2445 if (DBG) Log.d(TAG, "serverReadPhy() - no connection to " + address); 2446 return; 2447 } 2448 2449 if (DBG) Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId); 2450 gattServerReadPhyNative(serverIf, address); 2451 } 2452 2453 void addService(int serverIf, BluetoothGattService service) { 2454 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2455 2456 if (DBG) Log.d(TAG, "addService() - uuid=" + service.getUuid()); 2457 2458 List<GattDbElement> db = new ArrayList<GattDbElement>(); 2459 2460 if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) 2461 db.add(GattDbElement.createPrimaryService(service.getUuid())); 2462 else db.add(GattDbElement.createSecondaryService(service.getUuid())); 2463 2464 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 2465 int permission = ((characteristic.getKeySize() - 7) << 12) 2466 + characteristic.getPermissions(); 2467 db.add(GattDbElement.createCharacteristic(characteristic.getUuid(), 2468 characteristic.getProperties(), permission)); 2469 2470 for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) { 2471 permission = ((characteristic.getKeySize() - 7) << 12) 2472 + descriptor.getPermissions(); 2473 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission)); 2474 } 2475 } 2476 2477 for (BluetoothGattService includedService : service.getIncludedServices()) { 2478 int inclSrvcHandle = includedService.getInstanceId(); 2479 2480 if (mHandleMap.checkServiceExists(includedService.getUuid(), inclSrvcHandle)) { 2481 db.add(GattDbElement.createIncludedService(inclSrvcHandle)); 2482 } else { 2483 Log.e(TAG, 2484 "included service with UUID " + includedService.getUuid() + " not found!"); 2485 } 2486 } 2487 2488 gattServerAddServiceNative(serverIf, db); 2489 } 2490 2491 void removeService(int serverIf, int handle) { 2492 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2493 2494 if (DBG) Log.d(TAG, "removeService() - handle=" + handle); 2495 2496 gattServerDeleteServiceNative(serverIf, handle); 2497 } 2498 2499 void clearServices(int serverIf) { 2500 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2501 2502 if (DBG) Log.d(TAG, "clearServices()"); 2503 deleteServices(serverIf); 2504 } 2505 2506 void sendResponse(int serverIf, String address, int requestId, 2507 int status, int offset, byte[] value) { 2508 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2509 2510 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 2511 2512 int handle = 0; 2513 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2514 if (entry != null) handle = entry.handle; 2515 2516 int connId = mServerMap.connIdByAddress(serverIf, address); 2517 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2518 handle, offset, value, (byte)0); 2519 mHandleMap.deleteRequest(requestId); 2520 } 2521 2522 void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) { 2523 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2524 2525 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle); 2526 2527 int connId = mServerMap.connIdByAddress(serverIf, address); 2528 if (connId == 0) return; 2529 2530 if (confirm) { 2531 gattServerSendIndicationNative(serverIf, handle, connId, value); 2532 } else { 2533 gattServerSendNotificationNative(serverIf, handle, connId, value); 2534 } 2535 } 2536 2537 2538 /************************************************************************** 2539 * Private functions 2540 *************************************************************************/ 2541 2542 private boolean isRestrictedCharUuid(final UUID charUuid) { 2543 return isHidUuid(charUuid); 2544 } 2545 2546 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2547 return isFidoUUID(srvcUuid); 2548 } 2549 2550 private boolean isHidUuid(final UUID uuid) { 2551 for (UUID hid_uuid : HID_UUIDS) { 2552 if (hid_uuid.equals(uuid)) return true; 2553 } 2554 return false; 2555 } 2556 2557 private boolean isFidoUUID(final UUID uuid) { 2558 for (UUID fido_uuid : FIDO_UUIDS) { 2559 if (fido_uuid.equals(uuid)) return true; 2560 } 2561 return false; 2562 } 2563 2564 private int getDeviceType(BluetoothDevice device) { 2565 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2566 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2567 + ", type=" + type); 2568 return type; 2569 } 2570 2571 private void enforceAdminPermission() { 2572 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2573 } 2574 2575 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2576 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2577 // BLE scan only mode needs special permission. 2578 if (adapter.getState() != BluetoothAdapter.STATE_ON) return true; 2579 2580 // Regular scan, no special permission. 2581 if (settings == null) return false; 2582 2583 // Regular scan, no special permission. 2584 if (settings.getReportDelayMillis() == 0) return false; 2585 2586 // Batch scan, truncated mode needs permission. 2587 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2588 } 2589 2590 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2591 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2592 private void enforcePrivilegedPermission() { 2593 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2594 "Need BLUETOOTH_PRIVILEGED permission"); 2595 } 2596 2597 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 2598 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 2599 // not have UPDATE_DEVICE_STATS permission. 2600 private void enforceImpersonatationPermission() { 2601 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 2602 "Need UPDATE_DEVICE_STATS permission"); 2603 } 2604 2605 private void stopNextService(int serverIf, int status) throws RemoteException { 2606 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2607 + ", status=" + status); 2608 2609 if (status == 0) { 2610 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2611 for(HandleMap.Entry entry : entries) { 2612 if (entry.type != HandleMap.TYPE_SERVICE || 2613 entry.serverIf != serverIf || 2614 !entry.started) 2615 continue; 2616 2617 gattServerStopServiceNative(serverIf, entry.handle); 2618 return; 2619 } 2620 } 2621 } 2622 2623 private void deleteServices(int serverIf) { 2624 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2625 2626 /* 2627 * Figure out which handles to delete. 2628 * The handles are copied into a new list to avoid race conditions. 2629 */ 2630 List<Integer> handleList = new ArrayList<Integer>(); 2631 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2632 for(HandleMap.Entry entry : entries) { 2633 if (entry.type != HandleMap.TYPE_SERVICE || 2634 entry.serverIf != serverIf) 2635 continue; 2636 handleList.add(entry.handle); 2637 } 2638 2639 /* Now actually delete the services.... */ 2640 for(Integer handle : handleList) { 2641 gattServerDeleteServiceNative(serverIf, handle); 2642 } 2643 } 2644 2645 private List<UUID> parseUuids(byte[] advData) { 2646 List<UUID> uuids = new ArrayList<UUID>(); 2647 2648 int offset = 0; 2649 while(offset < (advData.length-2)) { 2650 int len = Byte.toUnsignedInt(advData[offset++]); 2651 if (len == 0) break; 2652 2653 int type = advData[offset++]; 2654 switch (type) { 2655 case 0x02: // Partial list of 16-bit UUIDs 2656 case 0x03: // Complete list of 16-bit UUIDs 2657 while (len > 1) { 2658 int uuid16 = advData[offset++]; 2659 uuid16 += (advData[offset++] << 8); 2660 len -= 2; 2661 uuids.add(UUID.fromString(String.format( 2662 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2663 } 2664 break; 2665 2666 default: 2667 offset += (len - 1); 2668 break; 2669 } 2670 } 2671 2672 return uuids; 2673 } 2674 2675 @Override 2676 public void dump(StringBuilder sb) { 2677 super.dump(sb); 2678 println(sb, "mAdvertisingServiceUuids:"); 2679 for (UUID uuid : mAdvertisingServiceUuids) { 2680 println(sb, " " + uuid); 2681 } 2682 2683 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2684 2685 sb.append("\nGATT Scanner Map\n"); 2686 mScannerMap.dump(sb); 2687 2688 sb.append("GATT Client Map\n"); 2689 mClientMap.dump(sb); 2690 2691 sb.append("GATT Server Map\n"); 2692 mServerMap.dump(sb); 2693 2694 sb.append("GATT Handle Map\n"); 2695 mHandleMap.dump(sb); 2696 } 2697 2698 void addScanResult() { 2699 if (mScanEvents.isEmpty()) 2700 return; 2701 2702 BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1); 2703 curr.setNumberResults(curr.getNumberResults() + 1); 2704 } 2705 2706 void addScanEvent(BluetoothProto.ScanEvent event) { 2707 synchronized(mScanEvents) { 2708 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 2709 mScanEvents.remove(0); 2710 mScanEvents.add(event); 2711 } 2712 } 2713 2714 @Override 2715 public void dumpProto(BluetoothProto.BluetoothLog proto) { 2716 synchronized(mScanEvents) { 2717 for (BluetoothProto.ScanEvent event : mScanEvents) { 2718 proto.addScanEvent(event); 2719 } 2720 } 2721 } 2722 2723 /************************************************************************** 2724 * GATT Test functions 2725 *************************************************************************/ 2726 2727 void gattTestCommand(int command, UUID uuid1, String bda1, 2728 int p1, int p2, int p3, int p4, int p5) { 2729 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2730 if (uuid1 != null) 2731 gattTestNative(command, uuid1.getLeastSignificantBits(), 2732 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2733 else 2734 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2735 } 2736 2737 private native void gattTestNative(int command, 2738 long uuid1Lsb, long uuid1Msb, String bda1, 2739 int p1, int p2, int p3, int p4, int p5); 2740 2741 /************************************************************************** 2742 * Native functions prototypes 2743 *************************************************************************/ 2744 2745 private static native void classInitNative(); 2746 private native void initializeNative(); 2747 private native void cleanupNative(); 2748 2749 private native int gattClientGetDeviceTypeNative(String address); 2750 2751 private native void gattClientRegisterAppNative(long appUuidLsb, 2752 long appUuidMsb); 2753 2754 private native void gattClientUnregisterAppNative(int clientIf); 2755 2756 private native void gattClientConnectNative(int clientIf, String address, boolean isDirect, 2757 int transport, boolean opportunistic, int initiatingPhys); 2758 2759 private native void gattClientDisconnectNative(int clientIf, String address, 2760 int connId); 2761 2762 private native void gattClientSetPreferredPhyNative( 2763 int clientIf, String address, int txPhy, int rxPhy, int phyOptions); 2764 2765 private native void gattClientReadPhyNative(int clientIf, String address); 2766 2767 private native void gattClientRefreshNative(int clientIf, String address); 2768 2769 private native void gattClientSearchServiceNative(int connId, 2770 boolean searchAll, long serviceUuidLsb, long serviceUuidMsb); 2771 2772 private native void gattClientDiscoverServiceByUuidNative( 2773 int connId, long serviceUuidLsb, long serviceUuidMsb); 2774 2775 private native void gattClientGetGattDbNative(int connId); 2776 2777 private native void gattClientReadCharacteristicNative(int connId, int handle, int authReq); 2778 2779 private native void gattClientReadUsingCharacteristicUuidNative( 2780 int connId, long uuidMsb, long uuidLsb, int sHandle, int eHandle, int authReq); 2781 2782 private native void gattClientReadDescriptorNative(int connId, int handle, int authReq); 2783 2784 private native void gattClientWriteCharacteristicNative(int connId, 2785 int handle, int writeType, int authReq, byte[] value); 2786 2787 private native void gattClientWriteDescriptorNative(int connId, int handle, 2788 int authReq, byte[] value); 2789 2790 private native void gattClientExecuteWriteNative(int connId, boolean execute); 2791 2792 private native void gattClientRegisterForNotificationsNative(int clientIf, 2793 String address, int handle, boolean enable); 2794 2795 private native void gattClientReadRemoteRssiNative(int clientIf, 2796 String address); 2797 2798 private native void gattClientConfigureMTUNative(int connId, int mtu); 2799 2800 private native void gattConnectionParameterUpdateNative(int clientIf, String address, 2801 int minInterval, int maxInterval, int latency, int timeout); 2802 2803 private native void gattServerRegisterAppNative(long appUuidLsb, 2804 long appUuidMsb); 2805 2806 private native void gattServerUnregisterAppNative(int serverIf); 2807 2808 private native void gattServerConnectNative(int serverIf, String address, 2809 boolean isDirect, int transport); 2810 2811 private native void gattServerDisconnectNative(int serverIf, String address, 2812 int connId); 2813 2814 private native void gattServerSetPreferredPhyNative( 2815 int clientIf, String address, int txPhy, int rxPhy, int phyOptions); 2816 2817 private native void gattServerReadPhyNative(int clientIf, String address); 2818 2819 private native void gattServerAddServiceNative(int serverIf, List<GattDbElement> service); 2820 2821 private native void gattServerStopServiceNative (int serverIf, 2822 int svcHandle); 2823 2824 private native void gattServerDeleteServiceNative (int serverIf, 2825 int svcHandle); 2826 2827 private native void gattServerSendIndicationNative (int serverIf, 2828 int attrHandle, int connId, byte[] val); 2829 2830 private native void gattServerSendNotificationNative (int serverIf, 2831 int attrHandle, int connId, byte[] val); 2832 2833 private native void gattServerSendResponseNative (int serverIf, 2834 int connId, int transId, int status, int handle, int offset, 2835 byte[] val, int authReq); 2836} 2837