GattService.java revision 52ec4e757eff12405d0d074d58822b061cd77d84
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 // Followings are callbacks for Bluetooth LE Advertise operations. 1164 // Start advertising flow is 1165 // register advertiser -> onAdvertiserRegistered 1166 // enable advertising instance -> onAdvertiseInstaceEnabled 1167 // -> set advertise data -> onAdvertiseDataSet 1168 // -> set scan response -> onAdvertiseDataSet 1169 1170 void onAdvertiserRegistered(int status, int advertiserId, long uuidLsb, long uuidMsb) 1171 throws RemoteException { 1172 UUID uuid = new UUID(uuidMsb, uuidLsb); 1173 if (DBG) Log.d(TAG, "onAdvertiserRegistered() - UUID=" + uuid 1174 + ", advertiserId=" + advertiserId + ", status=" + status); 1175 1176 AdvertiserMap.App app = mAdvertiserMap.getByUuid(uuid); 1177 if (app != null) { 1178 if (status == 0) { 1179 app.id = advertiserId; 1180 app.linkToDeath(new AdvertiserDeathRecipient(advertiserId)); 1181 } else { 1182 mAdvertiserMap.remove(advertiserId); 1183 } 1184 app.callback.onAdvertiserRegistered(status, advertiserId); 1185 } 1186 } 1187 1188 void onAdvertiserStarted(int status, int advertiserId) 1189 throws RemoteException { 1190 if (DBG) Log.d(TAG, "onAdvertiserStarted() - advertiserId=" + advertiserId + 1191 ", status=" + status); 1192 1193 AdvertiserMap.App app = mAdvertiserMap.getById(advertiserId); 1194 if (app != null) { 1195 if (status == 0) { 1196 app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS, 1197 true, null); 1198 } else { 1199 app.callback.onMultiAdvertiseCallback( 1200 AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR, true, null); 1201 } 1202 } 1203 } 1204 1205 // Callback when advertise instance is enabled. 1206 void onAdvertiseInstanceEnabled(int status, int advertiserId, 1207 boolean enable) throws RemoteException { 1208 if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - " 1209 + "advertiserId=" + advertiserId + ", status=" + status + ", enable=" + enable); 1210 1211 AdvertiserMap.App app = mAdvertiserMap.getById(advertiserId); 1212 if (app != null) { 1213 if (status == 0) { 1214 app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS, 1215 enable, null); 1216 } else { 1217 app.callback.onMultiAdvertiseCallback( 1218 AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR, enable, null); 1219 } 1220 } 1221 } 1222 1223 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1224 if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1225 1226 ClientMap.App app = mClientMap.getByConnId(connId); 1227 1228 if (app != null) { 1229 app.isCongested = congested; 1230 while(!app.isCongested) { 1231 CallbackInfo callbackInfo = app.popQueuedCallback(); 1232 if (callbackInfo == null) return; 1233 app.callback.onCharacteristicWrite(callbackInfo.address, 1234 callbackInfo.status, callbackInfo.handle); 1235 } 1236 } 1237 } 1238 1239 /************************************************************************** 1240 * GATT Service functions - Shared CLIENT/SERVER 1241 *************************************************************************/ 1242 1243 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1244 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1245 1246 final int DEVICE_TYPE_BREDR = 0x1; 1247 1248 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1249 Integer>(); 1250 1251 // Add paired LE devices 1252 1253 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1254 for (BluetoothDevice device : bondedDevices) { 1255 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1256 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1257 } 1258 } 1259 1260 // Add connected deviceStates 1261 1262 Set<String> connectedDevices = new HashSet<String>(); 1263 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1264 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1265 1266 for (String address : connectedDevices ) { 1267 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1268 if (device != null) { 1269 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1270 } 1271 } 1272 1273 // Create matching device sub-set 1274 1275 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1276 1277 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1278 for(int state : states) { 1279 if (entry.getValue() == state) { 1280 deviceList.add(entry.getKey()); 1281 } 1282 } 1283 } 1284 1285 return deviceList; 1286 } 1287 1288 void registerScanner(IScannerCallback callback) { 1289 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1290 1291 UUID uuid = UUID.randomUUID(); 1292 if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid); 1293 mScannerMap.add(uuid, callback, this); 1294 mScanManager.registerScanner(uuid); 1295 } 1296 1297 void unregisterScanner(int scannerId) { 1298 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1299 1300 if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); 1301 mScannerMap.remove(scannerId); 1302 mScanManager.unregisterScanner(scannerId); 1303 } 1304 1305 void startScan(int scannerId, ScanSettings settings, 1306 List<ScanFilter> filters, WorkSource workSource, 1307 List<List<ResultStorageDescriptor>> storages, String callingPackage) { 1308 if (DBG) Log.d(TAG, "start scan with filters"); 1309 enforceAdminPermission(); 1310 if (needsPrivilegedPermissionForScan(settings)) { 1311 enforcePrivilegedPermission(); 1312 } 1313 if (workSource != null) { 1314 enforceImpersonatationPermission(); 1315 } else { 1316 // Blame the caller if the work source is unspecified. 1317 workSource = new WorkSource(Binder.getCallingUid(), callingPackage); 1318 } 1319 final ScanClient scanClient = new ScanClient(scannerId, settings, filters, workSource, 1320 storages); 1321 scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps, 1322 callingPackage); 1323 scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission( 1324 this); 1325 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); 1326 1327 AppScanStats app = null; 1328 app = mClientMap.getAppScanStatsById(scannerId); 1329 1330 if (app != null) { 1331 if (app.isScanningTooFrequently() && 1332 checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) { 1333 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 1334 return; 1335 } 1336 scanClient.stats = app; 1337 app.recordScanStart(settings); 1338 } 1339 1340 mScanManager.startScan(scanClient); 1341 } 1342 1343 void flushPendingBatchResults(int scannerId) { 1344 if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); 1345 mScanManager.flushBatchScanResults(new ScanClient(scannerId)); 1346 } 1347 1348 void stopScan(ScanClient client) { 1349 enforceAdminPermission(); 1350 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1351 mScanManager.getRegularScanQueue().size(); 1352 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1353 1354 AppScanStats app = null; 1355 app = mScannerMap.getAppScanStatsById(client.scannerId); 1356 if (app != null) app.recordScanStop(); 1357 1358 mScanManager.stopScan(client); 1359 } 1360 1361 void disconnectAll() { 1362 if (DBG) Log.d(TAG, "disconnectAll()"); 1363 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 1364 for(Map.Entry<Integer, String> entry:connMap.entrySet()){ 1365 if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue()); 1366 clientDisconnect(entry.getKey(), entry.getValue()); 1367 //clientDisconnect(int clientIf, String address) 1368 } 1369 } 1370 1371 void unregAll() { 1372 for(ClientMap.App app:mClientMap.mApps){ 1373 if (DBG) Log.d(TAG, "unreg:" + app.id); 1374 unregisterClient(app.id); 1375 } 1376 } 1377 1378 /************************************************************************** 1379 * ADVERTISER 1380 *************************************************************************/ 1381 1382 void registerAdvertiser(IAdvertiserCallback callback) { 1383 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1384 1385 UUID uuid = UUID.randomUUID(); 1386 if (DBG) Log.d(TAG, "registerAdvertiser() - UUID=" + uuid); 1387 mAdvertiserMap.add(uuid, callback, this); 1388 mAdvertiseManager.registerAdvertiser(uuid); 1389 } 1390 1391 void unregisterAdvertiser(int advertiserId) { 1392 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1393 1394 if (DBG) Log.d(TAG, "unregisterAdvertiser() - advertiserId=" + advertiserId); 1395 mAdvertiserMap.remove(advertiserId); 1396 mAdvertiseManager.unregisterAdvertiser(advertiserId); 1397 } 1398 1399 void startMultiAdvertising(int advertiserId, AdvertiseData advertiseData, 1400 AdvertiseData scanResponse, AdvertiseSettings settings) { 1401 enforceAdminPermission(); 1402 1403 if (DBG) Log.d(TAG, "startMultiAdvertising() - advertiserId=" + advertiserId); 1404 mAdvertiseManager.startAdvertising(new AdvertiseClient(advertiserId, settings, advertiseData, 1405 scanResponse)); 1406 } 1407 1408 void stopMultiAdvertising(AdvertiseClient client) { 1409 enforceAdminPermission(); 1410 1411 if (DBG) Log.d(TAG, "stopMultiAdvertising() - advertiserId=" + client.advertiserId); 1412 mAdvertiseManager.stopAdvertising(client); 1413 } 1414 1415 /************************************************************************** 1416 * GATT Service functions - CLIENT 1417 *************************************************************************/ 1418 1419 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1420 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1421 1422 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1423 mClientMap.add(uuid, callback, this); 1424 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1425 uuid.getMostSignificantBits()); 1426 } 1427 1428 void unregisterClient(int clientIf) { 1429 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1430 1431 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1432 mClientMap.remove(clientIf); 1433 gattClientUnregisterAppNative(clientIf); 1434 } 1435 1436 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1437 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1438 1439 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1440 gattClientConnectNative(clientIf, address, isDirect, transport); 1441 } 1442 1443 void clientDisconnect(int clientIf, String address) { 1444 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1445 1446 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1447 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1448 1449 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1450 } 1451 1452 int numHwTrackFiltersAvailable() { 1453 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 1454 - mScanManager.getCurrentUsedTrackingAdvertisement()); 1455 } 1456 1457 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1458 Utils.enforceAdminPermission(this); 1459 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1460 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1461 serviceUuids.add(new ParcelUuid(entry.uuid)); 1462 } 1463 return serviceUuids; 1464 } 1465 1466 List<String> getConnectedDevices() { 1467 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1468 1469 Set<String> connectedDevAddress = new HashSet<String>(); 1470 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1471 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1472 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1473 return connectedDeviceList; 1474 } 1475 1476 void refreshDevice(int clientIf, String address) { 1477 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1478 1479 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1480 gattClientRefreshNative(clientIf, address); 1481 } 1482 1483 void discoverServices(int clientIf, String address) { 1484 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1485 1486 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1487 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1488 1489 if (connId != null) 1490 gattClientSearchServiceNative(connId, true, 0, 0); 1491 else 1492 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1493 } 1494 1495 void readCharacteristic(int clientIf, String address, int handle, int authReq) { 1496 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1497 1498 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1499 1500 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1501 if (connId == null) { 1502 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1503 return; 1504 } 1505 1506 if (!permissionCheck(connId, handle)) { 1507 Log.w(TAG, "readCharacteristic() - permission check failed!"); 1508 return; 1509 } 1510 1511 gattClientReadCharacteristicNative(connId, handle, authReq); 1512 } 1513 1514 void writeCharacteristic(int clientIf, String address, int handle, int writeType, 1515 int authReq, byte[] value) { 1516 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1517 1518 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1519 1520 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1521 1522 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1523 if (connId == null) { 1524 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1525 return; 1526 } 1527 1528 if (!permissionCheck(connId, handle)) { 1529 Log.w(TAG, "writeCharacteristic() - permission check failed!"); 1530 return; 1531 } 1532 1533 gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value); 1534 } 1535 1536 void readDescriptor(int clientIf, String address, int handle, int authReq) { 1537 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1538 1539 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1540 1541 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1542 if (connId == null) { 1543 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1544 return; 1545 } 1546 1547 if (!permissionCheck(connId, handle)) { 1548 Log.w(TAG, "readDescriptor() - permission check failed!"); 1549 return; 1550 } 1551 1552 gattClientReadDescriptorNative(connId, handle, authReq); 1553 }; 1554 1555 void writeDescriptor(int clientIf, String address, int handle, 1556 int authReq, byte[] value) { 1557 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1558 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1559 1560 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1561 if (connId == null) { 1562 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1563 return; 1564 } 1565 1566 if (!permissionCheck(connId, handle)) { 1567 Log.w(TAG, "writeDescriptor() - permission check failed!"); 1568 return; 1569 } 1570 1571 gattClientWriteDescriptorNative(connId, handle, authReq, value); 1572 } 1573 1574 void beginReliableWrite(int clientIf, String address) { 1575 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1576 1577 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1578 mReliableQueue.add(address); 1579 } 1580 1581 void endReliableWrite(int clientIf, String address, boolean execute) { 1582 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1583 1584 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1585 + " execute: " + execute); 1586 mReliableQueue.remove(address); 1587 1588 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1589 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1590 } 1591 1592 void registerForNotification(int clientIf, String address, int handle, boolean enable) { 1593 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1594 1595 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1596 1597 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1598 if (connId == null) { 1599 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1600 return; 1601 } 1602 1603 if (!permissionCheck(connId, handle)) { 1604 Log.w(TAG, "registerForNotification() - permission check failed!"); 1605 return; 1606 } 1607 1608 gattClientRegisterForNotificationsNative(clientIf, address, handle, enable); 1609 } 1610 1611 void readRemoteRssi(int clientIf, String address) { 1612 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1613 1614 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1615 gattClientReadRemoteRssiNative(clientIf, address); 1616 } 1617 1618 void configureMTU(int clientIf, String address, int mtu) { 1619 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1620 1621 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1622 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1623 if (connId != null) { 1624 gattClientConfigureMTUNative(connId, mtu); 1625 } else { 1626 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1627 } 1628 } 1629 1630 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1631 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1632 1633 int minInterval; 1634 int maxInterval; 1635 1636 // Slave latency 1637 int latency; 1638 1639 // Link supervision timeout is measured in N * 10ms 1640 int timeout = 2000; // 20s 1641 1642 switch (connectionPriority) 1643 { 1644 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1645 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 1646 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 1647 latency = getResources().getInteger(R.integer.gatt_high_priority_latency); 1648 break; 1649 1650 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 1651 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval); 1652 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval); 1653 latency = getResources().getInteger(R.integer.gatt_low_power_latency); 1654 break; 1655 1656 default: 1657 // Using the values for CONNECTION_PRIORITY_BALANCED. 1658 minInterval = 1659 getResources().getInteger(R.integer.gatt_balanced_priority_min_interval); 1660 maxInterval = 1661 getResources().getInteger(R.integer.gatt_balanced_priority_max_interval); 1662 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency); 1663 break; 1664 } 1665 1666 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1667 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1668 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1669 latency, timeout); 1670 } 1671 1672 /************************************************************************** 1673 * Callback functions - SERVER 1674 *************************************************************************/ 1675 1676 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1677 throws RemoteException { 1678 1679 UUID uuid = new UUID(uuidMsb, uuidLsb); 1680 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1681 ServerMap.App app = mServerMap.getByUuid(uuid); 1682 if (app != null) { 1683 app.id = serverIf; 1684 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1685 app.callback.onServerRegistered(status, serverIf); 1686 } 1687 } 1688 1689 void onServiceAdded(int status, int serverIf, List<GattDbElement> service) 1690 throws RemoteException { 1691 if (DBG) Log.d(TAG, "onServiceAdded(), status=" + status); 1692 1693 if (status != 0) { 1694 return; 1695 } 1696 1697 GattDbElement svcEl = service.get(0); 1698 int srvcHandle = svcEl.attributeHandle; 1699 1700 BluetoothGattService svc = null; 1701 1702 for (GattDbElement el : service) { 1703 if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) { 1704 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 1705 BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false); 1706 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 1707 BluetoothGattService.SERVICE_TYPE_PRIMARY); 1708 } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) { 1709 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 1710 BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false); 1711 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 1712 BluetoothGattService.SERVICE_TYPE_SECONDARY); 1713 } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) { 1714 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle); 1715 svc.addCharacteristic(new BluetoothGattCharacteristic(el.uuid, 1716 el.attributeHandle, el.properties, el.permissions)); 1717 } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) { 1718 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle); 1719 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics(); 1720 chars.get(chars.size()-1).addDescriptor( 1721 new BluetoothGattDescriptor(el.uuid, el.attributeHandle, el.permissions)); 1722 } 1723 } 1724 mHandleMap.setStarted(serverIf, srvcHandle, true); 1725 1726 ServerMap.App app = mServerMap.getById(serverIf); 1727 if (app != null) { 1728 app.callback.onServiceAdded(status, svc); 1729 } 1730 } 1731 1732 void onServiceStopped(int status, int serverIf, int srvcHandle) 1733 throws RemoteException { 1734 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1735 + ", status=" + status); 1736 if (status == 0) 1737 mHandleMap.setStarted(serverIf, srvcHandle, false); 1738 stopNextService(serverIf, status); 1739 } 1740 1741 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1742 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1743 + ", status=" + status); 1744 mHandleMap.deleteService(serverIf, srvcHandle); 1745 } 1746 1747 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1748 throws RemoteException { 1749 1750 if (DBG) Log.d(TAG, "onClientConnected() connId=" + connId 1751 + ", address=" + address + ", connected=" + connected); 1752 1753 ServerMap.App app = mServerMap.getById(serverIf); 1754 if (app == null) return; 1755 1756 if (connected) { 1757 mServerMap.addConnection(serverIf, connId, address); 1758 } else { 1759 mServerMap.removeConnection(serverIf, connId); 1760 } 1761 1762 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1763 } 1764 1765 void onServerReadCharacteristic(String address, int connId, int transId, 1766 int handle, int offset, boolean isLong) 1767 throws RemoteException { 1768 if (VDBG) Log.d(TAG, "onServerReadCharacteristic() connId=" + connId 1769 + ", address=" + address + ", handle=" + handle 1770 + ", requestId=" + transId + ", offset=" + offset); 1771 1772 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 1773 if (entry == null) return; 1774 1775 mHandleMap.addRequest(transId, handle); 1776 1777 ServerMap.App app = mServerMap.getById(entry.serverIf); 1778 if (app == null) return; 1779 1780 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); 1781 } 1782 1783 void onServerReadDescriptor(String address, int connId, int transId, 1784 int handle, int offset, boolean isLong) 1785 throws RemoteException { 1786 if (VDBG) Log.d(TAG, "onServerReadDescriptor() connId=" + connId 1787 + ", address=" + address + ", handle=" + handle 1788 + ", requestId=" + transId + ", offset=" + offset); 1789 1790 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 1791 if (entry == null) return; 1792 1793 mHandleMap.addRequest(transId, handle); 1794 1795 ServerMap.App app = mServerMap.getById(entry.serverIf); 1796 if (app == null) return; 1797 1798 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); 1799 } 1800 1801 void onServerWriteCharacteristic(String address, int connId, int transId, 1802 int handle, int offset, int length, 1803 boolean needRsp, boolean isPrep, 1804 byte[] data) 1805 throws RemoteException { 1806 if (VDBG) Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId 1807 + ", address=" + address + ", handle=" + handle 1808 + ", requestId=" + transId + ", isPrep=" + isPrep 1809 + ", offset=" + offset); 1810 1811 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 1812 if (entry == null) return; 1813 1814 mHandleMap.addRequest(transId, handle); 1815 1816 ServerMap.App app = mServerMap.getById(entry.serverIf); 1817 if (app == null) return; 1818 1819 app.callback.onCharacteristicWriteRequest(address, transId, 1820 offset, length, isPrep, needRsp, handle, data); 1821 } 1822 1823 void onServerWriteDescriptor(String address, int connId, int transId, 1824 int handle, int offset, int length, 1825 boolean needRsp, boolean isPrep, 1826 byte[] data) 1827 throws RemoteException { 1828 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1829 + ", address=" + address + ", handle=" + handle 1830 + ", requestId=" + transId + ", isPrep=" + isPrep 1831 + ", offset=" + offset); 1832 1833 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 1834 if (entry == null) return; 1835 1836 mHandleMap.addRequest(transId, handle); 1837 1838 ServerMap.App app = mServerMap.getById(entry.serverIf); 1839 if (app == null) return; 1840 1841 app.callback.onDescriptorWriteRequest(address, transId, 1842 offset, length, isPrep, needRsp, handle, data); 1843 } 1844 1845 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1846 throws RemoteException { 1847 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1848 + ", address=" + address + ", transId=" + transId); 1849 1850 ServerMap.App app = mServerMap.getByConnId(connId); 1851 if (app == null) return; 1852 1853 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1854 } 1855 1856 void onResponseSendCompleted(int status, int attrHandle) { 1857 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1858 } 1859 1860 void onNotificationSent(int connId, int status) throws RemoteException { 1861 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1862 1863 String address = mServerMap.addressByConnId(connId); 1864 if (address == null) return; 1865 1866 ServerMap.App app = mServerMap.getByConnId(connId); 1867 if (app == null) return; 1868 1869 if (!app.isCongested) { 1870 app.callback.onNotificationSent(address, status); 1871 } else { 1872 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1873 status = BluetoothGatt.GATT_SUCCESS; 1874 } 1875 app.queueCallback(new CallbackInfo(address, status)); 1876 } 1877 } 1878 1879 void onServerCongestion(int connId, boolean congested) throws RemoteException { 1880 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1881 1882 ServerMap.App app = mServerMap.getByConnId(connId); 1883 if (app == null) return; 1884 1885 app.isCongested = congested; 1886 while(!app.isCongested) { 1887 CallbackInfo callbackInfo = app.popQueuedCallback(); 1888 if (callbackInfo == null) return; 1889 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 1890 } 1891 } 1892 1893 void onMtuChanged(int connId, int mtu) throws RemoteException { 1894 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 1895 1896 String address = mServerMap.addressByConnId(connId); 1897 if (address == null) return; 1898 1899 ServerMap.App app = mServerMap.getByConnId(connId); 1900 if (app == null) return; 1901 1902 app.callback.onMtuChanged(address, mtu); 1903 } 1904 1905 /************************************************************************** 1906 * GATT Service functions - SERVER 1907 *************************************************************************/ 1908 1909 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1910 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1911 1912 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1913 mServerMap.add(uuid, callback, this); 1914 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1915 uuid.getMostSignificantBits()); 1916 } 1917 1918 void unregisterServer(int serverIf) { 1919 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1920 1921 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1922 1923 deleteServices(serverIf); 1924 1925 mServerMap.remove(serverIf); 1926 gattServerUnregisterAppNative(serverIf); 1927 } 1928 1929 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1930 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1931 1932 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1933 gattServerConnectNative(serverIf, address, isDirect,transport); 1934 } 1935 1936 void serverDisconnect(int serverIf, String address) { 1937 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1938 1939 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1940 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1941 1942 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1943 } 1944 1945 void addService(int serverIf, BluetoothGattService service) { 1946 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1947 1948 if (DBG) Log.d(TAG, "addService() - uuid=" + service.getUuid()); 1949 1950 List<GattDbElement> db = new ArrayList<GattDbElement>(); 1951 1952 if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) 1953 db.add(GattDbElement.createPrimaryService(service.getUuid())); 1954 else db.add(GattDbElement.createSecondaryService(service.getUuid())); 1955 1956 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 1957 int permission = ((characteristic.getKeySize() - 7) << 12) 1958 + characteristic.getPermissions(); 1959 db.add(GattDbElement.createCharacteristic(characteristic.getUuid(), 1960 characteristic.getProperties(), permission)); 1961 1962 for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) { 1963 permission = ((characteristic.getKeySize() - 7) << 12) 1964 + descriptor.getPermissions(); 1965 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission)); 1966 } 1967 } 1968 1969 for (BluetoothGattService includedService : service.getIncludedServices()) { 1970 int inclSrvc = mHandleMap.getServiceHandle(includedService.getUuid(), 1971 includedService.getType(), includedService.getInstanceId()); 1972 db.add(GattDbElement.createIncludedService(inclSrvc)); 1973 } 1974 1975 gattServerAddServiceNative(serverIf, db); 1976 } 1977 1978 void removeService(int serverIf, int handle) { 1979 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1980 1981 if (DBG) Log.d(TAG, "removeService() - handle=" + handle); 1982 1983 gattServerDeleteServiceNative(serverIf, handle); 1984 } 1985 1986 void clearServices(int serverIf) { 1987 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1988 1989 if (DBG) Log.d(TAG, "clearServices()"); 1990 deleteServices(serverIf); 1991 } 1992 1993 void sendResponse(int serverIf, String address, int requestId, 1994 int status, int offset, byte[] value) { 1995 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1996 1997 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 1998 1999 int handle = 0; 2000 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2001 if (entry != null) handle = entry.handle; 2002 2003 int connId = mServerMap.connIdByAddress(serverIf, address); 2004 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2005 handle, offset, value, (byte)0); 2006 mHandleMap.deleteRequest(requestId); 2007 } 2008 2009 void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) { 2010 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2011 2012 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle); 2013 2014 int connId = mServerMap.connIdByAddress(serverIf, address); 2015 if (connId == 0) return; 2016 2017 if (confirm) { 2018 gattServerSendIndicationNative(serverIf, handle, connId, value); 2019 } else { 2020 gattServerSendNotificationNative(serverIf, handle, connId, value); 2021 } 2022 } 2023 2024 2025 /************************************************************************** 2026 * Private functions 2027 *************************************************************************/ 2028 2029 private boolean isRestrictedCharUuid(final UUID charUuid) { 2030 return isHidUuid(charUuid); 2031 } 2032 2033 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2034 return isFidoUUID(srvcUuid); 2035 } 2036 2037 private boolean isHidUuid(final UUID uuid) { 2038 for (UUID hid_uuid : HID_UUIDS) { 2039 if (hid_uuid.equals(uuid)) return true; 2040 } 2041 return false; 2042 } 2043 2044 private boolean isFidoUUID(final UUID uuid) { 2045 for (UUID fido_uuid : FIDO_UUIDS) { 2046 if (fido_uuid.equals(uuid)) return true; 2047 } 2048 return false; 2049 } 2050 2051 private int getDeviceType(BluetoothDevice device) { 2052 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2053 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2054 + ", type=" + type); 2055 return type; 2056 } 2057 2058 private void enforceAdminPermission() { 2059 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2060 } 2061 2062 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2063 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2064 // BLE scan only mode needs special permission. 2065 if (adapter.getState() != BluetoothAdapter.STATE_ON) return true; 2066 2067 // Regular scan, no special permission. 2068 if (settings == null) return false; 2069 2070 // Regular scan, no special permission. 2071 if (settings.getReportDelayMillis() == 0) return false; 2072 2073 // Batch scan, truncated mode needs permission. 2074 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2075 } 2076 2077 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2078 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2079 private void enforcePrivilegedPermission() { 2080 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2081 "Need BLUETOOTH_PRIVILEGED permission"); 2082 } 2083 2084 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 2085 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 2086 // not have UPDATE_DEVICE_STATS permission. 2087 private void enforceImpersonatationPermission() { 2088 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 2089 "Need UPDATE_DEVICE_STATS permission"); 2090 } 2091 2092 private void stopNextService(int serverIf, int status) throws RemoteException { 2093 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2094 + ", status=" + status); 2095 2096 if (status == 0) { 2097 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2098 for(HandleMap.Entry entry : entries) { 2099 if (entry.type != HandleMap.TYPE_SERVICE || 2100 entry.serverIf != serverIf || 2101 entry.started == false) 2102 continue; 2103 2104 gattServerStopServiceNative(serverIf, entry.handle); 2105 return; 2106 } 2107 } 2108 } 2109 2110 private void deleteServices(int serverIf) { 2111 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2112 2113 /* 2114 * Figure out which handles to delete. 2115 * The handles are copied into a new list to avoid race conditions. 2116 */ 2117 List<Integer> handleList = new ArrayList<Integer>(); 2118 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2119 for(HandleMap.Entry entry : entries) { 2120 if (entry.type != HandleMap.TYPE_SERVICE || 2121 entry.serverIf != serverIf) 2122 continue; 2123 handleList.add(entry.handle); 2124 } 2125 2126 /* Now actually delete the services.... */ 2127 for(Integer handle : handleList) { 2128 gattServerDeleteServiceNative(serverIf, handle); 2129 } 2130 } 2131 2132 private List<UUID> parseUuids(byte[] adv_data) { 2133 List<UUID> uuids = new ArrayList<UUID>(); 2134 2135 int offset = 0; 2136 while(offset < (adv_data.length-2)) { 2137 int len = adv_data[offset++]; 2138 if (len == 0) break; 2139 2140 int type = adv_data[offset++]; 2141 switch (type) { 2142 case 0x02: // Partial list of 16-bit UUIDs 2143 case 0x03: // Complete list of 16-bit UUIDs 2144 while (len > 1) { 2145 int uuid16 = adv_data[offset++]; 2146 uuid16 += (adv_data[offset++] << 8); 2147 len -= 2; 2148 uuids.add(UUID.fromString(String.format( 2149 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2150 } 2151 break; 2152 2153 default: 2154 offset += (len - 1); 2155 break; 2156 } 2157 } 2158 2159 return uuids; 2160 } 2161 2162 @Override 2163 public void dump(StringBuilder sb) { 2164 super.dump(sb); 2165 println(sb, "mAdvertisingServiceUuids:"); 2166 for (UUID uuid : mAdvertisingServiceUuids) { 2167 println(sb, " " + uuid); 2168 } 2169 2170 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2171 2172 sb.append("\nGATT Client Map\n"); 2173 mClientMap.dump(sb); 2174 2175 sb.append("GATT Server Map\n"); 2176 mServerMap.dump(sb); 2177 2178 sb.append("GATT Handle Map\n"); 2179 mHandleMap.dump(sb); 2180 } 2181 2182 void addScanResult() { 2183 if (mScanEvents.isEmpty()) 2184 return; 2185 2186 BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1); 2187 curr.setNumberResults(curr.getNumberResults() + 1); 2188 } 2189 2190 void addScanEvent(BluetoothProto.ScanEvent event) { 2191 synchronized(mScanEvents) { 2192 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 2193 mScanEvents.remove(0); 2194 mScanEvents.add(event); 2195 } 2196 } 2197 2198 @Override 2199 public void dumpProto(BluetoothProto.BluetoothLog proto) { 2200 synchronized(mScanEvents) { 2201 for (BluetoothProto.ScanEvent event : mScanEvents) { 2202 proto.addScanEvent(event); 2203 } 2204 } 2205 } 2206 2207 /************************************************************************** 2208 * GATT Test functions 2209 *************************************************************************/ 2210 2211 void gattTestCommand(int command, UUID uuid1, String bda1, 2212 int p1, int p2, int p3, int p4, int p5) { 2213 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2214 if (uuid1 != null) 2215 gattTestNative(command, uuid1.getLeastSignificantBits(), 2216 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2217 else 2218 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2219 } 2220 2221 private native void gattTestNative(int command, 2222 long uuid1_lsb, long uuid1_msb, String bda1, 2223 int p1, int p2, int p3, int p4, int p5); 2224 2225 /************************************************************************** 2226 * Native functions prototypes 2227 *************************************************************************/ 2228 2229 private native static void classInitNative(); 2230 private native void initializeNative(); 2231 private native void cleanupNative(); 2232 2233 private native int gattClientGetDeviceTypeNative(String address); 2234 2235 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2236 long app_uuid_msb); 2237 2238 private native void gattClientUnregisterAppNative(int clientIf); 2239 2240 private native void gattClientConnectNative(int clientIf, String address, 2241 boolean isDirect, int transport); 2242 2243 private native void gattClientDisconnectNative(int clientIf, String address, 2244 int conn_id); 2245 2246 private native void gattClientRefreshNative(int clientIf, String address); 2247 2248 private native void gattClientSearchServiceNative(int conn_id, 2249 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2250 2251 private native void gattClientGetGattDbNative(int conn_id); 2252 2253 private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq); 2254 2255 private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq); 2256 2257 private native void gattClientWriteCharacteristicNative(int conn_id, 2258 int handle, int write_type, int auth_req, byte[] value); 2259 2260 private native void gattClientWriteDescriptorNative(int conn_id, int handle, 2261 int auth_req, byte[] value); 2262 2263 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2264 2265 private native void gattClientRegisterForNotificationsNative(int clientIf, 2266 String address, int handle, boolean enable); 2267 2268 private native void gattClientReadRemoteRssiNative(int clientIf, 2269 String address); 2270 2271 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2272 2273 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2274 int minInterval, int maxInterval, int latency, int timeout); 2275 2276 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2277 long app_uuid_msb); 2278 2279 private native void gattServerUnregisterAppNative(int serverIf); 2280 2281 private native void gattServerConnectNative(int server_if, String address, 2282 boolean is_direct, int transport); 2283 2284 private native void gattServerDisconnectNative(int serverIf, String address, 2285 int conn_id); 2286 2287 private native void gattServerAddServiceNative(int server_if, List<GattDbElement> service); 2288 2289 private native void gattServerStopServiceNative (int server_if, 2290 int svc_handle); 2291 2292 private native void gattServerDeleteServiceNative (int server_if, 2293 int svc_handle); 2294 2295 private native void gattServerSendIndicationNative (int server_if, 2296 int attr_handle, int conn_id, byte[] val); 2297 2298 private native void gattServerSendNotificationNative (int server_if, 2299 int attr_handle, int conn_id, byte[] val); 2300 2301 private native void gattServerSendResponseNative (int server_if, 2302 int conn_id, int trans_id, int status, int handle, int offset, 2303 byte[] val, int auth_req); 2304} 2305