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