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