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