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