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