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