GattService.java revision 910de1c2af404c3a9b232e0ad4764a439840f979
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.bluetooth.gatt; 18 19import android.app.AppOpsManager; 20import android.app.PendingIntent; 21import android.app.Service; 22import android.bluetooth.BluetoothAdapter; 23import android.bluetooth.BluetoothDevice; 24import android.bluetooth.BluetoothGatt; 25import android.bluetooth.BluetoothGattCharacteristic; 26import android.bluetooth.BluetoothGattDescriptor; 27import android.bluetooth.BluetoothGattService; 28import android.bluetooth.BluetoothProfile; 29import android.bluetooth.IBluetoothGatt; 30import android.bluetooth.IBluetoothGattCallback; 31import android.bluetooth.IBluetoothGattServerCallback; 32import android.bluetooth.le.AdvertiseData; 33import android.bluetooth.le.AdvertisingSetParameters; 34import android.bluetooth.le.BluetoothLeScanner; 35import android.bluetooth.le.IAdvertisingSetCallback; 36import android.bluetooth.le.IPeriodicAdvertisingCallback; 37import android.bluetooth.le.IScannerCallback; 38import android.bluetooth.le.PeriodicAdvertisingParameters; 39import android.bluetooth.le.ResultStorageDescriptor; 40import android.bluetooth.le.ScanFilter; 41import android.bluetooth.le.ScanRecord; 42import android.bluetooth.le.ScanResult; 43import android.bluetooth.le.ScanSettings; 44import android.content.Intent; 45import android.os.Binder; 46import android.os.IBinder; 47import android.os.ParcelUuid; 48import android.os.RemoteException; 49import android.os.SystemClock; 50import android.os.WorkSource; 51import android.provider.Settings; 52import android.util.Log; 53 54import com.android.bluetooth.R; 55import com.android.bluetooth.Utils; 56import com.android.bluetooth.btservice.AdapterService; 57import com.android.bluetooth.btservice.BluetoothProto; 58import com.android.bluetooth.btservice.ProfileService; 59import com.android.bluetooth.util.NumberUtils; 60import com.android.internal.annotations.VisibleForTesting; 61 62import java.util.ArrayList; 63import java.util.Arrays; 64import java.util.Collections; 65import java.util.HashMap; 66import java.util.HashSet; 67import java.util.List; 68import java.util.Map; 69import java.util.Set; 70import java.util.UUID; 71import java.util.concurrent.TimeUnit; 72 73import static android.content.pm.PackageManager.PERMISSION_GRANTED; 74/** 75 * Provides Bluetooth Gatt profile, as a service in 76 * the Bluetooth application. 77 * @hide 78 */ 79public 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(int clientIf, String address, boolean isDirect, int transport, 421 boolean opportunistic, int phy) { 422 GattService service = getService(); 423 if (service == null) return; 424 service.clientConnect(clientIf, address, isDirect, transport, opportunistic, 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 clientIf, String address, int txPhy, int rxPhy, int status) 938 throws RemoteException { 939 if (DBG) 940 Log.d(TAG, "onClientPhyRead() - address=" + address + ", status=" + status 941 + ", clientIf=" + clientIf); 942 943 Integer connId = mClientMap.connIdByAddress(clientIf, address); 944 if (connId == null) { 945 Log.d(TAG, "onClientPhyRead() - no connection to " + address); 946 return; 947 } 948 949 ClientMap.App app = mClientMap.getByConnId(connId); 950 if (app == null) return; 951 952 app.callback.onPhyRead(address, txPhy, rxPhy, status); 953 } 954 955 void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) 956 throws RemoteException { 957 if (DBG) Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status); 958 959 String address = mClientMap.addressByConnId(connId); 960 if (address == null) return; 961 962 ClientMap.App app = mClientMap.getByConnId(connId); 963 if (app == null) return; 964 965 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 966 } 967 968 void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 969 if (DBG) Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status); 970 971 String address = mServerMap.addressByConnId(connId); 972 if (address == null) return; 973 974 ServerMap.App app = mServerMap.getByConnId(connId); 975 if (app == null) return; 976 977 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 978 } 979 980 void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) 981 throws RemoteException { 982 if (DBG) Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status); 983 984 Integer connId = mServerMap.connIdByAddress(serverIf, address); 985 if (connId == null) { 986 Log.d(TAG, "onServerPhyRead() - no connection to " + address); 987 return; 988 } 989 990 ServerMap.App app = mServerMap.getByConnId(connId); 991 if (app == null) return; 992 993 app.callback.onPhyRead(address, txPhy, rxPhy, status); 994 } 995 996 void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) 997 throws RemoteException { 998 if (DBG) Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status); 999 1000 String address = mServerMap.addressByConnId(connId); 1001 if (address == null) return; 1002 1003 ServerMap.App app = mServerMap.getByConnId(connId); 1004 if (app == null) return; 1005 1006 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 1007 } 1008 1009 void onSearchCompleted(int connId, int status) throws RemoteException { 1010 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 1011 // Gatt DB is ready! 1012 1013 // This callback was called from the jni_workqueue thread. If we make request to the stack 1014 // on the same thread, it might cause deadlock. Schedule request on a new thread instead. 1015 Thread t = new Thread(new Runnable() { 1016 public void run() { 1017 gattClientGetGattDbNative(connId); 1018 } 1019 }); 1020 t.start(); 1021 } 1022 1023 GattDbElement GetSampleGattDbElement() { 1024 return new GattDbElement(); 1025 } 1026 1027 void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException { 1028 String address = mClientMap.addressByConnId(connId); 1029 1030 if (DBG) Log.d(TAG, "onGetGattDb() - address=" + address); 1031 1032 ClientMap.App app = mClientMap.getByConnId(connId); 1033 if (app == null || app.callback == null) { 1034 Log.e(TAG, "app or callback is null"); 1035 return; 1036 } 1037 1038 List<BluetoothGattService> db_out = new ArrayList<BluetoothGattService>(); 1039 1040 BluetoothGattService currSrvc = null; 1041 BluetoothGattCharacteristic currChar = null; 1042 1043 for (GattDbElement el: db) { 1044 switch (el.type) 1045 { 1046 case GattDbElement.TYPE_PRIMARY_SERVICE: 1047 case GattDbElement.TYPE_SECONDARY_SERVICE: 1048 if (DBG) Log.d(TAG, "got service with UUID=" + el.uuid); 1049 1050 currSrvc = new BluetoothGattService(el.uuid, el.id, el.type); 1051 db_out.add(currSrvc); 1052 break; 1053 1054 case GattDbElement.TYPE_CHARACTERISTIC: 1055 if (DBG) Log.d(TAG, "got characteristic with UUID=" + el.uuid); 1056 1057 currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0); 1058 currSrvc.addCharacteristic(currChar); 1059 break; 1060 1061 case GattDbElement.TYPE_DESCRIPTOR: 1062 if (DBG) Log.d(TAG, "got descriptor with UUID=" + el.uuid); 1063 1064 currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0)); 1065 break; 1066 1067 case GattDbElement.TYPE_INCLUDED_SERVICE: 1068 if (DBG) Log.d(TAG, "got included service with UUID=" + el.uuid); 1069 1070 currSrvc.addIncludedService(new BluetoothGattService(el.uuid, el.id, el.type)); 1071 break; 1072 1073 default: 1074 Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid); 1075 } 1076 } 1077 1078 // Search is complete when there was error, or nothing more to process 1079 gattClientDatabases.put(connId, db_out); 1080 app.callback.onSearchComplete(address, db_out, 0 /* status */); 1081 } 1082 1083 void onRegisterForNotifications(int connId, int status, int registered, int handle) { 1084 String address = mClientMap.addressByConnId(connId); 1085 1086 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 1087 + ", status=" + status + ", registered=" + registered 1088 + ", handle=" + handle); 1089 } 1090 1091 void onNotify(int connId, String address, int handle, 1092 boolean isNotify, byte[] data) throws RemoteException { 1093 1094 if (VDBG) Log.d(TAG, "onNotify() - address=" + address 1095 + ", handle=" + handle + ", length=" + data.length); 1096 1097 if (!permissionCheck(connId, handle)) { 1098 Log.w(TAG, "onNotify() - permission check failed!"); 1099 return; 1100 } 1101 1102 ClientMap.App app = mClientMap.getByConnId(connId); 1103 if (app != null) { 1104 app.callback.onNotify(address, handle, data); 1105 } 1106 } 1107 1108 void onReadCharacteristic(int connId, int status, int handle, byte[] data) throws RemoteException { 1109 String address = mClientMap.addressByConnId(connId); 1110 1111 if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 1112 + ", status=" + status + ", length=" + data.length); 1113 1114 ClientMap.App app = mClientMap.getByConnId(connId); 1115 if (app != null) { 1116 app.callback.onCharacteristicRead(address, status, handle, data); 1117 } 1118 } 1119 1120 void onWriteCharacteristic(int connId, int status, int handle) 1121 throws RemoteException { 1122 String address = mClientMap.addressByConnId(connId); 1123 1124 if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 1125 + ", status=" + status); 1126 1127 ClientMap.App app = mClientMap.getByConnId(connId); 1128 if (app == null) return; 1129 1130 if (!app.isCongested) { 1131 app.callback.onCharacteristicWrite(address, status, handle); 1132 } else { 1133 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1134 status = BluetoothGatt.GATT_SUCCESS; 1135 } 1136 CallbackInfo callbackInfo = new CallbackInfo(address, status, handle); 1137 app.queueCallback(callbackInfo); 1138 } 1139 } 1140 1141 void onExecuteCompleted(int connId, int status) throws RemoteException { 1142 String address = mClientMap.addressByConnId(connId); 1143 if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 1144 + ", status=" + status); 1145 1146 ClientMap.App app = mClientMap.getByConnId(connId); 1147 if (app != null) { 1148 app.callback.onExecuteWrite(address, status); 1149 } 1150 } 1151 1152 void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { 1153 String address = mClientMap.addressByConnId(connId); 1154 1155 if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address 1156 + ", status=" + status + ", length=" + data.length); 1157 1158 ClientMap.App app = mClientMap.getByConnId(connId); 1159 if (app != null) { 1160 app.callback.onDescriptorRead(address, status, handle, data); 1161 } 1162 } 1163 1164 void onWriteDescriptor(int connId, int status, int handle) throws RemoteException { 1165 String address = mClientMap.addressByConnId(connId); 1166 1167 if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 1168 + ", status=" + status); 1169 1170 ClientMap.App app = mClientMap.getByConnId(connId); 1171 if (app != null) { 1172 app.callback.onDescriptorWrite(address, status, handle); 1173 } 1174 } 1175 1176 void onReadRemoteRssi(int clientIf, String address, 1177 int rssi, int status) throws RemoteException{ 1178 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 1179 address + ", rssi=" + rssi + ", status=" + status); 1180 1181 ClientMap.App app = mClientMap.getById(clientIf); 1182 if (app != null) { 1183 app.callback.onReadRemoteRssi(address, rssi, status); 1184 } 1185 } 1186 1187 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 1188 if (DBG) { 1189 Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 1190 + ", action=" + action); 1191 } 1192 mScanManager.callbackDone(clientIf, status); 1193 } 1194 1195 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 1196 if (DBG) { 1197 Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf 1198 + ", status=" + status + ", action=" + action 1199 + ", availableSpace=" + availableSpace); 1200 } 1201 mScanManager.callbackDone(clientIf, status); 1202 } 1203 1204 void onScanFilterConfig(int action, int status, int clientIf, int filterType, 1205 int availableSpace) { 1206 if (DBG) { 1207 Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 1208 + " status = " + status + ", filterType=" + filterType 1209 + ", availableSpace=" + availableSpace); 1210 } 1211 1212 mScanManager.callbackDone(clientIf, status); 1213 } 1214 1215 void onBatchScanStorageConfigured(int status, int clientIf) { 1216 if (DBG) { 1217 Log.d(TAG, 1218 "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); 1219 } 1220 mScanManager.callbackDone(clientIf, status); 1221 } 1222 1223 // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. 1224 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 1225 if (DBG) { 1226 Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf 1227 + ", status=" + status + ", startStopAction=" + startStopAction); 1228 } 1229 mScanManager.callbackDone(clientIf, status); 1230 } 1231 1232 void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, 1233 byte[] recordData) throws RemoteException { 1234 if (DBG) { 1235 Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status 1236 + ", reportType=" + reportType + ", numRecords=" + numRecords); 1237 } 1238 mScanManager.callbackDone(scannerId, status); 1239 Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 1240 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1241 // We only support single client for truncated mode. 1242 ScannerMap.App app = mScannerMap.getById(scannerId); 1243 if (app == null) return; 1244 if (app.callback != null) { 1245 app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); 1246 } else { 1247 // PendingIntent based 1248 try { 1249 sendResultsByPendingIntent(app.info, new ArrayList<ScanResult>(results), 1250 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1251 } catch (PendingIntent.CanceledException e) { 1252 } 1253 } 1254 } else { 1255 for (ScanClient client : mScanManager.getFullBatchScanQueue()) { 1256 // Deliver results for each client. 1257 deliverBatchScan(client, results); 1258 } 1259 } 1260 } 1261 1262 private void sendBatchScanResults( 1263 ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results) { 1264 try { 1265 if (app.callback != null) { 1266 app.callback.onBatchScanResults(results); 1267 } else { 1268 sendResultsByPendingIntent(app.info, results, 1269 ScanSettings.CALLBACK_TYPE_ALL_MATCHES); 1270 } 1271 } catch (RemoteException | PendingIntent.CanceledException e) { 1272 Log.e(TAG, "Exception: " + e); 1273 mScannerMap.remove(client.scannerId); 1274 mScanManager.stopScan(client); 1275 } 1276 } 1277 1278 // Check and deliver scan results for different scan clients. 1279 private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws 1280 RemoteException { 1281 ScannerMap.App app = mScannerMap.getById(client.scannerId); 1282 if (app == null) return; 1283 if (client.filters == null || client.filters.isEmpty()) { 1284 sendBatchScanResults(app, client, new ArrayList<ScanResult>(allResults)); 1285 // TODO: Question to reviewer: Shouldn't there be a return here? 1286 } 1287 // Reconstruct the scan results. 1288 ArrayList<ScanResult> results = new ArrayList<ScanResult>(); 1289 for (ScanResult scanResult : allResults) { 1290 if (matchesFilters(client, scanResult)) { 1291 results.add(scanResult); 1292 } 1293 } 1294 sendBatchScanResults(app, client, results); 1295 } 1296 1297 private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 1298 byte[] batchRecord) { 1299 if (numRecords == 0) { 1300 return Collections.emptySet(); 1301 } 1302 if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 1303 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1304 return parseTruncatedResults(numRecords, batchRecord); 1305 } else { 1306 return parseFullResults(numRecords, batchRecord); 1307 } 1308 } 1309 1310 private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 1311 if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 1312 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1313 long now = SystemClock.elapsedRealtimeNanos(); 1314 for (int i = 0; i < numRecords; ++i) { 1315 byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, 1316 TRUNCATED_RESULT_SIZE); 1317 byte[] address = extractBytes(record, 0, 6); 1318 reverse(address); 1319 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1320 int rssi = record[8]; 1321 long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); 1322 results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), 1323 rssi, timestampNanos)); 1324 } 1325 return results; 1326 } 1327 1328 @VisibleForTesting 1329 long parseTimestampNanos(byte[] data) { 1330 long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); 1331 // Timestamp is in every 50 ms. 1332 return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 1333 } 1334 1335 private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 1336 if (DBG) Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 1337 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1338 int position = 0; 1339 long now = SystemClock.elapsedRealtimeNanos(); 1340 while (position < batchRecord.length) { 1341 byte[] address = extractBytes(batchRecord, position, 6); 1342 // TODO: remove temp hack. 1343 reverse(address); 1344 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1345 position += 6; 1346 // Skip address type. 1347 position++; 1348 // Skip tx power level. 1349 position++; 1350 int rssi = batchRecord[position++]; 1351 long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); 1352 position += 2; 1353 1354 // Combine advertise packet and scan response packet. 1355 int advertisePacketLen = batchRecord[position++]; 1356 byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 1357 position += advertisePacketLen; 1358 int scanResponsePacketLen = batchRecord[position++]; 1359 byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 1360 position += scanResponsePacketLen; 1361 byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 1362 System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 1363 System.arraycopy(scanResponseBytes, 0, scanRecord, 1364 advertisePacketLen, scanResponsePacketLen); 1365 if (DBG) Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 1366 results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), 1367 rssi, timestampNanos)); 1368 } 1369 return results; 1370 } 1371 1372 // Reverse byte array. 1373 private void reverse(byte[] address) { 1374 int len = address.length; 1375 for (int i = 0; i < len / 2; ++i) { 1376 byte b = address[i]; 1377 address[i] = address[len - 1 - i]; 1378 address[len - 1 - i] = b; 1379 } 1380 } 1381 1382 // Helper method to extract bytes from byte array. 1383 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 1384 byte[] bytes = new byte[length]; 1385 System.arraycopy(scanRecord, start, bytes, 0, length); 1386 return bytes; 1387 } 1388 1389 void onBatchScanThresholdCrossed(int clientIf) { 1390 if (DBG) { 1391 Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 1392 } 1393 flushPendingBatchResults(clientIf); 1394 } 1395 1396 AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len, 1397 byte[] adv_pkt, int scan_rsp_len, byte[] scan_rsp, int filt_index, int adv_state, 1398 int adv_info_present, String address, int addr_type, int tx_power, int rssi_value, 1399 int time_stamp) { 1400 1401 return new AdvtFilterOnFoundOnLostInfo(client_if, adv_pkt_len, adv_pkt, 1402 scan_rsp_len, scan_rsp, filt_index, adv_state, 1403 adv_info_present, address, addr_type, tx_power, 1404 rssi_value, time_stamp); 1405 } 1406 1407 void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { 1408 if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() 1409 + " address = " + trackingInfo.getAddress() 1410 + " adv_state = " + trackingInfo.getAdvState()); 1411 1412 ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); 1413 if (app == null || (app.callback == null && app.info == null)) { 1414 Log.e(TAG, "app or callback is null"); 1415 return; 1416 } 1417 1418 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() 1419 .getRemoteDevice(trackingInfo.getAddress()); 1420 int advertiserState = trackingInfo.getAdvState(); 1421 ScanResult result = new ScanResult(device, 1422 ScanRecord.parseFromBytes(trackingInfo.getResult()), 1423 trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); 1424 1425 for (ScanClient client : mScanManager.getRegularScanQueue()) { 1426 if (client.scannerId == trackingInfo.getClientIf()) { 1427 ScanSettings settings = client.settings; 1428 if ((advertiserState == ADVT_STATE_ONFOUND) 1429 && ((settings.getCallbackType() 1430 & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0)) { 1431 if (app.callback != null) { 1432 app.callback.onFoundOrLost(true, result); 1433 } else { 1434 sendResultByPendingIntent(app.info, result, 1435 ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); 1436 } 1437 } else if ((advertiserState == ADVT_STATE_ONLOST) 1438 && ((settings.getCallbackType() 1439 & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0)) { 1440 if (app.callback != null) { 1441 app.callback.onFoundOrLost(false, result); 1442 } else { 1443 sendResultByPendingIntent(app.info, result, 1444 ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); 1445 } 1446 } else { 1447 if (DBG) { 1448 Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState 1449 + " scannerId = " + client.scannerId + " callbackType " 1450 + settings.getCallbackType()); 1451 } 1452 } 1453 } 1454 } 1455 } 1456 1457 void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { 1458 ScannerMap.App app = mScannerMap.getById(scannerId); 1459 if (app == null || app.callback == null) { 1460 Log.e(TAG, "Advertise app or callback is null"); 1461 return; 1462 } 1463 if (DBG) Log.d(TAG, "onScanParamSetupCompleted : " + status); 1464 } 1465 1466 // callback from ScanManager for dispatch of errors apps. 1467 void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { 1468 ScannerMap.App app = mScannerMap.getById(scannerId); 1469 if (app == null || (app.callback == null && app.info == null)) { 1470 Log.e(TAG, "App or callback is null"); 1471 return; 1472 } 1473 if (app.callback != null) { 1474 app.callback.onScanManagerErrorCallback(errorCode); 1475 } else { 1476 try { 1477 sendErrorByPendingIntent(app.info, errorCode); 1478 } catch (PendingIntent.CanceledException e) { 1479 Log.e(TAG, "Error sending error code via PendingIntent:" + e); 1480 } 1481 } 1482 } 1483 1484 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 1485 String address = mClientMap.addressByConnId(connId); 1486 1487 if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 1488 + status + ", mtu=" + mtu); 1489 1490 ClientMap.App app = mClientMap.getByConnId(connId); 1491 if (app != null) { 1492 app.callback.onConfigureMTU(address, mtu, status); 1493 } 1494 } 1495 1496 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1497 if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1498 1499 ClientMap.App app = mClientMap.getByConnId(connId); 1500 1501 if (app != null) { 1502 app.isCongested = congested; 1503 while(!app.isCongested) { 1504 CallbackInfo callbackInfo = app.popQueuedCallback(); 1505 if (callbackInfo == null) return; 1506 app.callback.onCharacteristicWrite(callbackInfo.address, 1507 callbackInfo.status, callbackInfo.handle); 1508 } 1509 } 1510 } 1511 1512 /************************************************************************** 1513 * GATT Service functions - Shared CLIENT/SERVER 1514 *************************************************************************/ 1515 1516 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1517 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1518 1519 final int DEVICE_TYPE_BREDR = 0x1; 1520 1521 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1522 Integer>(); 1523 1524 // Add paired LE devices 1525 1526 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1527 for (BluetoothDevice device : bondedDevices) { 1528 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1529 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1530 } 1531 } 1532 1533 // Add connected deviceStates 1534 1535 Set<String> connectedDevices = new HashSet<String>(); 1536 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1537 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1538 1539 for (String address : connectedDevices ) { 1540 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1541 if (device != null) { 1542 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1543 } 1544 } 1545 1546 // Create matching device sub-set 1547 1548 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1549 1550 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1551 for(int state : states) { 1552 if (entry.getValue() == state) { 1553 deviceList.add(entry.getKey()); 1554 } 1555 } 1556 } 1557 1558 return deviceList; 1559 } 1560 1561 void registerScanner(IScannerCallback callback, WorkSource workSource) { 1562 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1563 1564 UUID uuid = UUID.randomUUID(); 1565 if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid); 1566 1567 if (workSource != null) { 1568 enforceImpersonatationPermission(); 1569 } 1570 1571 mScannerMap.add(uuid, workSource, callback, null, this); 1572 mScanManager.registerScanner(uuid); 1573 } 1574 1575 void unregisterScanner(int scannerId) { 1576 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1577 1578 if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); 1579 mScannerMap.remove(scannerId); 1580 mScanManager.unregisterScanner(scannerId); 1581 } 1582 1583 void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 1584 List<List<ResultStorageDescriptor>> storages, String callingPackage) { 1585 if (DBG) Log.d(TAG, "start scan with filters"); 1586 enforceAdminPermission(); 1587 if (needsPrivilegedPermissionForScan(settings)) { 1588 enforcePrivilegedPermission(); 1589 } 1590 final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages); 1591 scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps, 1592 callingPackage); 1593 scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission( 1594 this); 1595 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); 1596 1597 AppScanStats app = null; 1598 app = mScannerMap.getAppScanStatsById(scannerId); 1599 1600 if (app != null) { 1601 if (app.isScanningTooFrequently() && 1602 checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) { 1603 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 1604 return; 1605 } 1606 scanClient.stats = app; 1607 1608 boolean isFilteredScan = (filters != null) && !filters.isEmpty(); 1609 app.recordScanStart(settings, isFilteredScan); 1610 } 1611 1612 mScanManager.startScan(scanClient); 1613 } 1614 1615 void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, 1616 List<ScanFilter> filters, String callingPackage) { 1617 if (DBG) Log.d(TAG, "start scan with filters, for PendingIntent"); 1618 enforceAdminPermission(); 1619 if (needsPrivilegedPermissionForScan(settings)) { 1620 enforcePrivilegedPermission(); 1621 } 1622 1623 UUID uuid = UUID.randomUUID(); 1624 if (DBG) Log.d(TAG, "startScan(PI) - UUID=" + uuid); 1625 PendingIntentInfo piInfo = new PendingIntentInfo(); 1626 piInfo.intent = pendingIntent; 1627 piInfo.settings = settings; 1628 piInfo.filters = filters; 1629 piInfo.callingPackage = callingPackage; 1630 mScannerMap.add(uuid, null, null, piInfo, this); 1631 mScanManager.registerScanner(uuid); 1632 } 1633 1634 void continuePiStartScan(int scannerId, PendingIntentInfo piInfo) { 1635 final ScanClient scanClient = 1636 new ScanClient(scannerId, piInfo.settings, piInfo.filters, null); 1637 scanClient.hasLocationPermission = 1638 true; // Utils.checkCallerHasLocationPermission(this, mAppOps, 1639 // piInfo.callingPackage); 1640 scanClient.hasPeersMacAddressPermission = 1641 true; // Utils.checkCallerHasPeersMacAddressPermission( 1642 // this); 1643 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, piInfo.callingPackage); 1644 1645 AppScanStats app = null; 1646 app = mScannerMap.getAppScanStatsById(scannerId); 1647 1648 if (app != null) { 1649 if (app.isScanningTooFrequently() 1650 && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) { 1651 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 1652 return; 1653 } 1654 scanClient.stats = app; 1655 1656 boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); 1657 app.recordScanStart(piInfo.settings, isFilteredScan); 1658 } 1659 1660 mScanManager.startScan(scanClient); 1661 } 1662 1663 void flushPendingBatchResults(int scannerId) { 1664 if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); 1665 mScanManager.flushBatchScanResults(new ScanClient(scannerId)); 1666 } 1667 1668 void stopScan(ScanClient client) { 1669 enforceAdminPermission(); 1670 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1671 mScanManager.getRegularScanQueue().size(); 1672 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1673 1674 AppScanStats app = null; 1675 app = mScannerMap.getAppScanStatsById(client.scannerId); 1676 if (app != null) app.recordScanStop(); 1677 1678 mScanManager.stopScan(client); 1679 } 1680 1681 void stopScan(PendingIntent intent, String callingPackage) { 1682 enforceAdminPermission(); 1683 PendingIntentInfo pii = new PendingIntentInfo(); 1684 pii.intent = intent; 1685 ScannerMap.App app = mScannerMap.getByContextInfo(pii); 1686 if (VDBG) Log.d(TAG, "stopScan(PendingIntent): app found = " + app); 1687 if (app != null) { 1688 final int scannerId = app.id; 1689 stopScan(new ScanClient(scannerId)); 1690 // Also unregister the scanner 1691 unregisterScanner(scannerId); 1692 } 1693 } 1694 1695 void disconnectAll() { 1696 if (DBG) Log.d(TAG, "disconnectAll()"); 1697 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 1698 for(Map.Entry<Integer, String> entry:connMap.entrySet()){ 1699 if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue()); 1700 clientDisconnect(entry.getKey(), entry.getValue()); 1701 //clientDisconnect(int clientIf, String address) 1702 } 1703 } 1704 1705 void unregAll() { 1706 for (Integer appId : mClientMap.getAllAppsIds()) { 1707 if (DBG) Log.d(TAG, "unreg:" + appId); 1708 unregisterClient(appId); 1709 } 1710 } 1711 1712 /************************************************************************** 1713 * PERIODIC SCANNING 1714 *************************************************************************/ 1715 void registerSync( 1716 ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback) { 1717 enforceAdminPermission(); 1718 mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); 1719 } 1720 1721 void unregisterSync(IPeriodicAdvertisingCallback callback) { 1722 enforceAdminPermission(); 1723 mPeriodicScanManager.stopSync(callback); 1724 } 1725 1726 /************************************************************************** 1727 * ADVERTISING SET 1728 *************************************************************************/ 1729 void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, 1730 AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, 1731 AdvertiseData periodicData, int duration, int maxExtAdvEvents, 1732 IAdvertisingSetCallback callback) { 1733 enforceAdminPermission(); 1734 mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse, 1735 periodicParameters, periodicData, duration, maxExtAdvEvents, callback); 1736 } 1737 1738 void stopAdvertisingSet(IAdvertisingSetCallback callback) { 1739 enforceAdminPermission(); 1740 mAdvertiseManager.stopAdvertisingSet(callback); 1741 } 1742 1743 void getOwnAddress(int advertiserId) { 1744 enforcePrivilegedPermission(); 1745 mAdvertiseManager.getOwnAddress(advertiserId); 1746 } 1747 1748 void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) { 1749 enforceAdminPermission(); 1750 mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 1751 } 1752 1753 void setAdvertisingData(int advertiserId, AdvertiseData data) { 1754 enforceAdminPermission(); 1755 mAdvertiseManager.setAdvertisingData(advertiserId, data); 1756 } 1757 1758 void setScanResponseData(int advertiserId, AdvertiseData data) { 1759 enforceAdminPermission(); 1760 mAdvertiseManager.setScanResponseData(advertiserId, data); 1761 } 1762 1763 void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) { 1764 enforceAdminPermission(); 1765 mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters); 1766 } 1767 1768 void setPeriodicAdvertisingParameters( 1769 int advertiserId, PeriodicAdvertisingParameters parameters) { 1770 enforceAdminPermission(); 1771 mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters); 1772 } 1773 1774 void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 1775 enforceAdminPermission(); 1776 mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data); 1777 } 1778 1779 void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 1780 enforceAdminPermission(); 1781 mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable); 1782 } 1783 1784 /************************************************************************** 1785 * GATT Service functions - CLIENT 1786 *************************************************************************/ 1787 1788 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1789 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1790 1791 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1792 mClientMap.add(uuid, null, callback, null, this); 1793 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1794 uuid.getMostSignificantBits()); 1795 } 1796 1797 void unregisterClient(int clientIf) { 1798 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1799 1800 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1801 mClientMap.remove(clientIf); 1802 gattClientUnregisterAppNative(clientIf); 1803 } 1804 1805 void clientConnect(int clientIf, String address, boolean isDirect, int transport, 1806 boolean opportunistic, int phy) { 1807 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1808 1809 if (DBG) { 1810 Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect + 1811 ", opportunistic=" + opportunistic + ", phy=" + phy); 1812 } 1813 gattClientConnectNative(clientIf, address, isDirect, transport, opportunistic, phy); 1814 } 1815 1816 void clientDisconnect(int clientIf, String address) { 1817 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1818 1819 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1820 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1821 1822 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1823 } 1824 1825 void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions) { 1826 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1827 1828 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1829 if (connId == null) { 1830 if (DBG) Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address); 1831 return; 1832 } 1833 1834 if (DBG) Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId); 1835 gattClientSetPreferredPhyNative(clientIf, address, txPhy, rxPhy, phyOptions); 1836 } 1837 1838 void clientReadPhy(int clientIf, String address) { 1839 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1840 1841 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1842 if (connId == null) { 1843 if (DBG) Log.d(TAG, "clientReadPhy() - no connection to " + address); 1844 return; 1845 } 1846 1847 if (DBG) Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId); 1848 gattClientReadPhyNative(clientIf, address); 1849 } 1850 1851 int numHwTrackFiltersAvailable() { 1852 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 1853 - mScanManager.getCurrentUsedTrackingAdvertisement()); 1854 } 1855 1856 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1857 Utils.enforceAdminPermission(this); 1858 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1859 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1860 serviceUuids.add(new ParcelUuid(entry.uuid)); 1861 } 1862 return serviceUuids; 1863 } 1864 1865 List<String> getConnectedDevices() { 1866 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1867 1868 Set<String> connectedDevAddress = new HashSet<String>(); 1869 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1870 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1871 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1872 return connectedDeviceList; 1873 } 1874 1875 void refreshDevice(int clientIf, String address) { 1876 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1877 1878 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1879 gattClientRefreshNative(clientIf, address); 1880 } 1881 1882 void discoverServices(int clientIf, String address) { 1883 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1884 1885 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1886 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1887 1888 if (connId != null) 1889 gattClientSearchServiceNative(connId, true, 0, 0); 1890 else 1891 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1892 } 1893 1894 void discoverServiceByUuid(int clientIf, String address, UUID uuid) { 1895 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1896 1897 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1898 if (connId != null) 1899 gattClientDiscoverServiceByUuidNative( 1900 connId, uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); 1901 else 1902 Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "..."); 1903 } 1904 1905 void readCharacteristic(int clientIf, String address, int handle, int authReq) { 1906 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1907 1908 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1909 1910 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1911 if (connId == null) { 1912 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1913 return; 1914 } 1915 1916 if (!permissionCheck(connId, handle)) { 1917 Log.w(TAG, "readCharacteristic() - permission check failed!"); 1918 return; 1919 } 1920 1921 gattClientReadCharacteristicNative(connId, handle, authReq); 1922 } 1923 1924 void readUsingCharacteristicUuid( 1925 int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq) { 1926 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1927 1928 if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address); 1929 1930 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1931 if (connId == null) { 1932 Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "..."); 1933 return; 1934 } 1935 1936 if (!permissionCheck(uuid)) { 1937 Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); 1938 return; 1939 } 1940 1941 gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(), 1942 uuid.getMostSignificantBits(), startHandle, endHandle, authReq); 1943 } 1944 1945 void writeCharacteristic(int clientIf, String address, int handle, int writeType, 1946 int authReq, byte[] value) { 1947 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1948 1949 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1950 1951 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1952 1953 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1954 if (connId == null) { 1955 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1956 return; 1957 } 1958 1959 if (!permissionCheck(connId, handle)) { 1960 Log.w(TAG, "writeCharacteristic() - permission check failed!"); 1961 return; 1962 } 1963 1964 gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value); 1965 } 1966 1967 void readDescriptor(int clientIf, String address, int handle, int authReq) { 1968 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1969 1970 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1971 1972 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1973 if (connId == null) { 1974 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1975 return; 1976 } 1977 1978 if (!permissionCheck(connId, handle)) { 1979 Log.w(TAG, "readDescriptor() - permission check failed!"); 1980 return; 1981 } 1982 1983 gattClientReadDescriptorNative(connId, handle, authReq); 1984 }; 1985 1986 void writeDescriptor(int clientIf, String address, int handle, 1987 int authReq, byte[] value) { 1988 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1989 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1990 1991 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1992 if (connId == null) { 1993 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1994 return; 1995 } 1996 1997 if (!permissionCheck(connId, handle)) { 1998 Log.w(TAG, "writeDescriptor() - permission check failed!"); 1999 return; 2000 } 2001 2002 gattClientWriteDescriptorNative(connId, handle, authReq, value); 2003 } 2004 2005 void beginReliableWrite(int clientIf, String address) { 2006 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2007 2008 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 2009 mReliableQueue.add(address); 2010 } 2011 2012 void endReliableWrite(int clientIf, String address, boolean execute) { 2013 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2014 2015 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 2016 + " execute: " + execute); 2017 mReliableQueue.remove(address); 2018 2019 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2020 if (connId != null) gattClientExecuteWriteNative(connId, execute); 2021 } 2022 2023 void registerForNotification(int clientIf, String address, int handle, boolean enable) { 2024 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2025 2026 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 2027 2028 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2029 if (connId == null) { 2030 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 2031 return; 2032 } 2033 2034 if (!permissionCheck(connId, handle)) { 2035 Log.w(TAG, "registerForNotification() - permission check failed!"); 2036 return; 2037 } 2038 2039 gattClientRegisterForNotificationsNative(clientIf, address, handle, enable); 2040 } 2041 2042 void readRemoteRssi(int clientIf, String address) { 2043 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2044 2045 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 2046 gattClientReadRemoteRssiNative(clientIf, address); 2047 } 2048 2049 void configureMTU(int clientIf, String address, int mtu) { 2050 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2051 2052 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 2053 Integer connId = mClientMap.connIdByAddress(clientIf, address); 2054 if (connId != null) { 2055 gattClientConfigureMTUNative(connId, mtu); 2056 } else { 2057 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 2058 } 2059 } 2060 2061 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 2062 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2063 2064 int minInterval; 2065 int maxInterval; 2066 2067 // Slave latency 2068 int latency; 2069 2070 // Link supervision timeout is measured in N * 10ms 2071 int timeout = 2000; // 20s 2072 2073 switch (connectionPriority) 2074 { 2075 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 2076 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 2077 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 2078 latency = getResources().getInteger(R.integer.gatt_high_priority_latency); 2079 break; 2080 2081 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 2082 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval); 2083 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval); 2084 latency = getResources().getInteger(R.integer.gatt_low_power_latency); 2085 break; 2086 2087 default: 2088 // Using the values for CONNECTION_PRIORITY_BALANCED. 2089 minInterval = 2090 getResources().getInteger(R.integer.gatt_balanced_priority_min_interval); 2091 maxInterval = 2092 getResources().getInteger(R.integer.gatt_balanced_priority_max_interval); 2093 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency); 2094 break; 2095 } 2096 2097 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 2098 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 2099 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 2100 latency, timeout); 2101 } 2102 2103 /************************************************************************** 2104 * Callback functions - SERVER 2105 *************************************************************************/ 2106 2107 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 2108 throws RemoteException { 2109 2110 UUID uuid = new UUID(uuidMsb, uuidLsb); 2111 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 2112 ServerMap.App app = mServerMap.getByUuid(uuid); 2113 if (app != null) { 2114 app.id = serverIf; 2115 app.linkToDeath(new ServerDeathRecipient(serverIf)); 2116 app.callback.onServerRegistered(status, serverIf); 2117 } 2118 } 2119 2120 void onServiceAdded(int status, int serverIf, List<GattDbElement> service) 2121 throws RemoteException { 2122 if (DBG) Log.d(TAG, "onServiceAdded(), status=" + status); 2123 2124 if (status != 0) { 2125 return; 2126 } 2127 2128 GattDbElement svcEl = service.get(0); 2129 int srvcHandle = svcEl.attributeHandle; 2130 2131 BluetoothGattService svc = null; 2132 2133 for (GattDbElement el : service) { 2134 if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) { 2135 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 2136 BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false); 2137 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 2138 BluetoothGattService.SERVICE_TYPE_PRIMARY); 2139 } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) { 2140 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 2141 BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false); 2142 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 2143 BluetoothGattService.SERVICE_TYPE_SECONDARY); 2144 } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) { 2145 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle); 2146 svc.addCharacteristic(new BluetoothGattCharacteristic(el.uuid, 2147 el.attributeHandle, el.properties, el.permissions)); 2148 } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) { 2149 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle); 2150 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics(); 2151 chars.get(chars.size()-1).addDescriptor( 2152 new BluetoothGattDescriptor(el.uuid, el.attributeHandle, el.permissions)); 2153 } 2154 } 2155 mHandleMap.setStarted(serverIf, srvcHandle, true); 2156 2157 ServerMap.App app = mServerMap.getById(serverIf); 2158 if (app != null) { 2159 app.callback.onServiceAdded(status, svc); 2160 } 2161 } 2162 2163 void onServiceStopped(int status, int serverIf, int srvcHandle) 2164 throws RemoteException { 2165 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 2166 + ", status=" + status); 2167 if (status == 0) 2168 mHandleMap.setStarted(serverIf, srvcHandle, false); 2169 stopNextService(serverIf, status); 2170 } 2171 2172 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 2173 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 2174 + ", status=" + status); 2175 mHandleMap.deleteService(serverIf, srvcHandle); 2176 } 2177 2178 void onClientConnected(String address, boolean connected, int connId, int serverIf) 2179 throws RemoteException { 2180 2181 if (DBG) Log.d(TAG, "onClientConnected() connId=" + connId 2182 + ", address=" + address + ", connected=" + connected); 2183 2184 ServerMap.App app = mServerMap.getById(serverIf); 2185 if (app == null) return; 2186 2187 if (connected) { 2188 mServerMap.addConnection(serverIf, connId, address); 2189 } else { 2190 mServerMap.removeConnection(serverIf, connId); 2191 } 2192 2193 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 2194 } 2195 2196 void onServerReadCharacteristic(String address, int connId, int transId, 2197 int handle, int offset, boolean isLong) 2198 throws RemoteException { 2199 if (VDBG) Log.d(TAG, "onServerReadCharacteristic() connId=" + connId 2200 + ", address=" + address + ", handle=" + handle 2201 + ", requestId=" + transId + ", offset=" + offset); 2202 2203 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2204 if (entry == null) return; 2205 2206 mHandleMap.addRequest(transId, handle); 2207 2208 ServerMap.App app = mServerMap.getById(entry.serverIf); 2209 if (app == null) return; 2210 2211 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); 2212 } 2213 2214 void onServerReadDescriptor(String address, int connId, int transId, 2215 int handle, int offset, boolean isLong) 2216 throws RemoteException { 2217 if (VDBG) Log.d(TAG, "onServerReadDescriptor() connId=" + connId 2218 + ", address=" + address + ", handle=" + handle 2219 + ", requestId=" + transId + ", offset=" + offset); 2220 2221 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2222 if (entry == null) return; 2223 2224 mHandleMap.addRequest(transId, handle); 2225 2226 ServerMap.App app = mServerMap.getById(entry.serverIf); 2227 if (app == null) return; 2228 2229 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); 2230 } 2231 2232 void onServerWriteCharacteristic(String address, int connId, int transId, 2233 int handle, int offset, int length, 2234 boolean needRsp, boolean isPrep, 2235 byte[] data) 2236 throws RemoteException { 2237 if (VDBG) Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId 2238 + ", address=" + address + ", handle=" + handle 2239 + ", requestId=" + transId + ", isPrep=" + isPrep 2240 + ", offset=" + offset); 2241 2242 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2243 if (entry == null) return; 2244 2245 mHandleMap.addRequest(transId, handle); 2246 2247 ServerMap.App app = mServerMap.getById(entry.serverIf); 2248 if (app == null) return; 2249 2250 app.callback.onCharacteristicWriteRequest(address, transId, 2251 offset, length, isPrep, needRsp, handle, data); 2252 } 2253 2254 void onServerWriteDescriptor(String address, int connId, int transId, 2255 int handle, int offset, int length, 2256 boolean needRsp, boolean isPrep, 2257 byte[] data) 2258 throws RemoteException { 2259 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 2260 + ", address=" + address + ", handle=" + handle 2261 + ", requestId=" + transId + ", isPrep=" + isPrep 2262 + ", offset=" + offset); 2263 2264 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2265 if (entry == null) return; 2266 2267 mHandleMap.addRequest(transId, handle); 2268 2269 ServerMap.App app = mServerMap.getById(entry.serverIf); 2270 if (app == null) return; 2271 2272 app.callback.onDescriptorWriteRequest(address, transId, 2273 offset, length, isPrep, needRsp, handle, data); 2274 } 2275 2276 void onExecuteWrite(String address, int connId, int transId, int execWrite) 2277 throws RemoteException { 2278 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 2279 + ", address=" + address + ", transId=" + transId); 2280 2281 ServerMap.App app = mServerMap.getByConnId(connId); 2282 if (app == null) return; 2283 2284 app.callback.onExecuteWrite(address, transId, execWrite == 1); 2285 } 2286 2287 void onResponseSendCompleted(int status, int attrHandle) { 2288 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 2289 } 2290 2291 void onNotificationSent(int connId, int status) throws RemoteException { 2292 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 2293 2294 String address = mServerMap.addressByConnId(connId); 2295 if (address == null) return; 2296 2297 ServerMap.App app = mServerMap.getByConnId(connId); 2298 if (app == null) return; 2299 2300 if (!app.isCongested) { 2301 app.callback.onNotificationSent(address, status); 2302 } else { 2303 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 2304 status = BluetoothGatt.GATT_SUCCESS; 2305 } 2306 app.queueCallback(new CallbackInfo(address, status)); 2307 } 2308 } 2309 2310 void onServerCongestion(int connId, boolean congested) throws RemoteException { 2311 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 2312 2313 ServerMap.App app = mServerMap.getByConnId(connId); 2314 if (app == null) return; 2315 2316 app.isCongested = congested; 2317 while(!app.isCongested) { 2318 CallbackInfo callbackInfo = app.popQueuedCallback(); 2319 if (callbackInfo == null) return; 2320 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 2321 } 2322 } 2323 2324 void onMtuChanged(int connId, int mtu) throws RemoteException { 2325 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 2326 2327 String address = mServerMap.addressByConnId(connId); 2328 if (address == null) return; 2329 2330 ServerMap.App app = mServerMap.getByConnId(connId); 2331 if (app == null) return; 2332 2333 app.callback.onMtuChanged(address, mtu); 2334 } 2335 2336 /************************************************************************** 2337 * GATT Service functions - SERVER 2338 *************************************************************************/ 2339 2340 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 2341 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2342 2343 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 2344 mServerMap.add(uuid, null, callback, null, this); 2345 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 2346 uuid.getMostSignificantBits()); 2347 } 2348 2349 void unregisterServer(int serverIf) { 2350 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2351 2352 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 2353 2354 deleteServices(serverIf); 2355 2356 mServerMap.remove(serverIf); 2357 gattServerUnregisterAppNative(serverIf); 2358 } 2359 2360 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 2361 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2362 2363 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 2364 gattServerConnectNative(serverIf, address, isDirect,transport); 2365 } 2366 2367 void serverDisconnect(int serverIf, String address) { 2368 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2369 2370 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2371 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 2372 2373 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 2374 } 2375 2376 void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions) { 2377 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2378 2379 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2380 if (connId == null) { 2381 if (DBG) Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address); 2382 return; 2383 } 2384 2385 if (DBG) Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId); 2386 gattServerSetPreferredPhyNative(serverIf, address, txPhy, rxPhy, phyOptions); 2387 } 2388 2389 void serverReadPhy(int serverIf, String address) { 2390 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2391 2392 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2393 if (connId == null) { 2394 if (DBG) Log.d(TAG, "serverReadPhy() - no connection to " + address); 2395 return; 2396 } 2397 2398 if (DBG) Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId); 2399 gattServerReadPhyNative(serverIf, address); 2400 } 2401 2402 void addService(int serverIf, BluetoothGattService service) { 2403 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2404 2405 if (DBG) Log.d(TAG, "addService() - uuid=" + service.getUuid()); 2406 2407 List<GattDbElement> db = new ArrayList<GattDbElement>(); 2408 2409 if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) 2410 db.add(GattDbElement.createPrimaryService(service.getUuid())); 2411 else db.add(GattDbElement.createSecondaryService(service.getUuid())); 2412 2413 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 2414 int permission = ((characteristic.getKeySize() - 7) << 12) 2415 + characteristic.getPermissions(); 2416 db.add(GattDbElement.createCharacteristic(characteristic.getUuid(), 2417 characteristic.getProperties(), permission)); 2418 2419 for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) { 2420 permission = ((characteristic.getKeySize() - 7) << 12) 2421 + descriptor.getPermissions(); 2422 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission)); 2423 } 2424 } 2425 2426 for (BluetoothGattService includedService : service.getIncludedServices()) { 2427 int inclSrvc = mHandleMap.getServiceHandle(includedService.getUuid(), 2428 includedService.getType(), includedService.getInstanceId()); 2429 db.add(GattDbElement.createIncludedService(inclSrvc)); 2430 } 2431 2432 gattServerAddServiceNative(serverIf, db); 2433 } 2434 2435 void removeService(int serverIf, int handle) { 2436 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2437 2438 if (DBG) Log.d(TAG, "removeService() - handle=" + handle); 2439 2440 gattServerDeleteServiceNative(serverIf, handle); 2441 } 2442 2443 void clearServices(int serverIf) { 2444 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2445 2446 if (DBG) Log.d(TAG, "clearServices()"); 2447 deleteServices(serverIf); 2448 } 2449 2450 void sendResponse(int serverIf, String address, int requestId, 2451 int status, int offset, byte[] value) { 2452 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2453 2454 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 2455 2456 int handle = 0; 2457 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2458 if (entry != null) handle = entry.handle; 2459 2460 int connId = mServerMap.connIdByAddress(serverIf, address); 2461 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2462 handle, offset, value, (byte)0); 2463 mHandleMap.deleteRequest(requestId); 2464 } 2465 2466 void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) { 2467 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2468 2469 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle); 2470 2471 int connId = mServerMap.connIdByAddress(serverIf, address); 2472 if (connId == 0) return; 2473 2474 if (confirm) { 2475 gattServerSendIndicationNative(serverIf, handle, connId, value); 2476 } else { 2477 gattServerSendNotificationNative(serverIf, handle, connId, value); 2478 } 2479 } 2480 2481 2482 /************************************************************************** 2483 * Private functions 2484 *************************************************************************/ 2485 2486 private boolean isRestrictedCharUuid(final UUID charUuid) { 2487 return isHidUuid(charUuid); 2488 } 2489 2490 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2491 return isFidoUUID(srvcUuid); 2492 } 2493 2494 private boolean isHidUuid(final UUID uuid) { 2495 for (UUID hid_uuid : HID_UUIDS) { 2496 if (hid_uuid.equals(uuid)) return true; 2497 } 2498 return false; 2499 } 2500 2501 private boolean isFidoUUID(final UUID uuid) { 2502 for (UUID fido_uuid : FIDO_UUIDS) { 2503 if (fido_uuid.equals(uuid)) return true; 2504 } 2505 return false; 2506 } 2507 2508 private int getDeviceType(BluetoothDevice device) { 2509 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2510 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2511 + ", type=" + type); 2512 return type; 2513 } 2514 2515 private void enforceAdminPermission() { 2516 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2517 } 2518 2519 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2520 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2521 // BLE scan only mode needs special permission. 2522 if (adapter.getState() != BluetoothAdapter.STATE_ON) return true; 2523 2524 // Regular scan, no special permission. 2525 if (settings == null) return false; 2526 2527 // Regular scan, no special permission. 2528 if (settings.getReportDelayMillis() == 0) return false; 2529 2530 // Batch scan, truncated mode needs permission. 2531 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2532 } 2533 2534 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2535 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2536 private void enforcePrivilegedPermission() { 2537 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2538 "Need BLUETOOTH_PRIVILEGED permission"); 2539 } 2540 2541 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 2542 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 2543 // not have UPDATE_DEVICE_STATS permission. 2544 private void enforceImpersonatationPermission() { 2545 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 2546 "Need UPDATE_DEVICE_STATS permission"); 2547 } 2548 2549 private void stopNextService(int serverIf, int status) throws RemoteException { 2550 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2551 + ", status=" + status); 2552 2553 if (status == 0) { 2554 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2555 for(HandleMap.Entry entry : entries) { 2556 if (entry.type != HandleMap.TYPE_SERVICE || 2557 entry.serverIf != serverIf || 2558 entry.started == false) 2559 continue; 2560 2561 gattServerStopServiceNative(serverIf, entry.handle); 2562 return; 2563 } 2564 } 2565 } 2566 2567 private void deleteServices(int serverIf) { 2568 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2569 2570 /* 2571 * Figure out which handles to delete. 2572 * The handles are copied into a new list to avoid race conditions. 2573 */ 2574 List<Integer> handleList = new ArrayList<Integer>(); 2575 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2576 for(HandleMap.Entry entry : entries) { 2577 if (entry.type != HandleMap.TYPE_SERVICE || 2578 entry.serverIf != serverIf) 2579 continue; 2580 handleList.add(entry.handle); 2581 } 2582 2583 /* Now actually delete the services.... */ 2584 for(Integer handle : handleList) { 2585 gattServerDeleteServiceNative(serverIf, handle); 2586 } 2587 } 2588 2589 private List<UUID> parseUuids(byte[] adv_data) { 2590 List<UUID> uuids = new ArrayList<UUID>(); 2591 2592 int offset = 0; 2593 while(offset < (adv_data.length-2)) { 2594 int len = Byte.toUnsignedInt(adv_data[offset++]); 2595 if (len == 0) break; 2596 2597 int type = adv_data[offset++]; 2598 switch (type) { 2599 case 0x02: // Partial list of 16-bit UUIDs 2600 case 0x03: // Complete list of 16-bit UUIDs 2601 while (len > 1) { 2602 int uuid16 = adv_data[offset++]; 2603 uuid16 += (adv_data[offset++] << 8); 2604 len -= 2; 2605 uuids.add(UUID.fromString(String.format( 2606 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2607 } 2608 break; 2609 2610 default: 2611 offset += (len - 1); 2612 break; 2613 } 2614 } 2615 2616 return uuids; 2617 } 2618 2619 @Override 2620 public void dump(StringBuilder sb) { 2621 super.dump(sb); 2622 println(sb, "mAdvertisingServiceUuids:"); 2623 for (UUID uuid : mAdvertisingServiceUuids) { 2624 println(sb, " " + uuid); 2625 } 2626 2627 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2628 2629 sb.append("\nGATT Scanner Map\n"); 2630 mScannerMap.dump(sb); 2631 2632 sb.append("GATT Client Map\n"); 2633 mClientMap.dump(sb); 2634 2635 sb.append("GATT Server Map\n"); 2636 mServerMap.dump(sb); 2637 2638 sb.append("GATT Handle Map\n"); 2639 mHandleMap.dump(sb); 2640 } 2641 2642 void addScanResult() { 2643 if (mScanEvents.isEmpty()) 2644 return; 2645 2646 BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1); 2647 curr.setNumberResults(curr.getNumberResults() + 1); 2648 } 2649 2650 void addScanEvent(BluetoothProto.ScanEvent event) { 2651 synchronized(mScanEvents) { 2652 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 2653 mScanEvents.remove(0); 2654 mScanEvents.add(event); 2655 } 2656 } 2657 2658 @Override 2659 public void dumpProto(BluetoothProto.BluetoothLog proto) { 2660 synchronized(mScanEvents) { 2661 for (BluetoothProto.ScanEvent event : mScanEvents) { 2662 proto.addScanEvent(event); 2663 } 2664 } 2665 } 2666 2667 /************************************************************************** 2668 * GATT Test functions 2669 *************************************************************************/ 2670 2671 void gattTestCommand(int command, UUID uuid1, String bda1, 2672 int p1, int p2, int p3, int p4, int p5) { 2673 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2674 if (uuid1 != null) 2675 gattTestNative(command, uuid1.getLeastSignificantBits(), 2676 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2677 else 2678 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2679 } 2680 2681 private native void gattTestNative(int command, 2682 long uuid1_lsb, long uuid1_msb, String bda1, 2683 int p1, int p2, int p3, int p4, int p5); 2684 2685 /************************************************************************** 2686 * Native functions prototypes 2687 *************************************************************************/ 2688 2689 private native static void classInitNative(); 2690 private native void initializeNative(); 2691 private native void cleanupNative(); 2692 2693 private native int gattClientGetDeviceTypeNative(String address); 2694 2695 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2696 long app_uuid_msb); 2697 2698 private native void gattClientUnregisterAppNative(int clientIf); 2699 2700 private native void gattClientConnectNative(int clientIf, String address, boolean isDirect, 2701 int transport, boolean opportunistic, int initiating_phys); 2702 2703 private native void gattClientDisconnectNative(int clientIf, String address, 2704 int conn_id); 2705 2706 private native void gattClientSetPreferredPhyNative( 2707 int clientIf, String address, int tx_phy, int rx_phy, int phy_options); 2708 2709 private native void gattClientReadPhyNative(int clientIf, String address); 2710 2711 private native void gattClientRefreshNative(int clientIf, String address); 2712 2713 private native void gattClientSearchServiceNative(int conn_id, 2714 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2715 2716 private native void gattClientDiscoverServiceByUuidNative( 2717 int conn_id, long service_uuid_lsb, long service_uuid_msb); 2718 2719 private native void gattClientGetGattDbNative(int conn_id); 2720 2721 private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq); 2722 2723 private native void gattClientReadUsingCharacteristicUuidNative( 2724 int conn_id, long uuid_msb, long uuid_lsb, int s_handle, int e_handle, int authReq); 2725 2726 private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq); 2727 2728 private native void gattClientWriteCharacteristicNative(int conn_id, 2729 int handle, int write_type, int auth_req, byte[] value); 2730 2731 private native void gattClientWriteDescriptorNative(int conn_id, int handle, 2732 int auth_req, byte[] value); 2733 2734 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2735 2736 private native void gattClientRegisterForNotificationsNative(int clientIf, 2737 String address, int handle, boolean enable); 2738 2739 private native void gattClientReadRemoteRssiNative(int clientIf, 2740 String address); 2741 2742 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2743 2744 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2745 int minInterval, int maxInterval, int latency, int timeout); 2746 2747 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2748 long app_uuid_msb); 2749 2750 private native void gattServerUnregisterAppNative(int serverIf); 2751 2752 private native void gattServerConnectNative(int server_if, String address, 2753 boolean is_direct, int transport); 2754 2755 private native void gattServerDisconnectNative(int serverIf, String address, 2756 int conn_id); 2757 2758 private native void gattServerSetPreferredPhyNative( 2759 int clientIf, String address, int tx_phy, int rx_phy, int phy_options); 2760 2761 private native void gattServerReadPhyNative(int clientIf, String address); 2762 2763 private native void gattServerAddServiceNative(int server_if, List<GattDbElement> service); 2764 2765 private native void gattServerStopServiceNative (int server_if, 2766 int svc_handle); 2767 2768 private native void gattServerDeleteServiceNative (int server_if, 2769 int svc_handle); 2770 2771 private native void gattServerSendIndicationNative (int server_if, 2772 int attr_handle, int conn_id, byte[] val); 2773 2774 private native void gattServerSendNotificationNative (int server_if, 2775 int attr_handle, int conn_id, byte[] val); 2776 2777 private native void gattServerSendResponseNative (int server_if, 2778 int conn_id, int trans_id, int status, int handle, int offset, 2779 byte[] val, int auth_req); 2780} 2781