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