GattService.java revision 4013e8a454c6c5cc9f70f52f2af35730d119c065
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 } 694 List<UUID> remoteUuids = parseUuids(adv_data); 695 addScanResult(); 696 697 byte[] legacy_adv_data = Arrays.copyOfRange(adv_data, 0, 62); 698 699 for (ScanClient client : mScanManager.getRegularScanQueue()) { 700 if (client.uuids.length > 0) { 701 int matches = 0; 702 for (UUID search : client.uuids) { 703 for (UUID remote: remoteUuids) { 704 if (remote.equals(search)) { 705 ++matches; 706 break; // Only count 1st match in case of duplicates 707 } 708 } 709 } 710 711 if (matches < client.uuids.length) continue; 712 } 713 714 ScannerMap.App app = mScannerMap.getById(client.scannerId); 715 if (app == null) { 716 continue; 717 } 718 719 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); 720 721 ScanSettings settings = client.settings; 722 byte[] scan_record_data; 723 // This is for compability with applications that assume fixed size scan data. 724 if (settings.getLegacy()) { 725 if ((event_type & ET_LEGACY_MASK) == 0) { 726 // If this is legacy scan, but nonlegacy result - skip. 727 continue; 728 } else { 729 // Some apps are used to fixed-size advertise data. 730 scan_record_data = legacy_adv_data; 731 } 732 } else { 733 scan_record_data = adv_data; 734 } 735 736 ScanResult result = new ScanResult(device, event_type, primary_phy, secondary_phy, 737 advertising_sid, tx_power, rssi, periodic_adv_int, 738 ScanRecord.parseFromBytes(scan_record_data), 739 SystemClock.elapsedRealtimeNanos()); 740 // Do no report if location mode is OFF or the client has no location permission 741 // PEERS_MAC_ADDRESS permission holders always get results 742 if (!hasScanResultPermission(client) || !matchesFilters(client, result)) { 743 continue; 744 } 745 746 if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) { 747 continue; 748 } 749 750 try { 751 app.appScanStats.addResult(); 752 app.callback.onScanResult(result); 753 } catch (RemoteException e) { 754 Log.e(TAG, "Exception: " + e); 755 mScannerMap.remove(client.scannerId); 756 mScanManager.stopScan(client); 757 } 758 } 759 } 760 761 void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) 762 throws RemoteException { 763 UUID uuid = new UUID(uuidMsb, uuidLsb); 764 if (DBG) Log.d(TAG, "onScannerRegistered() - UUID=" + uuid 765 + ", scannerId=" + scannerId + ", status=" + status); 766 767 ScannerMap.App app = mScannerMap.getByUuid(uuid); 768 if (app != null) { 769 if (status == 0) { 770 app.id = scannerId; 771 app.linkToDeath(new ScannerDeathRecipient(scannerId)); 772 } else { 773 mScannerMap.remove(scannerId); 774 } 775 app.callback.onScannerRegistered(status, scannerId); 776 } 777 } 778 779 /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ 780 private boolean hasScanResultPermission(final ScanClient client) { 781 final boolean requiresLocationEnabled = 782 getResources().getBoolean(R.bool.strict_location_check); 783 final boolean locationEnabledSetting = Settings.Secure.getInt(getContentResolver(), 784 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF) 785 != Settings.Secure.LOCATION_MODE_OFF; 786 final boolean locationEnabled = !requiresLocationEnabled || locationEnabledSetting 787 || client.legacyForegroundApp; 788 return (client.hasPeersMacAddressPermission 789 || (client.hasLocationPermission && locationEnabled)); 790 } 791 792 // Check if a scan record matches a specific filters. 793 private boolean matchesFilters(ScanClient client, ScanResult scanResult) { 794 if (client.filters == null || client.filters.isEmpty()) { 795 return true; 796 } 797 for (ScanFilter filter : client.filters) { 798 if (filter.matches(scanResult)) { 799 return true; 800 } 801 } 802 return false; 803 } 804 805 void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) 806 throws RemoteException { 807 UUID uuid = new UUID(uuidMsb, uuidLsb); 808 if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); 809 ClientMap.App app = mClientMap.getByUuid(uuid); 810 if (app != null) { 811 if (status == 0) { 812 app.id = clientIf; 813 app.linkToDeath(new ClientDeathRecipient(clientIf)); 814 } else { 815 mClientMap.remove(uuid); 816 } 817 app.callback.onClientRegistered(status, clientIf); 818 } 819 } 820 821 void onConnected(int clientIf, int connId, int status, String address) 822 throws RemoteException { 823 if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf 824 + ", connId=" + connId + ", address=" + address); 825 826 if (status == 0) mClientMap.addConnection(clientIf, connId, address); 827 ClientMap.App app = mClientMap.getById(clientIf); 828 if (app != null) { 829 app.callback.onClientConnectionState(status, clientIf, 830 (status==BluetoothGatt.GATT_SUCCESS), address); 831 } 832 } 833 834 void onDisconnected(int clientIf, int connId, int status, String address) 835 throws RemoteException { 836 if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf 837 + ", connId=" + connId + ", address=" + address); 838 839 mClientMap.removeConnection(clientIf, connId); 840 ClientMap.App app = mClientMap.getById(clientIf); 841 if (app != null) { 842 app.callback.onClientConnectionState(status, clientIf, false, address); 843 } 844 } 845 846 void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 847 if (DBG) Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status); 848 849 String address = mClientMap.addressByConnId(connId); 850 if (address == null) return; 851 852 ClientMap.App app = mClientMap.getByConnId(connId); 853 if (app == null) return; 854 855 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 856 } 857 858 void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status) 859 throws RemoteException { 860 if (DBG) 861 Log.d(TAG, "onClientPhyRead() - address=" + address + ", status=" + status 862 + ", clientIf=" + clientIf); 863 864 Integer connId = mClientMap.connIdByAddress(clientIf, address); 865 if (connId == null) { 866 Log.d(TAG, "onClientPhyRead() - no connection to " + address); 867 return; 868 } 869 870 ClientMap.App app = mClientMap.getByConnId(connId); 871 if (app == null) return; 872 873 app.callback.onPhyRead(address, txPhy, rxPhy, status); 874 } 875 876 void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) 877 throws RemoteException { 878 if (DBG) Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status); 879 880 String address = mClientMap.addressByConnId(connId); 881 if (address == null) return; 882 883 ClientMap.App app = mClientMap.getByConnId(connId); 884 if (app == null) return; 885 886 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 887 } 888 889 void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { 890 if (DBG) Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status); 891 892 String address = mServerMap.addressByConnId(connId); 893 if (address == null) return; 894 895 ServerMap.App app = mServerMap.getByConnId(connId); 896 if (app == null) return; 897 898 app.callback.onPhyUpdate(address, txPhy, rxPhy, status); 899 } 900 901 void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) 902 throws RemoteException { 903 if (DBG) Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status); 904 905 Integer connId = mServerMap.connIdByAddress(serverIf, address); 906 if (connId == null) { 907 Log.d(TAG, "onServerPhyRead() - no connection to " + address); 908 return; 909 } 910 911 ServerMap.App app = mServerMap.getByConnId(connId); 912 if (app == null) return; 913 914 app.callback.onPhyRead(address, txPhy, rxPhy, status); 915 } 916 917 void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) 918 throws RemoteException { 919 if (DBG) Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status); 920 921 String address = mServerMap.addressByConnId(connId); 922 if (address == null) return; 923 924 ServerMap.App app = mServerMap.getByConnId(connId); 925 if (app == null) return; 926 927 app.callback.onConnectionUpdated(address, interval, latency, timeout, status); 928 } 929 930 void onSearchCompleted(int connId, int status) throws RemoteException { 931 if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); 932 // Gatt DB is ready! 933 934 // This callback was called from the jni_workqueue thread. If we make request to the stack 935 // on the same thread, it might cause deadlock. Schedule request on a new thread instead. 936 Thread t = new Thread(new Runnable() { 937 public void run() { 938 gattClientGetGattDbNative(connId); 939 } 940 }); 941 t.start(); 942 } 943 944 GattDbElement GetSampleGattDbElement() { 945 return new GattDbElement(); 946 } 947 948 void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException { 949 String address = mClientMap.addressByConnId(connId); 950 951 if (DBG) Log.d(TAG, "onGetGattDb() - address=" + address); 952 953 ClientMap.App app = mClientMap.getByConnId(connId); 954 if (app == null || app.callback == null) { 955 Log.e(TAG, "app or callback is null"); 956 return; 957 } 958 959 List<BluetoothGattService> db_out = new ArrayList<BluetoothGattService>(); 960 961 BluetoothGattService currSrvc = null; 962 BluetoothGattCharacteristic currChar = null; 963 964 for (GattDbElement el: db) { 965 switch (el.type) 966 { 967 case GattDbElement.TYPE_PRIMARY_SERVICE: 968 case GattDbElement.TYPE_SECONDARY_SERVICE: 969 if (DBG) Log.d(TAG, "got service with UUID=" + el.uuid); 970 971 currSrvc = new BluetoothGattService(el.uuid, el.id, el.type); 972 db_out.add(currSrvc); 973 break; 974 975 case GattDbElement.TYPE_CHARACTERISTIC: 976 if (DBG) Log.d(TAG, "got characteristic with UUID=" + el.uuid); 977 978 currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0); 979 currSrvc.addCharacteristic(currChar); 980 break; 981 982 case GattDbElement.TYPE_DESCRIPTOR: 983 if (DBG) Log.d(TAG, "got descriptor with UUID=" + el.uuid); 984 985 currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0)); 986 break; 987 988 case GattDbElement.TYPE_INCLUDED_SERVICE: 989 if (DBG) Log.d(TAG, "got included service with UUID=" + el.uuid); 990 991 currSrvc.addIncludedService(new BluetoothGattService(el.uuid, el.id, el.type)); 992 break; 993 994 default: 995 Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid); 996 } 997 } 998 999 // Search is complete when there was error, or nothing more to process 1000 gattClientDatabases.put(connId, db_out); 1001 app.callback.onSearchComplete(address, db_out, 0 /* status */); 1002 } 1003 1004 void onRegisterForNotifications(int connId, int status, int registered, int handle) { 1005 String address = mClientMap.addressByConnId(connId); 1006 1007 if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address 1008 + ", status=" + status + ", registered=" + registered 1009 + ", handle=" + handle); 1010 } 1011 1012 void onNotify(int connId, String address, int handle, 1013 boolean isNotify, byte[] data) throws RemoteException { 1014 1015 if (VDBG) Log.d(TAG, "onNotify() - address=" + address 1016 + ", handle=" + handle + ", length=" + data.length); 1017 1018 if (!permissionCheck(connId, handle)) { 1019 Log.w(TAG, "onNotify() - permission check failed!"); 1020 return; 1021 } 1022 1023 ClientMap.App app = mClientMap.getByConnId(connId); 1024 if (app != null) { 1025 app.callback.onNotify(address, handle, data); 1026 } 1027 } 1028 1029 void onReadCharacteristic(int connId, int status, int handle, byte[] data) throws RemoteException { 1030 String address = mClientMap.addressByConnId(connId); 1031 1032 if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address 1033 + ", status=" + status + ", length=" + data.length); 1034 1035 ClientMap.App app = mClientMap.getByConnId(connId); 1036 if (app != null) { 1037 app.callback.onCharacteristicRead(address, status, handle, data); 1038 } 1039 } 1040 1041 void onWriteCharacteristic(int connId, int status, int handle) 1042 throws RemoteException { 1043 String address = mClientMap.addressByConnId(connId); 1044 1045 if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address 1046 + ", status=" + status); 1047 1048 ClientMap.App app = mClientMap.getByConnId(connId); 1049 if (app == null) return; 1050 1051 if (!app.isCongested) { 1052 app.callback.onCharacteristicWrite(address, status, handle); 1053 } else { 1054 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1055 status = BluetoothGatt.GATT_SUCCESS; 1056 } 1057 CallbackInfo callbackInfo = new CallbackInfo(address, status, handle); 1058 app.queueCallback(callbackInfo); 1059 } 1060 } 1061 1062 void onExecuteCompleted(int connId, int status) throws RemoteException { 1063 String address = mClientMap.addressByConnId(connId); 1064 if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address 1065 + ", status=" + status); 1066 1067 ClientMap.App app = mClientMap.getByConnId(connId); 1068 if (app != null) { 1069 app.callback.onExecuteWrite(address, status); 1070 } 1071 } 1072 1073 void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { 1074 String address = mClientMap.addressByConnId(connId); 1075 1076 if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address 1077 + ", status=" + status + ", length=" + data.length); 1078 1079 ClientMap.App app = mClientMap.getByConnId(connId); 1080 if (app != null) { 1081 app.callback.onDescriptorRead(address, status, handle, data); 1082 } 1083 } 1084 1085 void onWriteDescriptor(int connId, int status, int handle) throws RemoteException { 1086 String address = mClientMap.addressByConnId(connId); 1087 1088 if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address 1089 + ", status=" + status); 1090 1091 ClientMap.App app = mClientMap.getByConnId(connId); 1092 if (app != null) { 1093 app.callback.onDescriptorWrite(address, status, handle); 1094 } 1095 } 1096 1097 void onReadRemoteRssi(int clientIf, String address, 1098 int rssi, int status) throws RemoteException{ 1099 if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + 1100 address + ", rssi=" + rssi + ", status=" + status); 1101 1102 ClientMap.App app = mClientMap.getById(clientIf); 1103 if (app != null) { 1104 app.callback.onReadRemoteRssi(address, rssi, status); 1105 } 1106 } 1107 1108 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 1109 if (DBG) { 1110 Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status 1111 + ", action=" + action); 1112 } 1113 mScanManager.callbackDone(clientIf, status); 1114 } 1115 1116 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 1117 if (DBG) { 1118 Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf 1119 + ", status=" + status + ", action=" + action 1120 + ", availableSpace=" + availableSpace); 1121 } 1122 mScanManager.callbackDone(clientIf, status); 1123 } 1124 1125 void onScanFilterConfig(int action, int status, int clientIf, int filterType, 1126 int availableSpace) { 1127 if (DBG) { 1128 Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action 1129 + " status = " + status + ", filterType=" + filterType 1130 + ", availableSpace=" + availableSpace); 1131 } 1132 1133 mScanManager.callbackDone(clientIf, status); 1134 } 1135 1136 void onBatchScanStorageConfigured(int status, int clientIf) { 1137 if (DBG) { 1138 Log.d(TAG, 1139 "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); 1140 } 1141 mScanManager.callbackDone(clientIf, status); 1142 } 1143 1144 // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. 1145 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 1146 if (DBG) { 1147 Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf 1148 + ", status=" + status + ", startStopAction=" + startStopAction); 1149 } 1150 mScanManager.callbackDone(clientIf, status); 1151 } 1152 1153 void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, 1154 byte[] recordData) throws RemoteException { 1155 if (DBG) { 1156 Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status 1157 + ", reportType=" + reportType + ", numRecords=" + numRecords); 1158 } 1159 mScanManager.callbackDone(scannerId, status); 1160 Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); 1161 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1162 // We only support single client for truncated mode. 1163 ScannerMap.App app = mScannerMap.getById(scannerId); 1164 if (app == null) return; 1165 app.callback.onBatchScanResults(new ArrayList<ScanResult>(results)); 1166 } else { 1167 for (ScanClient client : mScanManager.getFullBatchScanQueue()) { 1168 // Deliver results for each client. 1169 deliverBatchScan(client, results); 1170 } 1171 } 1172 } 1173 1174 // Check and deliver scan results for different scan clients. 1175 private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws 1176 RemoteException { 1177 ScannerMap.App app = mScannerMap.getById(client.scannerId); 1178 if (app == null) return; 1179 if (client.filters == null || client.filters.isEmpty()) { 1180 app.callback.onBatchScanResults(new ArrayList<ScanResult>(allResults)); 1181 } 1182 // Reconstruct the scan results. 1183 List<ScanResult> results = new ArrayList<ScanResult>(); 1184 for (ScanResult scanResult : allResults) { 1185 if (matchesFilters(client, scanResult)) { 1186 results.add(scanResult); 1187 } 1188 } 1189 app.callback.onBatchScanResults(results); 1190 } 1191 1192 private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, 1193 byte[] batchRecord) { 1194 if (numRecords == 0) { 1195 return Collections.emptySet(); 1196 } 1197 if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); 1198 if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { 1199 return parseTruncatedResults(numRecords, batchRecord); 1200 } else { 1201 return parseFullResults(numRecords, batchRecord); 1202 } 1203 } 1204 1205 private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { 1206 if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); 1207 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1208 long now = SystemClock.elapsedRealtimeNanos(); 1209 for (int i = 0; i < numRecords; ++i) { 1210 byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, 1211 TRUNCATED_RESULT_SIZE); 1212 byte[] address = extractBytes(record, 0, 6); 1213 reverse(address); 1214 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1215 int rssi = record[8]; 1216 long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); 1217 results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), 1218 rssi, timestampNanos)); 1219 } 1220 return results; 1221 } 1222 1223 @VisibleForTesting 1224 long parseTimestampNanos(byte[] data) { 1225 long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); 1226 // Timestamp is in every 50 ms. 1227 return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); 1228 } 1229 1230 private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { 1231 if (DBG) Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); 1232 Set<ScanResult> results = new HashSet<ScanResult>(numRecords); 1233 int position = 0; 1234 long now = SystemClock.elapsedRealtimeNanos(); 1235 while (position < batchRecord.length) { 1236 byte[] address = extractBytes(batchRecord, position, 6); 1237 // TODO: remove temp hack. 1238 reverse(address); 1239 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1240 position += 6; 1241 // Skip address type. 1242 position++; 1243 // Skip tx power level. 1244 position++; 1245 int rssi = batchRecord[position++]; 1246 long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); 1247 position += 2; 1248 1249 // Combine advertise packet and scan response packet. 1250 int advertisePacketLen = batchRecord[position++]; 1251 byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); 1252 position += advertisePacketLen; 1253 int scanResponsePacketLen = batchRecord[position++]; 1254 byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); 1255 position += scanResponsePacketLen; 1256 byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; 1257 System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); 1258 System.arraycopy(scanResponseBytes, 0, scanRecord, 1259 advertisePacketLen, scanResponsePacketLen); 1260 if (DBG) Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); 1261 results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), 1262 rssi, timestampNanos)); 1263 } 1264 return results; 1265 } 1266 1267 // Reverse byte array. 1268 private void reverse(byte[] address) { 1269 int len = address.length; 1270 for (int i = 0; i < len / 2; ++i) { 1271 byte b = address[i]; 1272 address[i] = address[len - 1 - i]; 1273 address[len - 1 - i] = b; 1274 } 1275 } 1276 1277 // Helper method to extract bytes from byte array. 1278 private static byte[] extractBytes(byte[] scanRecord, int start, int length) { 1279 byte[] bytes = new byte[length]; 1280 System.arraycopy(scanRecord, start, bytes, 0, length); 1281 return bytes; 1282 } 1283 1284 void onBatchScanThresholdCrossed(int clientIf) { 1285 if (DBG) { 1286 Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); 1287 } 1288 flushPendingBatchResults(clientIf); 1289 } 1290 1291 AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len, 1292 byte[] adv_pkt, int scan_rsp_len, byte[] scan_rsp, int filt_index, int adv_state, 1293 int adv_info_present, String address, int addr_type, int tx_power, int rssi_value, 1294 int time_stamp) { 1295 1296 return new AdvtFilterOnFoundOnLostInfo(client_if, adv_pkt_len, adv_pkt, 1297 scan_rsp_len, scan_rsp, filt_index, adv_state, 1298 adv_info_present, address, addr_type, tx_power, 1299 rssi_value, time_stamp); 1300 } 1301 1302 void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { 1303 if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() 1304 + " address = " + trackingInfo.getAddress() 1305 + " adv_state = " + trackingInfo.getAdvState()); 1306 1307 ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); 1308 if (app == null || app.callback == null) { 1309 Log.e(TAG, "app or callback is null"); 1310 return; 1311 } 1312 1313 BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() 1314 .getRemoteDevice(trackingInfo.getAddress()); 1315 int advertiserState = trackingInfo.getAdvState(); 1316 ScanResult result = new ScanResult(device, 1317 ScanRecord.parseFromBytes(trackingInfo.getResult()), 1318 trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); 1319 1320 for (ScanClient client : mScanManager.getRegularScanQueue()) { 1321 if (client.scannerId == trackingInfo.getClientIf()) { 1322 ScanSettings settings = client.settings; 1323 if ((advertiserState == ADVT_STATE_ONFOUND) 1324 && ((settings.getCallbackType() 1325 & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0)) { 1326 app.callback.onFoundOrLost(true, result); 1327 } else if ((advertiserState == ADVT_STATE_ONLOST) 1328 && ((settings.getCallbackType() 1329 & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0)) { 1330 app.callback.onFoundOrLost(false, result); 1331 } else { 1332 if (DBG) { 1333 Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState 1334 + " scannerId = " + client.scannerId + " callbackType " 1335 + settings.getCallbackType()); 1336 } 1337 } 1338 } 1339 } 1340 } 1341 1342 void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { 1343 ScannerMap.App app = mScannerMap.getById(scannerId); 1344 if (app == null || app.callback == null) { 1345 Log.e(TAG, "Advertise app or callback is null"); 1346 return; 1347 } 1348 if (DBG) Log.d(TAG, "onScanParamSetupCompleted : " + status); 1349 } 1350 1351 // callback from ScanManager for dispatch of errors apps. 1352 void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { 1353 ScannerMap.App app = mScannerMap.getById(scannerId); 1354 if (app == null || app.callback == null) { 1355 Log.e(TAG, "App or callback is null"); 1356 return; 1357 } 1358 app.callback.onScanManagerErrorCallback(errorCode); 1359 } 1360 1361 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 1362 String address = mClientMap.addressByConnId(connId); 1363 1364 if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 1365 + status + ", mtu=" + mtu); 1366 1367 ClientMap.App app = mClientMap.getByConnId(connId); 1368 if (app != null) { 1369 app.callback.onConfigureMTU(address, mtu, status); 1370 } 1371 } 1372 1373 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1374 if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1375 1376 ClientMap.App app = mClientMap.getByConnId(connId); 1377 1378 if (app != null) { 1379 app.isCongested = congested; 1380 while(!app.isCongested) { 1381 CallbackInfo callbackInfo = app.popQueuedCallback(); 1382 if (callbackInfo == null) return; 1383 app.callback.onCharacteristicWrite(callbackInfo.address, 1384 callbackInfo.status, callbackInfo.handle); 1385 } 1386 } 1387 } 1388 1389 /************************************************************************** 1390 * GATT Service functions - Shared CLIENT/SERVER 1391 *************************************************************************/ 1392 1393 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1394 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1395 1396 final int DEVICE_TYPE_BREDR = 0x1; 1397 1398 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1399 Integer>(); 1400 1401 // Add paired LE devices 1402 1403 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1404 for (BluetoothDevice device : bondedDevices) { 1405 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1406 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1407 } 1408 } 1409 1410 // Add connected deviceStates 1411 1412 Set<String> connectedDevices = new HashSet<String>(); 1413 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1414 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1415 1416 for (String address : connectedDevices ) { 1417 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1418 if (device != null) { 1419 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1420 } 1421 } 1422 1423 // Create matching device sub-set 1424 1425 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1426 1427 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1428 for(int state : states) { 1429 if (entry.getValue() == state) { 1430 deviceList.add(entry.getKey()); 1431 } 1432 } 1433 } 1434 1435 return deviceList; 1436 } 1437 1438 void registerScanner(IScannerCallback callback, WorkSource workSource) { 1439 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1440 1441 UUID uuid = UUID.randomUUID(); 1442 if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid); 1443 1444 if (workSource != null) { 1445 enforceImpersonatationPermission(); 1446 } 1447 1448 mScannerMap.add(uuid, workSource, callback, this); 1449 mScanManager.registerScanner(uuid); 1450 } 1451 1452 void unregisterScanner(int scannerId) { 1453 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1454 1455 if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); 1456 mScannerMap.remove(scannerId); 1457 mScanManager.unregisterScanner(scannerId); 1458 } 1459 1460 void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, 1461 List<List<ResultStorageDescriptor>> storages, String callingPackage) { 1462 if (DBG) Log.d(TAG, "start scan with filters"); 1463 enforceAdminPermission(); 1464 if (needsPrivilegedPermissionForScan(settings)) { 1465 enforcePrivilegedPermission(); 1466 } 1467 final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages); 1468 scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps, 1469 callingPackage); 1470 scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission( 1471 this); 1472 scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage); 1473 1474 AppScanStats app = null; 1475 app = mScannerMap.getAppScanStatsById(scannerId); 1476 1477 if (app != null) { 1478 if (app.isScanningTooFrequently() && 1479 checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) { 1480 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); 1481 return; 1482 } 1483 scanClient.stats = app; 1484 1485 boolean isFilteredScan = (filters != null) && !filters.isEmpty(); 1486 app.recordScanStart(settings, isFilteredScan); 1487 } 1488 1489 mScanManager.startScan(scanClient); 1490 } 1491 1492 void flushPendingBatchResults(int scannerId) { 1493 if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); 1494 mScanManager.flushBatchScanResults(new ScanClient(scannerId)); 1495 } 1496 1497 void stopScan(ScanClient client) { 1498 enforceAdminPermission(); 1499 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1500 mScanManager.getRegularScanQueue().size(); 1501 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1502 1503 AppScanStats app = null; 1504 app = mScannerMap.getAppScanStatsById(client.scannerId); 1505 if (app != null) app.recordScanStop(); 1506 1507 mScanManager.stopScan(client); 1508 } 1509 1510 void disconnectAll() { 1511 if (DBG) Log.d(TAG, "disconnectAll()"); 1512 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 1513 for(Map.Entry<Integer, String> entry:connMap.entrySet()){ 1514 if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue()); 1515 clientDisconnect(entry.getKey(), entry.getValue()); 1516 //clientDisconnect(int clientIf, String address) 1517 } 1518 } 1519 1520 void unregAll() { 1521 for (Integer appId : mClientMap.getAllAppsIds()) { 1522 if (DBG) Log.d(TAG, "unreg:" + appId); 1523 unregisterClient(appId); 1524 } 1525 } 1526 1527 /************************************************************************** 1528 * PERIODIC SCANNING 1529 *************************************************************************/ 1530 void registerSync( 1531 ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback) { 1532 enforceAdminPermission(); 1533 mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); 1534 } 1535 1536 void unregisterSync(IPeriodicAdvertisingCallback callback) { 1537 enforceAdminPermission(); 1538 mPeriodicScanManager.stopSync(callback); 1539 } 1540 1541 /************************************************************************** 1542 * ADVERTISING SET 1543 *************************************************************************/ 1544 void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, 1545 AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, 1546 AdvertiseData periodicData, int duration, int maxExtAdvEvents, 1547 IAdvertisingSetCallback callback) { 1548 enforceAdminPermission(); 1549 mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse, 1550 periodicParameters, periodicData, duration, maxExtAdvEvents, callback); 1551 } 1552 1553 void stopAdvertisingSet(IAdvertisingSetCallback callback) { 1554 enforceAdminPermission(); 1555 mAdvertiseManager.stopAdvertisingSet(callback); 1556 } 1557 1558 void getOwnAddress(int advertiserId) { 1559 enforcePrivilegedPermission(); 1560 mAdvertiseManager.getOwnAddress(advertiserId); 1561 } 1562 1563 void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) { 1564 enforceAdminPermission(); 1565 mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); 1566 } 1567 1568 void setAdvertisingData(int advertiserId, AdvertiseData data) { 1569 enforceAdminPermission(); 1570 mAdvertiseManager.setAdvertisingData(advertiserId, data); 1571 } 1572 1573 void setScanResponseData(int advertiserId, AdvertiseData data) { 1574 enforceAdminPermission(); 1575 mAdvertiseManager.setScanResponseData(advertiserId, data); 1576 } 1577 1578 void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) { 1579 enforceAdminPermission(); 1580 mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters); 1581 } 1582 1583 void setPeriodicAdvertisingParameters( 1584 int advertiserId, PeriodicAdvertisingParameters parameters) { 1585 enforceAdminPermission(); 1586 mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters); 1587 } 1588 1589 void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) { 1590 enforceAdminPermission(); 1591 mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data); 1592 } 1593 1594 void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) { 1595 enforceAdminPermission(); 1596 mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable); 1597 } 1598 1599 /************************************************************************** 1600 * GATT Service functions - CLIENT 1601 *************************************************************************/ 1602 1603 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1604 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1605 1606 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1607 mClientMap.add(uuid, null, callback, this); 1608 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1609 uuid.getMostSignificantBits()); 1610 } 1611 1612 void unregisterClient(int clientIf) { 1613 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1614 1615 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1616 mClientMap.remove(clientIf); 1617 gattClientUnregisterAppNative(clientIf); 1618 } 1619 1620 void clientConnect(int clientIf, String address, boolean isDirect, int transport, int phy) { 1621 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1622 1623 if (DBG) { 1624 Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect + ", phy= " 1625 + phy); 1626 } 1627 gattClientConnectNative(clientIf, address, isDirect, transport, phy); 1628 } 1629 1630 void clientDisconnect(int clientIf, String address) { 1631 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1632 1633 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1634 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1635 1636 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1637 } 1638 1639 void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions) { 1640 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1641 1642 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1643 if (connId == null) { 1644 if (DBG) Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address); 1645 return; 1646 } 1647 1648 if (DBG) Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId); 1649 gattClientSetPreferredPhyNative(clientIf, address, txPhy, rxPhy, phyOptions); 1650 } 1651 1652 void clientReadPhy(int clientIf, String address) { 1653 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1654 1655 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1656 if (connId == null) { 1657 if (DBG) Log.d(TAG, "clientReadPhy() - no connection to " + address); 1658 return; 1659 } 1660 1661 if (DBG) Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId); 1662 gattClientReadPhyNative(clientIf, address); 1663 } 1664 1665 int numHwTrackFiltersAvailable() { 1666 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 1667 - mScanManager.getCurrentUsedTrackingAdvertisement()); 1668 } 1669 1670 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1671 Utils.enforceAdminPermission(this); 1672 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1673 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1674 serviceUuids.add(new ParcelUuid(entry.uuid)); 1675 } 1676 return serviceUuids; 1677 } 1678 1679 List<String> getConnectedDevices() { 1680 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1681 1682 Set<String> connectedDevAddress = new HashSet<String>(); 1683 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1684 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1685 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1686 return connectedDeviceList; 1687 } 1688 1689 void refreshDevice(int clientIf, String address) { 1690 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1691 1692 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1693 gattClientRefreshNative(clientIf, address); 1694 } 1695 1696 void discoverServices(int clientIf, String address) { 1697 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1698 1699 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1700 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1701 1702 if (connId != null) 1703 gattClientSearchServiceNative(connId, true, 0, 0); 1704 else 1705 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1706 } 1707 1708 void discoverServiceByUuid(int clientIf, String address, UUID uuid) { 1709 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1710 1711 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1712 if (connId != null) 1713 gattClientDiscoverServiceByUuidNative( 1714 connId, uuid.getLeastSignificantBits(), uuid.getMostSignificantBits()); 1715 else 1716 Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "..."); 1717 } 1718 1719 void readCharacteristic(int clientIf, String address, int handle, int authReq) { 1720 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1721 1722 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1723 1724 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1725 if (connId == null) { 1726 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1727 return; 1728 } 1729 1730 if (!permissionCheck(connId, handle)) { 1731 Log.w(TAG, "readCharacteristic() - permission check failed!"); 1732 return; 1733 } 1734 1735 gattClientReadCharacteristicNative(connId, handle, authReq); 1736 } 1737 1738 void readUsingCharacteristicUuid( 1739 int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq) { 1740 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1741 1742 if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address); 1743 1744 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1745 if (connId == null) { 1746 Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "..."); 1747 return; 1748 } 1749 1750 if (!permissionCheck(uuid)) { 1751 Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); 1752 return; 1753 } 1754 1755 gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(), 1756 uuid.getMostSignificantBits(), startHandle, endHandle, authReq); 1757 } 1758 1759 void writeCharacteristic(int clientIf, String address, int handle, int writeType, 1760 int authReq, byte[] value) { 1761 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1762 1763 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1764 1765 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1766 1767 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1768 if (connId == null) { 1769 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1770 return; 1771 } 1772 1773 if (!permissionCheck(connId, handle)) { 1774 Log.w(TAG, "writeCharacteristic() - permission check failed!"); 1775 return; 1776 } 1777 1778 gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value); 1779 } 1780 1781 void readDescriptor(int clientIf, String address, int handle, int authReq) { 1782 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1783 1784 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1785 1786 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1787 if (connId == null) { 1788 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1789 return; 1790 } 1791 1792 if (!permissionCheck(connId, handle)) { 1793 Log.w(TAG, "readDescriptor() - permission check failed!"); 1794 return; 1795 } 1796 1797 gattClientReadDescriptorNative(connId, handle, authReq); 1798 }; 1799 1800 void writeDescriptor(int clientIf, String address, int handle, 1801 int authReq, byte[] value) { 1802 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1803 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1804 1805 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1806 if (connId == null) { 1807 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1808 return; 1809 } 1810 1811 if (!permissionCheck(connId, handle)) { 1812 Log.w(TAG, "writeDescriptor() - permission check failed!"); 1813 return; 1814 } 1815 1816 gattClientWriteDescriptorNative(connId, handle, authReq, value); 1817 } 1818 1819 void beginReliableWrite(int clientIf, String address) { 1820 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1821 1822 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1823 mReliableQueue.add(address); 1824 } 1825 1826 void endReliableWrite(int clientIf, String address, boolean execute) { 1827 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1828 1829 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1830 + " execute: " + execute); 1831 mReliableQueue.remove(address); 1832 1833 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1834 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1835 } 1836 1837 void registerForNotification(int clientIf, String address, int handle, boolean enable) { 1838 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1839 1840 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1841 1842 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1843 if (connId == null) { 1844 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1845 return; 1846 } 1847 1848 if (!permissionCheck(connId, handle)) { 1849 Log.w(TAG, "registerForNotification() - permission check failed!"); 1850 return; 1851 } 1852 1853 gattClientRegisterForNotificationsNative(clientIf, address, handle, enable); 1854 } 1855 1856 void readRemoteRssi(int clientIf, String address) { 1857 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1858 1859 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1860 gattClientReadRemoteRssiNative(clientIf, address); 1861 } 1862 1863 void configureMTU(int clientIf, String address, int mtu) { 1864 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1865 1866 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1867 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1868 if (connId != null) { 1869 gattClientConfigureMTUNative(connId, mtu); 1870 } else { 1871 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1872 } 1873 } 1874 1875 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1876 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1877 1878 int minInterval; 1879 int maxInterval; 1880 1881 // Slave latency 1882 int latency; 1883 1884 // Link supervision timeout is measured in N * 10ms 1885 int timeout = 2000; // 20s 1886 1887 switch (connectionPriority) 1888 { 1889 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1890 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 1891 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 1892 latency = getResources().getInteger(R.integer.gatt_high_priority_latency); 1893 break; 1894 1895 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 1896 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval); 1897 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval); 1898 latency = getResources().getInteger(R.integer.gatt_low_power_latency); 1899 break; 1900 1901 default: 1902 // Using the values for CONNECTION_PRIORITY_BALANCED. 1903 minInterval = 1904 getResources().getInteger(R.integer.gatt_balanced_priority_min_interval); 1905 maxInterval = 1906 getResources().getInteger(R.integer.gatt_balanced_priority_max_interval); 1907 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency); 1908 break; 1909 } 1910 1911 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1912 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1913 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1914 latency, timeout); 1915 } 1916 1917 /************************************************************************** 1918 * Callback functions - SERVER 1919 *************************************************************************/ 1920 1921 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1922 throws RemoteException { 1923 1924 UUID uuid = new UUID(uuidMsb, uuidLsb); 1925 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1926 ServerMap.App app = mServerMap.getByUuid(uuid); 1927 if (app != null) { 1928 app.id = serverIf; 1929 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1930 app.callback.onServerRegistered(status, serverIf); 1931 } 1932 } 1933 1934 void onServiceAdded(int status, int serverIf, List<GattDbElement> service) 1935 throws RemoteException { 1936 if (DBG) Log.d(TAG, "onServiceAdded(), status=" + status); 1937 1938 if (status != 0) { 1939 return; 1940 } 1941 1942 GattDbElement svcEl = service.get(0); 1943 int srvcHandle = svcEl.attributeHandle; 1944 1945 BluetoothGattService svc = null; 1946 1947 for (GattDbElement el : service) { 1948 if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) { 1949 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 1950 BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false); 1951 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 1952 BluetoothGattService.SERVICE_TYPE_PRIMARY); 1953 } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) { 1954 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid, 1955 BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false); 1956 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle, 1957 BluetoothGattService.SERVICE_TYPE_SECONDARY); 1958 } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) { 1959 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle); 1960 svc.addCharacteristic(new BluetoothGattCharacteristic(el.uuid, 1961 el.attributeHandle, el.properties, el.permissions)); 1962 } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) { 1963 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle); 1964 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics(); 1965 chars.get(chars.size()-1).addDescriptor( 1966 new BluetoothGattDescriptor(el.uuid, el.attributeHandle, el.permissions)); 1967 } 1968 } 1969 mHandleMap.setStarted(serverIf, srvcHandle, true); 1970 1971 ServerMap.App app = mServerMap.getById(serverIf); 1972 if (app != null) { 1973 app.callback.onServiceAdded(status, svc); 1974 } 1975 } 1976 1977 void onServiceStopped(int status, int serverIf, int srvcHandle) 1978 throws RemoteException { 1979 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1980 + ", status=" + status); 1981 if (status == 0) 1982 mHandleMap.setStarted(serverIf, srvcHandle, false); 1983 stopNextService(serverIf, status); 1984 } 1985 1986 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1987 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1988 + ", status=" + status); 1989 mHandleMap.deleteService(serverIf, srvcHandle); 1990 } 1991 1992 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1993 throws RemoteException { 1994 1995 if (DBG) Log.d(TAG, "onClientConnected() connId=" + connId 1996 + ", address=" + address + ", connected=" + connected); 1997 1998 ServerMap.App app = mServerMap.getById(serverIf); 1999 if (app == null) return; 2000 2001 if (connected) { 2002 mServerMap.addConnection(serverIf, connId, address); 2003 } else { 2004 mServerMap.removeConnection(serverIf, connId); 2005 } 2006 2007 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 2008 } 2009 2010 void onServerReadCharacteristic(String address, int connId, int transId, 2011 int handle, int offset, boolean isLong) 2012 throws RemoteException { 2013 if (VDBG) Log.d(TAG, "onServerReadCharacteristic() connId=" + connId 2014 + ", address=" + address + ", handle=" + handle 2015 + ", requestId=" + transId + ", offset=" + offset); 2016 2017 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2018 if (entry == null) return; 2019 2020 mHandleMap.addRequest(transId, handle); 2021 2022 ServerMap.App app = mServerMap.getById(entry.serverIf); 2023 if (app == null) return; 2024 2025 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); 2026 } 2027 2028 void onServerReadDescriptor(String address, int connId, int transId, 2029 int handle, int offset, boolean isLong) 2030 throws RemoteException { 2031 if (VDBG) Log.d(TAG, "onServerReadDescriptor() connId=" + connId 2032 + ", address=" + address + ", handle=" + handle 2033 + ", requestId=" + transId + ", offset=" + offset); 2034 2035 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2036 if (entry == null) return; 2037 2038 mHandleMap.addRequest(transId, handle); 2039 2040 ServerMap.App app = mServerMap.getById(entry.serverIf); 2041 if (app == null) return; 2042 2043 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); 2044 } 2045 2046 void onServerWriteCharacteristic(String address, int connId, int transId, 2047 int handle, int offset, int length, 2048 boolean needRsp, boolean isPrep, 2049 byte[] data) 2050 throws RemoteException { 2051 if (VDBG) Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId 2052 + ", address=" + address + ", handle=" + handle 2053 + ", requestId=" + transId + ", isPrep=" + isPrep 2054 + ", offset=" + offset); 2055 2056 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2057 if (entry == null) return; 2058 2059 mHandleMap.addRequest(transId, handle); 2060 2061 ServerMap.App app = mServerMap.getById(entry.serverIf); 2062 if (app == null) return; 2063 2064 app.callback.onCharacteristicWriteRequest(address, transId, 2065 offset, length, isPrep, needRsp, handle, data); 2066 } 2067 2068 void onServerWriteDescriptor(String address, int connId, int transId, 2069 int handle, int offset, int length, 2070 boolean needRsp, boolean isPrep, 2071 byte[] data) 2072 throws RemoteException { 2073 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 2074 + ", address=" + address + ", handle=" + handle 2075 + ", requestId=" + transId + ", isPrep=" + isPrep 2076 + ", offset=" + offset); 2077 2078 HandleMap.Entry entry = mHandleMap.getByHandle(handle); 2079 if (entry == null) return; 2080 2081 mHandleMap.addRequest(transId, handle); 2082 2083 ServerMap.App app = mServerMap.getById(entry.serverIf); 2084 if (app == null) return; 2085 2086 app.callback.onDescriptorWriteRequest(address, transId, 2087 offset, length, isPrep, needRsp, handle, data); 2088 } 2089 2090 void onExecuteWrite(String address, int connId, int transId, int execWrite) 2091 throws RemoteException { 2092 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 2093 + ", address=" + address + ", transId=" + transId); 2094 2095 ServerMap.App app = mServerMap.getByConnId(connId); 2096 if (app == null) return; 2097 2098 app.callback.onExecuteWrite(address, transId, execWrite == 1); 2099 } 2100 2101 void onResponseSendCompleted(int status, int attrHandle) { 2102 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 2103 } 2104 2105 void onNotificationSent(int connId, int status) throws RemoteException { 2106 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 2107 2108 String address = mServerMap.addressByConnId(connId); 2109 if (address == null) return; 2110 2111 ServerMap.App app = mServerMap.getByConnId(connId); 2112 if (app == null) return; 2113 2114 if (!app.isCongested) { 2115 app.callback.onNotificationSent(address, status); 2116 } else { 2117 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 2118 status = BluetoothGatt.GATT_SUCCESS; 2119 } 2120 app.queueCallback(new CallbackInfo(address, status)); 2121 } 2122 } 2123 2124 void onServerCongestion(int connId, boolean congested) throws RemoteException { 2125 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 2126 2127 ServerMap.App app = mServerMap.getByConnId(connId); 2128 if (app == null) return; 2129 2130 app.isCongested = congested; 2131 while(!app.isCongested) { 2132 CallbackInfo callbackInfo = app.popQueuedCallback(); 2133 if (callbackInfo == null) return; 2134 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 2135 } 2136 } 2137 2138 void onMtuChanged(int connId, int mtu) throws RemoteException { 2139 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 2140 2141 String address = mServerMap.addressByConnId(connId); 2142 if (address == null) return; 2143 2144 ServerMap.App app = mServerMap.getByConnId(connId); 2145 if (app == null) return; 2146 2147 app.callback.onMtuChanged(address, mtu); 2148 } 2149 2150 /************************************************************************** 2151 * GATT Service functions - SERVER 2152 *************************************************************************/ 2153 2154 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 2155 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2156 2157 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 2158 mServerMap.add(uuid, null, callback, this); 2159 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 2160 uuid.getMostSignificantBits()); 2161 } 2162 2163 void unregisterServer(int serverIf) { 2164 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2165 2166 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 2167 2168 deleteServices(serverIf); 2169 2170 mServerMap.remove(serverIf); 2171 gattServerUnregisterAppNative(serverIf); 2172 } 2173 2174 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 2175 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2176 2177 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 2178 gattServerConnectNative(serverIf, address, isDirect,transport); 2179 } 2180 2181 void serverDisconnect(int serverIf, String address) { 2182 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2183 2184 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2185 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 2186 2187 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 2188 } 2189 2190 void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions) { 2191 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2192 2193 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2194 if (connId == null) { 2195 if (DBG) Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address); 2196 return; 2197 } 2198 2199 if (DBG) Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId); 2200 gattServerSetPreferredPhyNative(serverIf, address, txPhy, rxPhy, phyOptions); 2201 } 2202 2203 void serverReadPhy(int serverIf, String address) { 2204 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2205 2206 Integer connId = mServerMap.connIdByAddress(serverIf, address); 2207 if (connId == null) { 2208 if (DBG) Log.d(TAG, "serverReadPhy() - no connection to " + address); 2209 return; 2210 } 2211 2212 if (DBG) Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId); 2213 gattServerReadPhyNative(serverIf, address); 2214 } 2215 2216 void addService(int serverIf, BluetoothGattService service) { 2217 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2218 2219 if (DBG) Log.d(TAG, "addService() - uuid=" + service.getUuid()); 2220 2221 List<GattDbElement> db = new ArrayList<GattDbElement>(); 2222 2223 if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) 2224 db.add(GattDbElement.createPrimaryService(service.getUuid())); 2225 else db.add(GattDbElement.createSecondaryService(service.getUuid())); 2226 2227 for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) { 2228 int permission = ((characteristic.getKeySize() - 7) << 12) 2229 + characteristic.getPermissions(); 2230 db.add(GattDbElement.createCharacteristic(characteristic.getUuid(), 2231 characteristic.getProperties(), permission)); 2232 2233 for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) { 2234 permission = ((characteristic.getKeySize() - 7) << 12) 2235 + descriptor.getPermissions(); 2236 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission)); 2237 } 2238 } 2239 2240 for (BluetoothGattService includedService : service.getIncludedServices()) { 2241 int inclSrvc = mHandleMap.getServiceHandle(includedService.getUuid(), 2242 includedService.getType(), includedService.getInstanceId()); 2243 db.add(GattDbElement.createIncludedService(inclSrvc)); 2244 } 2245 2246 gattServerAddServiceNative(serverIf, db); 2247 } 2248 2249 void removeService(int serverIf, int handle) { 2250 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2251 2252 if (DBG) Log.d(TAG, "removeService() - handle=" + handle); 2253 2254 gattServerDeleteServiceNative(serverIf, handle); 2255 } 2256 2257 void clearServices(int serverIf) { 2258 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2259 2260 if (DBG) Log.d(TAG, "clearServices()"); 2261 deleteServices(serverIf); 2262 } 2263 2264 void sendResponse(int serverIf, String address, int requestId, 2265 int status, int offset, byte[] value) { 2266 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2267 2268 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 2269 2270 int handle = 0; 2271 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2272 if (entry != null) handle = entry.handle; 2273 2274 int connId = mServerMap.connIdByAddress(serverIf, address); 2275 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2276 handle, offset, value, (byte)0); 2277 mHandleMap.deleteRequest(requestId); 2278 } 2279 2280 void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) { 2281 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2282 2283 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle); 2284 2285 int connId = mServerMap.connIdByAddress(serverIf, address); 2286 if (connId == 0) return; 2287 2288 if (confirm) { 2289 gattServerSendIndicationNative(serverIf, handle, connId, value); 2290 } else { 2291 gattServerSendNotificationNative(serverIf, handle, connId, value); 2292 } 2293 } 2294 2295 2296 /************************************************************************** 2297 * Private functions 2298 *************************************************************************/ 2299 2300 private boolean isRestrictedCharUuid(final UUID charUuid) { 2301 return isHidUuid(charUuid); 2302 } 2303 2304 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2305 return isFidoUUID(srvcUuid); 2306 } 2307 2308 private boolean isHidUuid(final UUID uuid) { 2309 for (UUID hid_uuid : HID_UUIDS) { 2310 if (hid_uuid.equals(uuid)) return true; 2311 } 2312 return false; 2313 } 2314 2315 private boolean isFidoUUID(final UUID uuid) { 2316 for (UUID fido_uuid : FIDO_UUIDS) { 2317 if (fido_uuid.equals(uuid)) return true; 2318 } 2319 return false; 2320 } 2321 2322 private int getDeviceType(BluetoothDevice device) { 2323 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2324 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2325 + ", type=" + type); 2326 return type; 2327 } 2328 2329 private void enforceAdminPermission() { 2330 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2331 } 2332 2333 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2334 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2335 // BLE scan only mode needs special permission. 2336 if (adapter.getState() != BluetoothAdapter.STATE_ON) return true; 2337 2338 // Regular scan, no special permission. 2339 if (settings == null) return false; 2340 2341 // Regular scan, no special permission. 2342 if (settings.getReportDelayMillis() == 0) return false; 2343 2344 // Batch scan, truncated mode needs permission. 2345 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2346 } 2347 2348 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2349 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2350 private void enforcePrivilegedPermission() { 2351 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2352 "Need BLUETOOTH_PRIVILEGED permission"); 2353 } 2354 2355 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 2356 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 2357 // not have UPDATE_DEVICE_STATS permission. 2358 private void enforceImpersonatationPermission() { 2359 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 2360 "Need UPDATE_DEVICE_STATS permission"); 2361 } 2362 2363 private void stopNextService(int serverIf, int status) throws RemoteException { 2364 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2365 + ", status=" + status); 2366 2367 if (status == 0) { 2368 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2369 for(HandleMap.Entry entry : entries) { 2370 if (entry.type != HandleMap.TYPE_SERVICE || 2371 entry.serverIf != serverIf || 2372 entry.started == false) 2373 continue; 2374 2375 gattServerStopServiceNative(serverIf, entry.handle); 2376 return; 2377 } 2378 } 2379 } 2380 2381 private void deleteServices(int serverIf) { 2382 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2383 2384 /* 2385 * Figure out which handles to delete. 2386 * The handles are copied into a new list to avoid race conditions. 2387 */ 2388 List<Integer> handleList = new ArrayList<Integer>(); 2389 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2390 for(HandleMap.Entry entry : entries) { 2391 if (entry.type != HandleMap.TYPE_SERVICE || 2392 entry.serverIf != serverIf) 2393 continue; 2394 handleList.add(entry.handle); 2395 } 2396 2397 /* Now actually delete the services.... */ 2398 for(Integer handle : handleList) { 2399 gattServerDeleteServiceNative(serverIf, handle); 2400 } 2401 } 2402 2403 private List<UUID> parseUuids(byte[] adv_data) { 2404 List<UUID> uuids = new ArrayList<UUID>(); 2405 2406 int offset = 0; 2407 while(offset < (adv_data.length-2)) { 2408 int len = Byte.toUnsignedInt(adv_data[offset++]); 2409 if (len == 0) break; 2410 2411 int type = adv_data[offset++]; 2412 switch (type) { 2413 case 0x02: // Partial list of 16-bit UUIDs 2414 case 0x03: // Complete list of 16-bit UUIDs 2415 while (len > 1) { 2416 int uuid16 = adv_data[offset++]; 2417 uuid16 += (adv_data[offset++] << 8); 2418 len -= 2; 2419 uuids.add(UUID.fromString(String.format( 2420 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2421 } 2422 break; 2423 2424 default: 2425 offset += (len - 1); 2426 break; 2427 } 2428 } 2429 2430 return uuids; 2431 } 2432 2433 @Override 2434 public void dump(StringBuilder sb) { 2435 super.dump(sb); 2436 println(sb, "mAdvertisingServiceUuids:"); 2437 for (UUID uuid : mAdvertisingServiceUuids) { 2438 println(sb, " " + uuid); 2439 } 2440 2441 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2442 2443 sb.append("\nGATT Scanner Map\n"); 2444 mScannerMap.dump(sb); 2445 2446 sb.append("GATT Client Map\n"); 2447 mClientMap.dump(sb); 2448 2449 sb.append("GATT Server Map\n"); 2450 mServerMap.dump(sb); 2451 2452 sb.append("GATT Handle Map\n"); 2453 mHandleMap.dump(sb); 2454 } 2455 2456 void addScanResult() { 2457 if (mScanEvents.isEmpty()) 2458 return; 2459 2460 BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1); 2461 curr.setNumberResults(curr.getNumberResults() + 1); 2462 } 2463 2464 void addScanEvent(BluetoothProto.ScanEvent event) { 2465 synchronized(mScanEvents) { 2466 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 2467 mScanEvents.remove(0); 2468 mScanEvents.add(event); 2469 } 2470 } 2471 2472 @Override 2473 public void dumpProto(BluetoothProto.BluetoothLog proto) { 2474 synchronized(mScanEvents) { 2475 for (BluetoothProto.ScanEvent event : mScanEvents) { 2476 proto.addScanEvent(event); 2477 } 2478 } 2479 } 2480 2481 /************************************************************************** 2482 * GATT Test functions 2483 *************************************************************************/ 2484 2485 void gattTestCommand(int command, UUID uuid1, String bda1, 2486 int p1, int p2, int p3, int p4, int p5) { 2487 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2488 if (uuid1 != null) 2489 gattTestNative(command, uuid1.getLeastSignificantBits(), 2490 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2491 else 2492 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2493 } 2494 2495 private native void gattTestNative(int command, 2496 long uuid1_lsb, long uuid1_msb, String bda1, 2497 int p1, int p2, int p3, int p4, int p5); 2498 2499 /************************************************************************** 2500 * Native functions prototypes 2501 *************************************************************************/ 2502 2503 private native static void classInitNative(); 2504 private native void initializeNative(); 2505 private native void cleanupNative(); 2506 2507 private native int gattClientGetDeviceTypeNative(String address); 2508 2509 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2510 long app_uuid_msb); 2511 2512 private native void gattClientUnregisterAppNative(int clientIf); 2513 2514 private native void gattClientConnectNative( 2515 int clientIf, String address, boolean isDirect, int transport, int initiating_phys); 2516 2517 private native void gattClientDisconnectNative(int clientIf, String address, 2518 int conn_id); 2519 2520 private native void gattClientSetPreferredPhyNative( 2521 int clientIf, String address, int tx_phy, int rx_phy, int phy_options); 2522 2523 private native void gattClientReadPhyNative(int clientIf, String address); 2524 2525 private native void gattClientRefreshNative(int clientIf, String address); 2526 2527 private native void gattClientSearchServiceNative(int conn_id, 2528 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2529 2530 private native void gattClientDiscoverServiceByUuidNative( 2531 int conn_id, long service_uuid_lsb, long service_uuid_msb); 2532 2533 private native void gattClientGetGattDbNative(int conn_id); 2534 2535 private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq); 2536 2537 private native void gattClientReadUsingCharacteristicUuidNative( 2538 int conn_id, long uuid_msb, long uuid_lsb, int s_handle, int e_handle, int authReq); 2539 2540 private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq); 2541 2542 private native void gattClientWriteCharacteristicNative(int conn_id, 2543 int handle, int write_type, int auth_req, byte[] value); 2544 2545 private native void gattClientWriteDescriptorNative(int conn_id, int handle, 2546 int auth_req, byte[] value); 2547 2548 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2549 2550 private native void gattClientRegisterForNotificationsNative(int clientIf, 2551 String address, int handle, boolean enable); 2552 2553 private native void gattClientReadRemoteRssiNative(int clientIf, 2554 String address); 2555 2556 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2557 2558 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2559 int minInterval, int maxInterval, int latency, int timeout); 2560 2561 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2562 long app_uuid_msb); 2563 2564 private native void gattServerUnregisterAppNative(int serverIf); 2565 2566 private native void gattServerConnectNative(int server_if, String address, 2567 boolean is_direct, int transport); 2568 2569 private native void gattServerDisconnectNative(int serverIf, String address, 2570 int conn_id); 2571 2572 private native void gattServerSetPreferredPhyNative( 2573 int clientIf, String address, int tx_phy, int rx_phy, int phy_options); 2574 2575 private native void gattServerReadPhyNative(int clientIf, String address); 2576 2577 private native void gattServerAddServiceNative(int server_if, List<GattDbElement> service); 2578 2579 private native void gattServerStopServiceNative (int server_if, 2580 int svc_handle); 2581 2582 private native void gattServerDeleteServiceNative (int server_if, 2583 int svc_handle); 2584 2585 private native void gattServerSendIndicationNative (int server_if, 2586 int attr_handle, int conn_id, byte[] val); 2587 2588 private native void gattServerSendNotificationNative (int server_if, 2589 int attr_handle, int conn_id, byte[] val); 2590 2591 private native void gattServerSendResponseNative (int server_if, 2592 int conn_id, int trans_id, int status, int handle, int offset, 2593 byte[] val, int auth_req); 2594} 2595