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