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