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