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