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