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