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