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