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