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