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