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