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