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