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