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