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