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