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