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