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