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