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