GattService.java revision 5ca43226937e098a2404d61de3f991af5c6a2689
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 mScanManager.startScan(new ScanClient(appIf, isServer, settings, filters, storages)); 1278 } 1279 1280 void flushPendingBatchResults(int clientIf, boolean isServer) { 1281 if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf + 1282 ", isServer=" + isServer); 1283 mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer)); 1284 } 1285 1286 void stopScan(ScanClient client) { 1287 enforceAdminPermission(); 1288 int scanQueueSize = mScanManager.getBatchScanQueue().size() + 1289 mScanManager.getRegularScanQueue().size(); 1290 if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); 1291 mScanManager.stopScan(client); 1292 } 1293 1294 /************************************************************************** 1295 * GATT Service functions - CLIENT 1296 *************************************************************************/ 1297 1298 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1299 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1300 1301 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1302 mClientMap.add(uuid, callback); 1303 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1304 uuid.getMostSignificantBits()); 1305 } 1306 1307 void unregisterClient(int clientIf) { 1308 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1309 1310 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1311 mClientMap.remove(clientIf); 1312 gattClientUnregisterAppNative(clientIf); 1313 } 1314 1315 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1316 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1317 1318 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1319 gattClientConnectNative(clientIf, address, isDirect, transport); 1320 } 1321 1322 void clientDisconnect(int clientIf, String address) { 1323 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1324 1325 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1326 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1327 1328 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1329 } 1330 1331 void startMultiAdvertising(int clientIf, AdvertiseData advertiseData, 1332 AdvertiseData scanResponse, AdvertiseSettings settings) { 1333 enforceAdminPermission(); 1334 mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData, 1335 scanResponse)); 1336 } 1337 1338 void stopMultiAdvertising(AdvertiseClient client) { 1339 enforceAdminPermission(); 1340 mAdvertiseManager.stopAdvertising(client); 1341 } 1342 1343 1344 synchronized List<ParcelUuid> getRegisteredServiceUuids() { 1345 Utils.enforceAdminPermission(this); 1346 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1347 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1348 serviceUuids.add(new ParcelUuid(entry.uuid)); 1349 } 1350 return serviceUuids; 1351 } 1352 1353 List<String> getConnectedDevices() { 1354 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1355 1356 Set<String> connectedDevAddress = new HashSet<String>(); 1357 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1358 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1359 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1360 return connectedDeviceList; 1361 } 1362 1363 void refreshDevice(int clientIf, String address) { 1364 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1365 1366 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1367 gattClientRefreshNative(clientIf, address); 1368 } 1369 1370 void discoverServices(int clientIf, String address) { 1371 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1372 1373 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1374 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1375 1376 if (connId != null) 1377 gattClientSearchServiceNative(connId, true, 0, 0); 1378 else 1379 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1380 } 1381 1382 void readCharacteristic(int clientIf, String address, int srvcType, 1383 int srvcInstanceId, UUID srvcUuid, 1384 int charInstanceId, UUID charUuid, int authReq) { 1385 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1386 1387 if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1388 1389 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1390 if (connId != null) 1391 gattClientReadCharacteristicNative(connId, srvcType, 1392 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1393 srvcUuid.getMostSignificantBits(), charInstanceId, 1394 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1395 authReq); 1396 else 1397 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1398 } 1399 1400 void writeCharacteristic(int clientIf, String address, int srvcType, 1401 int srvcInstanceId, UUID srvcUuid, 1402 int charInstanceId, UUID charUuid, int writeType, 1403 int authReq, byte[] value) { 1404 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1405 1406 if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1407 1408 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1409 1410 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1411 if (connId != null) 1412 gattClientWriteCharacteristicNative(connId, srvcType, 1413 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1414 srvcUuid.getMostSignificantBits(), charInstanceId, 1415 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1416 writeType, authReq, value); 1417 else 1418 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1419 } 1420 1421 void readDescriptor(int clientIf, String address, int srvcType, 1422 int srvcInstanceId, UUID srvcUuid, 1423 int charInstanceId, UUID charUuid, 1424 int descrInstanceId, UUID descrUuid, 1425 int authReq) { 1426 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1427 1428 if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address); 1429 1430 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1431 if (connId != null) 1432 gattClientReadDescriptorNative(connId, srvcType, 1433 srvcInstanceId, 1434 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1435 charInstanceId, 1436 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1437 descrInstanceId, 1438 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1439 authReq); 1440 else 1441 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1442 }; 1443 1444 void writeDescriptor(int clientIf, String address, int srvcType, 1445 int srvcInstanceId, UUID srvcUuid, 1446 int charInstanceId, UUID charUuid, 1447 int descrInstanceId, UUID descrUuid, 1448 int writeType, int authReq, byte[] value) { 1449 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1450 1451 if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1452 1453 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1454 if (connId != null) 1455 gattClientWriteDescriptorNative(connId, srvcType, 1456 srvcInstanceId, 1457 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1458 charInstanceId, 1459 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1460 descrInstanceId, 1461 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1462 writeType, authReq, value); 1463 else 1464 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1465 } 1466 1467 void beginReliableWrite(int clientIf, String address) { 1468 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1469 1470 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1471 mReliableQueue.add(address); 1472 } 1473 1474 void endReliableWrite(int clientIf, String address, boolean execute) { 1475 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1476 1477 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1478 + " execute: " + execute); 1479 mReliableQueue.remove(address); 1480 1481 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1482 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1483 } 1484 1485 void registerForNotification(int clientIf, String address, int srvcType, 1486 int srvcInstanceId, UUID srvcUuid, 1487 int charInstanceId, UUID charUuid, 1488 boolean enable) { 1489 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1490 1491 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1492 1493 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1494 if (connId != null) { 1495 gattClientRegisterForNotificationsNative(clientIf, address, 1496 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1497 srvcUuid.getMostSignificantBits(), charInstanceId, 1498 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1499 enable); 1500 } else { 1501 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1502 } 1503 } 1504 1505 void readRemoteRssi(int clientIf, String address) { 1506 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1507 1508 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1509 gattClientReadRemoteRssiNative(clientIf, address); 1510 } 1511 1512 void configureMTU(int clientIf, String address, int mtu) { 1513 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1514 1515 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1516 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1517 if (connId != null) { 1518 gattClientConfigureMTUNative(connId, mtu); 1519 } else { 1520 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1521 } 1522 } 1523 1524 void connectionParameterUpdate(int clientIf, String address, int connectionPriority) { 1525 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1526 1527 // Default spec recommended interval is 30->50 ms 1528 int minInterval = 24; // 24 * 1.25ms = 30ms 1529 int maxInterval = 40; // 40 * 1.25ms = 50ms 1530 1531 // Slave latency 1532 int latency = 0; 1533 1534 // Link supervision timeout is measured in N * 10ms 1535 int timeout = 2000; // 20s 1536 1537 switch (connectionPriority) 1538 { 1539 case BluetoothGatt.CONNECTION_PRIORITY_HIGH: 1540 minInterval = 6; // 7.5ms 1541 maxInterval = 8; // 10ms 1542 break; 1543 1544 case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER: 1545 minInterval = 80; // 100ms 1546 maxInterval = 100; // 125ms 1547 latency = 2; 1548 break; 1549 } 1550 1551 if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address 1552 + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval); 1553 gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, 1554 latency, timeout); 1555 } 1556 1557 /************************************************************************** 1558 * Callback functions - SERVER 1559 *************************************************************************/ 1560 1561 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1562 throws RemoteException { 1563 1564 UUID uuid = new UUID(uuidMsb, uuidLsb); 1565 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1566 ServerMap.App app = mServerMap.getByUuid(uuid); 1567 if (app != null) { 1568 app.id = serverIf; 1569 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1570 app.callback.onServerRegistered(status, serverIf); 1571 } 1572 } 1573 1574 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1575 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1576 throws RemoteException { 1577 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1578 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1579 + ", handle=" + srvcHandle); 1580 if (status == 0) { 1581 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1582 mAdvertisingServiceUuids.remove(uuid)); 1583 } 1584 1585 continueServiceDeclaration(serverIf, status, srvcHandle); 1586 } 1587 1588 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1589 int includedSrvcHandle) throws RemoteException { 1590 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1591 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1592 continueServiceDeclaration(serverIf, status, srvcHandle); 1593 } 1594 1595 void onCharacteristicAdded(int status, int serverIf, 1596 long charUuidLsb, long charUuidMsb, 1597 int srvcHandle, int charHandle) 1598 throws RemoteException { 1599 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1600 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1601 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1602 if (status == 0) 1603 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1604 continueServiceDeclaration(serverIf, status, srvcHandle); 1605 } 1606 1607 void onDescriptorAdded(int status, int serverIf, 1608 long descrUuidLsb, long descrUuidMsb, 1609 int srvcHandle, int descrHandle) 1610 throws RemoteException { 1611 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1612 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1613 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1614 if (status == 0) 1615 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1616 continueServiceDeclaration(serverIf, status, srvcHandle); 1617 } 1618 1619 void onServiceStarted(int status, int serverIf, int srvcHandle) 1620 throws RemoteException { 1621 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1622 + ", status=" + status); 1623 if (status == 0) 1624 mHandleMap.setStarted(serverIf, srvcHandle, true); 1625 } 1626 1627 void onServiceStopped(int status, int serverIf, int srvcHandle) 1628 throws RemoteException { 1629 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1630 + ", status=" + status); 1631 if (status == 0) 1632 mHandleMap.setStarted(serverIf, srvcHandle, false); 1633 stopNextService(serverIf, status); 1634 } 1635 1636 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1637 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1638 + ", status=" + status); 1639 mHandleMap.deleteService(serverIf, srvcHandle); 1640 } 1641 1642 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1643 throws RemoteException { 1644 1645 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1646 + ", address=" + address + ", connected=" + connected); 1647 1648 ServerMap.App app = mServerMap.getById(serverIf); 1649 if (app == null) return; 1650 1651 if (connected) { 1652 mServerMap.addConnection(serverIf, connId, address); 1653 } else { 1654 mServerMap.removeConnection(serverIf, connId); 1655 } 1656 1657 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1658 } 1659 1660 void onAttributeRead(String address, int connId, int transId, 1661 int attrHandle, int offset, boolean isLong) 1662 throws RemoteException { 1663 if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1664 + ", address=" + address + ", handle=" + attrHandle 1665 + ", requestId=" + transId + ", offset=" + offset); 1666 1667 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1668 if (entry == null) return; 1669 1670 if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 1671 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1672 1673 mHandleMap.addRequest(transId, attrHandle); 1674 1675 ServerMap.App app = mServerMap.getById(entry.serverIf); 1676 if (app == null) return; 1677 1678 switch(entry.type) { 1679 case HandleMap.TYPE_CHARACTERISTIC: 1680 { 1681 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1682 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1683 serviceEntry.serviceType, serviceEntry.instance, 1684 new ParcelUuid(serviceEntry.uuid), entry.instance, 1685 new ParcelUuid(entry.uuid)); 1686 break; 1687 } 1688 1689 case HandleMap.TYPE_DESCRIPTOR: 1690 { 1691 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1692 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1693 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1694 serviceEntry.serviceType, serviceEntry.instance, 1695 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1696 new ParcelUuid(charEntry.uuid), 1697 new ParcelUuid(entry.uuid)); 1698 break; 1699 } 1700 1701 default: 1702 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1703 break; 1704 } 1705 } 1706 1707 void onAttributeWrite(String address, int connId, int transId, 1708 int attrHandle, int offset, int length, 1709 boolean needRsp, boolean isPrep, 1710 byte[] data) 1711 throws RemoteException { 1712 if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1713 + ", address=" + address + ", handle=" + attrHandle 1714 + ", requestId=" + transId + ", isPrep=" + isPrep 1715 + ", offset=" + offset); 1716 1717 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1718 if (entry == null) return; 1719 1720 if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1721 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1722 1723 mHandleMap.addRequest(transId, attrHandle); 1724 1725 ServerMap.App app = mServerMap.getById(entry.serverIf); 1726 if (app == null) return; 1727 1728 switch(entry.type) { 1729 case HandleMap.TYPE_CHARACTERISTIC: 1730 { 1731 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1732 app.callback.onCharacteristicWriteRequest(address, transId, 1733 offset, length, isPrep, needRsp, 1734 serviceEntry.serviceType, serviceEntry.instance, 1735 new ParcelUuid(serviceEntry.uuid), entry.instance, 1736 new ParcelUuid(entry.uuid), data); 1737 break; 1738 } 1739 1740 case HandleMap.TYPE_DESCRIPTOR: 1741 { 1742 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1743 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1744 app.callback.onDescriptorWriteRequest(address, transId, 1745 offset, length, isPrep, needRsp, 1746 serviceEntry.serviceType, serviceEntry.instance, 1747 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1748 new ParcelUuid(charEntry.uuid), 1749 new ParcelUuid(entry.uuid), data); 1750 break; 1751 } 1752 1753 default: 1754 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1755 break; 1756 } 1757 } 1758 1759 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1760 throws RemoteException { 1761 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1762 + ", address=" + address + ", transId=" + transId); 1763 1764 ServerMap.App app = mServerMap.getByConnId(connId); 1765 if (app == null) return; 1766 1767 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1768 } 1769 1770 void onResponseSendCompleted(int status, int attrHandle) { 1771 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1772 } 1773 1774 void onNotificationSent(int connId, int status) throws RemoteException { 1775 if (DBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); 1776 1777 String address = mServerMap.addressByConnId(connId); 1778 if (address == null) return; 1779 1780 ServerMap.App app = mServerMap.getByConnId(connId); 1781 if (app == null) return; 1782 1783 app.callback.onNotificationSent(address, status); 1784 } 1785 1786 void onServerCongestion(int connId, boolean congested) throws RemoteException { 1787 if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); 1788 1789 ServerMap.App app = mServerMap.getByConnId(connId); 1790 if (app != null) { 1791 app.callback.onConnectionCongested(mServerMap.addressByConnId(connId), congested); 1792 } 1793 } 1794 1795 /************************************************************************** 1796 * GATT Service functions - SERVER 1797 *************************************************************************/ 1798 1799 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1800 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1801 1802 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1803 mServerMap.add(uuid, callback); 1804 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1805 uuid.getMostSignificantBits()); 1806 } 1807 1808 void unregisterServer(int serverIf) { 1809 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1810 1811 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1812 1813 deleteServices(serverIf); 1814 1815 mServerMap.remove(serverIf); 1816 gattServerUnregisterAppNative(serverIf); 1817 } 1818 1819 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1820 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1821 1822 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1823 gattServerConnectNative(serverIf, address, isDirect,transport); 1824 } 1825 1826 void serverDisconnect(int serverIf, String address) { 1827 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1828 1829 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1830 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1831 1832 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1833 } 1834 1835 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1836 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1837 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1838 1839 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1840 ServiceDeclaration serviceDeclaration = addDeclaration(); 1841 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1842 advertisePreferred); 1843 } 1844 1845 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1846 UUID srvcUuid) { 1847 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1848 1849 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1850 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1851 } 1852 1853 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1854 int permissions) { 1855 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1856 1857 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1858 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1859 } 1860 1861 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1862 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1863 1864 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1865 getActiveDeclaration().addDescriptor(descUuid, permissions); 1866 } 1867 1868 void endServiceDeclaration(int serverIf) { 1869 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1870 1871 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1872 1873 if (getActiveDeclaration() == getPendingDeclaration()) { 1874 try { 1875 continueServiceDeclaration(serverIf, (byte)0, 0); 1876 } catch (RemoteException e) { 1877 Log.e(TAG,""+e); 1878 } 1879 } 1880 } 1881 1882 void removeService(int serverIf, int srvcType, 1883 int srvcInstanceId, UUID srvcUuid) { 1884 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1885 1886 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 1887 1888 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1889 if (srvcHandle == 0) return; 1890 gattServerDeleteServiceNative(serverIf, srvcHandle); 1891 } 1892 1893 void clearServices(int serverIf) { 1894 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1895 1896 if (DBG) Log.d(TAG, "clearServices()"); 1897 deleteServices(serverIf); 1898 } 1899 1900 void sendResponse(int serverIf, String address, int requestId, 1901 int status, int offset, byte[] value) { 1902 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1903 1904 if (VDBG) Log.d(TAG, "sendResponse() - address=" + address); 1905 1906 int handle = 0; 1907 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 1908 if (entry != null) handle = entry.handle; 1909 1910 int connId = mServerMap.connIdByAddress(serverIf, address); 1911 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 1912 handle, offset, value, (byte)0); 1913 mHandleMap.deleteRequest(requestId); 1914 } 1915 1916 void sendNotification(int serverIf, String address, int srvcType, 1917 int srvcInstanceId, UUID srvcUuid, 1918 int charInstanceId, UUID charUuid, 1919 boolean confirm, byte[] value) { 1920 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1921 1922 if (VDBG) Log.d(TAG, "sendNotification() - address=" + address); 1923 1924 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 1925 if (srvcHandle == 0) return; 1926 1927 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 1928 if (charHandle == 0) return; 1929 1930 int connId = mServerMap.connIdByAddress(serverIf, address); 1931 if (connId == 0) return; 1932 1933 if (confirm) { 1934 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 1935 } else { 1936 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 1937 } 1938 } 1939 1940 1941 /************************************************************************** 1942 * Private functions 1943 *************************************************************************/ 1944 1945 private int getDeviceType(BluetoothDevice device) { 1946 int type = gattClientGetDeviceTypeNative(device.getAddress()); 1947 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 1948 + ", type=" + type); 1949 return type; 1950 } 1951 1952 private void enforceAdminPermission() { 1953 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 1954 } 1955 1956 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 1957 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 1958 private void enforcePrivilegedPermission() { 1959 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 1960 "Need BLUETOOTH_PRIVILEGED permission"); 1961 } 1962 1963 private void continueSearch(int connId, int status) throws RemoteException { 1964 if (status == 0 && !mSearchQueue.isEmpty()) { 1965 SearchQueue.Entry svc = mSearchQueue.pop(); 1966 1967 if (svc.charUuidLsb == 0) { 1968 // Characteristic is up next 1969 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 1970 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 1971 } else { 1972 // Descriptor is up next 1973 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 1974 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 1975 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 1976 } 1977 } else { 1978 ClientMap.App app = mClientMap.getByConnId(connId); 1979 if (app != null) { 1980 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 1981 } 1982 } 1983 } 1984 1985 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 1986 if (mServiceDeclarations.size() == 0) return; 1987 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 1988 1989 boolean finished = false; 1990 1991 ServiceDeclaration.Entry entry = null; 1992 if (status == 0) 1993 entry = getPendingDeclaration().getNext(); 1994 1995 if (entry != null) { 1996 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 1997 + entry.type); 1998 switch(entry.type) { 1999 case ServiceDeclaration.TYPE_SERVICE: 2000 if (entry.advertisePreferred) { 2001 mAdvertisingServiceUuids.add(entry.uuid); 2002 } 2003 gattServerAddServiceNative(serverIf, entry.serviceType, 2004 entry.instance, 2005 entry.uuid.getLeastSignificantBits(), 2006 entry.uuid.getMostSignificantBits(), 2007 getPendingDeclaration().getNumHandles()); 2008 break; 2009 2010 case ServiceDeclaration.TYPE_CHARACTERISTIC: 2011 gattServerAddCharacteristicNative(serverIf, srvcHandle, 2012 entry.uuid.getLeastSignificantBits(), 2013 entry.uuid.getMostSignificantBits(), 2014 entry.properties, entry.permissions); 2015 break; 2016 2017 case ServiceDeclaration.TYPE_DESCRIPTOR: 2018 gattServerAddDescriptorNative(serverIf, srvcHandle, 2019 entry.uuid.getLeastSignificantBits(), 2020 entry.uuid.getMostSignificantBits(), 2021 entry.permissions); 2022 break; 2023 2024 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2025 { 2026 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2027 entry.serviceType, entry.instance); 2028 if (inclSrvc != 0) { 2029 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2030 inclSrvc); 2031 } else { 2032 finished = true; 2033 } 2034 break; 2035 } 2036 } 2037 } else { 2038 gattServerStartServiceNative(serverIf, srvcHandle, 2039 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2040 finished = true; 2041 } 2042 2043 if (finished) { 2044 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2045 ServerMap.App app = mServerMap.getById(serverIf); 2046 if (app != null) { 2047 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2048 2049 if (serviceEntry != null) { 2050 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2051 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2052 } else { 2053 app.callback.onServiceAdded(status, 0, 0, null); 2054 } 2055 } 2056 removePendingDeclaration(); 2057 2058 if (getPendingDeclaration() != null) { 2059 continueServiceDeclaration(serverIf, (byte)0, 0); 2060 } 2061 } 2062 } 2063 2064 private void stopNextService(int serverIf, int status) throws RemoteException { 2065 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2066 + ", status=" + status); 2067 2068 if (status == 0) { 2069 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2070 for(HandleMap.Entry entry : entries) { 2071 if (entry.type != HandleMap.TYPE_SERVICE || 2072 entry.serverIf != serverIf || 2073 entry.started == false) 2074 continue; 2075 2076 gattServerStopServiceNative(serverIf, entry.handle); 2077 return; 2078 } 2079 } 2080 } 2081 2082 private void deleteServices(int serverIf) { 2083 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2084 2085 /* 2086 * Figure out which handles to delete. 2087 * The handles are copied into a new list to avoid race conditions. 2088 */ 2089 List<Integer> handleList = new ArrayList<Integer>(); 2090 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2091 for(HandleMap.Entry entry : entries) { 2092 if (entry.type != HandleMap.TYPE_SERVICE || 2093 entry.serverIf != serverIf) 2094 continue; 2095 handleList.add(entry.handle); 2096 } 2097 2098 /* Now actually delete the services.... */ 2099 for(Integer handle : handleList) { 2100 gattServerDeleteServiceNative(serverIf, handle); 2101 } 2102 } 2103 2104 private List<UUID> parseUuids(byte[] adv_data) { 2105 List<UUID> uuids = new ArrayList<UUID>(); 2106 2107 int offset = 0; 2108 while(offset < (adv_data.length-2)) { 2109 int len = adv_data[offset++]; 2110 if (len == 0) break; 2111 2112 int type = adv_data[offset++]; 2113 switch (type) { 2114 case 0x02: // Partial list of 16-bit UUIDs 2115 case 0x03: // Complete list of 16-bit UUIDs 2116 while (len > 1) { 2117 int uuid16 = adv_data[offset++]; 2118 uuid16 += (adv_data[offset++] << 8); 2119 len -= 2; 2120 uuids.add(UUID.fromString(String.format( 2121 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2122 } 2123 break; 2124 2125 default: 2126 offset += (len - 1); 2127 break; 2128 } 2129 } 2130 2131 return uuids; 2132 } 2133 2134 /************************************************************************** 2135 * GATT Test functions 2136 *************************************************************************/ 2137 2138 void gattTestCommand(int command, UUID uuid1, String bda1, 2139 int p1, int p2, int p3, int p4, int p5) { 2140 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2141 if (uuid1 != null) 2142 gattTestNative(command, uuid1.getLeastSignificantBits(), 2143 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2144 else 2145 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2146 } 2147 2148 private native void gattTestNative(int command, 2149 long uuid1_lsb, long uuid1_msb, String bda1, 2150 int p1, int p2, int p3, int p4, int p5); 2151 2152 /************************************************************************** 2153 * Native functions prototypes 2154 *************************************************************************/ 2155 2156 private native static void classInitNative(); 2157 private native void initializeNative(); 2158 private native void cleanupNative(); 2159 2160 private native int gattClientGetDeviceTypeNative(String address); 2161 2162 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2163 long app_uuid_msb); 2164 2165 private native void gattClientUnregisterAppNative(int clientIf); 2166 2167 private native void gattClientConnectNative(int clientIf, String address, 2168 boolean isDirect, int transport); 2169 2170 private native void gattClientDisconnectNative(int clientIf, String address, 2171 int conn_id); 2172 2173 private native void gattClientRefreshNative(int clientIf, String address); 2174 2175 private native void gattClientSearchServiceNative(int conn_id, 2176 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2177 2178 private native void gattClientGetCharacteristicNative(int conn_id, 2179 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2180 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2181 long char_id_uuid_msb); 2182 2183 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2184 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2185 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2186 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2187 2188 private native void gattClientGetIncludedServiceNative(int conn_id, 2189 int service_type, int service_id_inst_id, 2190 long service_id_uuid_lsb, long service_id_uuid_msb, 2191 int incl_service_id_inst_id, int incl_service_type, 2192 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2193 2194 private native void gattClientReadCharacteristicNative(int conn_id, 2195 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2196 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2197 long char_id_uuid_msb, int authReq); 2198 2199 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2200 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2201 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2202 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2203 int authReq); 2204 2205 private native void gattClientWriteCharacteristicNative(int conn_id, 2206 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2207 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2208 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2209 2210 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2211 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2212 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2213 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2214 int write_type, int auth_req, byte[] value); 2215 2216 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2217 2218 private native void gattClientRegisterForNotificationsNative(int clientIf, 2219 String address, int service_type, int service_id_inst_id, 2220 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 boolean enable); 2223 2224 private native void gattClientReadRemoteRssiNative(int clientIf, 2225 String address); 2226 2227 private native void gattAdvertiseNative(int client_if, boolean start); 2228 2229 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2230 2231 private native void gattConnectionParameterUpdateNative(int client_if, String address, 2232 int minInterval, int maxInterval, int latency, int timeout); 2233 2234 private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 2235 boolean inclTxPower, int minInterval, int maxInterval, 2236 int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid); 2237 2238 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2239 long app_uuid_msb); 2240 2241 private native void gattServerUnregisterAppNative(int serverIf); 2242 2243 private native void gattServerConnectNative(int server_if, String address, 2244 boolean is_direct, int transport); 2245 2246 private native void gattServerDisconnectNative(int serverIf, String address, 2247 int conn_id); 2248 2249 private native void gattServerAddServiceNative (int server_if, 2250 int service_type, int service_id_inst_id, 2251 long service_id_uuid_lsb, long service_id_uuid_msb, 2252 int num_handles); 2253 2254 private native void gattServerAddIncludedServiceNative (int server_if, 2255 int svc_handle, int included_svc_handle); 2256 2257 private native void gattServerAddCharacteristicNative (int server_if, 2258 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2259 int properties, int permissions); 2260 2261 private native void gattServerAddDescriptorNative (int server_if, 2262 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2263 int permissions); 2264 2265 private native void gattServerStartServiceNative (int server_if, 2266 int svc_handle, int transport ); 2267 2268 private native void gattServerStopServiceNative (int server_if, 2269 int svc_handle); 2270 2271 private native void gattServerDeleteServiceNative (int server_if, 2272 int svc_handle); 2273 2274 private native void gattServerSendIndicationNative (int server_if, 2275 int attr_handle, int conn_id, byte[] val); 2276 2277 private native void gattServerSendNotificationNative (int server_if, 2278 int attr_handle, int conn_id, byte[] val); 2279 2280 private native void gattServerSendResponseNative (int server_if, 2281 int conn_id, int trans_id, int status, int handle, int offset, 2282 byte[] val, int auth_req); 2283} 2284