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