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