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