GattService.java revision a6ebe46992bcdf60bfc40cbb78974425b8901449
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 mScanManager.startScan(scanClient); 1393 } 1394 1395 void flushPendingBatchResults(int clientIf, boolean isServer) { 1396 if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + 1397 ", isServer=" + isServer); 1398 mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); 1399 } 1400 1401 void stopScan(ScanClient client) { 1402 enforceAdminPermission(); 1403 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1404 mScanManager.getRegularScanQueue().size(); 1405 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1406 mScanManager.stopScan(client); 1407 } 1408 1409 void disconnectAll() { 1410 if (DBG) Log.d(TAG, "disconnectAll()"); 1411 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 1412 for(Map.Entry<Integer, String> entry:connMap.entrySet()){ 1413 if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue()); 1414 clientDisconnect(entry.getKey(), entry.getValue()); 1415 //clientDisconnect(int clientIf, String address) 1416 } 1417 } 1418 1419 void unregAll() { 1420 for(ClientMap.App app:mClientMap.mApps){ 1421 if (DBG) Log.d(TAG, "unreg:" + app.id); 1422 unregisterClient(app.id); 1423 } 1424 } 1425 1426 /************************************************************************** 1427 * GATT Service functions - CLIENT 1428 *************************************************************************/ 1429 1430 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1431 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1432 1433 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1434 mClientMap.add(uuid, callback); 1435 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1436 uuid.getMostSignificantBits()); 1437 } 1438 1439 void unregisterClient(int clientIf) { 1440 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1441 1442 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1443 mClientMap.remove(clientIf); 1444 gattClientUnregisterAppNative(clientIf); 1445 } 1446 1447 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1448 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1449 1450 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1451 gattClientConnectNative(clientIf, address, isDirect, transport); 1452 } 1453 1454 void clientDisconnect(int clientIf, String address) { 1455 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1456 1457 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1458 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1459 1460 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1461 } 1462 1463 void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 1464 AdvertiseData scanResponse, AdvertiseSettings settings) { 1465 enforceAdminPermission(); 1466 mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData, 1467 scanResponse)); 1468 } 1469 1470 void stopMultiAdvertising(AdvertiseClient client) { 1471 enforceAdminPermission(); 1472 mAdvertiseManager.stopAdvertising(client); 1473 } 1474 1475 int numHwTrackFiltersAvailable() { 1476 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 1477 - mScanManager.getCurrentUsedTrackingAdvertisement()); 1478 } 1479 1480 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1481 Utils.enforceAdminPermission(this); 1482 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1483 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1484 serviceUuids.add(new ParcelUuid(entry.uuid)); 1485 } 1486 return serviceUuids; 1487 } 1488 1489 List<String> getConnectedDevices() { 1490 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1491 1492 Set<String> connectedDevAddress = new HashSet<String>(); 1493 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1494 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1495 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1496 return connectedDeviceList; 1497 } 1498 1499 void refreshDevice(int clientIf, String address) { 1500 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1501 1502 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1503 gattClientRefreshNative(clientIf, address); 1504 } 1505 1506 void discoverServices(int clientIf, String address) { 1507 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1508 1509 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1510 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1511 1512 if (connId != null) 1513 gattClientSearchServiceNative(connId, true, 0, 0); 1514 else 1515 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1516 } 1517 1518 void readCharacteristic(int clientIf, String address, int srvcType, 1519 int srvcInstanceId, UUID srvcUuid, 1520 int charInstanceId, UUID charUuid, int authReq) { 1521 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1522 if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) { 1523 enforcePrivilegedPermission(); 1524 } 1525 1526 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1527 1528 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1529 if (connId != null) 1530 gattClientReadCharacteristicNative(connId, srvcType, 1531 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1532 srvcUuid.getMostSignificantBits(), charInstanceId, 1533 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1534 authReq); 1535 else 1536 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1537 } 1538 1539 void writeCharacteristic(int clientIf, String address, int srvcType, 1540 int srvcInstanceId, UUID srvcUuid, 1541 int charInstanceId, UUID charUuid, int writeType, 1542 int authReq, byte[] value) { 1543 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1544 if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) { 1545 enforcePrivilegedPermission(); 1546 } 1547 1548 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1549 1550 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1551 1552 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1553 if (connId != null) 1554 gattClientWriteCharacteristicNative(connId, srvcType, 1555 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1556 srvcUuid.getMostSignificantBits(), charInstanceId, 1557 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1558 writeType, authReq, value); 1559 else 1560 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1561 } 1562 1563 void readDescriptor(int clientIf, String address, int srvcType, 1564 int srvcInstanceId, UUID srvcUuid, 1565 int charInstanceId, UUID charUuid, 1566 int descrInstanceId, UUID descrUuid, 1567 int authReq) { 1568 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1569 if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) { 1570 enforcePrivilegedPermission(); 1571 } 1572 1573 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1574 1575 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1576 if (connId != null) 1577 gattClientReadDescriptorNative(connId, srvcType, 1578 srvcInstanceId, 1579 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1580 charInstanceId, 1581 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1582 descrInstanceId, 1583 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1584 authReq); 1585 else 1586 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1587 }; 1588 1589 void writeDescriptor(int clientIf, String address, int srvcType, 1590 int srvcInstanceId, UUID srvcUuid, 1591 int charInstanceId, UUID charUuid, 1592 int descrInstanceId, UUID descrUuid, 1593 int writeType, int authReq, byte[] value) { 1594 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1595 if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) { 1596 enforcePrivilegedPermission(); 1597 } 1598 1599 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1600 1601 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1602 if (connId != null) 1603 gattClientWriteDescriptorNative(connId, srvcType, 1604 srvcInstanceId, 1605 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1606 charInstanceId, 1607 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1608 descrInstanceId, 1609 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1610 writeType, authReq, value); 1611 else 1612 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1613 } 1614 1615 void beginReliableWrite(int clientIf, String address) { 1616 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1617 1618 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1619 mReliableQueue.add(address); 1620 } 1621 1622 void endReliableWrite(int clientIf, String address, boolean execute) { 1623 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1624 1625 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1626 + " execute: " + execute); 1627 mReliableQueue.remove(address); 1628 1629 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1630 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1631 } 1632 1633 void registerForNotification(int clientIf, String address, int srvcType, 1634 int srvcInstanceId, UUID srvcUuid, 1635 int charInstanceId, UUID charUuid, 1636 boolean enable) { 1637 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1638 if (isRestrictedCharUuid(charUuid) || isRestrictedSrvcUuid(srvcUuid)) { 1639 enforcePrivilegedPermission(); 1640 } 1641 1642 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1643 1644 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1645 if (connId != null) { 1646 gattClientRegisterForNotificationsNative(clientIf, address, 1647 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1648 srvcUuid.getMostSignificantBits(), charInstanceId, 1649 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1650 enable); 1651 } else { 1652 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1653 } 1654 } 1655 1656 void readRemoteRssi(int clientIf, String address) { 1657 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1658 1659 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1660 gattClientReadRemoteRssiNative(clientIf, address); 1661 } 1662 1663 void configureMTU(int clientIf, String address, int mtu) { 1664 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1665 1666 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1667 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1668 if (connId != null) { 1669 gattClientConfigureMTUNative(connId, mtu); 1670 } else { 1671 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1672 } 1673 } 1674 1675 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1676 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1677 1678 // Default spec recommended interval is 30->50 ms 1679 int minInterval = 24; // 24 * 1.25ms = 30ms 1680 int maxInterval = 40; // 40 * 1.25ms = 50ms 1681 1682 // Slave latency 1683 int latency = 0; 1684 1685 // Link supervision timeout is measured in N * 10ms 1686 int timeout = 2000; // 20s 1687 1688 switch (connectionPriority) 1689 { 1690 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1691 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval); 1692 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval); 1693 break; 1694 1695 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 1696 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval); 1697 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval); 1698 latency = 2; 1699 break; 1700 } 1701 1702 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1703 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1704 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1705 latency, timeout); 1706 } 1707 1708 /************************************************************************** 1709 * Callback functions - SERVER 1710 *************************************************************************/ 1711 1712 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1713 throws RemoteException { 1714 1715 UUID uuid = new UUID(uuidMsb, uuidLsb); 1716 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1717 ServerMap.App app = mServerMap.getByUuid(uuid); 1718 if (app != null) { 1719 app.id = serverIf; 1720 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1721 app.callback.onServerRegistered(status, serverIf); 1722 } 1723 } 1724 1725 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1726 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1727 throws RemoteException { 1728 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1729 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1730 + ", handle=" + srvcHandle); 1731 if (status == 0) { 1732 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1733 mAdvertisingServiceUuids.remove(uuid)); 1734 } 1735 1736 continueServiceDeclaration(serverIf, status, srvcHandle); 1737 } 1738 1739 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1740 int includedSrvcHandle) throws RemoteException { 1741 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1742 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1743 continueServiceDeclaration(serverIf, status, srvcHandle); 1744 } 1745 1746 void onCharacteristicAdded(int status, int serverIf, 1747 long charUuidLsb, long charUuidMsb, 1748 int srvcHandle, int charHandle) 1749 throws RemoteException { 1750 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1751 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1752 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1753 if (status == 0) 1754 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1755 continueServiceDeclaration(serverIf, status, srvcHandle); 1756 } 1757 1758 void onDescriptorAdded(int status, int serverIf, 1759 long descrUuidLsb, long descrUuidMsb, 1760 int srvcHandle, int descrHandle) 1761 throws RemoteException { 1762 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1763 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1764 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1765 if (status == 0) 1766 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1767 continueServiceDeclaration(serverIf, status, srvcHandle); 1768 } 1769 1770 void onServiceStarted(int status, int serverIf, int srvcHandle) 1771 throws RemoteException { 1772 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1773 + ", status=" + status); 1774 if (status == 0) 1775 mHandleMap.setStarted(serverIf, srvcHandle, true); 1776 } 1777 1778 void onServiceStopped(int status, int serverIf, int srvcHandle) 1779 throws RemoteException { 1780 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1781 + ", status=" + status); 1782 if (status == 0) 1783 mHandleMap.setStarted(serverIf, srvcHandle, false); 1784 stopNextService(serverIf, status); 1785 } 1786 1787 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1788 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1789 + ", status=" + status); 1790 mHandleMap.deleteService(serverIf, srvcHandle); 1791 } 1792 1793 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1794 throws RemoteException { 1795 1796 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1797 + ", address=" + address + ", connected=" + connected); 1798 1799 ServerMap.App app = mServerMap.getById(serverIf); 1800 if (app == null) return; 1801 1802 if (connected) { 1803 mServerMap.addConnection(serverIf, connId, address); 1804 } else { 1805 mServerMap.removeConnection(serverIf, connId); 1806 } 1807 1808 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1809 } 1810 1811 void onAttributeRead(String address, int connId, int transId, 1812 int attrHandle, int offset, boolean isLong) 1813 throws RemoteException { 1814 if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1815 + ", address=" + address + ", handle=" + attrHandle 1816 + ", requestId=" + transId + ", offset=" + offset); 1817 1818 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1819 if (entry == null) return; 1820 1821 mHandleMap.addRequest(transId, attrHandle); 1822 1823 ServerMap.App app = mServerMap.getById(entry.serverIf); 1824 if (app == null) return; 1825 1826 switch(entry.type) { 1827 case HandleMap.TYPE_CHARACTERISTIC: 1828 { 1829 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1830 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1831 serviceEntry.serviceType, serviceEntry.instance, 1832 new ParcelUuid(serviceEntry.uuid), entry.instance, 1833 new ParcelUuid(entry.uuid)); 1834 break; 1835 } 1836 1837 case HandleMap.TYPE_DESCRIPTOR: 1838 { 1839 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1840 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1841 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1842 serviceEntry.serviceType, serviceEntry.instance, 1843 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1844 new ParcelUuid(charEntry.uuid), 1845 new ParcelUuid(entry.uuid)); 1846 break; 1847 } 1848 1849 default: 1850 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1851 break; 1852 } 1853 } 1854 1855 void onAttributeWrite(String address, int connId, int transId, 1856 int attrHandle, int offset, int length, 1857 boolean needRsp, boolean isPrep, 1858 byte[] data) 1859 throws RemoteException { 1860 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1861 + ", address=" + address + ", handle=" + attrHandle 1862 + ", requestId=" + transId + ", isPrep=" + isPrep 1863 + ", offset=" + offset); 1864 1865 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1866 if (entry == null) return; 1867 1868 mHandleMap.addRequest(transId, attrHandle); 1869 1870 ServerMap.App app = mServerMap.getById(entry.serverIf); 1871 if (app == null) return; 1872 1873 switch(entry.type) { 1874 case HandleMap.TYPE_CHARACTERISTIC: 1875 { 1876 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1877 app.callback.onCharacteristicWriteRequest(address, transId, 1878 offset, length, isPrep, needRsp, 1879 serviceEntry.serviceType, serviceEntry.instance, 1880 new ParcelUuid(serviceEntry.uuid), entry.instance, 1881 new ParcelUuid(entry.uuid), data); 1882 break; 1883 } 1884 1885 case HandleMap.TYPE_DESCRIPTOR: 1886 { 1887 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1888 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1889 app.callback.onDescriptorWriteRequest(address, transId, 1890 offset, length, isPrep, needRsp, 1891 serviceEntry.serviceType, serviceEntry.instance, 1892 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1893 new ParcelUuid(charEntry.uuid), 1894 new ParcelUuid(entry.uuid), data); 1895 break; 1896 } 1897 1898 default: 1899 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1900 break; 1901 } 1902 } 1903 1904 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1905 throws RemoteException { 1906 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1907 + ", address=" + address + ", transId=" + transId); 1908 1909 ServerMap.App app = mServerMap.getByConnId(connId); 1910 if (app == null) return; 1911 1912 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1913 } 1914 1915 void onResponseSendCompleted(int status, int attrHandle) { 1916 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1917 } 1918 1919 void onNotificationSent(int connId, int status) throws RemoteException { 1920 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1921 1922 String address = mServerMap.addressByConnId(connId); 1923 if (address == null) return; 1924 1925 ServerMap.App app = mServerMap.getByConnId(connId); 1926 if (app == null) return; 1927 1928 if (!app.isCongested) { 1929 app.callback.onNotificationSent(address, status); 1930 } else { 1931 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1932 status = BluetoothGatt.GATT_SUCCESS; 1933 } 1934 app.queueCallback(new CallbackInfo(address, status)); 1935 } 1936 } 1937 1938 void onServerCongestion(int connId, boolean congested) throws RemoteException { 1939 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1940 1941 ServerMap.App app = mServerMap.getByConnId(connId); 1942 if (app == null) return; 1943 1944 app.isCongested = congested; 1945 while(!app.isCongested) { 1946 CallbackInfo callbackInfo = app.popQueuedCallback(); 1947 if (callbackInfo == null) return; 1948 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 1949 } 1950 } 1951 1952 void onMtuChanged(int connId, int mtu) throws RemoteException { 1953 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 1954 1955 String address = mServerMap.addressByConnId(connId); 1956 if (address == null) return; 1957 1958 ServerMap.App app = mServerMap.getByConnId(connId); 1959 if (app == null) return; 1960 1961 app.callback.onMtuChanged(address, mtu); 1962 } 1963 1964 /************************************************************************** 1965 * GATT Service functions - SERVER 1966 *************************************************************************/ 1967 1968 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1969 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1970 1971 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1972 mServerMap.add(uuid, callback); 1973 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1974 uuid.getMostSignificantBits()); 1975 } 1976 1977 void unregisterServer(int serverIf) { 1978 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1979 1980 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1981 1982 deleteServices(serverIf); 1983 1984 mServerMap.remove(serverIf); 1985 gattServerUnregisterAppNative(serverIf); 1986 } 1987 1988 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1989 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1990 1991 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1992 gattServerConnectNative(serverIf, address, isDirect,transport); 1993 } 1994 1995 void serverDisconnect(int serverIf, String address) { 1996 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1997 1998 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1999 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 2000 2001 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 2002 } 2003 2004 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 2005 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 2006 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2007 2008 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 2009 ServiceDeclaration serviceDeclaration = addDeclaration(); 2010 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 2011 advertisePreferred); 2012 } 2013 2014 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 2015 UUID srvcUuid) { 2016 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2017 2018 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 2019 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 2020 } 2021 2022 void addCharacteristic(int serverIf, UUID charUuid, int properties, 2023 int permissions) { 2024 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2025 2026 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 2027 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 2028 } 2029 2030 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 2031 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2032 2033 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 2034 getActiveDeclaration().addDescriptor(descUuid, permissions); 2035 } 2036 2037 void endServiceDeclaration(int serverIf) { 2038 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2039 2040 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 2041 2042 if (getActiveDeclaration() == getPendingDeclaration()) { 2043 try { 2044 continueServiceDeclaration(serverIf, (byte)0, 0); 2045 } catch (RemoteException e) { 2046 Log.e(TAG,""+e); 2047 } 2048 } 2049 } 2050 2051 void removeService(int serverIf, int srvcType, 2052 int srvcInstanceId, UUID srvcUuid) { 2053 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2054 2055 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 2056 2057 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2058 if (srvcHandle == 0) return; 2059 gattServerDeleteServiceNative(serverIf, srvcHandle); 2060 } 2061 2062 void clearServices(int serverIf) { 2063 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2064 2065 if (DBG) Log.d(TAG, "clearServices()"); 2066 deleteServices(serverIf); 2067 } 2068 2069 void sendResponse(int serverIf, String address, int requestId, 2070 int status, int offset, byte[] value) { 2071 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2072 2073 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 2074 2075 int handle = 0; 2076 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2077 if (entry != null) handle = entry.handle; 2078 2079 int connId = mServerMap.connIdByAddress(serverIf, address); 2080 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2081 handle, offset, value, (byte)0); 2082 mHandleMap.deleteRequest(requestId); 2083 } 2084 2085 void sendNotification(int serverIf, String address, int srvcType, 2086 int srvcInstanceId, UUID srvcUuid, 2087 int charInstanceId, UUID charUuid, 2088 boolean confirm, byte[] value) { 2089 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2090 2091 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address); 2092 2093 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2094 if (srvcHandle == 0) return; 2095 2096 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 2097 if (charHandle == 0) return; 2098 2099 int connId = mServerMap.connIdByAddress(serverIf, address); 2100 if (connId == 0) return; 2101 2102 if (confirm) { 2103 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 2104 } else { 2105 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 2106 } 2107 } 2108 2109 2110 /************************************************************************** 2111 * Private functions 2112 *************************************************************************/ 2113 2114 private boolean isRestrictedCharUuid(final UUID charUuid) { 2115 return isHidUuid(charUuid); 2116 } 2117 2118 private boolean isRestrictedSrvcUuid(final UUID srvcUuid) { 2119 return isFidoUUID(srvcUuid); 2120 } 2121 2122 private boolean isHidUuid(final UUID uuid) { 2123 for (UUID hid_uuid : HID_UUIDS) { 2124 if (hid_uuid.equals(uuid)) return true; 2125 } 2126 return false; 2127 } 2128 2129 private boolean isFidoUUID(final UUID uuid) { 2130 for (UUID fido_uuid : FIDO_UUIDS) { 2131 if (fido_uuid.equals(uuid)) return true; 2132 } 2133 return false; 2134 } 2135 2136 private int getDeviceType(BluetoothDevice device) { 2137 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2138 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2139 + ", type=" + type); 2140 return type; 2141 } 2142 2143 private void enforceAdminPermission() { 2144 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2145 } 2146 2147 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2148 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2149 // BLE scan only mode needs special permission. 2150 if (adapter.getState() != BluetoothAdapter.STATE_ON) return true; 2151 2152 // Regular scan, no special permission. 2153 if (settings == null) return false; 2154 2155 // Regular scan, no special permission. 2156 if (settings.getReportDelayMillis() == 0) return false; 2157 2158 // Batch scan, truncated mode needs permission. 2159 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2160 } 2161 2162 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2163 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2164 private void enforcePrivilegedPermission() { 2165 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2166 "Need BLUETOOTH_PRIVILEGED permission"); 2167 } 2168 2169 private void continueSearch(int connId, int status) throws RemoteException { 2170 2171 // Search is complete when there was error, or nothing more to process 2172 if (status != 0 || mSearchQueue.isEmptyFor(connId)) { 2173 // In case we complete because of error, clean up 2174 // any remaining operations for this connection. 2175 mSearchQueue.removeConnId(connId); 2176 2177 ClientMap.App app = mClientMap.getByConnId(connId); 2178 if (app != null) { 2179 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 2180 } 2181 } 2182 2183 if (!mSearchQueue.isEmpty()) { 2184 SearchQueue.Entry svc = mSearchQueue.pop(); 2185 2186 if (svc.charUuidLsb == 0) { 2187 // Characteristic is up next 2188 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 2189 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 2190 } else { 2191 // Descriptor is up next 2192 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 2193 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 2194 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 2195 } 2196 } 2197 } 2198 2199 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 2200 if (mServiceDeclarations.size() == 0) return; 2201 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 2202 2203 boolean finished = false; 2204 2205 ServiceDeclaration.Entry entry = null; 2206 if (status == 0) 2207 entry = getPendingDeclaration().getNext(); 2208 2209 if (entry != null) { 2210 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 2211 + entry.type); 2212 switch(entry.type) { 2213 case ServiceDeclaration.TYPE_SERVICE: 2214 if (entry.advertisePreferred) { 2215 mAdvertisingServiceUuids.add(entry.uuid); 2216 } 2217 gattServerAddServiceNative(serverIf, entry.serviceType, 2218 entry.instance, 2219 entry.uuid.getLeastSignificantBits(), 2220 entry.uuid.getMostSignificantBits(), 2221 getPendingDeclaration().getNumHandles()); 2222 break; 2223 2224 case ServiceDeclaration.TYPE_CHARACTERISTIC: 2225 gattServerAddCharacteristicNative(serverIf, srvcHandle, 2226 entry.uuid.getLeastSignificantBits(), 2227 entry.uuid.getMostSignificantBits(), 2228 entry.properties, entry.permissions); 2229 break; 2230 2231 case ServiceDeclaration.TYPE_DESCRIPTOR: 2232 gattServerAddDescriptorNative(serverIf, srvcHandle, 2233 entry.uuid.getLeastSignificantBits(), 2234 entry.uuid.getMostSignificantBits(), 2235 entry.permissions); 2236 break; 2237 2238 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2239 { 2240 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2241 entry.serviceType, entry.instance); 2242 if (inclSrvc != 0) { 2243 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2244 inclSrvc); 2245 } else { 2246 finished = true; 2247 } 2248 break; 2249 } 2250 } 2251 } else { 2252 gattServerStartServiceNative(serverIf, srvcHandle, 2253 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2254 finished = true; 2255 } 2256 2257 if (finished) { 2258 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2259 ServerMap.App app = mServerMap.getById(serverIf); 2260 if (app != null) { 2261 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2262 2263 if (serviceEntry != null) { 2264 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2265 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2266 } else { 2267 app.callback.onServiceAdded(status, 0, 0, null); 2268 } 2269 } 2270 removePendingDeclaration(); 2271 2272 if (getPendingDeclaration() != null) { 2273 continueServiceDeclaration(serverIf, (byte)0, 0); 2274 } 2275 } 2276 } 2277 2278 private void stopNextService(int serverIf, int status) throws RemoteException { 2279 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2280 + ", status=" + status); 2281 2282 if (status == 0) { 2283 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2284 for(HandleMap.Entry entry : entries) { 2285 if (entry.type != HandleMap.TYPE_SERVICE || 2286 entry.serverIf != serverIf || 2287 entry.started == false) 2288 continue; 2289 2290 gattServerStopServiceNative(serverIf, entry.handle); 2291 return; 2292 } 2293 } 2294 } 2295 2296 private void deleteServices(int serverIf) { 2297 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2298 2299 /* 2300 * Figure out which handles to delete. 2301 * The handles are copied into a new list to avoid race conditions. 2302 */ 2303 List<Integer> handleList = new ArrayList<Integer>(); 2304 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2305 for(HandleMap.Entry entry : entries) { 2306 if (entry.type != HandleMap.TYPE_SERVICE || 2307 entry.serverIf != serverIf) 2308 continue; 2309 handleList.add(entry.handle); 2310 } 2311 2312 /* Now actually delete the services.... */ 2313 for(Integer handle : handleList) { 2314 gattServerDeleteServiceNative(serverIf, handle); 2315 } 2316 } 2317 2318 private List<UUID> parseUuids(byte[] adv_data) { 2319 List<UUID> uuids = new ArrayList<UUID>(); 2320 2321 int offset = 0; 2322 while(offset < (adv_data.length-2)) { 2323 int len = adv_data[offset++]; 2324 if (len == 0) break; 2325 2326 int type = adv_data[offset++]; 2327 switch (type) { 2328 case 0x02: // Partial list of 16-bit UUIDs 2329 case 0x03: // Complete list of 16-bit UUIDs 2330 while (len > 1) { 2331 int uuid16 = adv_data[offset++]; 2332 uuid16 += (adv_data[offset++] << 8); 2333 len -= 2; 2334 uuids.add(UUID.fromString(String.format( 2335 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2336 } 2337 break; 2338 2339 default: 2340 offset += (len - 1); 2341 break; 2342 } 2343 } 2344 2345 return uuids; 2346 } 2347 2348 @Override 2349 public void dump(StringBuilder sb) { 2350 super.dump(sb); 2351 println(sb, "mAdvertisingServiceUuids:"); 2352 for (UUID uuid : mAdvertisingServiceUuids) { 2353 println(sb, " " + uuid); 2354 } 2355 for (ServiceDeclaration declaration : mServiceDeclarations) { 2356 println(sb, " " + declaration); 2357 } 2358 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2359 2360 sb.append("\nGATT Client Map\n"); 2361 mClientMap.dump(sb); 2362 2363 sb.append("\nGATT Server Map\n"); 2364 mServerMap.dump(sb); 2365 2366 sb.append("\nGATT Handle Map\n"); 2367 mHandleMap.dump(sb); 2368 } 2369 2370 /************************************************************************** 2371 * GATT Test functions 2372 *************************************************************************/ 2373 2374 void gattTestCommand(int command, UUID uuid1, String bda1, 2375 int p1, int p2, int p3, int p4, int p5) { 2376 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2377 if (uuid1 != null) 2378 gattTestNative(command, uuid1.getLeastSignificantBits(), 2379 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2380 else 2381 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2382 } 2383 2384 private native void gattTestNative(int command, 2385 long uuid1_lsb, long uuid1_msb, String bda1, 2386 int p1, int p2, int p3, int p4, int p5); 2387 2388 /************************************************************************** 2389 * Native functions prototypes 2390 *************************************************************************/ 2391 2392 private native static void classInitNative(); 2393 private native void initializeNative(); 2394 private native void cleanupNative(); 2395 2396 private native int gattClientGetDeviceTypeNative(String address); 2397 2398 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2399 long app_uuid_msb); 2400 2401 private native void gattClientUnregisterAppNative(int clientIf); 2402 2403 private native void gattClientConnectNative(int clientIf, String address, 2404 boolean isDirect, int transport); 2405 2406 private native void gattClientDisconnectNative(int clientIf, String address, 2407 int conn_id); 2408 2409 private native void gattClientRefreshNative(int clientIf, String address); 2410 2411 private native void gattClientSearchServiceNative(int conn_id, 2412 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2413 2414 private native void gattClientGetCharacteristicNative(int conn_id, 2415 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2416 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2417 long char_id_uuid_msb); 2418 2419 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2420 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2421 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2422 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2423 2424 private native void gattClientGetIncludedServiceNative(int conn_id, 2425 int service_type, int service_id_inst_id, 2426 long service_id_uuid_lsb, long service_id_uuid_msb, 2427 int incl_service_id_inst_id, int incl_service_type, 2428 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2429 2430 private native void gattClientReadCharacteristicNative(int conn_id, 2431 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2432 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2433 long char_id_uuid_msb, int authReq); 2434 2435 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2436 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2437 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2438 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2439 int authReq); 2440 2441 private native void gattClientWriteCharacteristicNative(int conn_id, 2442 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2443 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2444 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2445 2446 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2447 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2448 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2449 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2450 int write_type, int auth_req, byte[] value); 2451 2452 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2453 2454 private native void gattClientRegisterForNotificationsNative(int clientIf, 2455 String address, int service_type, int service_id_inst_id, 2456 long service_id_uuid_lsb, long service_id_uuid_msb, 2457 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2458 boolean enable); 2459 2460 private native void gattClientReadRemoteRssiNative(int clientIf, 2461 String address); 2462 2463 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2464 2465 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2466 int minInterval, int maxInterval, int latency, int timeout); 2467 2468 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2469 long app_uuid_msb); 2470 2471 private native void gattServerUnregisterAppNative(int serverIf); 2472 2473 private native void gattServerConnectNative(int server_if, String address, 2474 boolean is_direct, int transport); 2475 2476 private native void gattServerDisconnectNative(int serverIf, String address, 2477 int conn_id); 2478 2479 private native void gattServerAddServiceNative (int server_if, 2480 int service_type, int service_id_inst_id, 2481 long service_id_uuid_lsb, long service_id_uuid_msb, 2482 int num_handles); 2483 2484 private native void gattServerAddIncludedServiceNative (int server_if, 2485 int svc_handle, int included_svc_handle); 2486 2487 private native void gattServerAddCharacteristicNative (int server_if, 2488 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2489 int properties, int permissions); 2490 2491 private native void gattServerAddDescriptorNative (int server_if, 2492 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2493 int permissions); 2494 2495 private native void gattServerStartServiceNative (int server_if, 2496 int svc_handle, int transport ); 2497 2498 private native void gattServerStopServiceNative (int server_if, 2499 int svc_handle); 2500 2501 private native void gattServerDeleteServiceNative (int server_if, 2502 int svc_handle); 2503 2504 private native void gattServerSendIndicationNative (int server_if, 2505 int attr_handle, int conn_id, byte[] val); 2506 2507 private native void gattServerSendNotificationNative (int server_if, 2508 int attr_handle, int conn_id, byte[] val); 2509 2510 private native void gattServerSendResponseNative (int server_if, 2511 int conn_id, int trans_id, int status, int handle, int offset, 2512 byte[] val, int auth_req); 2513} 2514