GattService.java revision bfb222069971808621cf0e1fd80584eca7372060
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 boolean isScaning = (!mScanQueue.isEmpty()); 1246 if (getScanClient(appIf, isServer) == null) { 1247 if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf); 1248 mScanQueue.add(new ScanClient(appIf, isServer, settings, filters)); 1249 } 1250 Set<BluetoothLeScanFilter> newFilters = configureScanFiltersLocked(); 1251 if (!Objects.deepEquals(newFilters, mScanFilters)) { 1252 mScanFilters = newFilters; 1253 // Restart scan using new filters. 1254 if (isScaning) { 1255 sendStopScanMessage(); 1256 } 1257 sendStartScanMessage(mScanFilters); 1258 } 1259 } 1260 } 1261 1262 void configureScanParams() { 1263 if (DBG) Log.d(TAG, "configureScanParams() - queue=" + mScanQueue.size()); 1264 1265 int scanWindow = 0, scanInterval = 0; 1266 int curDutyCycle = 0; 1267 1268 for(ScanClient client : mScanQueue) { 1269 // Pick the highest duty cycle - most stressful on battery 1270 int newDutyCycle = (client.scanWindow * 100)/client.scanInterval; 1271 if (newDutyCycle > curDutyCycle && newDutyCycle <= 100) { 1272 curDutyCycle = newDutyCycle; 1273 scanWindow = client.scanWindow; 1274 scanInterval = client.scanInterval; 1275 } 1276 } 1277 1278 if (DBG) Log.d(TAG, "configureScanParams() - dutyCyle=" + curDutyCycle + 1279 " scanWindow=" + scanWindow + " scanInterval=" + scanInterval + 1280 " lastConfiguredDutyCycle=" + lastConfiguredDutyCycle); 1281 1282 if (curDutyCycle != 0) { 1283 if (curDutyCycle != lastConfiguredDutyCycle) { 1284 // convert scanWindow and scanInterval from ms to LE scan units(0.625ms) 1285 scanWindow = (scanWindow * 1000)/625; 1286 scanInterval = (scanInterval * 1000)/625; 1287 // Presence of scan clients means scan is active. 1288 sendStopScanMessage(); 1289 gattSetScanParametersNative(scanInterval, scanWindow); 1290 lastConfiguredDutyCycle = curDutyCycle; 1291 mScanFilters.clear(); 1292 sendStartScanMessage(mScanFilters); 1293 } else { 1294 // Duty cycle did not change but scan filters changed. 1295 if (!mScanFilters.isEmpty()) { 1296 mScanFilters.clear(); 1297 sendStopScanMessage(); 1298 sendStartScanMessage(mScanFilters); 1299 } 1300 } 1301 } else { 1302 lastConfiguredDutyCycle = curDutyCycle; 1303 sendStopScanMessage(); 1304 if (DBG) Log.d(TAG, "configureScanParams() - queue emtpy, scan stopped"); 1305 } 1306 } 1307 1308 private Set<BluetoothLeScanFilter> configureScanFiltersLocked() { 1309 Set<BluetoothLeScanFilter> filters = new HashSet<BluetoothLeScanFilter>(); 1310 for (ScanClient client : mScanQueue) { 1311 if (client.filters == null || client.filters.isEmpty()) { 1312 filters.clear(); 1313 return filters; 1314 } 1315 filters.addAll(client.filters); 1316 } 1317 return filters; 1318 } 1319 1320 private void sendStartScanMessage(Set<BluetoothLeScanFilter> filters) { 1321 Message message = mStateMachine.obtainMessage(GattServiceStateMachine.START_BLE_SCAN); 1322 message.obj = filters; 1323 mStateMachine.sendMessage(message); 1324 } 1325 1326 private void sendStopScanMessage() { 1327 Message message = mStateMachine.obtainMessage(GattServiceStateMachine.STOP_BLE_SCAN); 1328 mStateMachine.sendMessage(message); 1329 } 1330 1331 void stopScan(int appIf, boolean isServer) { 1332 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH_ADMIN permission"); 1333 1334 if (DBG) Log.d(TAG, "stopScan() - queue=" + mScanQueue.size()); 1335 removeScanClient(appIf, isServer); 1336 configureScanParams(); 1337 1338 if (mScanQueue.isEmpty()) { 1339 if (DBG) Log.d(TAG, "stopScan() - queue empty; stopping scan"); 1340 } 1341 } 1342 1343 /************************************************************************** 1344 * GATT Service functions - CLIENT 1345 *************************************************************************/ 1346 1347 void registerClient(UUID uuid, IBluetoothGattCallback callback) { 1348 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1349 1350 if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid); 1351 mClientMap.add(uuid, callback); 1352 gattClientRegisterAppNative(uuid.getLeastSignificantBits(), 1353 uuid.getMostSignificantBits()); 1354 } 1355 1356 void unregisterClient(int clientIf) { 1357 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1358 1359 if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf); 1360 mClientMap.remove(clientIf); 1361 gattClientUnregisterAppNative(clientIf); 1362 } 1363 1364 void clientConnect(int clientIf, String address, boolean isDirect, int transport) { 1365 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1366 1367 if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect); 1368 gattClientConnectNative(clientIf, address, isDirect, transport); 1369 } 1370 1371 void clientDisconnect(int clientIf, String address) { 1372 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1373 1374 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1375 if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId); 1376 1377 gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0); 1378 } 1379 1380 synchronized boolean setAdvServiceData(byte[] serviceData) { 1381 enforcePrivilegedPermission(); 1382 if (serviceData == null) return false; 1383 // Calculate how many more bytes are needed for advertising service data field. 1384 int extraBytes = (mServiceData == null) ? 1385 FIELD_OVERHEAD_BYTES + serviceData.length : 1386 serviceData.length - mServiceData.length; 1387 if (getAvailableSize() < extraBytes) { 1388 Log.e(TAG, "cannot set service data, available size " + getAvailableSize()); 1389 return false; 1390 } 1391 mServiceData = serviceData; 1392 return true; 1393 } 1394 1395 byte[] getAdvServiceData() { 1396 enforcePrivilegedPermission(); 1397 return mServiceData; 1398 } 1399 1400 synchronized boolean setAdvManufacturerCodeAndData( 1401 int manufacturerCode, byte[] manufacturerData) { 1402 enforcePrivilegedPermission(); 1403 if (manufacturerCode <= 0 || manufacturerData == null) { 1404 return false; 1405 } 1406 if (mManufacturerCode > 0 && mManufacturerData != null) { 1407 Log.e(TAG, "manufacture data is already set"); 1408 return false; 1409 } 1410 if (getAvailableSize() < 1411 FIELD_OVERHEAD_BYTES + manufacturerData.length) { 1412 Log.e(TAG, "cannot set manu data, available size " + getAvailableSize()); 1413 return false; 1414 } 1415 this.mManufacturerCode = manufacturerCode; 1416 this.mManufacturerData = manufacturerData; 1417 return true; 1418 } 1419 1420 void removeAdvManufacturerCodeAndData(int manufacturerCode) { 1421 enforcePrivilegedPermission(); 1422 if (mManufacturerCode != manufacturerCode) { 1423 return; 1424 } 1425 mManufacturerCode = -1; 1426 mManufacturerData = new byte[0]; 1427 } 1428 1429 byte[] getAdvManufacturerData() { 1430 enforcePrivilegedPermission(); 1431 return mManufacturerData; 1432 } 1433 1434 synchronized List<ParcelUuid> getAdvServiceUuids() { 1435 enforcePrivilegedPermission();; 1436 boolean fullUuidFound = false; 1437 List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); 1438 for (HandleMap.Entry entry : mHandleMap.mEntries) { 1439 if (entry.advertisePreferred) { 1440 ParcelUuid parcelUuid = new ParcelUuid(entry.uuid); 1441 if (BluetoothUuid.is16BitUuid(parcelUuid)) { 1442 serviceUuids.add(parcelUuid); 1443 } else { 1444 // Allow at most one 128 bit service uuid to be advertised. 1445 if (!fullUuidFound) { 1446 fullUuidFound = true; 1447 serviceUuids.add(parcelUuid); 1448 } 1449 } 1450 } 1451 } 1452 return serviceUuids; 1453 } 1454 1455 boolean isAdvertising() { 1456 enforcePrivilegedPermission(); 1457 return mAdvertisingState != BluetoothAdapter.STATE_ADVERTISE_STOPPED; 1458 } 1459 1460 void startAdvertising(int clientIf) { 1461 enforcePrivilegedPermission(); 1462 if (DBG) Log.d(TAG, "start advertising for app - " + clientIf); 1463 List<ParcelUuid> serviceUuids = getAdvServiceUuids(); 1464 int advertisingServiceUuidLength = serviceUuids == null ? 0 : serviceUuids.size(); 1465 1466 // Note according to Bluetooth Spec Version 4.0, for advertising and scan response data 1467 // "all numerical multi-byte entities and values shall use little-endian byte order". 1468 ByteBuffer advertisingUuidBytes = ByteBuffer.allocate(advertisingServiceUuidLength * 16) 1469 .order(ByteOrder.LITTLE_ENDIAN); 1470 for (ParcelUuid parcelUuid : serviceUuids) { 1471 UUID uuid = parcelUuid.getUuid(); 1472 // Least signifcant bits first as the advertising uuid should be in little-endian. 1473 advertisingUuidBytes.putLong(uuid.getLeastSignificantBits()) 1474 .putLong(uuid.getMostSignificantBits()); 1475 } 1476 1477 // Set advertising data. 1478 gattSetAdvDataNative(clientIf, 1479 false, // not scan response data 1480 false, // no device name 1481 false, // no tx power included 1482 DEFAULT_SCAN_INTERVAL_MILLIS, 1483 DEFAULT_SCAN_INTERVAL_MILLIS, 1484 0, // no appearance limit 1485 mManufacturerData, 1486 mServiceData, 1487 advertisingUuidBytes.array()); 1488 1489 // Start advertising if advertising is not already started. 1490 if (!isAdvertising()) { 1491 gattAdvertiseNative(clientIf, true); 1492 mAdvertisingClientIf = clientIf; 1493 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STARTING; 1494 } 1495 } 1496 1497 void stopAdvertising() { 1498 stopAdvertising(false); 1499 } 1500 1501 void stopAdvertising(boolean forceStop) { 1502 enforcePrivilegedPermission(); 1503 gattAdvertiseNative(mAdvertisingClientIf, false); 1504 synchronized (mLock) { 1505 if (forceStop) { 1506 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_FORCE_STOPPING; 1507 } else { 1508 mAdvertisingState = BluetoothAdapter.STATE_ADVERTISE_STOPPING; 1509 } 1510 } 1511 } 1512 1513 void startMultiAdvertising(int clientIf, AdvertisementData advertiseData, 1514 AdvertisementData scanResponse, BluetoothLeAdvertiser.Settings settings) { 1515 enforceAdminPermission(); 1516 Message message = mStateMachine.obtainMessage(GattServiceStateMachine.START_ADVERTISING); 1517 message.obj = new AdvertiseClient(clientIf, settings, advertiseData, scanResponse); 1518 mStateMachine.sendMessage(message); 1519 } 1520 1521 void stopMultiAdvertising(int clientIf) { 1522 enforceAdminPermission(); 1523 Message message = mStateMachine.obtainMessage(GattServiceStateMachine.STOP_ADVERTISING); 1524 message.arg1 = clientIf; 1525 mStateMachine.sendMessage(message); 1526 } 1527 1528 List<String> getConnectedDevices() { 1529 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1530 1531 Set<String> connectedDevAddress = new HashSet<String>(); 1532 connectedDevAddress.addAll(mClientMap.getConnectedDevices()); 1533 connectedDevAddress.addAll(mServerMap.getConnectedDevices()); 1534 List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress); 1535 return connectedDeviceList; 1536 } 1537 1538 void refreshDevice(int clientIf, String address) { 1539 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1540 1541 if (DBG) Log.d(TAG, "refreshDevice() - address=" + address); 1542 gattClientRefreshNative(clientIf, address); 1543 } 1544 1545 void discoverServices(int clientIf, String address) { 1546 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1547 1548 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1549 if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId); 1550 1551 if (connId != null) 1552 gattClientSearchServiceNative(connId, true, 0, 0); 1553 else 1554 Log.e(TAG, "discoverServices() - No connection for " + address + "..."); 1555 } 1556 1557 void readCharacteristic(int clientIf, String address, int srvcType, 1558 int srvcInstanceId, UUID srvcUuid, 1559 int charInstanceId, UUID charUuid, int authReq) { 1560 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1561 1562 if (DBG) Log.d(TAG, "readCharacteristic() - address=" + address); 1563 1564 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1565 if (connId != null) 1566 gattClientReadCharacteristicNative(connId, srvcType, 1567 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1568 srvcUuid.getMostSignificantBits(), charInstanceId, 1569 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1570 authReq); 1571 else 1572 Log.e(TAG, "readCharacteristic() - No connection for " + address + "..."); 1573 } 1574 1575 void writeCharacteristic(int clientIf, String address, int srvcType, 1576 int srvcInstanceId, UUID srvcUuid, 1577 int charInstanceId, UUID charUuid, int writeType, 1578 int authReq, byte[] value) { 1579 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1580 1581 if (DBG) Log.d(TAG, "writeCharacteristic() - address=" + address); 1582 1583 if (mReliableQueue.contains(address)) writeType = 3; // Prepared write 1584 1585 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1586 if (connId != null) 1587 gattClientWriteCharacteristicNative(connId, srvcType, 1588 srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1589 srvcUuid.getMostSignificantBits(), charInstanceId, 1590 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1591 writeType, authReq, value); 1592 else 1593 Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); 1594 } 1595 1596 void readDescriptor(int clientIf, String address, int srvcType, 1597 int srvcInstanceId, UUID srvcUuid, 1598 int charInstanceId, UUID charUuid, 1599 int descrInstanceId, UUID descrUuid, 1600 int authReq) { 1601 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1602 1603 if (DBG) Log.d(TAG, "readDescriptor() - address=" + address); 1604 1605 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1606 if (connId != null) 1607 gattClientReadDescriptorNative(connId, srvcType, 1608 srvcInstanceId, 1609 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1610 charInstanceId, 1611 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1612 descrInstanceId, 1613 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1614 authReq); 1615 else 1616 Log.e(TAG, "readDescriptor() - No connection for " + address + "..."); 1617 }; 1618 1619 void writeDescriptor(int clientIf, String address, int srvcType, 1620 int srvcInstanceId, UUID srvcUuid, 1621 int charInstanceId, UUID charUuid, 1622 int descrInstanceId, UUID descrUuid, 1623 int writeType, int authReq, byte[] value) { 1624 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1625 1626 if (DBG) Log.d(TAG, "writeDescriptor() - address=" + address); 1627 1628 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1629 if (connId != null) 1630 gattClientWriteDescriptorNative(connId, srvcType, 1631 srvcInstanceId, 1632 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(), 1633 charInstanceId, 1634 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1635 descrInstanceId, 1636 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(), 1637 writeType, authReq, value); 1638 else 1639 Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); 1640 } 1641 1642 void beginReliableWrite(int clientIf, String address) { 1643 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1644 1645 if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address); 1646 mReliableQueue.add(address); 1647 } 1648 1649 void endReliableWrite(int clientIf, String address, boolean execute) { 1650 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1651 1652 if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address 1653 + " execute: " + execute); 1654 mReliableQueue.remove(address); 1655 1656 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1657 if (connId != null) gattClientExecuteWriteNative(connId, execute); 1658 } 1659 1660 void registerForNotification(int clientIf, String address, int srvcType, 1661 int srvcInstanceId, UUID srvcUuid, 1662 int charInstanceId, UUID charUuid, 1663 boolean enable) { 1664 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1665 1666 if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable); 1667 1668 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1669 if (connId != null) { 1670 gattClientRegisterForNotificationsNative(clientIf, address, 1671 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(), 1672 srvcUuid.getMostSignificantBits(), charInstanceId, 1673 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(), 1674 enable); 1675 } else { 1676 Log.e(TAG, "registerForNotification() - No connection for " + address + "..."); 1677 } 1678 } 1679 1680 void readRemoteRssi(int clientIf, String address) { 1681 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1682 1683 if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address); 1684 gattClientReadRemoteRssiNative(clientIf, address); 1685 } 1686 1687 void configureMTU(int clientIf, String address, int mtu) { 1688 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1689 1690 if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu); 1691 Integer connId = mClientMap.connIdByAddress(clientIf, address); 1692 if (connId != null) { 1693 gattClientConfigureMTUNative(connId, mtu); 1694 } else { 1695 Log.e(TAG, "configureMTU() - No connection for " + address + "..."); 1696 } 1697 } 1698 1699 /************************************************************************** 1700 * Callback functions - SERVER 1701 *************************************************************************/ 1702 1703 void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) 1704 throws RemoteException { 1705 1706 UUID uuid = new UUID(uuidMsb, uuidLsb); 1707 if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); 1708 ServerMap.App app = mServerMap.getByUuid(uuid); 1709 if (app != null) { 1710 app.id = serverIf; 1711 app.linkToDeath(new ServerDeathRecipient(serverIf)); 1712 app.callback.onServerRegistered(status, serverIf); 1713 } 1714 } 1715 1716 void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, 1717 long srvcUuidLsb, long srvcUuidMsb, int srvcHandle) 1718 throws RemoteException { 1719 UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb); 1720 if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status 1721 + ", handle=" + srvcHandle); 1722 if (status == 0) { 1723 mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId, 1724 mAdvertisingServiceUuids.remove(uuid)); 1725 } 1726 1727 continueServiceDeclaration(serverIf, status, srvcHandle); 1728 } 1729 1730 void onIncludedServiceAdded(int status, int serverIf, int srvcHandle, 1731 int includedSrvcHandle) throws RemoteException { 1732 if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status 1733 + ", service=" + srvcHandle + ", included=" + includedSrvcHandle); 1734 continueServiceDeclaration(serverIf, status, srvcHandle); 1735 } 1736 1737 void onCharacteristicAdded(int status, int serverIf, 1738 long charUuidLsb, long charUuidMsb, 1739 int srvcHandle, int charHandle) 1740 throws RemoteException { 1741 UUID uuid = new UUID(charUuidMsb, charUuidLsb); 1742 if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status 1743 + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle); 1744 if (status == 0) 1745 mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle); 1746 continueServiceDeclaration(serverIf, status, srvcHandle); 1747 } 1748 1749 void onDescriptorAdded(int status, int serverIf, 1750 long descrUuidLsb, long descrUuidMsb, 1751 int srvcHandle, int descrHandle) 1752 throws RemoteException { 1753 UUID uuid = new UUID(descrUuidMsb, descrUuidLsb); 1754 if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status 1755 + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle); 1756 if (status == 0) 1757 mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle); 1758 continueServiceDeclaration(serverIf, status, srvcHandle); 1759 } 1760 1761 void onServiceStarted(int status, int serverIf, int srvcHandle) 1762 throws RemoteException { 1763 if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle 1764 + ", status=" + status); 1765 if (status == 0) 1766 mHandleMap.setStarted(serverIf, srvcHandle, true); 1767 } 1768 1769 void onServiceStopped(int status, int serverIf, int srvcHandle) 1770 throws RemoteException { 1771 if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle 1772 + ", status=" + status); 1773 if (status == 0) 1774 mHandleMap.setStarted(serverIf, srvcHandle, false); 1775 stopNextService(serverIf, status); 1776 } 1777 1778 void onServiceDeleted(int status, int serverIf, int srvcHandle) { 1779 if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle 1780 + ", status=" + status); 1781 mHandleMap.deleteService(serverIf, srvcHandle); 1782 } 1783 1784 void onClientConnected(String address, boolean connected, int connId, int serverIf) 1785 throws RemoteException { 1786 1787 if (DBG) Log.d(TAG, "onConnected() connId=" + connId 1788 + ", address=" + address + ", connected=" + connected); 1789 1790 ServerMap.App app = mServerMap.getById(serverIf); 1791 if (app == null) return; 1792 1793 if (connected) { 1794 mServerMap.addConnection(serverIf, connId, address); 1795 } else { 1796 mServerMap.removeConnection(serverIf, connId); 1797 } 1798 1799 app.callback.onServerConnectionState((byte)0, serverIf, connected, address); 1800 } 1801 1802 void onAttributeRead(String address, int connId, int transId, 1803 int attrHandle, int offset, boolean isLong) 1804 throws RemoteException { 1805 if (DBG) Log.d(TAG, "onAttributeRead() connId=" + connId 1806 + ", address=" + address + ", handle=" + attrHandle 1807 + ", requestId=" + transId + ", offset=" + offset); 1808 1809 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1810 if (entry == null) return; 1811 1812 if (DBG) Log.d(TAG, "onAttributeRead() UUID=" + entry.uuid 1813 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1814 1815 mHandleMap.addRequest(transId, attrHandle); 1816 1817 ServerMap.App app = mServerMap.getById(entry.serverIf); 1818 if (app == null) return; 1819 1820 switch(entry.type) { 1821 case HandleMap.TYPE_CHARACTERISTIC: 1822 { 1823 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1824 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, 1825 serviceEntry.serviceType, serviceEntry.instance, 1826 new ParcelUuid(serviceEntry.uuid), entry.instance, 1827 new ParcelUuid(entry.uuid)); 1828 break; 1829 } 1830 1831 case HandleMap.TYPE_DESCRIPTOR: 1832 { 1833 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1834 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1835 app.callback.onDescriptorReadRequest(address, transId, offset, isLong, 1836 serviceEntry.serviceType, serviceEntry.instance, 1837 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1838 new ParcelUuid(charEntry.uuid), 1839 new ParcelUuid(entry.uuid)); 1840 break; 1841 } 1842 1843 default: 1844 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type."); 1845 break; 1846 } 1847 } 1848 1849 void onAttributeWrite(String address, int connId, int transId, 1850 int attrHandle, int offset, int length, 1851 boolean needRsp, boolean isPrep, 1852 byte[] data) 1853 throws RemoteException { 1854 if (DBG) Log.d(TAG, "onAttributeWrite() connId=" + connId 1855 + ", address=" + address + ", handle=" + attrHandle 1856 + ", requestId=" + transId + ", isPrep=" + isPrep 1857 + ", offset=" + offset); 1858 1859 HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle); 1860 if (entry == null) return; 1861 1862 if (DBG) Log.d(TAG, "onAttributeWrite() UUID=" + entry.uuid 1863 + ", serverIf=" + entry.serverIf + ", type=" + entry.type); 1864 1865 mHandleMap.addRequest(transId, attrHandle); 1866 1867 ServerMap.App app = mServerMap.getById(entry.serverIf); 1868 if (app == null) return; 1869 1870 switch(entry.type) { 1871 case HandleMap.TYPE_CHARACTERISTIC: 1872 { 1873 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1874 app.callback.onCharacteristicWriteRequest(address, transId, 1875 offset, length, isPrep, needRsp, 1876 serviceEntry.serviceType, serviceEntry.instance, 1877 new ParcelUuid(serviceEntry.uuid), entry.instance, 1878 new ParcelUuid(entry.uuid), data); 1879 break; 1880 } 1881 1882 case HandleMap.TYPE_DESCRIPTOR: 1883 { 1884 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle); 1885 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle); 1886 app.callback.onDescriptorWriteRequest(address, transId, 1887 offset, length, isPrep, needRsp, 1888 serviceEntry.serviceType, serviceEntry.instance, 1889 new ParcelUuid(serviceEntry.uuid), charEntry.instance, 1890 new ParcelUuid(charEntry.uuid), 1891 new ParcelUuid(entry.uuid), data); 1892 break; 1893 } 1894 1895 default: 1896 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type."); 1897 break; 1898 } 1899 } 1900 1901 void onExecuteWrite(String address, int connId, int transId, int execWrite) 1902 throws RemoteException { 1903 if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId 1904 + ", address=" + address + ", transId=" + transId); 1905 1906 ServerMap.App app = mServerMap.getByConnId(connId); 1907 if (app == null) return; 1908 1909 app.callback.onExecuteWrite(address, transId, execWrite == 1); 1910 } 1911 1912 void onResponseSendCompleted(int status, int attrHandle) { 1913 if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); 1914 } 1915 1916 /************************************************************************** 1917 * GATT Service functions - SERVER 1918 *************************************************************************/ 1919 1920 void registerServer(UUID uuid, IBluetoothGattServerCallback callback) { 1921 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1922 1923 if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid); 1924 mServerMap.add(uuid, callback); 1925 gattServerRegisterAppNative(uuid.getLeastSignificantBits(), 1926 uuid.getMostSignificantBits()); 1927 } 1928 1929 void unregisterServer(int serverIf) { 1930 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1931 1932 if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf); 1933 1934 deleteServices(serverIf); 1935 1936 mServerMap.remove(serverIf); 1937 gattServerUnregisterAppNative(serverIf); 1938 } 1939 1940 void serverConnect(int serverIf, String address, boolean isDirect, int transport) { 1941 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1942 1943 if (DBG) Log.d(TAG, "serverConnect() - address=" + address); 1944 gattServerConnectNative(serverIf, address, isDirect,transport); 1945 } 1946 1947 void serverDisconnect(int serverIf, String address) { 1948 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1949 1950 Integer connId = mServerMap.connIdByAddress(serverIf, address); 1951 if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId); 1952 1953 gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0); 1954 } 1955 1956 void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, 1957 int minHandles, UUID srvcUuid, boolean advertisePreferred) { 1958 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1959 1960 if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid); 1961 ServiceDeclaration serviceDeclaration = addDeclaration(); 1962 serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles, 1963 advertisePreferred); 1964 } 1965 1966 void addIncludedService(int serverIf, int srvcType, int srvcInstanceId, 1967 UUID srvcUuid) { 1968 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1969 1970 if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid); 1971 getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId); 1972 } 1973 1974 void addCharacteristic(int serverIf, UUID charUuid, int properties, 1975 int permissions) { 1976 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1977 1978 if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid); 1979 getActiveDeclaration().addCharacteristic(charUuid, properties, permissions); 1980 } 1981 1982 void addDescriptor(int serverIf, UUID descUuid, int permissions) { 1983 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1984 1985 if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid); 1986 getActiveDeclaration().addDescriptor(descUuid, permissions); 1987 } 1988 1989 void endServiceDeclaration(int serverIf) { 1990 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 1991 1992 if (DBG) Log.d(TAG, "endServiceDeclaration()"); 1993 1994 if (getActiveDeclaration() == getPendingDeclaration()) { 1995 try { 1996 continueServiceDeclaration(serverIf, (byte)0, 0); 1997 } catch (RemoteException e) { 1998 Log.e(TAG,""+e); 1999 } 2000 } 2001 } 2002 2003 void removeService(int serverIf, int srvcType, 2004 int srvcInstanceId, UUID srvcUuid) { 2005 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2006 2007 if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid); 2008 2009 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2010 if (srvcHandle == 0) return; 2011 gattServerDeleteServiceNative(serverIf, srvcHandle); 2012 } 2013 2014 void clearServices(int serverIf) { 2015 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2016 2017 if (DBG) Log.d(TAG, "clearServices()"); 2018 deleteServices(serverIf); 2019 } 2020 2021 void sendResponse(int serverIf, String address, int requestId, 2022 int status, int offset, byte[] value) { 2023 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2024 2025 if (DBG) Log.d(TAG, "sendResponse() - address=" + address); 2026 2027 int handle = 0; 2028 HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); 2029 if (entry != null) handle = entry.handle; 2030 2031 int connId = mServerMap.connIdByAddress(serverIf, address); 2032 gattServerSendResponseNative(serverIf, connId, requestId, (byte)status, 2033 handle, offset, value, (byte)0); 2034 mHandleMap.deleteRequest(requestId); 2035 } 2036 2037 void sendNotification(int serverIf, String address, int srvcType, 2038 int srvcInstanceId, UUID srvcUuid, 2039 int charInstanceId, UUID charUuid, 2040 boolean confirm, byte[] value) { 2041 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 2042 2043 if (DBG) Log.d(TAG, "sendNotification() - address=" + address); 2044 2045 int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId); 2046 if (srvcHandle == 0) return; 2047 2048 int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId); 2049 if (charHandle == 0) return; 2050 2051 int connId = mServerMap.connIdByAddress(serverIf, address); 2052 if (connId == 0) return; 2053 2054 if (confirm) { 2055 gattServerSendIndicationNative(serverIf, charHandle, connId, value); 2056 } else { 2057 gattServerSendNotificationNative(serverIf, charHandle, connId, value); 2058 } 2059 } 2060 2061 2062 /************************************************************************** 2063 * Private functions 2064 *************************************************************************/ 2065 2066 private int getDeviceType(BluetoothDevice device) { 2067 int type = gattClientGetDeviceTypeNative(device.getAddress()); 2068 if (DBG) Log.d(TAG, "getDeviceType() - device=" + device 2069 + ", type=" + type); 2070 return type; 2071 } 2072 2073 private synchronized int getAvailableSize() { 2074 enforcePrivilegedPermission(); 2075 int availableSize = ADVERTISING_PACKET_MAX_BYTES - ADVERTISING_FLAGS_BYTES; 2076 2077 for (ParcelUuid parcelUuid : getAdvServiceUuids()) { 2078 if (BluetoothUuid.is16BitUuid(parcelUuid)) { 2079 availableSize -= FIELD_OVERHEAD_BYTES + SHORT_UUID_BYTES; 2080 } else { 2081 availableSize -= FIELD_OVERHEAD_BYTES + FULL_UUID_BYTES; 2082 } 2083 } 2084 if (mManufacturerCode > 0 && mManufacturerData != null) { 2085 availableSize -= (FIELD_OVERHEAD_BYTES + mManufacturerData.length); 2086 } 2087 if (mServiceData != null) { 2088 availableSize -= (FIELD_OVERHEAD_BYTES + mServiceData.length); 2089 } 2090 return availableSize; 2091 } 2092 2093 private void enforceAdminPermission() { 2094 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 2095 } 2096 2097 // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be 2098 // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. 2099 private void enforcePrivilegedPermission() { 2100 enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, 2101 "Need BLUETOOTH_PRIVILEGED permission"); 2102 } 2103 2104 private void continueSearch(int connId, int status) throws RemoteException { 2105 if (status == 0 && !mSearchQueue.isEmpty()) { 2106 SearchQueue.Entry svc = mSearchQueue.pop(); 2107 2108 if (svc.charUuidLsb == 0) { 2109 // Characteristic is up next 2110 gattClientGetCharacteristicNative(svc.connId, svc.srvcType, 2111 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0); 2112 } else { 2113 // Descriptor is up next 2114 gattClientGetDescriptorNative(svc.connId, svc.srvcType, 2115 svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 2116 svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0); 2117 } 2118 } else { 2119 ClientMap.App app = mClientMap.getByConnId(connId); 2120 if (app != null) { 2121 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status); 2122 } 2123 } 2124 } 2125 2126 private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException { 2127 if (mServiceDeclarations.size() == 0) return; 2128 if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle); 2129 2130 boolean finished = false; 2131 2132 ServiceDeclaration.Entry entry = null; 2133 if (status == 0) 2134 entry = getPendingDeclaration().getNext(); 2135 2136 if (entry != null) { 2137 if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type=" 2138 + entry.type); 2139 switch(entry.type) { 2140 case ServiceDeclaration.TYPE_SERVICE: 2141 if (entry.advertisePreferred) { 2142 mAdvertisingServiceUuids.add(entry.uuid); 2143 } 2144 gattServerAddServiceNative(serverIf, entry.serviceType, 2145 entry.instance, 2146 entry.uuid.getLeastSignificantBits(), 2147 entry.uuid.getMostSignificantBits(), 2148 getPendingDeclaration().getNumHandles()); 2149 break; 2150 2151 case ServiceDeclaration.TYPE_CHARACTERISTIC: 2152 gattServerAddCharacteristicNative(serverIf, srvcHandle, 2153 entry.uuid.getLeastSignificantBits(), 2154 entry.uuid.getMostSignificantBits(), 2155 entry.properties, entry.permissions); 2156 break; 2157 2158 case ServiceDeclaration.TYPE_DESCRIPTOR: 2159 gattServerAddDescriptorNative(serverIf, srvcHandle, 2160 entry.uuid.getLeastSignificantBits(), 2161 entry.uuid.getMostSignificantBits(), 2162 entry.permissions); 2163 break; 2164 2165 case ServiceDeclaration.TYPE_INCLUDED_SERVICE: 2166 { 2167 int inclSrvc = mHandleMap.getServiceHandle(entry.uuid, 2168 entry.serviceType, entry.instance); 2169 if (inclSrvc != 0) { 2170 gattServerAddIncludedServiceNative(serverIf, srvcHandle, 2171 inclSrvc); 2172 } else { 2173 finished = true; 2174 } 2175 break; 2176 } 2177 } 2178 } else { 2179 gattServerStartServiceNative(serverIf, srvcHandle, 2180 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE); 2181 finished = true; 2182 } 2183 2184 if (finished) { 2185 if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed."); 2186 ServerMap.App app = mServerMap.getById(serverIf); 2187 if (app != null) { 2188 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle); 2189 2190 if (serviceEntry != null) { 2191 app.callback.onServiceAdded(status, serviceEntry.serviceType, 2192 serviceEntry.instance, new ParcelUuid(serviceEntry.uuid)); 2193 } else { 2194 app.callback.onServiceAdded(status, 0, 0, null); 2195 } 2196 } 2197 removePendingDeclaration(); 2198 2199 if (getPendingDeclaration() != null) { 2200 continueServiceDeclaration(serverIf, (byte)0, 0); 2201 } 2202 } 2203 } 2204 2205 private void stopNextService(int serverIf, int status) throws RemoteException { 2206 if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf 2207 + ", status=" + status); 2208 2209 if (status == 0) { 2210 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2211 for(HandleMap.Entry entry : entries) { 2212 if (entry.type != HandleMap.TYPE_SERVICE || 2213 entry.serverIf != serverIf || 2214 entry.started == false) 2215 continue; 2216 2217 gattServerStopServiceNative(serverIf, entry.handle); 2218 return; 2219 } 2220 } 2221 } 2222 2223 private void deleteServices(int serverIf) { 2224 if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf); 2225 2226 /* 2227 * Figure out which handles to delete. 2228 * The handles are copied into a new list to avoid race conditions. 2229 */ 2230 List<Integer> handleList = new ArrayList<Integer>(); 2231 List<HandleMap.Entry> entries = mHandleMap.getEntries(); 2232 for(HandleMap.Entry entry : entries) { 2233 if (entry.type != HandleMap.TYPE_SERVICE || 2234 entry.serverIf != serverIf) 2235 continue; 2236 handleList.add(entry.handle); 2237 } 2238 2239 /* Now actually delete the services.... */ 2240 for(Integer handle : handleList) { 2241 gattServerDeleteServiceNative(serverIf, handle); 2242 } 2243 } 2244 2245 private List<UUID> parseUuids(byte[] adv_data) { 2246 List<UUID> uuids = new ArrayList<UUID>(); 2247 2248 int offset = 0; 2249 while(offset < (adv_data.length-2)) { 2250 int len = adv_data[offset++]; 2251 if (len == 0) break; 2252 2253 int type = adv_data[offset++]; 2254 switch (type) { 2255 case 0x02: // Partial list of 16-bit UUIDs 2256 case 0x03: // Complete list of 16-bit UUIDs 2257 while (len > 1) { 2258 int uuid16 = adv_data[offset++]; 2259 uuid16 += (adv_data[offset++] << 8); 2260 len -= 2; 2261 uuids.add(UUID.fromString(String.format( 2262 "%08x-0000-1000-8000-00805f9b34fb", uuid16))); 2263 } 2264 break; 2265 2266 default: 2267 offset += (len - 1); 2268 break; 2269 } 2270 } 2271 2272 return uuids; 2273 } 2274 2275 /************************************************************************** 2276 * GATT Test functions 2277 *************************************************************************/ 2278 2279 void gattTestCommand(int command, UUID uuid1, String bda1, 2280 int p1, int p2, int p3, int p4, int p5) { 2281 if (bda1 == null) bda1 = "00:00:00:00:00:00"; 2282 if (uuid1 != null) 2283 gattTestNative(command, uuid1.getLeastSignificantBits(), 2284 uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5); 2285 else 2286 gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5); 2287 } 2288 2289 private native void gattTestNative(int command, 2290 long uuid1_lsb, long uuid1_msb, String bda1, 2291 int p1, int p2, int p3, int p4, int p5); 2292 2293 /************************************************************************** 2294 * Native functions prototypes 2295 *************************************************************************/ 2296 2297 private native static void classInitNative(); 2298 private native void initializeNative(); 2299 private native void cleanupNative(); 2300 2301 private native int gattClientGetDeviceTypeNative(String address); 2302 2303 private native void gattClientRegisterAppNative(long app_uuid_lsb, 2304 long app_uuid_msb); 2305 2306 private native void gattClientUnregisterAppNative(int clientIf); 2307 2308 private native void gattSetScanParametersNative(int scan_interval, int scan_window); 2309 2310 private native void gattClientConnectNative(int clientIf, String address, 2311 boolean isDirect, int transport); 2312 2313 private native void gattClientDisconnectNative(int clientIf, String address, 2314 int conn_id); 2315 2316 private native void gattClientRefreshNative(int clientIf, String address); 2317 2318 private native void gattClientSearchServiceNative(int conn_id, 2319 boolean search_all, long service_uuid_lsb, long service_uuid_msb); 2320 2321 private native void gattClientGetCharacteristicNative(int conn_id, 2322 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2323 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2324 long char_id_uuid_msb); 2325 2326 private native void gattClientGetDescriptorNative(int conn_id, int service_type, 2327 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2328 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2329 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb); 2330 2331 private native void gattClientGetIncludedServiceNative(int conn_id, 2332 int service_type, int service_id_inst_id, 2333 long service_id_uuid_lsb, long service_id_uuid_msb, 2334 int incl_service_id_inst_id, int incl_service_type, 2335 long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb); 2336 2337 private native void gattClientReadCharacteristicNative(int conn_id, 2338 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2339 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2340 long char_id_uuid_msb, int authReq); 2341 2342 private native void gattClientReadDescriptorNative(int conn_id, int service_type, 2343 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2344 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2345 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2346 int authReq); 2347 2348 private native void gattClientWriteCharacteristicNative(int conn_id, 2349 int service_type, int service_id_inst_id, long service_id_uuid_lsb, 2350 long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, 2351 long char_id_uuid_msb, int write_type, int auth_req, byte[] value); 2352 2353 private native void gattClientWriteDescriptorNative(int conn_id, int service_type, 2354 int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, 2355 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2356 int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, 2357 int write_type, int auth_req, byte[] value); 2358 2359 private native void gattClientExecuteWriteNative(int conn_id, boolean execute); 2360 2361 private native void gattClientRegisterForNotificationsNative(int clientIf, 2362 String address, int service_type, int service_id_inst_id, 2363 long service_id_uuid_lsb, long service_id_uuid_msb, 2364 int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, 2365 boolean enable); 2366 2367 private native void gattClientReadRemoteRssiNative(int clientIf, 2368 String address); 2369 2370 private native void gattAdvertiseNative(int client_if, boolean start); 2371 2372 private native void gattClientConfigureMTUNative(int conn_id, int mtu); 2373 2374 private native void gattSetAdvDataNative(int serverIf, boolean setScanRsp, boolean inclName, 2375 boolean inclTxPower, int minInterval, int maxInterval, 2376 int appearance, byte[] manufacturerData, byte[] serviceData, byte[] serviceUuid); 2377 2378 private native void gattServerRegisterAppNative(long app_uuid_lsb, 2379 long app_uuid_msb); 2380 2381 private native void gattServerUnregisterAppNative(int serverIf); 2382 2383 private native void gattServerConnectNative(int server_if, String address, 2384 boolean is_direct, int transport); 2385 2386 private native void gattServerDisconnectNative(int serverIf, String address, 2387 int conn_id); 2388 2389 private native void gattServerAddServiceNative (int server_if, 2390 int service_type, int service_id_inst_id, 2391 long service_id_uuid_lsb, long service_id_uuid_msb, 2392 int num_handles); 2393 2394 private native void gattServerAddIncludedServiceNative (int server_if, 2395 int svc_handle, int included_svc_handle); 2396 2397 private native void gattServerAddCharacteristicNative (int server_if, 2398 int svc_handle, long char_uuid_lsb, long char_uuid_msb, 2399 int properties, int permissions); 2400 2401 private native void gattServerAddDescriptorNative (int server_if, 2402 int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, 2403 int permissions); 2404 2405 private native void gattServerStartServiceNative (int server_if, 2406 int svc_handle, int transport ); 2407 2408 private native void gattServerStopServiceNative (int server_if, 2409 int svc_handle); 2410 2411 private native void gattServerDeleteServiceNative (int server_if, 2412 int svc_handle); 2413 2414 private native void gattServerSendIndicationNative (int server_if, 2415 int attr_handle, int conn_id, byte[] val); 2416 2417 private native void gattServerSendNotificationNative (int server_if, 2418 int attr_handle, int conn_id, byte[] val); 2419 2420 private native void gattServerSendResponseNative (int server_if, 2421 int conn_id, int trans_id, int status, int handle, int offset, 2422 byte[] val, int auth_req); 2423} 2424