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.wifi; 18 19 import java.util.Arrays; 20 import java.util.Iterator; 21 import java.util.List; 22 import java.util.Set; 23 import java.util.concurrent.Callable; 24 import java.util.concurrent.ConcurrentHashMap; 25 26 import org.json.JSONArray; 27 import org.json.JSONException; 28 import org.json.JSONObject; 29 30 import com.googlecode.android_scripting.Log; 31 import com.googlecode.android_scripting.MainThread; 32 import com.googlecode.android_scripting.facade.EventFacade; 33 import com.googlecode.android_scripting.facade.FacadeManager; 34 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 35 import com.googlecode.android_scripting.rpc.Rpc; 36 import com.googlecode.android_scripting.rpc.RpcOptional; 37 import com.googlecode.android_scripting.rpc.RpcParameter; 38 39 import android.app.Service; 40 import android.content.Context; 41 import android.net.wifi.ScanResult; 42 import android.net.wifi.WifiScanner; 43 import android.net.wifi.WifiScanner.BssidInfo; 44 import android.net.wifi.WifiScanner.ChannelSpec; 45 import android.net.wifi.WifiScanner.ScanData; 46 import android.net.wifi.WifiScanner.ScanSettings; 47 import android.os.Bundle; 48 import android.os.SystemClock; 49 import android.provider.Settings.Global; 50 import android.provider.Settings.SettingNotFoundException; 51 52 /** 53 * WifiScanner functions. 54 */ 55 public class WifiScannerFacade extends RpcReceiver { 56 private final Service mService; 57 private final EventFacade mEventFacade; 58 private final WifiScanner mScan; 59 // These counters are just for indexing; 60 // they do not represent the total number of listeners 61 private static int WifiScanListenerCnt; 62 private static int WifiChangeListenerCnt; 63 private static int WifiBssidListenerCnt; 64 private final ConcurrentHashMap<Integer, WifiScanListener> scanListeners; 65 private final ConcurrentHashMap<Integer, WifiScanListener> scanBackgroundListeners; 66 private final ConcurrentHashMap<Integer, ChangeListener> trackChangeListeners; 67 private final ConcurrentHashMap<Integer, WifiBssidListener> trackBssidListeners; 68 private static ConcurrentHashMap<Integer, ScanResult[]> wifiScannerResultList; 69 private static ConcurrentHashMap<Integer, ScanData[]> wifiScannerDataList; 70 WifiScannerFacade(FacadeManager manager)71 public WifiScannerFacade(FacadeManager manager) { 72 super(manager); 73 mService = manager.getService(); 74 mScan = (WifiScanner) mService.getSystemService(Context.WIFI_SCANNING_SERVICE); 75 mEventFacade = manager.getReceiver(EventFacade.class); 76 scanListeners = new ConcurrentHashMap<Integer, WifiScanListener>(); 77 scanBackgroundListeners = new ConcurrentHashMap<Integer, WifiScanListener>(); 78 trackChangeListeners = new ConcurrentHashMap<Integer, ChangeListener>(); 79 trackBssidListeners = new ConcurrentHashMap<Integer, WifiBssidListener>(); 80 wifiScannerResultList = new ConcurrentHashMap<Integer, ScanResult[]>(); 81 wifiScannerDataList = new ConcurrentHashMap<Integer, ScanData[]>(); 82 } 83 getWifiScanResult(Integer listenerIndex)84 public static List<ScanResult> getWifiScanResult(Integer listenerIndex) { 85 ScanResult[] sr = wifiScannerResultList.get(listenerIndex); 86 return Arrays.asList(sr); 87 } 88 89 private class WifiActionListener implements WifiScanner.ActionListener { 90 private final Bundle mResults; 91 public int mIndex; 92 protected String mEventType; 93 private long startScanElapsedRealTime; 94 WifiActionListener(String type, int idx, Bundle resultBundle, long startScanERT)95 public WifiActionListener(String type, int idx, Bundle resultBundle, long startScanERT) { 96 this.mIndex = idx; 97 this.mEventType = type; 98 this.mResults = resultBundle; 99 this.startScanElapsedRealTime = startScanERT; 100 } 101 102 @Override onSuccess()103 public void onSuccess() { 104 Log.d("onSuccess " + mEventType + " " + mIndex); 105 mResults.putString("Type", "onSuccess"); 106 mResults.putInt("Index", mIndex); 107 mResults.putLong("ScanElapsedRealtime", startScanElapsedRealTime); 108 mEventFacade.postEvent(mEventType + mIndex + "onSuccess", mResults.clone()); 109 mResults.clear(); 110 } 111 112 @Override onFailure(int reason, String description)113 public void onFailure(int reason, String description) { 114 Log.d("onFailure " + mEventType + " " + mIndex); 115 mResults.putString("Type", "onFailure"); 116 mResults.putInt("Index", mIndex); 117 mResults.putInt("Reason", reason); 118 mResults.putString("Description", description); 119 mEventFacade.postEvent(mEventType + mIndex + "onFailure", mResults.clone()); 120 mResults.clear(); 121 } 122 reportResult(ScanResult[] results, String type)123 public void reportResult(ScanResult[] results, String type) { 124 Log.d("reportResult " + mEventType + " " + mIndex); 125 mResults.putInt("Index", mIndex); 126 mResults.putLong("ResultElapsedRealtime", SystemClock.elapsedRealtime()); 127 mResults.putString("Type", type); 128 mResults.putParcelableArray("Results", results); 129 mEventFacade.postEvent(mEventType + mIndex + type, mResults.clone()); 130 mResults.clear(); 131 } 132 } 133 134 /** 135 * Constructs a wifiScanListener obj and returns it 136 * 137 * @return WifiScanListener 138 */ genWifiScanListener()139 private WifiScanListener genWifiScanListener() { 140 WifiScanListener mWifiScannerListener = MainThread.run(mService, 141 new Callable<WifiScanListener>() { 142 @Override 143 public WifiScanListener call() throws Exception { 144 return new WifiScanListener(); 145 } 146 }); 147 scanListeners.put(mWifiScannerListener.mIndex, mWifiScannerListener); 148 return mWifiScannerListener; 149 } 150 151 /** 152 * Constructs a wifiScanListener obj for background scan and returns it 153 * 154 * @return WifiScanListener 155 */ genBackgroundWifiScanListener()156 private WifiScanListener genBackgroundWifiScanListener() { 157 WifiScanListener mWifiScannerListener = MainThread.run(mService, 158 new Callable<WifiScanListener>() { 159 @Override 160 public WifiScanListener call() throws Exception { 161 return new WifiScanListener(); 162 } 163 }); 164 scanBackgroundListeners.put(mWifiScannerListener.mIndex, mWifiScannerListener); 165 return mWifiScannerListener; 166 } 167 168 private class WifiScanListener implements WifiScanner.ScanListener { 169 private static final String mEventType = "WifiScannerScan"; 170 protected final Bundle mScanResults; 171 protected final Bundle mScanData; 172 private final WifiActionListener mWAL; 173 public int mIndex; 174 WifiScanListener()175 public WifiScanListener() { 176 mScanResults = new Bundle(); 177 mScanData = new Bundle(); 178 WifiScanListenerCnt += 1; 179 mIndex = WifiScanListenerCnt; 180 mWAL = new WifiActionListener(mEventType, mIndex, mScanResults, 181 SystemClock.elapsedRealtime()); 182 } 183 184 @Override onSuccess()185 public void onSuccess() { 186 mWAL.onSuccess(); 187 } 188 189 @Override onFailure(int reason, String description)190 public void onFailure(int reason, String description) { 191 scanListeners.remove(mIndex); 192 mWAL.onFailure(reason, description); 193 } 194 195 @Override onPeriodChanged(int periodInMs)196 public void onPeriodChanged(int periodInMs) { 197 Log.d("onPeriodChanged " + mEventType + " " + mIndex); 198 mScanResults.putString("Type", "onPeriodChanged"); 199 mScanResults.putInt("NewPeriod", periodInMs); 200 mEventFacade.postEvent(mEventType + mIndex, mScanResults.clone()); 201 mScanResults.clear(); 202 } 203 204 @Override onFullResult(ScanResult fullScanResult)205 public void onFullResult(ScanResult fullScanResult) { 206 Log.d("onFullResult WifiScanListener " + mIndex); 207 mWAL.reportResult(new ScanResult[] { 208 fullScanResult 209 }, "onFullResult"); 210 } 211 onResults(ScanData[] results)212 public void onResults(ScanData[] results) { 213 Log.d("onResult WifiScanListener " + mIndex); 214 wifiScannerDataList.put(mIndex, results); 215 mScanData.putInt("Index", mIndex); 216 mScanData.putLong("ResultElapsedRealtime", SystemClock.elapsedRealtime()); 217 mScanData.putString("Type", "onResults"); 218 mScanData.putParcelableArray("Results", results); 219 mEventFacade.postEvent(mEventType + mIndex + "onResults", mScanData.clone()); 220 mScanData.clear(); 221 } 222 } 223 224 /** 225 * Constructs a ChangeListener obj and returns it 226 * 227 * @return ChangeListener 228 */ genWifiChangeListener()229 private ChangeListener genWifiChangeListener() { 230 ChangeListener mWifiChangeListener = MainThread.run(mService, 231 new Callable<ChangeListener>() { 232 @Override 233 public ChangeListener call() throws Exception { 234 return new ChangeListener(); 235 } 236 }); 237 trackChangeListeners.put(mWifiChangeListener.mIndex, mWifiChangeListener); 238 return mWifiChangeListener; 239 } 240 241 private class ChangeListener implements WifiScanner.WifiChangeListener { 242 private static final String mEventType = "WifiScannerChange"; 243 protected final Bundle mResults; 244 private final WifiActionListener mWAL; 245 public int mIndex; 246 ChangeListener()247 public ChangeListener() { 248 mResults = new Bundle(); 249 WifiChangeListenerCnt += 1; 250 mIndex = WifiChangeListenerCnt; 251 mWAL = new WifiActionListener(mEventType, mIndex, mResults, 252 SystemClock.elapsedRealtime()); 253 } 254 255 @Override onSuccess()256 public void onSuccess() { 257 mWAL.onSuccess(); 258 } 259 260 @Override onFailure(int reason, String description)261 public void onFailure(int reason, String description) { 262 trackChangeListeners.remove(mIndex); 263 mWAL.onFailure(reason, description); 264 } 265 266 /** 267 * indicates that changes were detected in wifi environment 268 * 269 * @param results indicate the access points that exhibited change 270 */ 271 @Override onChanging(ScanResult[] results)272 public void onChanging(ScanResult[] results) { /* changes are found */ 273 mWAL.reportResult(results, "onChanging"); 274 } 275 276 /** 277 * indicates that no wifi changes are being detected for a while 278 * 279 * @param results indicate the access points that are bing monitored for change 280 */ 281 @Override onQuiescence(ScanResult[] results)282 public void onQuiescence(ScanResult[] results) { /* changes settled down */ 283 mWAL.reportResult(results, "onQuiescence"); 284 } 285 } 286 genWifiBssidListener()287 private WifiBssidListener genWifiBssidListener() { 288 WifiBssidListener mWifiBssidListener = MainThread.run(mService, 289 new Callable<WifiBssidListener>() { 290 @Override 291 public WifiBssidListener call() throws Exception { 292 return new WifiBssidListener(); 293 } 294 }); 295 trackBssidListeners.put(mWifiBssidListener.mIndex, mWifiBssidListener); 296 return mWifiBssidListener; 297 } 298 299 private class WifiBssidListener implements WifiScanner.BssidListener { 300 private static final String mEventType = "WifiScannerBssid"; 301 protected final Bundle mResults; 302 private final WifiActionListener mWAL; 303 public int mIndex; 304 WifiBssidListener()305 public WifiBssidListener() { 306 mResults = new Bundle(); 307 WifiBssidListenerCnt += 1; 308 mIndex = WifiBssidListenerCnt; 309 mWAL = new WifiActionListener(mEventType, mIndex, mResults, 310 SystemClock.elapsedRealtime()); 311 } 312 313 @Override onSuccess()314 public void onSuccess() { 315 mWAL.onSuccess(); 316 } 317 318 @Override onFailure(int reason, String description)319 public void onFailure(int reason, String description) { 320 trackBssidListeners.remove(mIndex); 321 mWAL.onFailure(reason, description); 322 } 323 324 @Override onFound(ScanResult[] results)325 public void onFound(ScanResult[] results) { 326 mWAL.reportResult(results, "onFound"); 327 } 328 329 @Override onLost(ScanResult[] results)330 public void onLost(ScanResult[] results) { 331 mWAL.reportResult(results, "onLost"); 332 } 333 } 334 parseScanSettings(JSONObject j)335 private ScanSettings parseScanSettings(JSONObject j) throws JSONException { 336 if (j == null) { 337 return null; 338 } 339 ScanSettings result = new ScanSettings(); 340 if (j.has("band")) { 341 result.band = j.optInt("band"); 342 } 343 if (j.has("channels")) { 344 JSONArray chs = j.getJSONArray("channels"); 345 ChannelSpec[] channels = new ChannelSpec[chs.length()]; 346 for (int i = 0; i < channels.length; i++) { 347 channels[i] = new ChannelSpec(chs.getInt(i)); 348 } 349 result.channels = channels; 350 } 351 if (j.has("maxScansToCache")) { 352 result.maxScansToCache = j.getInt("maxScansToCache"); 353 } 354 /* periodInMs and reportEvents are required */ 355 result.periodInMs = j.getInt("periodInMs"); 356 if (j.has("maxPeriodInMs")) { 357 result.maxPeriodInMs = j.getInt("maxPeriodInMs"); 358 } 359 if (j.has("stepCount")) { 360 result.stepCount = j.getInt("stepCount"); 361 } 362 result.reportEvents = j.getInt("reportEvents"); 363 if (j.has("numBssidsPerScan")) { 364 result.numBssidsPerScan = j.getInt("numBssidsPerScan"); 365 } 366 return result; 367 } 368 parseBssidInfo(JSONArray jBssids)369 private BssidInfo[] parseBssidInfo(JSONArray jBssids) throws JSONException { 370 BssidInfo[] bssids = new BssidInfo[jBssids.length()]; 371 for (int i = 0; i < bssids.length; i++) { 372 JSONObject bi = (JSONObject) jBssids.get(i); 373 BssidInfo bssidInfo = new BssidInfo(); 374 bssidInfo.bssid = bi.getString("BSSID"); 375 bssidInfo.high = bi.getInt("high"); 376 bssidInfo.low = bi.getInt("low"); 377 if (bi.has("frequencyHint")) { 378 bssidInfo.frequencyHint = bi.getInt("frequencyHint"); 379 } 380 bssids[i] = bssidInfo; 381 } 382 return bssids; 383 } 384 385 /** 386 * Starts periodic WifiScanner scan 387 * 388 * @param scanSettings 389 * @return the id of the scan listener associated with this scan 390 * @throws JSONException 391 */ 392 @Rpc(description = "Starts a WifiScanner Background scan") wifiScannerStartBackgroundScan( @pcParametername = "scanSettings") JSONObject scanSettings)393 public Integer wifiScannerStartBackgroundScan( 394 @RpcParameter(name = "scanSettings") JSONObject scanSettings) 395 throws JSONException { 396 ScanSettings ss = parseScanSettings(scanSettings); 397 Log.d("startWifiScannerScan with " + ss.channels); 398 WifiScanListener listener = genBackgroundWifiScanListener(); 399 mScan.startBackgroundScan(ss, listener); 400 return listener.mIndex; 401 } 402 403 /** 404 * Get currently available scan results on appropriate listeners 405 * 406 * @return true if all scan results were reported correctly 407 * @throws JSONException 408 */ 409 @Rpc(description = "Get currently available scan results on appropriate listeners") wifiScannerGetScanResults()410 public Boolean wifiScannerGetScanResults() throws JSONException { 411 mScan.getScanResults(); 412 return true; 413 } 414 415 /** 416 * Stops a WifiScanner scan 417 * 418 * @param listenerIndex the id of the scan listener whose scan to stop 419 * @throws Exception 420 */ 421 @Rpc(description = "Stops an ongoing WifiScanner Background scan") wifiScannerStopBackgroundScan( @pcParametername = "listener") Integer listenerIndex)422 public void wifiScannerStopBackgroundScan( 423 @RpcParameter(name = "listener") Integer listenerIndex) 424 throws Exception { 425 if (!scanBackgroundListeners.containsKey(listenerIndex)) { 426 throw new Exception("Background scan session " + listenerIndex + " does not exist"); 427 } 428 WifiScanListener listener = scanBackgroundListeners.get(listenerIndex); 429 Log.d("stopWifiScannerScan listener " + listener.mIndex); 430 mScan.stopBackgroundScan(listener); 431 wifiScannerResultList.remove(listenerIndex); 432 scanBackgroundListeners.remove(listenerIndex); 433 } 434 435 /** 436 * Starts periodic WifiScanner scan 437 * 438 * @param scanSettings 439 * @return the id of the scan listener associated with this scan 440 * @throws JSONException 441 */ 442 @Rpc(description = "Starts a WifiScanner single scan") wifiScannerStartScan( @pcParametername = "scanSettings") JSONObject scanSettings)443 public Integer wifiScannerStartScan( 444 @RpcParameter(name = "scanSettings") JSONObject scanSettings) 445 throws JSONException { 446 ScanSettings ss = parseScanSettings(scanSettings); 447 Log.d("startWifiScannerScan with " + ss.channels); 448 WifiScanListener listener = genWifiScanListener(); 449 mScan.startScan(ss, listener); 450 return listener.mIndex; 451 } 452 453 /** 454 * Stops a WifiScanner scan 455 * 456 * @param listenerIndex the id of the scan listener whose scan to stop 457 * @throws Exception 458 */ 459 @Rpc(description = "Stops an ongoing WifiScanner Single scan") wifiScannerStopScan(@pcParametername = "listener") Integer listenerIndex)460 public void wifiScannerStopScan(@RpcParameter(name = "listener") Integer listenerIndex) 461 throws Exception { 462 if (!scanListeners.containsKey(listenerIndex)) { 463 throw new Exception("Single scan session " + listenerIndex + " does not exist"); 464 } 465 WifiScanListener listener = scanListeners.get(listenerIndex); 466 Log.d("stopWifiScannerScan listener " + listener.mIndex); 467 mScan.stopScan(listener); 468 wifiScannerResultList.remove(listener.mIndex); 469 scanListeners.remove(listenerIndex); 470 } 471 472 /** RPC Methods */ 473 @Rpc(description = "Returns the channels covered by the specified band number.") wifiScannerGetAvailableChannels( @pcParametername = "band") Integer band)474 public List<Integer> wifiScannerGetAvailableChannels( 475 @RpcParameter(name = "band") Integer band) { 476 return mScan.getAvailableChannels(band); 477 } 478 479 /** 480 * Starts tracking wifi changes 481 * 482 * @return the id of the change listener associated with this track 483 * @throws Exception 484 */ 485 @Rpc(description = "Starts tracking wifi changes") wifiScannerStartTrackingChange()486 public Integer wifiScannerStartTrackingChange() throws Exception { 487 ChangeListener listener = genWifiChangeListener(); 488 mScan.startTrackingWifiChange(listener); 489 return listener.mIndex; 490 } 491 492 /** 493 * Stops tracking wifi changes 494 * 495 * @param listenerIndex the id of the change listener whose track to stop 496 * @throws Exception 497 */ 498 @Rpc(description = "Stops tracking wifi changes") wifiScannerStopTrackingChange( @pcParametername = "listener") Integer listenerIndex)499 public void wifiScannerStopTrackingChange( 500 @RpcParameter(name = "listener") Integer listenerIndex) throws Exception { 501 if (!trackChangeListeners.containsKey(listenerIndex)) { 502 throw new Exception("Wifi change tracking session " + listenerIndex 503 + " does not exist"); 504 } 505 ChangeListener listener = trackChangeListeners.get(listenerIndex); 506 mScan.stopTrackingWifiChange(listener); 507 trackChangeListeners.remove(listenerIndex); 508 } 509 510 /** 511 * Starts tracking changes of the specified bssids. 512 * 513 * @param bssidInfos An array of json strings, each representing a BssidInfo object. 514 * @param apLostThreshold 515 * @return The index of the listener used to start the tracking. 516 * @throws JSONException 517 */ 518 @Rpc(description = "Starts tracking changes of the specified bssids.") wifiScannerStartTrackingBssids( @pcParametername = "bssidInfos") JSONArray bssidInfos, @RpcParameter(name = "apLostThreshold") Integer apLostThreshold)519 public Integer wifiScannerStartTrackingBssids( 520 @RpcParameter(name = "bssidInfos") JSONArray bssidInfos, 521 @RpcParameter(name = "apLostThreshold") Integer apLostThreshold) throws JSONException { 522 BssidInfo[] bssids = parseBssidInfo(bssidInfos); 523 WifiBssidListener listener = genWifiBssidListener(); 524 mScan.startTrackingBssids(bssids, apLostThreshold, listener); 525 return listener.mIndex; 526 } 527 528 /** 529 * Stops tracking the list of APs associated with the input listener 530 * 531 * @param listenerIndex the id of the bssid listener whose track to stop 532 * @throws Exception 533 */ 534 @Rpc(description = "Stops tracking changes in the APs on the list") wifiScannerStopTrackingBssids( @pcParametername = "listener") Integer listenerIndex)535 public void wifiScannerStopTrackingBssids( 536 @RpcParameter(name = "listener") Integer listenerIndex) throws Exception { 537 if (!trackBssidListeners.containsKey(listenerIndex)) { 538 throw new Exception("Bssid tracking session " + listenerIndex + " does not exist"); 539 } 540 WifiBssidListener listener = trackBssidListeners.get(listenerIndex); 541 mScan.stopTrackingBssids(listener); 542 trackBssidListeners.remove(listenerIndex); 543 } 544 545 @Rpc(description = "Toggle the 'WiFi scan always available' option. If an input is given, the " 546 + "option is set to what the input boolean indicates.") wifiScannerToggleAlwaysAvailable( @pcParametername = "alwaysAvailable") @pcOptional Boolean alwaysAvailable)547 public void wifiScannerToggleAlwaysAvailable( 548 @RpcParameter(name = "alwaysAvailable") @RpcOptional Boolean alwaysAvailable) 549 throws SettingNotFoundException { 550 int new_state = 0; 551 if (alwaysAvailable == null) { 552 int current_state = Global.getInt(mService.getContentResolver(), 553 Global.WIFI_SCAN_ALWAYS_AVAILABLE); 554 new_state = current_state ^ 0x1; 555 } else { 556 new_state = alwaysAvailable ? 1 : 0; 557 } 558 Global.putInt(mService.getContentResolver(), Global.WIFI_SCAN_ALWAYS_AVAILABLE, new_state); 559 } 560 561 @Rpc(description = "Returns true if WiFi scan is always available, false otherwise.") wifiScannerIsAlwaysAvailable()562 public Boolean wifiScannerIsAlwaysAvailable() throws SettingNotFoundException { 563 int current_state = Global.getInt(mService.getContentResolver(), 564 Global.WIFI_SCAN_ALWAYS_AVAILABLE); 565 if (current_state == 1) { 566 return true; 567 } 568 return false; 569 } 570 571 @Rpc(description = "Returns a list of mIndexes of existing listeners") wifiGetCurrentScanIndexes()572 public Set<Integer> wifiGetCurrentScanIndexes() { 573 return scanListeners.keySet(); 574 } 575 576 /** 577 * Starts tracking wifi changes 578 * 579 * @return the id of the change listener associated with this track 580 * @throws Exception 581 */ 582 @Rpc(description = "Starts tracking wifi changes with track settings") wifiScannerStartTrackingChangeWithSetting( @pcParametername = "trackSettings") JSONArray bssidSettings, @RpcParameter(name = "rssiSS") Integer rssiSS, @RpcParameter(name = "lostApSS") Integer lostApSS, @RpcParameter(name = "unchangedSS") Integer unchangedSS, @RpcParameter(name = "minApsBreachingThreshold") Integer minApsBreachingThreshold, @RpcParameter(name = "periodInMs") Integer periodInMs)583 public Integer wifiScannerStartTrackingChangeWithSetting( 584 @RpcParameter(name = "trackSettings") JSONArray bssidSettings, 585 @RpcParameter(name = "rssiSS") Integer rssiSS, 586 @RpcParameter(name = "lostApSS") Integer lostApSS, 587 @RpcParameter(name = "unchangedSS") Integer unchangedSS, 588 @RpcParameter(name = "minApsBreachingThreshold") Integer minApsBreachingThreshold, 589 @RpcParameter(name = "periodInMs") Integer periodInMs) throws Exception { 590 Log.d("starting change track with track settings"); 591 BssidInfo[] bssids = parseBssidInfo(bssidSettings); 592 mScan.configureWifiChange(rssiSS, lostApSS, unchangedSS, minApsBreachingThreshold, 593 periodInMs, bssids); 594 ChangeListener listener = genWifiChangeListener(); 595 mScan.startTrackingWifiChange(listener); 596 return listener.mIndex; 597 } 598 599 /** 600 * Shuts down all activities associated with WifiScanner 601 */ 602 @Rpc(description = "Shuts down all WifiScanner activities and remove listeners.") wifiScannerShutdown()603 public void wifiScannerShutdown() { 604 this.shutdown(); 605 } 606 607 /** 608 * Stops all activity 609 */ 610 @Override shutdown()611 public void shutdown() { 612 try { 613 if (!scanListeners.isEmpty()) { 614 Iterator<ConcurrentHashMap.Entry<Integer, WifiScanListener>> iter = scanListeners 615 .entrySet().iterator(); 616 while (iter.hasNext()) { 617 ConcurrentHashMap.Entry<Integer, WifiScanListener> entry = iter.next(); 618 this.wifiScannerStopScan(entry.getKey()); 619 } 620 } 621 if (!scanBackgroundListeners.isEmpty()) { 622 Iterator<ConcurrentHashMap.Entry<Integer, WifiScanListener>> iter = scanBackgroundListeners 623 .entrySet().iterator(); 624 while (iter.hasNext()) { 625 ConcurrentHashMap.Entry<Integer, WifiScanListener> entry = iter.next(); 626 this.wifiScannerStopBackgroundScan(entry.getKey()); 627 } 628 } 629 if (!trackChangeListeners.isEmpty()) { 630 Iterator<ConcurrentHashMap.Entry<Integer, ChangeListener>> iter = trackChangeListeners 631 .entrySet().iterator(); 632 while (iter.hasNext()) { 633 ConcurrentHashMap.Entry<Integer, ChangeListener> entry = iter.next(); 634 this.wifiScannerStopTrackingChange(entry.getKey()); 635 } 636 } 637 if (!trackBssidListeners.isEmpty()) { 638 Iterator<ConcurrentHashMap.Entry<Integer, WifiBssidListener>> iter = trackBssidListeners 639 .entrySet().iterator(); 640 while (iter.hasNext()) { 641 ConcurrentHashMap.Entry<Integer, WifiBssidListener> entry = iter.next(); 642 this.wifiScannerStopTrackingBssids(entry.getKey()); 643 } 644 } 645 } catch (Exception e) { 646 Log.e("Shutdown failed: " + e.toString()); 647 } 648 } 649 } 650