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