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 int minInterval; 1598 int maxInterval; 1599 1600 // Slave latency 1601 int latency; 1602 1603 // Link supervision timeout is measured in N * 10ms 1604 int timeout = 2000; // 20s 1605 1606 switch (connectionPriority) 1607 { 1608 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1609 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 1610 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 1611 latency = getResources().getInteger(R.integer.gatt_high_priority_latency); 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 = getResources().getInteger(R.integer.gatt_low_power_latency); 1618 break; 1619 1620 default: 1621 // Using the values for CONNECTION_PRIORITY_BALANCED. 1622 minInterval = 1623 getResources().getInteger(R.integer.gatt_balanced_priority_min_interval); 1624 maxInterval = 1625 getResources().getInteger(R.integer.gatt_balanced_priority_max_interval); 1626 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency); 1627 break; 1628 } 1629 1630 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1631 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1632 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1633 latency, timeout); 1634 } 1635 1636 /************************************************************************** 1637 * Callback functions - SERVER 1638 *************************************************************************/ 1639 onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)1640 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1641 throws RemoteException { 1642 1643 UUID uuid = new UUID(uuidMsb, uuidLsb); 1644 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1645 ServerMap.App app = mServerMap.getByUuid(uuid); 1646 if (app != null) { 1647 app.id = serverIf; 1648 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1649 app.callback.onServerRegistered(status, serverIf); 1650 } 1651 } 1652 onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int srvcHandle)1653 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1654 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1655 throws RemoteException { 1656 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1657 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1658 + ", handle=" + srvcHandle); 1659 if (status == 0) { 1660 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1661 mAdvertisingServiceUuids.remove(uuid)); 1662 } 1663 1664 continueServiceDeclaration(serverIf, status, srvcHandle); 1665 } 1666 onIncludedServiceAdded(int status, int serverIf, int srvcHandle, int includedSrvcHandle)1667 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1668 int includedSrvcHandle) throws RemoteException { 1669 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1670 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1671 continueServiceDeclaration(serverIf, status, srvcHandle); 1672 } 1673 onCharacteristicAdded(int status, int serverIf, long charUuidLsb, long charUuidMsb, int srvcHandle, int charHandle)1674 void onCharacteristicAdded(int status, int serverIf, 1675 long charUuidLsb, long charUuidMsb, 1676 int srvcHandle, int charHandle) 1677 throws RemoteException { 1678 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1679 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1680 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1681 if (status == 0) 1682 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1683 continueServiceDeclaration(serverIf, status, srvcHandle); 1684 } 1685 onDescriptorAdded(int status, int serverIf, long descrUuidLsb, long descrUuidMsb, int srvcHandle, int descrHandle)1686 void onDescriptorAdded(int status, int serverIf, 1687 long descrUuidLsb, long descrUuidMsb, 1688 int srvcHandle, int descrHandle) 1689 throws RemoteException { 1690 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1691 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1692 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1693 if (status == 0) 1694 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1695 continueServiceDeclaration(serverIf, status, srvcHandle); 1696 } 1697 onServiceStarted(int status, int serverIf, int srvcHandle)1698 void onServiceStarted(int status, int serverIf, int srvcHandle) 1699 throws RemoteException { 1700 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1701 + ", status=" + status); 1702 if (status == 0) 1703 mHandleMap.setStarted(serverIf, srvcHandle, true); 1704 } 1705 onServiceStopped(int status, int serverIf, int srvcHandle)1706 void onServiceStopped(int status, int serverIf, int srvcHandle) 1707 throws RemoteException { 1708 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1709 + ", status=" + status); 1710 if (status == 0) 1711 mHandleMap.setStarted(serverIf, srvcHandle, false); 1712 stopNextService(serverIf, status); 1713 } 1714 onServiceDeleted(int status, int serverIf, int srvcHandle)1715 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1716 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1717 + ", status=" + status); 1718 mHandleMap.deleteService(serverIf, srvcHandle); 1719 } 1720 onClientConnected(String address, boolean connected, int connId, int serverIf)1721 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1722 throws RemoteException { 1723 1724 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1725 + ", address=" + address + ", connected=" + connected); 1726 1727 ServerMap.App app = mServerMap.getById(serverIf); 1728 if (app == null) return; 1729 1730 if (connected) { 1731 mServerMap.addConnection(serverIf, connId, address); 1732 } else { 1733 mServerMap.removeConnection(serverIf, connId); 1734 } 1735 1736 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1737 } 1738 onAttributeRead(String address, int connId, int transId, int attrHandle, int offset, boolean isLong)1739 void onAttributeRead(String address, int connId, int transId, 1740 int attrHandle, int offset, boolean isLong) 1741 throws RemoteException { 1742 if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1743 + ", address=" + address + ", handle=" + attrHandle 1744 + ", requestId=" + transId + ", offset=" + offset); 1745 1746 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1747 if (entry == null) return; 1748 1749 mHandleMap.addRequest(transId, attrHandle); 1750 1751 ServerMap.App app = mServerMap.getById(entry.serverIf); 1752 if (app == null) return; 1753 1754 switch(entry.type) { 1755 case HandleMap.TYPE_CHARACTERISTIC: 1756 { 1757 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1758 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1759 serviceEntry.serviceType, serviceEntry.instance, 1760 new ParcelUuid(serviceEntry.uuid), entry.instance, 1761 new ParcelUuid(entry.uuid)); 1762 break; 1763 } 1764 1765 case HandleMap.TYPE_DESCRIPTOR: 1766 { 1767 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1768 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1769 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1770 serviceEntry.serviceType, serviceEntry.instance, 1771 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1772 new ParcelUuid(charEntry.uuid), 1773 new ParcelUuid(entry.uuid)); 1774 break; 1775 } 1776 1777 default: 1778 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1779 break; 1780 } 1781 } 1782 onAttributeWrite(String address, int connId, int transId, int attrHandle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)1783 void onAttributeWrite(String address, int connId, int transId, 1784 int attrHandle, int offset, int length, 1785 boolean needRsp, boolean isPrep, 1786 byte[] data) 1787 throws RemoteException { 1788 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1789 + ", address=" + address + ", handle=" + attrHandle 1790 + ", requestId=" + transId + ", isPrep=" + isPrep 1791 + ", offset=" + offset); 1792 1793 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1794 if (entry == null) return; 1795 1796 mHandleMap.addRequest(transId, attrHandle); 1797 1798 ServerMap.App app = mServerMap.getById(entry.serverIf); 1799 if (app == null) return; 1800 1801 switch(entry.type) { 1802 case HandleMap.TYPE_CHARACTERISTIC: 1803 { 1804 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1805 app.callback.onCharacteristicWriteRequest(address, transId, 1806 offset, length, isPrep, needRsp, 1807 serviceEntry.serviceType, serviceEntry.instance, 1808 new ParcelUuid(serviceEntry.uuid), entry.instance, 1809 new ParcelUuid(entry.uuid), data); 1810 break; 1811 } 1812 1813 case HandleMap.TYPE_DESCRIPTOR: 1814 { 1815 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1816 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1817 app.callback.onDescriptorWriteRequest(address, transId, 1818 offset, length, isPrep, needRsp, 1819 serviceEntry.serviceType, serviceEntry.instance, 1820 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1821 new ParcelUuid(charEntry.uuid), 1822 new ParcelUuid(entry.uuid), data); 1823 break; 1824 } 1825 1826 default: 1827 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1828 break; 1829 } 1830 } 1831 onExecuteWrite(String address, int connId, int transId, int execWrite)1832 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1833 throws RemoteException { 1834 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1835 + ", address=" + address + ", transId=" + transId); 1836 1837 ServerMap.App app = mServerMap.getByConnId(connId); 1838 if (app == null) return; 1839 1840 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1841 } 1842 onResponseSendCompleted(int status, int attrHandle)1843 void onResponseSendCompleted(int status, int attrHandle) { 1844 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1845 } 1846 onNotificationSent(int connId, int status)1847 void onNotificationSent(int connId, int status) throws RemoteException { 1848 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1849 1850 String address = mServerMap.addressByConnId(connId); 1851 if (address == null) return; 1852 1853 ServerMap.App app = mServerMap.getByConnId(connId); 1854 if (app == null) return; 1855 1856 if (!app.isCongested) { 1857 app.callback.onNotificationSent(address, status); 1858 } else { 1859 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1860 status = BluetoothGatt.GATT_SUCCESS; 1861 } 1862 app.queueCallback(new CallbackInfo(address, status)); 1863 } 1864 } 1865 onServerCongestion(int connId, boolean congested)1866 void onServerCongestion(int connId, boolean congested) throws RemoteException { 1867 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1868 1869 ServerMap.App app = mServerMap.getByConnId(connId); 1870 if (app == null) return; 1871 1872 app.isCongested = congested; 1873 while(!app.isCongested) { 1874 CallbackInfo callbackInfo = app.popQueuedCallback(); 1875 if (callbackInfo == null) return; 1876 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 1877 } 1878 } 1879 onMtuChanged(int connId, int mtu)1880 void onMtuChanged(int connId, int mtu) throws RemoteException { 1881 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 1882 1883 String address = mServerMap.addressByConnId(connId); 1884 if (address == null) return; 1885 1886 ServerMap.App app = mServerMap.getByConnId(connId); 1887 if (app == null) return; 1888 1889 app.callback.onMtuChanged(address, mtu); 1890 } 1891 1892 /************************************************************************** 1893 * GATT Service functions - SERVER 1894 *************************************************************************/ 1895 registerServer(UUID uuid, IBluetoothGattServerCallback callback)1896 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1897 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1898 1899 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1900 mServerMap.add(uuid, callback, this); 1901 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1902 uuid.getMostSignificantBits()); 1903 } 1904 unregisterServer(int serverIf)1905 void unregisterServer(int serverIf) { 1906 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1907 1908 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1909 1910 deleteServices(serverIf); 1911 1912 mServerMap.remove(serverIf); 1913 gattServerUnregisterAppNative(serverIf); 1914 } 1915 serverConnect(int serverIf, String address, boolean isDirect, int transport)1916 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1917 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1918 1919 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1920 gattServerConnectNative(serverIf, address, isDirect,transport); 1921 } 1922 serverDisconnect(int serverIf, String address)1923 void serverDisconnect(int serverIf, String address) { 1924 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1925 1926 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1927 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1928 1929 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1930 } 1931 beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, int minHandles, UUID srvcUuid, boolean advertisePreferred)1932 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1933 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1934 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1935 1936 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1937 ServiceDeclaration serviceDeclaration = addDeclaration(); 1938 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1939 advertisePreferred); 1940 } 1941 addIncludedService(int serverIf, int srvcType, int srvcInstanceId, UUID srvcUuid)1942 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1943 UUID srvcUuid) { 1944 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1945 1946 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1947 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1948 } 1949 addCharacteristic(int serverIf, UUID charUuid, int properties, int permissions)1950 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1951 int permissions) { 1952 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1953 1954 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1955 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1956 } 1957 addDescriptor(int serverIf, UUID descUuid, int permissions)1958 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1959 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1960 1961 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1962 getActiveDeclaration().addDescriptor(descUuid, permissions); 1963 } 1964 endServiceDeclaration(int serverIf)1965 void endServiceDeclaration(int serverIf) { 1966 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1967 1968 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1969 1970 if (getActiveDeclaration() == getPendingDeclaration()) { 1971 try { 1972 continueServiceDeclaration(serverIf, (byte)0, 0); 1973 } catch (RemoteException e) { 1974 Log.e(TAG,""+e); 1975 } 1976 } 1977 } 1978 removeService(int serverIf, int srvcType, int srvcInstanceId, UUID srvcUuid)1979 void removeService(int serverIf, int srvcType, 1980 int srvcInstanceId, UUID srvcUuid) { 1981 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1982 1983 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1984 1985 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1986 if (srvcHandle == 0) return; 1987 gattServerDeleteServiceNative(serverIf, srvcHandle); 1988 } 1989 clearServices(int serverIf)1990 void clearServices(int serverIf) { 1991 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1992 1993 if (DBG) Log.d(TAG, "clearServices()"); 1994 deleteServices(serverIf); 1995 } 1996 sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value)1997 void sendResponse(int serverIf, String address, int requestId, 1998 int status, int offset, byte[] value) { 1999 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2000 2001 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 2002 2003 int handle = 0; 2004 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2005 if (entry != null) handle = entry.handle; 2006 2007 int connId = mServerMap.connIdByAddress(serverIf, address); 2008 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2009 handle, offset, value, (byte)0); 2010 mHandleMap.deleteRequest(requestId); 2011 } 2012 sendNotification(int serverIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, boolean confirm, byte[] value)2013 void sendNotification(int serverIf, String address, int srvcType, 2014 int srvcInstanceId, UUID srvcUuid, 2015 int charInstanceId, UUID charUuid, 2016 boolean confirm, byte[] value) { 2017 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2018 2019 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address); 2020 2021 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2022 if (srvcHandle == 0) return; 2023 2024 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 2025 if (charHandle == 0) return; 2026 2027 int connId = mServerMap.connIdByAddress(serverIf, address); 2028 if (connId == 0) return; 2029 2030 if (confirm) { 2031 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 2032 } else { 2033 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 2034 } 2035 } 2036 2037 2038 /************************************************************************** 2039 * Private functions 2040 *************************************************************************/ 2041 isRestrictedCharUuid(final UUID charUuid)2042 private boolean isRestrictedCharUuid(final UUID charUuid) { 2043 return isHidUuid(charUuid); 2044 } 2045 isRestrictedSrvcUuid(final UUID srvcUuid)2046 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2047 return isFidoUUID(srvcUuid); 2048 } 2049 isHidUuid(final UUID uuid)2050 private boolean isHidUuid(final UUID uuid) { 2051 for (UUID hid_uuid : HID_UUIDS) { 2052 if (hid_uuid.equals(uuid)) return true; 2053 } 2054 return false; 2055 } 2056 isFidoUUID(final UUID uuid)2057 private boolean isFidoUUID(final UUID uuid) { 2058 for (UUID fido_uuid : FIDO_UUIDS) { 2059 if (fido_uuid.equals(uuid)) return true; 2060 } 2061 return false; 2062 } 2063 getDeviceType(BluetoothDevice device)2064 private int getDeviceType(BluetoothDevice device) { 2065 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2066 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2067 + ", type=" + type); 2068 return type; 2069 } 2070 enforceAdminPermission()2071 private void enforceAdminPermission() { 2072 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2073 } 2074 needsPrivilegedPermissionForScan(ScanSettings settings)2075 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2076 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2077 // BLE scan only mode needs special permission. 2078 if (adapter.getState() != BluetoothAdapter.STATE_ON) return true; 2079 2080 // Regular scan, no special permission. 2081 if (settings == null) return false; 2082 2083 // Regular scan, no special permission. 2084 if (settings.getReportDelayMillis() == 0) return false; 2085 2086 // Batch scan, truncated mode needs permission. 2087 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2088 } 2089 2090 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2091 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. enforcePrivilegedPermission()2092 private void enforcePrivilegedPermission() { 2093 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2094 "Need BLUETOOTH_PRIVILEGED permission"); 2095 } 2096 2097 // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other 2098 // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does 2099 // not have UPDATE_DEVICE_STATS permission. enforceImpersonatationPermission()2100 private void enforceImpersonatationPermission() { 2101 enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 2102 "Need UPDATE_DEVICE_STATS permission"); 2103 } 2104 continueServiceDeclaration(int serverIf, int status, int srvcHandle)2105 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 2106 if (mServiceDeclarations.size() == 0) return; 2107 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 2108 2109 boolean finished = false; 2110 2111 ServiceDeclaration.Entry entry = null; 2112 if (status == 0) 2113 entry = getPendingDeclaration().getNext(); 2114 2115 if (entry != null) { 2116 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 2117 + entry.type); 2118 switch(entry.type) { 2119 case ServiceDeclaration.TYPE_SERVICE: 2120 if (entry.advertisePreferred) { 2121 mAdvertisingServiceUuids.add(entry.uuid); 2122 } 2123 gattServerAddServiceNative(serverIf, entry.serviceType, 2124 entry.instance, 2125 entry.uuid.getLeastSignificantBits(), 2126 entry.uuid.getMostSignificantBits(), 2127 getPendingDeclaration().getNumHandles()); 2128 break; 2129 2130 case ServiceDeclaration.TYPE_CHARACTERISTIC: 2131 gattServerAddCharacteristicNative(serverIf, srvcHandle, 2132 entry.uuid.getLeastSignificantBits(), 2133 entry.uuid.getMostSignificantBits(), 2134 entry.properties, entry.permissions); 2135 break; 2136 2137 case ServiceDeclaration.TYPE_DESCRIPTOR: 2138 gattServerAddDescriptorNative(serverIf, srvcHandle, 2139 entry.uuid.getLeastSignificantBits(), 2140 entry.uuid.getMostSignificantBits(), 2141 entry.permissions); 2142 break; 2143 2144 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2145 { 2146 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2147 entry.serviceType, entry.instance); 2148 if (inclSrvc != 0) { 2149 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2150 inclSrvc); 2151 } else { 2152 finished = true; 2153 } 2154 break; 2155 } 2156 } 2157 } else { 2158 gattServerStartServiceNative(serverIf, srvcHandle, 2159 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2160 finished = true; 2161 } 2162 2163 if (finished) { 2164 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2165 ServerMap.App app = mServerMap.getById(serverIf); 2166 if (app != null) { 2167 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2168 2169 if (serviceEntry != null) { 2170 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2171 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2172 } else { 2173 app.callback.onServiceAdded(status, 0, 0, null); 2174 } 2175 } 2176 removePendingDeclaration(); 2177 2178 if (getPendingDeclaration() != null) { 2179 continueServiceDeclaration(serverIf, (byte)0, 0); 2180 } 2181 } 2182 } 2183 stopNextService(int serverIf, int status)2184 private void stopNextService(int serverIf, int status) throws RemoteException { 2185 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2186 + ", status=" + status); 2187 2188 if (status == 0) { 2189 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2190 for(HandleMap.Entry entry : entries) { 2191 if (entry.type != HandleMap.TYPE_SERVICE || 2192 entry.serverIf != serverIf || 2193 entry.started == false) 2194 continue; 2195 2196 gattServerStopServiceNative(serverIf, entry.handle); 2197 return; 2198 } 2199 } 2200 } 2201 deleteServices(int serverIf)2202 private void deleteServices(int serverIf) { 2203 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2204 2205 /* 2206 * Figure out which handles to delete. 2207 * The handles are copied into a new list to avoid race conditions. 2208 */ 2209 List<Integer> handleList = new ArrayList<Integer>(); 2210 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2211 for(HandleMap.Entry entry : entries) { 2212 if (entry.type != HandleMap.TYPE_SERVICE || 2213 entry.serverIf != serverIf) 2214 continue; 2215 handleList.add(entry.handle); 2216 } 2217 2218 /* Now actually delete the services.... */ 2219 for(Integer handle : handleList) { 2220 gattServerDeleteServiceNative(serverIf, handle); 2221 } 2222 } 2223 parseUuids(byte[] adv_data)2224 private List<UUID> parseUuids(byte[] adv_data) { 2225 List<UUID> uuids = new ArrayList<UUID>(); 2226 2227 int offset = 0; 2228 while(offset < (adv_data.length-2)) { 2229 int len = adv_data[offset++]; 2230 if (len == 0) break; 2231 2232 int type = adv_data[offset++]; 2233 switch (type) { 2234 case 0x02: // Partial list of 16-bit UUIDs 2235 case 0x03: // Complete list of 16-bit UUIDs 2236 while (len > 1) { 2237 int uuid16 = adv_data[offset++]; 2238 uuid16 += (adv_data[offset++] << 8); 2239 len -= 2; 2240 uuids.add(UUID.fromString(String.format( 2241 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2242 } 2243 break; 2244 2245 default: 2246 offset += (len - 1); 2247 break; 2248 } 2249 } 2250 2251 return uuids; 2252 } 2253 2254 @Override dump(StringBuilder sb)2255 public void dump(StringBuilder sb) { 2256 super.dump(sb); 2257 println(sb, "mAdvertisingServiceUuids:"); 2258 for (UUID uuid : mAdvertisingServiceUuids) { 2259 println(sb, " " + uuid); 2260 } 2261 for (ServiceDeclaration declaration : mServiceDeclarations) { 2262 println(sb, " " + declaration); 2263 } 2264 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2265 2266 sb.append("\nGATT Client Map\n"); 2267 mClientMap.dump(sb); 2268 2269 sb.append("GATT Server Map\n"); 2270 mServerMap.dump(sb); 2271 2272 sb.append("GATT Handle Map\n"); 2273 mHandleMap.dump(sb); 2274 } 2275 addScanResult()2276 void addScanResult() { 2277 if (mScanEvents.isEmpty()) 2278 return; 2279 2280 BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1); 2281 curr.setNumberResults(curr.getNumberResults() + 1); 2282 } 2283 addScanEvent(BluetoothProto.ScanEvent event)2284 void addScanEvent(BluetoothProto.ScanEvent event) { 2285 synchronized(mScanEvents) { 2286 if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 2287 mScanEvents.remove(0); 2288 mScanEvents.add(event); 2289 } 2290 } 2291 2292 @Override dumpProto(BluetoothProto.BluetoothLog proto)2293 public void dumpProto(BluetoothProto.BluetoothLog proto) { 2294 synchronized(mScanEvents) { 2295 for (BluetoothProto.ScanEvent event : mScanEvents) { 2296 proto.addScanEvent(event); 2297 } 2298 } 2299 } 2300 2301 /************************************************************************** 2302 * GATT Test functions 2303 *************************************************************************/ 2304 gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, int p5)2305 void gattTestCommand(int command, UUID uuid1, String bda1, 2306 int p1, int p2, int p3, int p4, int p5) { 2307 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2308 if (uuid1 != null) 2309 gattTestNative(command, uuid1.getLeastSignificantBits(), 2310 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2311 else 2312 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2313 } 2314 gattTestNative(int command, long uuid1_lsb, long uuid1_msb, String bda1, int p1, int p2, int p3, int p4, int p5)2315 private native void gattTestNative(int command, 2316 long uuid1_lsb, long uuid1_msb, String bda1, 2317 int p1, int p2, int p3, int p4, int p5); 2318 2319 /************************************************************************** 2320 * Native functions prototypes 2321 *************************************************************************/ 2322 classInitNative()2323 private native static void classInitNative(); initializeNative()2324 private native void initializeNative(); cleanupNative()2325 private native void cleanupNative(); 2326 gattClientGetDeviceTypeNative(String address)2327 private native int gattClientGetDeviceTypeNative(String address); 2328 gattClientRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2329 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2330 long app_uuid_msb); 2331 gattClientUnregisterAppNative(int clientIf)2332 private native void gattClientUnregisterAppNative(int clientIf); 2333 gattClientConnectNative(int clientIf, String address, boolean isDirect, int transport)2334 private native void gattClientConnectNative(int clientIf, String address, 2335 boolean isDirect, int transport); 2336 gattClientDisconnectNative(int clientIf, String address, int conn_id)2337 private native void gattClientDisconnectNative(int clientIf, String address, 2338 int conn_id); 2339 gattClientRefreshNative(int clientIf, String address)2340 private native void gattClientRefreshNative(int clientIf, String address); 2341 gattClientSearchServiceNative(int conn_id, boolean search_all, long service_uuid_lsb, long service_uuid_msb)2342 private native void gattClientSearchServiceNative(int conn_id, 2343 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2344 gattClientGetGattDbNative(int conn_id)2345 private native void gattClientGetGattDbNative(int conn_id); 2346 gattClientReadCharacteristicNative(int conn_id, int handle, int authReq)2347 private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq); 2348 gattClientReadDescriptorNative(int conn_id, int handle, int authReq)2349 private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq); 2350 gattClientWriteCharacteristicNative(int conn_id, int handle, int write_type, int auth_req, byte[] value)2351 private native void gattClientWriteCharacteristicNative(int conn_id, 2352 int handle, int write_type, int auth_req, byte[] value); 2353 gattClientWriteDescriptorNative(int conn_id, int handle, int write_type, int auth_req, byte[] value)2354 private native void gattClientWriteDescriptorNative(int conn_id, int handle, 2355 int write_type, int auth_req, byte[] value); 2356 gattClientExecuteWriteNative(int conn_id, boolean execute)2357 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2358 gattClientRegisterForNotificationsNative(int clientIf, String address, int handle, boolean enable)2359 private native void gattClientRegisterForNotificationsNative(int clientIf, 2360 String address, int handle, boolean enable); 2361 gattClientReadRemoteRssiNative(int clientIf, String address)2362 private native void gattClientReadRemoteRssiNative(int clientIf, 2363 String address); 2364 gattClientConfigureMTUNative(int conn_id, int mtu)2365 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2366 gattConnectionParameterUpdateNative(int client_if, String address, int minInterval, int maxInterval, int latency, int timeout)2367 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2368 int minInterval, int maxInterval, int latency, int timeout); 2369 gattServerRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2370 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2371 long app_uuid_msb); 2372 gattServerUnregisterAppNative(int serverIf)2373 private native void gattServerUnregisterAppNative(int serverIf); 2374 gattServerConnectNative(int server_if, String address, boolean is_direct, int transport)2375 private native void gattServerConnectNative(int server_if, String address, 2376 boolean is_direct, int transport); 2377 gattServerDisconnectNative(int serverIf, String address, int conn_id)2378 private native void gattServerDisconnectNative(int serverIf, String address, 2379 int conn_id); 2380 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)2381 private native void gattServerAddServiceNative (int server_if, 2382 int service_type, int service_id_inst_id, 2383 long service_id_uuid_lsb, long service_id_uuid_msb, 2384 int num_handles); 2385 gattServerAddIncludedServiceNative(int server_if, int svc_handle, int included_svc_handle)2386 private native void gattServerAddIncludedServiceNative (int server_if, 2387 int svc_handle, int included_svc_handle); 2388 gattServerAddCharacteristicNative(int server_if, int svc_handle, long char_uuid_lsb, long char_uuid_msb, int properties, int permissions)2389 private native void gattServerAddCharacteristicNative (int server_if, 2390 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2391 int properties, int permissions); 2392 gattServerAddDescriptorNative(int server_if, int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, int permissions)2393 private native void gattServerAddDescriptorNative (int server_if, 2394 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2395 int permissions); 2396 gattServerStartServiceNative(int server_if, int svc_handle, int transport )2397 private native void gattServerStartServiceNative (int server_if, 2398 int svc_handle, int transport ); 2399 gattServerStopServiceNative(int server_if, int svc_handle)2400 private native void gattServerStopServiceNative (int server_if, 2401 int svc_handle); 2402 gattServerDeleteServiceNative(int server_if, int svc_handle)2403 private native void gattServerDeleteServiceNative (int server_if, 2404 int svc_handle); 2405 gattServerSendIndicationNative(int server_if, int attr_handle, int conn_id, byte[] val)2406 private native void gattServerSendIndicationNative (int server_if, 2407 int attr_handle, int conn_id, byte[] val); 2408 gattServerSendNotificationNative(int server_if, int attr_handle, int conn_id, byte[] val)2409 private native void gattServerSendNotificationNative (int server_if, 2410 int attr_handle, int conn_id, byte[] val); 2411 gattServerSendResponseNative(int server_if, int conn_id, int trans_id, int status, int handle, int offset, byte[] val, int auth_req)2412 private native void gattServerSendResponseNative (int server_if, 2413 int conn_id, int trans_id, int status, int handle, int offset, 2414 byte[] val, int auth_req); 2415 } 2416