GattService.java revision 35e1ec3c673b81022339978a37f191b5ed67f065
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 void onScanParamSetupCompleted(int status, int clientIf) throws RemoteException { 1194 ClientMap.App app = mClientMap.getById(clientIf); 1195 if (app == null || app.callback == null) { 1196 Log.e(TAG, "Advertise app or callback is null"); 1197 return; 1198 } 1199 Log.d(TAG, "onScanParamSetupCompleted : " + status); 1200 } 1201 1202 // callback from AdvertiseManager for advertise status dispatch. 1203 void onMultipleAdvertiseCallback(int clientIf, int status, boolean isStart, 1204 AdvertiseSettings settings) throws RemoteException { 1205 ClientMap.App app = mClientMap.getById(clientIf); 1206 if (app == null || app.callback == null) { 1207 Log.e(TAG, "Advertise app or callback is null"); 1208 return; 1209 } 1210 app.callback.onMultiAdvertiseCallback(status, isStart, settings); 1211 } 1212 1213 // callback from ScanManager for dispatch of errors apps. 1214 void onScanManagerErrorCallback(int clientIf, int errorCode) throws RemoteException { 1215 ClientMap.App app = mClientMap.getById(clientIf); 1216 if (app == null || app.callback == null) { 1217 Log.e(TAG, "App or callback is null"); 1218 return; 1219 } 1220 app.callback.onScanManagerErrorCallback(errorCode); 1221 } 1222 1223 void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { 1224 String address = mClientMap.addressByConnId(connId); 1225 1226 if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" 1227 + status + ", mtu=" + mtu); 1228 1229 ClientMap.App app = mClientMap.getByConnId(connId); 1230 if (app != null) { 1231 app.callback.onConfigureMTU(address, mtu, status); 1232 } 1233 } 1234 1235 // Callback for standard advertising instance. 1236 void onAdvertiseCallback(int status, int clientIf) { 1237 if (DBG) Log.d(TAG, "onAdvertiseCallback,- clientIf=" + clientIf + ", status=" + status); 1238 mAdvertiseManager.callbackDone(clientIf, status); 1239 } 1240 1241 // Followings are callbacks for Bluetooth LE Advertise operations. 1242 // Start advertising flow is 1243 // enable advertising instance -> onAdvertiseInstaceEnabled 1244 // -> set advertise data -> onAdvertiseDataSet 1245 // -> set scan response -> onAdvertiseDataSet 1246 1247 // Callback when advertise instance is enabled. 1248 void onAdvertiseInstanceEnabled(int status, int clientIf) { 1249 if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - " 1250 + "clientIf=" + clientIf + ", status=" + status); 1251 mAdvertiseManager.callbackDone(clientIf, status); 1252 } 1253 1254 // Not really used. 1255 void onAdvertiseDataUpdated(int status, int client_if) { 1256 if (DBG) Log.d(TAG, "onAdvertiseDataUpdated() - client_if=" + client_if 1257 + ", status=" + status); 1258 } 1259 1260 // Callback when advertise data or scan response is set. 1261 void onAdvertiseDataSet(int status, int clientIf) { 1262 if (DBG) Log.d(TAG, "onAdvertiseDataSet() - clientIf=" + clientIf 1263 + ", status=" + status); 1264 mAdvertiseManager.callbackDone(clientIf, status); 1265 } 1266 1267 // Callback when advertise instance is disabled 1268 void onAdvertiseInstanceDisabled(int status, int clientIf) throws RemoteException { 1269 if (DBG) Log.d(TAG, "onAdvertiseInstanceDisabled() - clientIf=" + clientIf 1270 + ", status=" + status); 1271 ClientMap.App app = mClientMap.getById(clientIf); 1272 if (app != null) { 1273 Log.d(TAG, "Client app is not null!"); 1274 boolean isStart = false; 1275 if (status == 0) { 1276 app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS, 1277 isStart, null); 1278 } else { 1279 app.callback.onMultiAdvertiseCallback( 1280 AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR, isStart, null); 1281 } 1282 } 1283 } 1284 1285 void onClientCongestion(int connId, boolean congested) throws RemoteException { 1286 if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); 1287 1288 ClientMap.App app = mClientMap.getByConnId(connId); 1289 1290 if (app != null) { 1291 app.isCongested = congested; 1292 while(!app.isCongested) { 1293 CallbackInfo callbackInfo = app.popQueuedCallback(); 1294 if (callbackInfo == null) return; 1295 app.callback.onCharacteristicWrite(callbackInfo.address, 1296 callbackInfo.status, callbackInfo.srvcType, 1297 callbackInfo.srvcInstId, new ParcelUuid(callbackInfo.srvcUuid), 1298 callbackInfo.charInstId, new ParcelUuid(callbackInfo.charUuid)); 1299 } 1300 } 1301 } 1302 1303 /************************************************************************** 1304 * GATT Service functions - Shared CLIENT/SERVER 1305 *************************************************************************/ 1306 1307 List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 1308 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1309 1310 final int DEVICE_TYPE_BREDR = 0x1; 1311 1312 Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, 1313 Integer>(); 1314 1315 // Add paired LE devices 1316 1317 Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); 1318 for (BluetoothDevice device : bondedDevices) { 1319 if (getDeviceType(device) != DEVICE_TYPE_BREDR) { 1320 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED); 1321 } 1322 } 1323 1324 // Add connected deviceStates 1325 1326 Set<String> connectedDevices = new HashSet<String>(); 1327 connectedDevices.addAll(mClientMap.getConnectedDevices()); 1328 connectedDevices.addAll(mServerMap.getConnectedDevices()); 1329 1330 for (String address : connectedDevices ) { 1331 BluetoothDevice device = mAdapter.getRemoteDevice(address); 1332 if (device != null) { 1333 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED); 1334 } 1335 } 1336 1337 // Create matching device sub-set 1338 1339 List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>(); 1340 1341 for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) { 1342 for(int state : states) { 1343 if (entry.getValue() == state) { 1344 deviceList.add(entry.getKey()); 1345 } 1346 } 1347 } 1348 1349 return deviceList; 1350 } 1351 1352 void startScan(int appIf, boolean isServer, ScanSettings settings, 1353 List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages) { 1354 if (DBG) Log.d(TAG, "start scan with filters"); 1355 enforceAdminPermission(); 1356 if (needsPrivilegedPermissionForScan(settings)) { 1357 enforcePrivilegedPermission(); 1358 } 1359 mScanManager.startScan(new ScanClient(appIf, isServer, settings, filters, storages)); 1360 } 1361 1362 void flushPendingBatchResults(int clientIf, boolean isServer) { 1363 if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + 1364 ", isServer=" + isServer); 1365 mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); 1366 } 1367 1368 void stopScan(ScanClient client) { 1369 enforceAdminPermission(); 1370 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1371 mScanManager.getRegularScanQueue().size(); 1372 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1373 mScanManager.stopScan(client); 1374 } 1375 1376 void disconnectAll() { 1377 if (DBG) Log.d(TAG, "disconnectAll()"); 1378 Map<Integer, String> connMap = mClientMap.getConnectedMap(); 1379 for(Map.Entry<Integer, String> entry:connMap.entrySet()){ 1380 if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue()); 1381 clientDisconnect(entry.getKey(), entry.getValue()); 1382 //clientDisconnect(int clientIf, String address) 1383 } 1384 } 1385 1386 void unregAll() { 1387 for(ClientMap.App app:mClientMap.mApps){ 1388 if (DBG) Log.d(TAG, "unreg:" + app.id); 1389 unregisterClient(app.id); 1390 } 1391 } 1392 1393 /************************************************************************** 1394 * GATT Service functions - CLIENT 1395 *************************************************************************/ 1396 1397 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1398 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1399 1400 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1401 mClientMap.add(uuid, callback); 1402 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1403 uuid.getMostSignificantBits()); 1404 } 1405 1406 void unregisterClient(int clientIf) { 1407 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1408 1409 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1410 mClientMap.remove(clientIf); 1411 gattClientUnregisterAppNative(clientIf); 1412 } 1413 1414 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1415 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1416 1417 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1418 gattClientConnectNative(clientIf, address, isDirect, transport); 1419 } 1420 1421 void clientDisconnect(int clientIf, String address) { 1422 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1423 1424 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1425 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1426 1427 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1428 } 1429 1430 void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 1431 AdvertiseData scanResponse, AdvertiseSettings settings) { 1432 enforceAdminPermission(); 1433 mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData, 1434 scanResponse)); 1435 } 1436 1437 void stopMultiAdvertising(AdvertiseClient client) { 1438 enforceAdminPermission(); 1439 mAdvertiseManager.stopAdvertising(client); 1440 } 1441 1442 int numHwTrackFiltersAvailable() { 1443 return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() 1444 - mScanManager.getCurrentUsedTrackingAdvertisement()); 1445 } 1446 1447 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1448 Utils.enforceAdminPermission(this); 1449 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1450 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1451 serviceUuids.add(new ParcelUuid(entry.uuid)); 1452 } 1453 return serviceUuids; 1454 } 1455 1456 List<String> getConnectedDevices() { 1457 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1458 1459 Set<String> connectedDevAddress = new HashSet<String>(); 1460 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1461 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1462 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1463 return connectedDeviceList; 1464 } 1465 1466 void refreshDevice(int clientIf, String address) { 1467 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1468 1469 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1470 gattClientRefreshNative(clientIf, address); 1471 } 1472 1473 void discoverServices(int clientIf, String address) { 1474 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1475 1476 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1477 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1478 1479 if (connId != null) 1480 gattClientSearchServiceNative(connId, true, 0, 0); 1481 else 1482 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1483 } 1484 1485 void readCharacteristic(int clientIf, String address, int srvcType, 1486 int srvcInstanceId, UUID srvcUuid, 1487 int charInstanceId, UUID charUuid, int authReq) { 1488 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1489 if (isHidUuid(charUuid)) enforcePrivilegedPermission(); 1490 1491 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1492 1493 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1494 if (connId != null) 1495 gattClientReadCharacteristicNative(connId, srvcType, 1496 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1497 srvcUuid.getMostSignificantBits(), charInstanceId, 1498 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1499 authReq); 1500 else 1501 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1502 } 1503 1504 void writeCharacteristic(int clientIf, String address, int srvcType, 1505 int srvcInstanceId, UUID srvcUuid, 1506 int charInstanceId, UUID charUuid, int writeType, 1507 int authReq, byte[] value) { 1508 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1509 if (isHidUuid(charUuid)) enforcePrivilegedPermission(); 1510 1511 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1512 1513 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1514 1515 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1516 if (connId != null) 1517 gattClientWriteCharacteristicNative(connId, srvcType, 1518 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1519 srvcUuid.getMostSignificantBits(), charInstanceId, 1520 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1521 writeType, authReq, value); 1522 else 1523 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1524 } 1525 1526 void readDescriptor(int clientIf, String address, int srvcType, 1527 int srvcInstanceId, UUID srvcUuid, 1528 int charInstanceId, UUID charUuid, 1529 int descrInstanceId, UUID descrUuid, 1530 int authReq) { 1531 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1532 if (isHidUuid(charUuid)) enforcePrivilegedPermission(); 1533 1534 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1535 1536 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1537 if (connId != null) 1538 gattClientReadDescriptorNative(connId, srvcType, 1539 srvcInstanceId, 1540 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1541 charInstanceId, 1542 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1543 descrInstanceId, 1544 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1545 authReq); 1546 else 1547 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1548 }; 1549 1550 void writeDescriptor(int clientIf, String address, int srvcType, 1551 int srvcInstanceId, UUID srvcUuid, 1552 int charInstanceId, UUID charUuid, 1553 int descrInstanceId, UUID descrUuid, 1554 int writeType, int authReq, byte[] value) { 1555 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1556 if (isHidUuid(charUuid)) enforcePrivilegedPermission(); 1557 1558 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1559 1560 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1561 if (connId != null) 1562 gattClientWriteDescriptorNative(connId, srvcType, 1563 srvcInstanceId, 1564 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1565 charInstanceId, 1566 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1567 descrInstanceId, 1568 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1569 writeType, authReq, value); 1570 else 1571 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1572 } 1573 1574 void beginReliableWrite(int clientIf, String address) { 1575 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1576 1577 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1578 mReliableQueue.add(address); 1579 } 1580 1581 void endReliableWrite(int clientIf, String address, boolean execute) { 1582 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1583 1584 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1585 + " execute: " + execute); 1586 mReliableQueue.remove(address); 1587 1588 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1589 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1590 } 1591 1592 void registerForNotification(int clientIf, String address, int srvcType, 1593 int srvcInstanceId, UUID srvcUuid, 1594 int charInstanceId, UUID charUuid, 1595 boolean enable) { 1596 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1597 if (isHidUuid(charUuid)) enforcePrivilegedPermission(); 1598 1599 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1600 1601 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1602 if (connId != null) { 1603 gattClientRegisterForNotificationsNative(clientIf, address, 1604 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1605 srvcUuid.getMostSignificantBits(), charInstanceId, 1606 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1607 enable); 1608 } else { 1609 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1610 } 1611 } 1612 1613 void readRemoteRssi(int clientIf, String address) { 1614 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1615 1616 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1617 gattClientReadRemoteRssiNative(clientIf, address); 1618 } 1619 1620 void configureMTU(int clientIf, String address, int mtu) { 1621 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1622 1623 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1624 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1625 if (connId != null) { 1626 gattClientConfigureMTUNative(connId, mtu); 1627 } else { 1628 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1629 } 1630 } 1631 1632 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1633 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1634 1635 // Default spec recommended interval is 30->50 ms 1636 int minInterval = 24; // 24 * 1.25ms = 30ms 1637 int maxInterval = 40; // 40 * 1.25ms = 50ms 1638 1639 // Slave latency 1640 int latency = 0; 1641 1642 // Link supervision timeout is measured in N * 10ms 1643 int timeout = 2000; // 20s 1644 1645 switch (connectionPriority) 1646 { 1647 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1648 minInterval = 9; // 11.25ms 1649 maxInterval = 12; // 15ms 1650 break; 1651 1652 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 1653 minInterval = 80; // 100ms 1654 maxInterval = 100; // 125ms 1655 latency = 2; 1656 break; 1657 } 1658 1659 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1660 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1661 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1662 latency, timeout); 1663 } 1664 1665 /************************************************************************** 1666 * Callback functions - SERVER 1667 *************************************************************************/ 1668 1669 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1670 throws RemoteException { 1671 1672 UUID uuid = new UUID(uuidMsb, uuidLsb); 1673 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1674 ServerMap.App app = mServerMap.getByUuid(uuid); 1675 if (app != null) { 1676 app.id = serverIf; 1677 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1678 app.callback.onServerRegistered(status, serverIf); 1679 } 1680 } 1681 1682 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1683 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1684 throws RemoteException { 1685 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1686 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1687 + ", handle=" + srvcHandle); 1688 if (status == 0) { 1689 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1690 mAdvertisingServiceUuids.remove(uuid)); 1691 } 1692 1693 continueServiceDeclaration(serverIf, status, srvcHandle); 1694 } 1695 1696 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1697 int includedSrvcHandle) throws RemoteException { 1698 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1699 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1700 continueServiceDeclaration(serverIf, status, srvcHandle); 1701 } 1702 1703 void onCharacteristicAdded(int status, int serverIf, 1704 long charUuidLsb, long charUuidMsb, 1705 int srvcHandle, int charHandle) 1706 throws RemoteException { 1707 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1708 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1709 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1710 if (status == 0) 1711 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1712 continueServiceDeclaration(serverIf, status, srvcHandle); 1713 } 1714 1715 void onDescriptorAdded(int status, int serverIf, 1716 long descrUuidLsb, long descrUuidMsb, 1717 int srvcHandle, int descrHandle) 1718 throws RemoteException { 1719 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1720 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1721 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1722 if (status == 0) 1723 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1724 continueServiceDeclaration(serverIf, status, srvcHandle); 1725 } 1726 1727 void onServiceStarted(int status, int serverIf, int srvcHandle) 1728 throws RemoteException { 1729 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1730 + ", status=" + status); 1731 if (status == 0) 1732 mHandleMap.setStarted(serverIf, srvcHandle, true); 1733 } 1734 1735 void onServiceStopped(int status, int serverIf, int srvcHandle) 1736 throws RemoteException { 1737 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1738 + ", status=" + status); 1739 if (status == 0) 1740 mHandleMap.setStarted(serverIf, srvcHandle, false); 1741 stopNextService(serverIf, status); 1742 } 1743 1744 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1745 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1746 + ", status=" + status); 1747 mHandleMap.deleteService(serverIf, srvcHandle); 1748 } 1749 1750 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1751 throws RemoteException { 1752 1753 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1754 + ", address=" + address + ", connected=" + connected); 1755 1756 ServerMap.App app = mServerMap.getById(serverIf); 1757 if (app == null) return; 1758 1759 if (connected) { 1760 mServerMap.addConnection(serverIf, connId, address); 1761 } else { 1762 mServerMap.removeConnection(serverIf, connId); 1763 } 1764 1765 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1766 } 1767 1768 void onAttributeRead(String address, int connId, int transId, 1769 int attrHandle, int offset, boolean isLong) 1770 throws RemoteException { 1771 if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1772 + ", address=" + address + ", handle=" + attrHandle 1773 + ", requestId=" + transId + ", offset=" + offset); 1774 1775 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1776 if (entry == null) return; 1777 1778 mHandleMap.addRequest(transId, attrHandle); 1779 1780 ServerMap.App app = mServerMap.getById(entry.serverIf); 1781 if (app == null) return; 1782 1783 switch(entry.type) { 1784 case HandleMap.TYPE_CHARACTERISTIC: 1785 { 1786 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1787 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1788 serviceEntry.serviceType, serviceEntry.instance, 1789 new ParcelUuid(serviceEntry.uuid), entry.instance, 1790 new ParcelUuid(entry.uuid)); 1791 break; 1792 } 1793 1794 case HandleMap.TYPE_DESCRIPTOR: 1795 { 1796 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1797 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1798 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1799 serviceEntry.serviceType, serviceEntry.instance, 1800 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1801 new ParcelUuid(charEntry.uuid), 1802 new ParcelUuid(entry.uuid)); 1803 break; 1804 } 1805 1806 default: 1807 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1808 break; 1809 } 1810 } 1811 1812 void onAttributeWrite(String address, int connId, int transId, 1813 int attrHandle, int offset, int length, 1814 boolean needRsp, boolean isPrep, 1815 byte[] data) 1816 throws RemoteException { 1817 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1818 + ", address=" + address + ", handle=" + attrHandle 1819 + ", requestId=" + transId + ", isPrep=" + isPrep 1820 + ", offset=" + offset); 1821 1822 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1823 if (entry == null) return; 1824 1825 mHandleMap.addRequest(transId, attrHandle); 1826 1827 ServerMap.App app = mServerMap.getById(entry.serverIf); 1828 if (app == null) return; 1829 1830 switch(entry.type) { 1831 case HandleMap.TYPE_CHARACTERISTIC: 1832 { 1833 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1834 app.callback.onCharacteristicWriteRequest(address, transId, 1835 offset, length, isPrep, needRsp, 1836 serviceEntry.serviceType, serviceEntry.instance, 1837 new ParcelUuid(serviceEntry.uuid), entry.instance, 1838 new ParcelUuid(entry.uuid), data); 1839 break; 1840 } 1841 1842 case HandleMap.TYPE_DESCRIPTOR: 1843 { 1844 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1845 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1846 app.callback.onDescriptorWriteRequest(address, transId, 1847 offset, length, isPrep, needRsp, 1848 serviceEntry.serviceType, serviceEntry.instance, 1849 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1850 new ParcelUuid(charEntry.uuid), 1851 new ParcelUuid(entry.uuid), data); 1852 break; 1853 } 1854 1855 default: 1856 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1857 break; 1858 } 1859 } 1860 1861 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1862 throws RemoteException { 1863 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1864 + ", address=" + address + ", transId=" + transId); 1865 1866 ServerMap.App app = mServerMap.getByConnId(connId); 1867 if (app == null) return; 1868 1869 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1870 } 1871 1872 void onResponseSendCompleted(int status, int attrHandle) { 1873 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1874 } 1875 1876 void onNotificationSent(int connId, int status) throws RemoteException { 1877 if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1878 1879 String address = mServerMap.addressByConnId(connId); 1880 if (address == null) return; 1881 1882 ServerMap.App app = mServerMap.getByConnId(connId); 1883 if (app == null) return; 1884 1885 if (!app.isCongested) { 1886 app.callback.onNotificationSent(address, status); 1887 } else { 1888 if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { 1889 status = BluetoothGatt.GATT_SUCCESS; 1890 } 1891 app.queueCallback(new CallbackInfo(address, status)); 1892 } 1893 } 1894 1895 void onServerCongestion(int connId, boolean congested) throws RemoteException { 1896 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1897 1898 ServerMap.App app = mServerMap.getByConnId(connId); 1899 if (app == null) return; 1900 1901 app.isCongested = congested; 1902 while(!app.isCongested) { 1903 CallbackInfo callbackInfo = app.popQueuedCallback(); 1904 if (callbackInfo == null) return; 1905 app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); 1906 } 1907 } 1908 1909 void onMtuChanged(int connId, int mtu) throws RemoteException { 1910 if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); 1911 1912 String address = mServerMap.addressByConnId(connId); 1913 if (address == null) return; 1914 1915 ServerMap.App app = mServerMap.getByConnId(connId); 1916 if (app == null) return; 1917 1918 app.callback.onMtuChanged(address, mtu); 1919 } 1920 1921 /************************************************************************** 1922 * GATT Service functions - SERVER 1923 *************************************************************************/ 1924 1925 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1926 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1927 1928 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1929 mServerMap.add(uuid, callback); 1930 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1931 uuid.getMostSignificantBits()); 1932 } 1933 1934 void unregisterServer(int serverIf) { 1935 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1936 1937 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1938 1939 deleteServices(serverIf); 1940 1941 mServerMap.remove(serverIf); 1942 gattServerUnregisterAppNative(serverIf); 1943 } 1944 1945 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1946 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1947 1948 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1949 gattServerConnectNative(serverIf, address, isDirect,transport); 1950 } 1951 1952 void serverDisconnect(int serverIf, String address) { 1953 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1954 1955 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1956 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1957 1958 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1959 } 1960 1961 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1962 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1963 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1964 1965 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1966 ServiceDeclaration serviceDeclaration = addDeclaration(); 1967 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1968 advertisePreferred); 1969 } 1970 1971 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1972 UUID srvcUuid) { 1973 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1974 1975 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1976 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1977 } 1978 1979 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1980 int permissions) { 1981 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1982 1983 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1984 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1985 } 1986 1987 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1988 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1989 1990 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1991 getActiveDeclaration().addDescriptor(descUuid, permissions); 1992 } 1993 1994 void endServiceDeclaration(int serverIf) { 1995 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1996 1997 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1998 1999 if (getActiveDeclaration() == getPendingDeclaration()) { 2000 try { 2001 continueServiceDeclaration(serverIf, (byte)0, 0); 2002 } catch (RemoteException e) { 2003 Log.e(TAG,""+e); 2004 } 2005 } 2006 } 2007 2008 void removeService(int serverIf, int srvcType, 2009 int srvcInstanceId, UUID srvcUuid) { 2010 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2011 2012 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 2013 2014 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2015 if (srvcHandle == 0) return; 2016 gattServerDeleteServiceNative(serverIf, srvcHandle); 2017 } 2018 2019 void clearServices(int serverIf) { 2020 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2021 2022 if (DBG) Log.d(TAG, "clearServices()"); 2023 deleteServices(serverIf); 2024 } 2025 2026 void sendResponse(int serverIf, String address, int requestId, 2027 int status, int offset, byte[] value) { 2028 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2029 2030 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 2031 2032 int handle = 0; 2033 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2034 if (entry != null) handle = entry.handle; 2035 2036 int connId = mServerMap.connIdByAddress(serverIf, address); 2037 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2038 handle, offset, value, (byte)0); 2039 mHandleMap.deleteRequest(requestId); 2040 } 2041 2042 void sendNotification(int serverIf, String address, int srvcType, 2043 int srvcInstanceId, UUID srvcUuid, 2044 int charInstanceId, UUID charUuid, 2045 boolean confirm, byte[] value) { 2046 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2047 2048 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address); 2049 2050 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2051 if (srvcHandle == 0) return; 2052 2053 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 2054 if (charHandle == 0) return; 2055 2056 int connId = mServerMap.connIdByAddress(serverIf, address); 2057 if (connId == 0) return; 2058 2059 if (confirm) { 2060 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 2061 } else { 2062 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 2063 } 2064 } 2065 2066 2067 /************************************************************************** 2068 * Private functions 2069 *************************************************************************/ 2070 2071 private boolean isHidUuid(final UUID uuid) { 2072 for (UUID hid_uuid : HID_UUIDS) { 2073 if (hid_uuid.equals(uuid)) return true; 2074 } 2075 return false; 2076 } 2077 2078 private int getDeviceType(BluetoothDevice device) { 2079 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2080 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2081 + ", type=" + type); 2082 return type; 2083 } 2084 2085 private void enforceAdminPermission() { 2086 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2087 } 2088 2089 private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { 2090 // Regular scan, no special permission. 2091 if (settings == null) { 2092 return false; 2093 } 2094 // Regular scan, no special permission. 2095 if (settings.getReportDelayMillis() == 0) { 2096 return false; 2097 } 2098 // Batch scan, truncated mode needs permission. 2099 return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; 2100 } 2101 2102 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2103 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2104 private void enforcePrivilegedPermission() { 2105 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2106 "Need BLUETOOTH_PRIVILEGED permission"); 2107 } 2108 2109 private void continueSearch(int connId, int status) throws RemoteException { 2110 if (status == 0 && !mSearchQueue.isEmpty()) { 2111 SearchQueue.Entry svc = mSearchQueue.pop(); 2112 2113 if (svc.charUuidLsb == 0) { 2114 // Characteristic is up next 2115 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 2116 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 2117 } else { 2118 // Descriptor is up next 2119 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 2120 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 2121 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 2122 } 2123 } else { 2124 ClientMap.App app = mClientMap.getByConnId(connId); 2125 if (app != null) { 2126 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 2127 } 2128 } 2129 } 2130 2131 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 2132 if (mServiceDeclarations.size() == 0) return; 2133 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 2134 2135 boolean finished = false; 2136 2137 ServiceDeclaration.Entry entry = null; 2138 if (status == 0) 2139 entry = getPendingDeclaration().getNext(); 2140 2141 if (entry != null) { 2142 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 2143 + entry.type); 2144 switch(entry.type) { 2145 case ServiceDeclaration.TYPE_SERVICE: 2146 if (entry.advertisePreferred) { 2147 mAdvertisingServiceUuids.add(entry.uuid); 2148 } 2149 gattServerAddServiceNative(serverIf, entry.serviceType, 2150 entry.instance, 2151 entry.uuid.getLeastSignificantBits(), 2152 entry.uuid.getMostSignificantBits(), 2153 getPendingDeclaration().getNumHandles()); 2154 break; 2155 2156 case ServiceDeclaration.TYPE_CHARACTERISTIC: 2157 gattServerAddCharacteristicNative(serverIf, srvcHandle, 2158 entry.uuid.getLeastSignificantBits(), 2159 entry.uuid.getMostSignificantBits(), 2160 entry.properties, entry.permissions); 2161 break; 2162 2163 case ServiceDeclaration.TYPE_DESCRIPTOR: 2164 gattServerAddDescriptorNative(serverIf, srvcHandle, 2165 entry.uuid.getLeastSignificantBits(), 2166 entry.uuid.getMostSignificantBits(), 2167 entry.permissions); 2168 break; 2169 2170 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2171 { 2172 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2173 entry.serviceType, entry.instance); 2174 if (inclSrvc != 0) { 2175 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2176 inclSrvc); 2177 } else { 2178 finished = true; 2179 } 2180 break; 2181 } 2182 } 2183 } else { 2184 gattServerStartServiceNative(serverIf, srvcHandle, 2185 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2186 finished = true; 2187 } 2188 2189 if (finished) { 2190 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2191 ServerMap.App app = mServerMap.getById(serverIf); 2192 if (app != null) { 2193 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2194 2195 if (serviceEntry != null) { 2196 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2197 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2198 } else { 2199 app.callback.onServiceAdded(status, 0, 0, null); 2200 } 2201 } 2202 removePendingDeclaration(); 2203 2204 if (getPendingDeclaration() != null) { 2205 continueServiceDeclaration(serverIf, (byte)0, 0); 2206 } 2207 } 2208 } 2209 2210 private void stopNextService(int serverIf, int status) throws RemoteException { 2211 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2212 + ", status=" + status); 2213 2214 if (status == 0) { 2215 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2216 for(HandleMap.Entry entry : entries) { 2217 if (entry.type != HandleMap.TYPE_SERVICE || 2218 entry.serverIf != serverIf || 2219 entry.started == false) 2220 continue; 2221 2222 gattServerStopServiceNative(serverIf, entry.handle); 2223 return; 2224 } 2225 } 2226 } 2227 2228 private void deleteServices(int serverIf) { 2229 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2230 2231 /* 2232 * Figure out which handles to delete. 2233 * The handles are copied into a new list to avoid race conditions. 2234 */ 2235 List<Integer> handleList = new ArrayList<Integer>(); 2236 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2237 for(HandleMap.Entry entry : entries) { 2238 if (entry.type != HandleMap.TYPE_SERVICE || 2239 entry.serverIf != serverIf) 2240 continue; 2241 handleList.add(entry.handle); 2242 } 2243 2244 /* Now actually delete the services.... */ 2245 for(Integer handle : handleList) { 2246 gattServerDeleteServiceNative(serverIf, handle); 2247 } 2248 } 2249 2250 private List<UUID> parseUuids(byte[] adv_data) { 2251 List<UUID> uuids = new ArrayList<UUID>(); 2252 2253 int offset = 0; 2254 while(offset < (adv_data.length-2)) { 2255 int len = adv_data[offset++]; 2256 if (len == 0) break; 2257 2258 int type = adv_data[offset++]; 2259 switch (type) { 2260 case 0x02: // Partial list of 16-bit UUIDs 2261 case 0x03: // Complete list of 16-bit UUIDs 2262 while (len > 1) { 2263 int uuid16 = adv_data[offset++]; 2264 uuid16 += (adv_data[offset++] << 8); 2265 len -= 2; 2266 uuids.add(UUID.fromString(String.format( 2267 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2268 } 2269 break; 2270 2271 default: 2272 offset += (len - 1); 2273 break; 2274 } 2275 } 2276 2277 return uuids; 2278 } 2279 2280 @Override 2281 public void dump(StringBuilder sb) { 2282 super.dump(sb); 2283 println(sb, "mAdvertisingServiceUuids:"); 2284 for (UUID uuid : mAdvertisingServiceUuids) { 2285 println(sb, " " + uuid); 2286 } 2287 for (ServiceDeclaration declaration : mServiceDeclarations) { 2288 println(sb, " " + declaration); 2289 } 2290 println(sb, "mMaxScanFilters: " + mMaxScanFilters); 2291 2292 sb.append("\nGATT Client Map\n"); 2293 mClientMap.dump(sb); 2294 2295 sb.append("\nGATT Server Map\n"); 2296 mServerMap.dump(sb); 2297 2298 sb.append("\nGATT Handle Map\n"); 2299 mHandleMap.dump(sb); 2300 } 2301 2302 /************************************************************************** 2303 * GATT Test functions 2304 *************************************************************************/ 2305 2306 void gattTestCommand(int command, UUID uuid1, String bda1, 2307 int p1, int p2, int p3, int p4, int p5) { 2308 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2309 if (uuid1 != null) 2310 gattTestNative(command, uuid1.getLeastSignificantBits(), 2311 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2312 else 2313 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2314 } 2315 2316 private native void gattTestNative(int command, 2317 long uuid1_lsb, long uuid1_msb, String bda1, 2318 int p1, int p2, int p3, int p4, int p5); 2319 2320 /************************************************************************** 2321 * Native functions prototypes 2322 *************************************************************************/ 2323 2324 private native static void classInitNative(); 2325 private native void initializeNative(); 2326 private native void cleanupNative(); 2327 2328 private native int gattClientGetDeviceTypeNative(String address); 2329 2330 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2331 long app_uuid_msb); 2332 2333 private native void gattClientUnregisterAppNative(int clientIf); 2334 2335 private native void gattClientConnectNative(int clientIf, String address, 2336 boolean isDirect, int transport); 2337 2338 private native void gattClientDisconnectNative(int clientIf, String address, 2339 int conn_id); 2340 2341 private native void gattClientRefreshNative(int clientIf, String address); 2342 2343 private native void gattClientSearchServiceNative(int conn_id, 2344 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2345 2346 private native void gattClientGetCharacteristicNative(int conn_id, 2347 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2348 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2349 long char_id_uuid_msb); 2350 2351 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2352 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2353 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2354 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2355 2356 private native void gattClientGetIncludedServiceNative(int conn_id, 2357 int service_type, int service_id_inst_id, 2358 long service_id_uuid_lsb, long service_id_uuid_msb, 2359 int incl_service_id_inst_id, int incl_service_type, 2360 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2361 2362 private native void gattClientReadCharacteristicNative(int conn_id, 2363 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2364 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2365 long char_id_uuid_msb, int authReq); 2366 2367 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2368 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2369 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2370 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2371 int authReq); 2372 2373 private native void gattClientWriteCharacteristicNative(int conn_id, 2374 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2375 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2376 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2377 2378 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2379 int service_id_inst_id, 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 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2382 int write_type, int auth_req, byte[] value); 2383 2384 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2385 2386 private native void gattClientRegisterForNotificationsNative(int clientIf, 2387 String address, int service_type, int service_id_inst_id, 2388 long service_id_uuid_lsb, long service_id_uuid_msb, 2389 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2390 boolean enable); 2391 2392 private native void gattClientReadRemoteRssiNative(int clientIf, 2393 String address); 2394 2395 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2396 2397 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2398 int minInterval, int maxInterval, int latency, int timeout); 2399 2400 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2401 long app_uuid_msb); 2402 2403 private native void gattServerUnregisterAppNative(int serverIf); 2404 2405 private native void gattServerConnectNative(int server_if, String address, 2406 boolean is_direct, int transport); 2407 2408 private native void gattServerDisconnectNative(int serverIf, String address, 2409 int conn_id); 2410 2411 private native void gattServerAddServiceNative (int server_if, 2412 int service_type, int service_id_inst_id, 2413 long service_id_uuid_lsb, long service_id_uuid_msb, 2414 int num_handles); 2415 2416 private native void gattServerAddIncludedServiceNative (int server_if, 2417 int svc_handle, int included_svc_handle); 2418 2419 private native void gattServerAddCharacteristicNative (int server_if, 2420 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2421 int properties, int permissions); 2422 2423 private native void gattServerAddDescriptorNative (int server_if, 2424 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2425 int permissions); 2426 2427 private native void gattServerStartServiceNative (int server_if, 2428 int svc_handle, int transport ); 2429 2430 private native void gattServerStopServiceNative (int server_if, 2431 int svc_handle); 2432 2433 private native void gattServerDeleteServiceNative (int server_if, 2434 int svc_handle); 2435 2436 private native void gattServerSendIndicationNative (int server_if, 2437 int attr_handle, int conn_id, byte[] val); 2438 2439 private native void gattServerSendNotificationNative (int server_if, 2440 int attr_handle, int conn_id, byte[] val); 2441 2442 private native void gattServerSendResponseNative (int server_if, 2443 int conn_id, int trans_id, int status, int handle, int offset, 2444 byte[] val, int auth_req); 2445} 2446