1 /* 2 * Copyright (C) 2017 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.googlecode.android_scripting.facade.bluetooth; 18 19 import android.app.Service; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.BluetoothAdapter.LeScanCallback; 22 import android.bluetooth.BluetoothDevice; 23 import android.bluetooth.le.BluetoothLeScanner; 24 import android.bluetooth.le.ScanCallback; 25 import android.bluetooth.le.ScanFilter; 26 import android.bluetooth.le.ScanFilter.Builder; 27 import android.bluetooth.le.ScanResult; 28 import android.bluetooth.le.ScanSettings; 29 import android.os.Bundle; 30 import android.os.ParcelUuid; 31 32 import com.googlecode.android_scripting.Log; 33 import com.googlecode.android_scripting.MainThread; 34 import com.googlecode.android_scripting.facade.EventFacade; 35 import com.googlecode.android_scripting.facade.FacadeManager; 36 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 37 import com.googlecode.android_scripting.rpc.Rpc; 38 import com.googlecode.android_scripting.rpc.RpcOptional; 39 import com.googlecode.android_scripting.rpc.RpcParameter; 40 41 import java.util.ArrayList; 42 import java.util.HashMap; 43 import java.util.List; 44 import java.util.UUID; 45 import java.util.concurrent.Callable; 46 47 /** 48 * BluetoothLe Scan functions. 49 */ 50 51 public class BluetoothLeScanFacade extends RpcReceiver { 52 53 private final EventFacade mEventFacade; 54 55 private BluetoothAdapter mBluetoothAdapter; 56 private static int ScanCallbackCount; 57 private static int FilterListCount; 58 private static int LeScanCallbackCount; 59 private static int ScanSettingsCount; 60 private final Service mService; 61 private final BluetoothLeScanner mScanner; 62 private android.bluetooth.le.ScanSettings.Builder mScanSettingsBuilder; 63 private Builder mScanFilterBuilder; 64 private final HashMap<Integer, myScanCallback> mScanCallbackList; 65 private final HashMap<Integer, myLeScanCallback> mLeScanCallbackList; 66 private final HashMap<Integer, ArrayList<ScanFilter>> mScanFilterList; 67 private final HashMap<Integer, ScanSettings> mScanSettingsList; 68 BluetoothLeScanFacade(FacadeManager manager)69 public BluetoothLeScanFacade(FacadeManager manager) { 70 super(manager); 71 mService = manager.getService(); 72 mBluetoothAdapter = MainThread.run(mService, 73 new Callable<BluetoothAdapter>() { 74 @Override 75 public BluetoothAdapter call() throws Exception { 76 return BluetoothAdapter.getDefaultAdapter(); 77 } 78 }); 79 mScanner = mBluetoothAdapter.getBluetoothLeScanner(); 80 mEventFacade = manager.getReceiver(EventFacade.class); 81 mScanFilterList = new HashMap<Integer, ArrayList<ScanFilter>>(); 82 mLeScanCallbackList = new HashMap<Integer, myLeScanCallback>(); 83 mScanSettingsList = new HashMap<Integer, ScanSettings>(); 84 mScanCallbackList = new HashMap<Integer, myScanCallback>(); 85 mScanFilterBuilder = new Builder(); 86 mScanSettingsBuilder = new android.bluetooth.le.ScanSettings.Builder(); 87 } 88 89 /** 90 * Constructs a myScanCallback obj and returns its index 91 * 92 * @return Integer myScanCallback.index 93 */ 94 @Rpc(description = "Generate a new myScanCallback Object") bleGenScanCallback()95 public Integer bleGenScanCallback() { 96 ScanCallbackCount += 1; 97 int index = ScanCallbackCount; 98 myScanCallback mScan = new myScanCallback(index); 99 mScanCallbackList.put(mScan.index, mScan); 100 return mScan.index; 101 } 102 103 /** 104 * Constructs a myLeScanCallback obj and returns its index 105 * 106 * @return Integer myScanCallback.index 107 */ 108 @Rpc(description = "Generate a new myScanCallback Object") bleGenLeScanCallback()109 public Integer bleGenLeScanCallback() { 110 LeScanCallbackCount += 1; 111 int index = LeScanCallbackCount; 112 myLeScanCallback mScan = new myLeScanCallback(index); 113 mLeScanCallbackList.put(mScan.index, mScan); 114 return mScan.index; 115 } 116 117 /** 118 * Constructs a new filter list array and returns its index 119 * 120 * @return Integer index 121 */ 122 @Rpc(description = "Generate a new Filter list") bleGenFilterList()123 public Integer bleGenFilterList() { 124 FilterListCount += 1; 125 int index = FilterListCount; 126 mScanFilterList.put(index, new ArrayList<ScanFilter>()); 127 return index; 128 } 129 130 /** 131 * Constructs a new filter list array and returns its index 132 * 133 * @return Integer index 134 */ 135 @Rpc(description = "Generate a new Filter list") bleBuildScanFilter( @pcParametername = "filterIndex") Integer filterIndex )136 public Integer bleBuildScanFilter( 137 @RpcParameter(name = "filterIndex") 138 Integer filterIndex 139 ) { 140 mScanFilterList.get(filterIndex).add(mScanFilterBuilder.build()); 141 mScanFilterBuilder = new Builder(); 142 return mScanFilterList.get(filterIndex).size()-1; 143 } 144 145 /** 146 * Constructs a new scan setting and returns its index 147 * 148 * @return Integer index 149 */ 150 @Rpc(description = "Generate a new scan settings Object") bleBuildScanSetting()151 public Integer bleBuildScanSetting() { 152 ScanSettingsCount += 1; 153 int index = ScanSettingsCount; 154 mScanSettingsList.put(index, mScanSettingsBuilder.build()); 155 mScanSettingsBuilder = new android.bluetooth.le.ScanSettings.Builder(); 156 return index; 157 } 158 159 /** 160 * Stops a ble scan 161 * 162 * @param index the id of the myScan whose ScanCallback to stop 163 * @throws Exception 164 */ 165 @Rpc(description = "Stops an ongoing ble advertisement scan") bleStopBleScan( @pcParametername = "index") Integer index)166 public void bleStopBleScan( 167 @RpcParameter(name = "index") 168 Integer index) throws Exception { 169 Log.d("bluetooth_le_scan mScanCallback " + index); 170 if (mScanCallbackList.get(index) != null) { 171 myScanCallback mScanCallback = mScanCallbackList.get(index); 172 mScanner.stopScan(mScanCallback); 173 } else { 174 throw new Exception("Invalid index input:" + Integer.toString(index)); 175 } 176 } 177 178 /** 179 * Stops a classic ble scan 180 * 181 * @param index the id of the myScan whose LeScanCallback to stop 182 * @throws Exception 183 */ 184 @Rpc(description = "Stops an ongoing classic ble scan") bleStopClassicBleScan( @pcParametername = "index") Integer index)185 public void bleStopClassicBleScan( 186 @RpcParameter(name = "index") 187 Integer index) throws Exception { 188 Log.d("bluetooth_le_scan mLeScanCallback " + index); 189 if (mLeScanCallbackList.get(index) != null) { 190 myLeScanCallback mLeScanCallback = mLeScanCallbackList.get(index); 191 mBluetoothAdapter.stopLeScan(mLeScanCallback); 192 } else { 193 throw new Exception("Invalid index input:" + Integer.toString(index)); 194 } 195 } 196 197 /** 198 * Starts a ble scan 199 * 200 * @param index the id of the myScan whose ScanCallback to start 201 * @throws Exception 202 */ 203 @Rpc(description = "Starts a ble advertisement scan") bleStartBleScan( @pcParametername = "filterListIndex") Integer filterListIndex, @RpcParameter(name = "scanSettingsIndex") Integer scanSettingsIndex, @RpcParameter(name = "callbackIndex") Integer callbackIndex )204 public void bleStartBleScan( 205 @RpcParameter(name = "filterListIndex") 206 Integer filterListIndex, 207 @RpcParameter(name = "scanSettingsIndex") 208 Integer scanSettingsIndex, 209 @RpcParameter(name = "callbackIndex") 210 Integer callbackIndex 211 ) throws Exception { 212 Log.d("bluetooth_le_scan starting a background scan"); 213 ArrayList<ScanFilter> mScanFilters = new ArrayList<ScanFilter>(); 214 mScanFilters.add(new ScanFilter.Builder().build()); 215 ScanSettings mScanSettings = new ScanSettings.Builder().build(); 216 if (mScanFilterList.get(filterListIndex) != null) { 217 mScanFilters = mScanFilterList.get(filterListIndex); 218 } else { 219 throw new Exception("Invalid filterListIndex input:" 220 + Integer.toString(filterListIndex)); 221 } 222 if (mScanSettingsList.get(scanSettingsIndex) != null) { 223 mScanSettings = mScanSettingsList.get(scanSettingsIndex); 224 } else if (!mScanSettingsList.isEmpty()) { 225 throw new Exception("Invalid scanSettingsIndex input:" 226 + Integer.toString(scanSettingsIndex)); 227 } 228 if (mScanCallbackList.get(callbackIndex) != null) { 229 mScanner.startScan(mScanFilters, mScanSettings, mScanCallbackList.get(callbackIndex)); 230 } else { 231 throw new Exception("Invalid filterListIndex input:" 232 + Integer.toString(filterListIndex)); 233 } 234 } 235 236 /** 237 * Starts a classic ble scan 238 * 239 * @param index the id of the myScan whose ScanCallback to start 240 * @throws Exception 241 */ 242 @Rpc(description = "Starts a classic ble advertisement scan") bleStartClassicBleScan( @pcParametername = "leCallbackIndex") Integer leCallbackIndex )243 public boolean bleStartClassicBleScan( 244 @RpcParameter(name = "leCallbackIndex") 245 Integer leCallbackIndex 246 ) throws Exception { 247 Log.d("bluetooth_le_scan starting a background scan"); 248 boolean result = false; 249 if (mLeScanCallbackList.get(leCallbackIndex) != null) { 250 result = mBluetoothAdapter.startLeScan(mLeScanCallbackList.get(leCallbackIndex)); 251 } else { 252 throw new Exception("Invalid leCallbackIndex input:" 253 + Integer.toString(leCallbackIndex)); 254 } 255 return result; 256 } 257 258 /** 259 * Starts a classic ble scan with service Uuids 260 * 261 * @param index the id of the myScan whose ScanCallback to start 262 * @throws Exception 263 */ 264 @Rpc(description = "Starts a classic ble advertisement scan with service Uuids") bleStartClassicBleScanWithServiceUuids( @pcParametername = "leCallbackIndex") Integer leCallbackIndex, @RpcParameter(name = "serviceUuids") String[] serviceUuidList )265 public boolean bleStartClassicBleScanWithServiceUuids( 266 @RpcParameter(name = "leCallbackIndex") 267 Integer leCallbackIndex, 268 @RpcParameter(name = "serviceUuids") 269 String[] serviceUuidList 270 ) throws Exception { 271 Log.d("bluetooth_le_scan starting a background scan"); 272 UUID[] serviceUuids = new UUID[serviceUuidList.length]; 273 for (int i = 0; i < serviceUuidList.length; i++) { 274 serviceUuids[i] = UUID.fromString(serviceUuidList[i]); 275 } 276 boolean result = false; 277 if (mLeScanCallbackList.get(leCallbackIndex) != null) { 278 result = mBluetoothAdapter.startLeScan(serviceUuids, 279 mLeScanCallbackList.get(leCallbackIndex)); 280 } else { 281 throw new Exception("Invalid leCallbackIndex input:" 282 + Integer.toString(leCallbackIndex)); 283 } 284 return result; 285 } 286 287 /** 288 * Trigger onBatchScanResults 289 * 290 * @throws Exception 291 */ 292 @Rpc(description = "Gets the results of the ble ScanCallback") bleFlushPendingScanResults( @pcParametername = "callbackIndex") Integer callbackIndex )293 public void bleFlushPendingScanResults( 294 @RpcParameter(name = "callbackIndex") 295 Integer callbackIndex 296 ) throws Exception { 297 if (mScanCallbackList.get(callbackIndex) != null) { 298 mBluetoothAdapter 299 .getBluetoothLeScanner().flushPendingScanResults( 300 mScanCallbackList.get(callbackIndex)); 301 } else { 302 throw new Exception("Invalid callbackIndex input:" 303 + Integer.toString(callbackIndex)); 304 } 305 } 306 307 /** 308 * Set scanSettings for ble scan. Note: You have to set all variables at once. 309 * 310 * @param callbackType Bluetooth LE scan callback type 311 * @param reportDelaySeconds Time of delay for reporting the scan result 312 * @param scanMode Bluetooth LE scan mode. 313 * @param scanResultType Bluetooth LE scan result type 314 * @throws Exception 315 */ 316 317 /** 318 * Set the scan setting's callback type 319 * @param callbackType Bluetooth LE scan callback type 320 */ 321 @Rpc(description = "Set the scan setting's callback type") bleSetScanSettingsCallbackType( @pcParametername = "callbackType") Integer callbackType)322 public void bleSetScanSettingsCallbackType( 323 @RpcParameter(name = "callbackType") 324 Integer callbackType) { 325 mScanSettingsBuilder.setCallbackType(callbackType); 326 } 327 328 /** 329 * Set the scan setting's report delay millis 330 * @param reportDelayMillis Time of delay for reporting the scan result 331 */ 332 @Rpc(description = "Set the scan setting's report delay millis") bleSetScanSettingsReportDelayMillis( @pcParametername = "reportDelayMillis") Long reportDelayMillis)333 public void bleSetScanSettingsReportDelayMillis( 334 @RpcParameter(name = "reportDelayMillis") 335 Long reportDelayMillis) { 336 mScanSettingsBuilder.setReportDelay(reportDelayMillis); 337 } 338 339 /** 340 * Set the scan setting's scan mode 341 * @param scanMode Bluetooth LE scan mode. 342 */ 343 @Rpc(description = "Set the scan setting's scan mode") bleSetScanSettingsScanMode( @pcParametername = "scanMode") Integer scanMode)344 public void bleSetScanSettingsScanMode( 345 @RpcParameter(name = "scanMode") 346 Integer scanMode) { 347 mScanSettingsBuilder.setScanMode(scanMode); 348 } 349 350 /** 351 * Set the scan setting's legacy mode 352 * @param legacy Wether scan is legacy. 353 */ 354 @Rpc(description = "Set the scan setting's legacy mode") bleSetScanSettingsLegacy( @pcParametername = "legacy") Boolean legacy)355 public void bleSetScanSettingsLegacy( 356 @RpcParameter(name = "legacy") 357 Boolean legacy) { 358 mScanSettingsBuilder.setLegacy(legacy); 359 } 360 361 /** 362 * Set the scan setting's phy mode 363 * @param phy 364 */ 365 @Rpc(description = "Set the scan setting's phy mode") bleSetScanSettingsPhy( @pcParametername = "phy") Integer phy)366 public void bleSetScanSettingsPhy( 367 @RpcParameter(name = "phy") 368 Integer phy) { 369 mScanSettingsBuilder.setPhy(phy); 370 } 371 372 /** 373 * Set the scan setting's scan result type 374 * @param scanResultType Bluetooth LE scan result type 375 */ 376 @Rpc(description = "Set the scan setting's scan result type") bleSetScanSettingsResultType( @pcParametername = "scanResultType") Integer scanResultType)377 public void bleSetScanSettingsResultType( 378 @RpcParameter(name = "scanResultType") 379 Integer scanResultType) { 380 mScanSettingsBuilder.setScanResultType(scanResultType); 381 } 382 /** 383 * Get ScanSetting's callback type 384 * 385 * @param index the ScanSetting object to use 386 * @return the ScanSetting's callback type 387 * @throws Exception 388 */ 389 @Rpc(description = "Get ScanSetting's callback type") bleGetScanSettingsCallbackType( @pcParametername = "index") Integer index )390 public Integer bleGetScanSettingsCallbackType( 391 @RpcParameter(name = "index") 392 Integer index 393 ) throws Exception { 394 if (mScanSettingsList.get(index) != null) { 395 ScanSettings mScanSettings = mScanSettingsList.get(index); 396 return mScanSettings.getCallbackType(); 397 } else { 398 throw new Exception("Invalid index input:" + Integer.toString(index)); 399 } 400 } 401 402 /** 403 * Get ScanSetting's report delay in milli seconds 404 * 405 * @param index the ScanSetting object to useSystemClock 406 * @return the ScanSetting's report delay in milliseconds 407 * @throws Exception 408 */ 409 @Rpc(description = "Get ScanSetting's report delay milliseconds") bleGetScanSettingsReportDelayMillis( @pcParametername = "index") Integer index)410 public Long bleGetScanSettingsReportDelayMillis( 411 @RpcParameter(name = "index") 412 Integer index) throws Exception { 413 if (mScanSettingsList.get(index) != null) { 414 ScanSettings mScanSettings = mScanSettingsList.get(index); 415 return mScanSettings.getReportDelayMillis(); 416 } else { 417 throw new Exception("Invalid index input:" + Integer.toString(index)); 418 } 419 } 420 421 /** 422 * Get ScanSetting's scan mode 423 * 424 * @param index the ScanSetting object to use 425 * @return the ScanSetting's scan mode 426 * @throws Exception 427 */ 428 @Rpc(description = "Get ScanSetting's scan mode") bleGetScanSettingsScanMode( @pcParametername = "index") Integer index)429 public Integer bleGetScanSettingsScanMode( 430 @RpcParameter(name = "index") 431 Integer index) throws Exception { 432 if (mScanSettingsList.get(index) != null) { 433 ScanSettings mScanSettings = mScanSettingsList.get(index); 434 return mScanSettings.getScanMode(); 435 } else { 436 throw new Exception("Invalid index input:" + Integer.toString(index)); 437 } 438 } 439 440 /** 441 * Get ScanSetting's scan result type 442 * 443 * @param index the ScanSetting object to use 444 * @return the ScanSetting's scan result type 445 * @throws Exception 446 */ 447 @Rpc(description = "Get ScanSetting's scan result type") bleGetScanSettingsScanResultType( @pcParametername = "index") Integer index)448 public Integer bleGetScanSettingsScanResultType( 449 @RpcParameter(name = "index") 450 Integer index) throws Exception { 451 if (mScanSettingsList.get(index) != null) { 452 ScanSettings mScanSettings = mScanSettingsList.get(index); 453 return mScanSettings.getScanResultType(); 454 } else { 455 throw new Exception("Invalid index input:" + Integer.toString(index)); 456 } 457 } 458 459 /** 460 * Get ScanFilter's Manufacturer Id 461 * 462 * @param index the ScanFilter object to use 463 * @return the ScanFilter's manufacturer id 464 * @throws Exception 465 */ 466 @Rpc(description = "Get ScanFilter's Manufacturer Id") bleGetScanFilterManufacturerId( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)467 public Integer bleGetScanFilterManufacturerId( 468 @RpcParameter(name = "index") 469 Integer index, 470 @RpcParameter(name = "filterIndex") 471 Integer filterIndex) 472 throws Exception { 473 if (mScanFilterList.get(index) != null) { 474 if (mScanFilterList.get(index).get(filterIndex) != null) { 475 return mScanFilterList.get(index) 476 .get(filterIndex).getManufacturerId(); 477 } else { 478 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 479 } 480 } else { 481 throw new Exception("Invalid index input:" + Integer.toString(index)); 482 } 483 } 484 485 /** 486 * Get ScanFilter's device address 487 * 488 * @param index the ScanFilter object to use 489 * @return the ScanFilter's device address 490 * @throws Exception 491 */ 492 @Rpc(description = "Get ScanFilter's device address") bleGetScanFilterDeviceAddress( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)493 public String bleGetScanFilterDeviceAddress( 494 @RpcParameter(name = "index") 495 Integer index, 496 @RpcParameter(name = "filterIndex") 497 Integer filterIndex) 498 throws Exception { 499 if (mScanFilterList.get(index) != null) { 500 if (mScanFilterList.get(index).get(filterIndex) != null) { 501 return mScanFilterList.get(index).get(filterIndex).getDeviceAddress(); 502 } else { 503 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 504 } 505 } else { 506 throw new Exception("Invalid index input:" + Integer.toString(index)); 507 } 508 } 509 510 /** 511 * Get ScanFilter's device name 512 * 513 * @param index the ScanFilter object to use 514 * @return the ScanFilter's device name 515 * @throws Exception 516 */ 517 @Rpc(description = "Get ScanFilter's device name") bleGetScanFilterDeviceName( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)518 public String bleGetScanFilterDeviceName( 519 @RpcParameter(name = "index") 520 Integer index, 521 @RpcParameter(name = "filterIndex") 522 Integer filterIndex) 523 throws Exception { 524 if (mScanFilterList.get(index) != null) { 525 if (mScanFilterList.get(index).get(filterIndex) != null) { 526 return mScanFilterList.get(index).get(filterIndex).getDeviceName(); 527 } else { 528 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 529 } 530 } else { 531 throw new Exception("Invalid index input:" + Integer.toString(index)); 532 } 533 } 534 535 /** 536 * Get ScanFilter's manufacturer data 537 * 538 * @param index the ScanFilter object to use 539 * @return the ScanFilter's manufacturer data 540 * @throws Exception 541 */ 542 @Rpc(description = "Get ScanFilter's manufacturer data") bleGetScanFilterManufacturerData( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)543 public byte[] bleGetScanFilterManufacturerData( 544 @RpcParameter(name = "index") 545 Integer index, 546 @RpcParameter(name = "filterIndex") 547 Integer filterIndex) 548 throws Exception { 549 if (mScanFilterList.get(index) != null) { 550 if (mScanFilterList.get(index).get(filterIndex) != null) { 551 return mScanFilterList.get(index).get(filterIndex).getManufacturerData(); 552 } else { 553 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 554 } 555 } else { 556 throw new Exception("Invalid index input:" + Integer.toString(index)); 557 } 558 } 559 560 /** 561 * Get ScanFilter's manufacturer data mask 562 * 563 * @param index the ScanFilter object to use 564 * @return the ScanFilter's manufacturer data mask 565 * @throws Exception 566 */ 567 @Rpc(description = "Get ScanFilter's manufacturer data mask") bleGetScanFilterManufacturerDataMask( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)568 public byte[] bleGetScanFilterManufacturerDataMask( 569 @RpcParameter(name = "index") 570 Integer index, 571 @RpcParameter(name = "filterIndex") 572 Integer filterIndex) 573 throws Exception { 574 if (mScanFilterList.get(index) != null) { 575 if (mScanFilterList.get(index).get(filterIndex) != null) { 576 return mScanFilterList.get(index).get(filterIndex).getManufacturerDataMask(); 577 } else { 578 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 579 } 580 } else { 581 throw new Exception("Invalid index input:" + Integer.toString(index)); 582 } 583 } 584 585 /** 586 * Get ScanFilter's service data 587 * 588 * @param index the ScanFilter object to use 589 * @return the ScanFilter's service data 590 * @throws Exception 591 */ 592 @Rpc(description = "Get ScanFilter's service data") bleGetScanFilterServiceData( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)593 public byte[] bleGetScanFilterServiceData( 594 @RpcParameter(name = "index") 595 Integer index, 596 @RpcParameter(name = "filterIndex") 597 Integer filterIndex) 598 throws Exception { 599 if (mScanFilterList.get(index) != null) { 600 if (mScanFilterList.get(index).get(filterIndex) != null) { 601 return mScanFilterList.get(index).get(filterIndex).getServiceData(); 602 } else { 603 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 604 } 605 } else { 606 throw new Exception("Invalid index input:" + Integer.toString(index)); 607 } 608 } 609 610 /** 611 * Get ScanFilter's service data mask 612 * 613 * @param index the ScanFilter object to use 614 * @return the ScanFilter's service data mask 615 * @throws Exception 616 */ 617 @Rpc(description = "Get ScanFilter's service data mask") bleGetScanFilterServiceDataMask( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)618 public byte[] bleGetScanFilterServiceDataMask( 619 @RpcParameter(name = "index") 620 Integer index, 621 @RpcParameter(name = "filterIndex") 622 Integer filterIndex) 623 throws Exception { 624 if (mScanFilterList.get(index) != null) { 625 if (mScanFilterList.get(index).get(filterIndex) != null) { 626 return mScanFilterList.get(index).get(filterIndex).getServiceDataMask(); 627 } else { 628 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 629 } 630 } else { 631 throw new Exception("Invalid index input:" + Integer.toString(index)); 632 } 633 } 634 635 /** 636 * Get ScanFilter's service uuid 637 * 638 * @param index the ScanFilter object to use 639 * @return the ScanFilter's service uuid 640 * @throws Exception 641 */ 642 @Rpc(description = "Get ScanFilter's service uuid") bleGetScanFilterServiceUuid( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)643 public String bleGetScanFilterServiceUuid( 644 @RpcParameter(name = "index") 645 Integer index, 646 @RpcParameter(name = "filterIndex") 647 Integer filterIndex) 648 throws Exception { 649 if (mScanFilterList.get(index) != null) { 650 if (mScanFilterList.get(index).get(filterIndex) != null) { 651 if (mScanFilterList.get(index).get(filterIndex).getServiceUuid() != null) { 652 return mScanFilterList.get(index).get(filterIndex).getServiceUuid().toString(); 653 } else { 654 throw new Exception("No Service Uuid set for filter:" 655 + Integer.toString(filterIndex)); 656 } 657 } else { 658 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 659 } 660 } else { 661 throw new Exception("Invalid index input:" + Integer.toString(index)); 662 } 663 } 664 665 /** 666 * Get ScanFilter's service uuid mask 667 * 668 * @param index the ScanFilter object to use 669 * @return the ScanFilter's service uuid mask 670 * @throws Exception 671 */ 672 @Rpc(description = "Get ScanFilter's service uuid mask") bleGetScanFilterServiceUuidMask( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)673 public String bleGetScanFilterServiceUuidMask( 674 @RpcParameter(name = "index") 675 Integer index, 676 @RpcParameter(name = "filterIndex") 677 Integer filterIndex) 678 throws Exception { 679 if (mScanFilterList.get(index) != null) { 680 if (mScanFilterList.get(index).get(filterIndex) != null) { 681 if (mScanFilterList.get(index).get(filterIndex).getServiceUuidMask() != null) { 682 return mScanFilterList.get(index).get(filterIndex).getServiceUuidMask() 683 .toString(); 684 } else { 685 throw new Exception("No Service Uuid Mask set for filter:" 686 + Integer.toString(filterIndex)); 687 } 688 } else { 689 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex)); 690 } 691 } else { 692 throw new Exception("Invalid index input:" + Integer.toString(index)); 693 } 694 } 695 696 /** 697 * Add filter "macAddress" to existing ScanFilter 698 * 699 * @param macAddress the macAddress to filter against 700 * @throws Exception 701 */ 702 @Rpc(description = "Add filter \"macAddress\" to existing ScanFilter") bleSetScanFilterDeviceAddress( @pcParametername = "macAddress") String macAddress )703 public void bleSetScanFilterDeviceAddress( 704 @RpcParameter(name = "macAddress") 705 String macAddress 706 ) { 707 mScanFilterBuilder.setDeviceAddress(macAddress); 708 } 709 710 /** 711 * Add filter "manufacturereDataId and/or manufacturerData" to existing ScanFilter 712 * 713 * @param manufacturerDataId the manufacturer data id to filter against 714 * @param manufacturerDataMask the manufacturere data mask to filter against 715 * @throws Exception 716 */ 717 @Rpc(description = "Add filter \"manufacturereDataId and/or manufacturerData\" to existing ScanFilter") bleSetScanFilterManufacturerData( @pcParametername = "manufacturerDataId") Integer manufacturerDataId, @RpcParameter(name = "manufacturerData") byte[] manufacturerData, @RpcParameter(name = "manufacturerDataMask") @RpcOptional byte[] manufacturerDataMask )718 public void bleSetScanFilterManufacturerData( 719 @RpcParameter(name = "manufacturerDataId") 720 Integer manufacturerDataId, 721 @RpcParameter(name = "manufacturerData") 722 byte[] manufacturerData, 723 @RpcParameter(name = "manufacturerDataMask") 724 @RpcOptional 725 byte[] manufacturerDataMask 726 ){ 727 if (manufacturerDataMask != null) { 728 mScanFilterBuilder.setManufacturerData(manufacturerDataId, 729 manufacturerData, manufacturerDataMask); 730 } else { 731 mScanFilterBuilder.setManufacturerData(manufacturerDataId, 732 manufacturerData); 733 } 734 } 735 736 /** 737 * Add filter "serviceData and serviceDataMask" to existing ScanFilter 738 * 739 * @param serviceData the service data to filter against 740 * @param serviceDataMask the servie data mask to filter against 741 * @throws Exception 742 */ 743 @Rpc(description = "Add filter \"serviceData and serviceDataMask\" to existing ScanFilter ") bleSetScanFilterServiceData( @pcParametername = "serviceUuid") String serviceUuid, @RpcParameter(name = "serviceData") byte[] serviceData, @RpcParameter(name = "serviceDataMask") @RpcOptional byte[] serviceDataMask )744 public void bleSetScanFilterServiceData( 745 @RpcParameter(name = "serviceUuid") 746 String serviceUuid, 747 @RpcParameter(name = "serviceData") 748 byte[] serviceData, 749 @RpcParameter(name = "serviceDataMask") 750 @RpcOptional 751 byte[] serviceDataMask 752 ) { 753 if (serviceDataMask != null) { 754 mScanFilterBuilder 755 .setServiceData( 756 ParcelUuid.fromString(serviceUuid), 757 serviceData, serviceDataMask); 758 } else { 759 mScanFilterBuilder.setServiceData(ParcelUuid.fromString(serviceUuid), 760 serviceData); 761 } 762 } 763 764 /** 765 * Add filter "serviceUuid and/or serviceMask" to existing ScanFilter 766 * 767 * @param serviceUuid the service uuid to filter against 768 * @param serviceMask the service mask to filter against 769 * @throws Exception 770 */ 771 @Rpc(description = "Add filter \"serviceUuid and/or serviceMask\" to existing ScanFilter") bleSetScanFilterServiceUuid( @pcParametername = "serviceUuid") String serviceUuid, @RpcParameter(name = "serviceMask") @RpcOptional String serviceMask )772 public void bleSetScanFilterServiceUuid( 773 @RpcParameter(name = "serviceUuid") 774 String serviceUuid, 775 @RpcParameter(name = "serviceMask") 776 @RpcOptional 777 String serviceMask 778 ) { 779 if (serviceMask != null) { 780 mScanFilterBuilder 781 .setServiceUuid(ParcelUuid.fromString(serviceUuid), 782 ParcelUuid.fromString(serviceMask)); 783 } else { 784 mScanFilterBuilder.setServiceUuid(ParcelUuid.fromString(serviceUuid)); 785 } 786 } 787 788 /** 789 * Add filter "device name" to existing ScanFilter 790 * 791 * @param name the device name to filter against 792 * @throws Exception 793 */ 794 @Rpc(description = "Sets the scan filter's device name") bleSetScanFilterDeviceName( @pcParametername = "name") String name )795 public void bleSetScanFilterDeviceName( 796 @RpcParameter(name = "name") 797 String name 798 ) { 799 mScanFilterBuilder.setDeviceName(name); 800 } 801 802 @Rpc(description = "Set the scan setting's match mode") bleSetScanSettingsMatchMode( @pcParametername = "mode") Integer mode)803 public void bleSetScanSettingsMatchMode( 804 @RpcParameter(name = "mode") Integer mode) { 805 mScanSettingsBuilder.setMatchMode(mode); 806 } 807 808 @Rpc(description = "Get the scan setting's match mode") bleGetScanSettingsMatchMode( @pcParametername = "scanSettingsIndex") Integer scanSettingsIndex )809 public int bleGetScanSettingsMatchMode( 810 @RpcParameter(name = "scanSettingsIndex") Integer scanSettingsIndex 811 ) { 812 return mScanSettingsList.get(scanSettingsIndex).getMatchMode(); 813 } 814 815 @Rpc(description = "Set the scan setting's number of matches") bleSetScanSettingsNumOfMatches( @pcParametername = "matches") Integer matches)816 public void bleSetScanSettingsNumOfMatches( 817 @RpcParameter(name = "matches") Integer matches) { 818 mScanSettingsBuilder.setNumOfMatches(matches); 819 } 820 821 @Rpc(description = "Get the scan setting's number of matches") bleGetScanSettingsNumberOfMatches( @pcParametername = "scanSettingsIndex") Integer scanSettingsIndex)822 public int bleGetScanSettingsNumberOfMatches( 823 @RpcParameter(name = "scanSettingsIndex") 824 Integer scanSettingsIndex) { 825 return mScanSettingsList.get(scanSettingsIndex).getNumOfMatches(); 826 } 827 828 private class myScanCallback extends ScanCallback { 829 public Integer index; 830 String mEventType; 831 private final Bundle mResults; 832 myScanCallback(Integer idx)833 public myScanCallback(Integer idx) { 834 index = idx; 835 mEventType = "BleScan"; 836 mResults = new Bundle(); 837 } 838 839 @Override onScanFailed(int errorCode)840 public void onScanFailed(int errorCode) { 841 String errorString = "UNKNOWN_ERROR_CODE"; 842 if (errorCode == ScanCallback.SCAN_FAILED_ALREADY_STARTED) { 843 errorString = "SCAN_FAILED_ALREADY_STARTED"; 844 } else if (errorCode == ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED) { 845 errorString = "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED"; 846 } else if (errorCode == ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED) { 847 errorString = "SCAN_FAILED_FEATURE_UNSUPPORTED"; 848 } else if (errorCode == ScanCallback.SCAN_FAILED_INTERNAL_ERROR) { 849 errorString = "SCAN_FAILED_INTERNAL_ERROR"; 850 } 851 Log.d("bluetooth_le_scan change onScanFailed " + mEventType + " " + index + " error " 852 + errorString); 853 mResults.putInt("ID", index); 854 mResults.putString("Type", "onScanFailed"); 855 mResults.putInt("ErrorCode", errorCode); 856 mResults.putString("Error", errorString); 857 mEventFacade.postEvent(mEventType + index + "onScanFailed", 858 mResults.clone()); 859 mResults.clear(); 860 } 861 862 @Override onScanResult(int callbackType, ScanResult result)863 public void onScanResult(int callbackType, ScanResult result) { 864 Log.d("bluetooth_le_scan change onUpdate " + mEventType + " " + index); 865 mResults.putInt("ID", index); 866 mResults.putInt("CallbackType", callbackType); 867 mResults.putString("Type", "onScanResult"); 868 mResults.putParcelable("Result", result); 869 mEventFacade.postEvent(mEventType + index + "onScanResults", mResults.clone()); 870 mResults.clear(); 871 } 872 873 @Override onBatchScanResults(List<ScanResult> results)874 public void onBatchScanResults(List<ScanResult> results) { 875 Log.d("reportResult " + mEventType + " " + index); 876 mResults.putLong("Timestamp", System.currentTimeMillis() / 1000); 877 mResults.putInt("ID", index); 878 mResults.putString("Type", "onBatchScanResults"); 879 mResults.putParcelableList("Results", results); 880 mEventFacade.postEvent(mEventType + index + "onBatchScanResult", mResults.clone()); 881 mResults.clear(); 882 } 883 } 884 885 private class myLeScanCallback implements LeScanCallback { 886 public Integer index; 887 String mEventType; 888 private final Bundle mResults; 889 myLeScanCallback(Integer idx)890 public myLeScanCallback(Integer idx) { 891 index = idx; 892 mEventType = "ClassicBleScan"; 893 mResults = new Bundle(); 894 } 895 896 @Override onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)897 public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { 898 Log.d("bluetooth_classic_le_scan " + mEventType + " " + index); 899 mResults.putParcelable("Device", device); 900 mResults.putInt("Rssi", rssi); 901 mResults.putByteArray("ScanRecord", scanRecord); 902 mResults.putString("Type", "onLeScan"); 903 mEventFacade.postEvent(mEventType + index + "onLeScan", mResults.clone()); 904 mResults.clear(); 905 } 906 } 907 908 @Override shutdown()909 public void shutdown() { 910 if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) { 911 for (myScanCallback mScanCallback : mScanCallbackList.values()) { 912 if (mScanCallback != null) { 913 try { 914 mBluetoothAdapter.getBluetoothLeScanner() 915 .stopScan(mScanCallback); 916 } catch (NullPointerException e) { 917 Log.e("Failed to stop ble scan callback.", e); 918 } 919 } 920 } 921 for (myLeScanCallback mLeScanCallback : mLeScanCallbackList.values()) { 922 if (mLeScanCallback != null) { 923 try { 924 mBluetoothAdapter.stopLeScan(mLeScanCallback); 925 } catch (NullPointerException e) { 926 Log.e("Failed to stop classic ble scan callback.", e); 927 } 928 } 929 } 930 } 931 mScanCallbackList.clear(); 932 mScanFilterList.clear(); 933 mScanSettingsList.clear(); 934 mLeScanCallbackList.clear(); 935 } 936 } 937