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