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