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