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