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