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