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