summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Wills <mwills@google.com>2016-01-29 23:33:50 +0000
committerAndroid Partner Code Review <android-gerrit-partner@google.com>2016-01-29 23:33:50 +0000
commit6788fcec7c1f46563aaf30e8cc1e8e7cb7773c60 (patch)
treea4e3a075696aeae8bd6d729e47f7c297211c6bd1
parentaae3592ef5a6fb1031a405248e40ce8727f3a3b9 (diff)
parent772124d1f1ddb2b9537de5efc748943808dafe80 (diff)
Merge "Refactor WifiScanner support for oneshot scans" into mm-wireless-dev
-rw-r--r--service/java/com/android/server/wifi/HalWifiScannerImpl.java32
-rw-r--r--service/java/com/android/server/wifi/ScanDetailUtil.java41
-rw-r--r--service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java39
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java35
-rw-r--r--service/java/com/android/server/wifi/WifiScanningScheduler.java16
-rw-r--r--service/java/com/android/server/wifi/WifiScanningServiceImpl.java513
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java99
-rw-r--r--tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java17
-rw-r--r--tests/wifitests/src/com/android/server/wifi/HalWifiScannerTest.java12
-rw-r--r--tests/wifitests/src/com/android/server/wifi/MultiClientSchedulerTest.java51
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ScanResults.java30
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java75
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java41
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiScanningServiceTest.java507
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java43
15 files changed, 1224 insertions, 327 deletions
diff --git a/service/java/com/android/server/wifi/HalWifiScannerImpl.java b/service/java/com/android/server/wifi/HalWifiScannerImpl.java
index fc5d18f4a..dc6fc1b61 100644
--- a/service/java/com/android/server/wifi/HalWifiScannerImpl.java
+++ b/service/java/com/android/server/wifi/HalWifiScannerImpl.java
@@ -50,14 +50,10 @@ public class HalWifiScannerImpl extends WifiScannerImpl implements Handler.Callb
mWifiNative = wifiNative;
mEventHandler = new Handler(looper, this);
- // We can't enable these until WifiStateMachine switches to using WifiScanner because
- // WifiMonitor only supports sending results to one listener
- // TODO Enable these
- // Also need to fix tests again when this is enabled
- // WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- // WifiMonitor.SCAN_FAILED_EVENT, mEventHandler);
- // WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- // WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler);
+ WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
+ WifiMonitor.SCAN_FAILED_EVENT, mEventHandler);
+ WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
+ WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler);
}
@Override
@@ -66,7 +62,9 @@ public class HalWifiScannerImpl extends WifiScannerImpl implements Handler.Callb
case WifiMonitor.SCAN_FAILED_EVENT:
Log.w(TAG, "Single scan failed");
if (mSingleScanEventHandler != null) {
- // TODO indicate failure to caller
+ if (mSingleScanEventHandler != null) {
+ mSingleScanEventHandler.onScanStatus(WifiNative.WIFI_SCAN_DISABLED);
+ }
mSingleScanEventHandler = null;
}
break;
@@ -116,9 +114,17 @@ public class HalWifiScannerImpl extends WifiScannerImpl implements Handler.Callb
}
mSingleScanEventHandler = eventHandler;
- if (!mWifiNative.scan(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, freqs)) {
- mSingleScanEventHandler = null;
- // TODO call on failure callback in handler
+ if (!mWifiNative.scan(freqs)) {
+ Log.e(TAG, "Failed to start scan, freqs=" + freqs);
+ // indicate scan failure async
+ mEventHandler.post(new Runnable() {
+ public void run() {
+ if (mSingleScanEventHandler != null) {
+ mSingleScanEventHandler.onScanStatus(WifiNative.WIFI_SCAN_DISABLED);
+ }
+ mSingleScanEventHandler = null;
+ }
+ });
}
return true;
}
@@ -148,7 +154,7 @@ public class HalWifiScannerImpl extends WifiScannerImpl implements Handler.Callb
Arrays.sort(results, SCAN_RESULT_SORT_COMPARATOR);
mLatestSingleScanResult = new WifiScanner.ScanData(0, 0, results);
if (mSingleScanEventHandler != null) {
- mSingleScanEventHandler.onScanResultsAvailable();
+ mSingleScanEventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
mSingleScanEventHandler = null;
}
}
diff --git a/service/java/com/android/server/wifi/ScanDetailUtil.java b/service/java/com/android/server/wifi/ScanDetailUtil.java
new file mode 100644
index 000000000..07eaafbb6
--- /dev/null
+++ b/service/java/com/android/server/wifi/ScanDetailUtil.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import android.net.wifi.ScanResult;
+
+import com.android.server.wifi.hotspot2.NetworkDetail;
+
+/**
+ * Utility for converting a ScanResult to a ScanDetail.
+ * Only fields that are suppported in ScanResult are copied.
+ */
+public class ScanDetailUtil {
+ private ScanDetailUtil() { /* not constructable */ }
+
+ public static ScanDetail toScanDetail(ScanResult scanResult) {
+ NetworkDetail networkDetail = new NetworkDetail(scanResult.BSSID,
+ scanResult.informationElements, scanResult.anqpLines, scanResult.frequency);
+ ScanDetail scanDetail = new ScanDetail(networkDetail, scanResult.wifiSsid,
+ scanResult.BSSID, scanResult.capabilities, scanResult.level, scanResult.frequency,
+ scanResult.timestamp);
+ scanDetail.getScanResult().informationElements = scanResult.informationElements;
+ scanDetail.getScanResult().anqpLines = scanResult.anqpLines;
+ return scanDetail;
+ }
+
+}
diff --git a/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java b/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java
index 78e213797..8c8b3f27d 100644
--- a/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantWifiScannerImpl.java
@@ -95,14 +95,10 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mEventHandler = new Handler(looper, this);
- // We can't enable these until WifiStateMachine switches to using WifiScanner because
- // WifiMonitor only supports sending results to one listener
- // TODO Enable these
- // Also need to fix tests again when this is enabled
- // WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- // WifiMonitor.SCAN_FAILED_EVENT, mEventHandler);
- // WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- // WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler);
+ WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
+ WifiMonitor.SCAN_FAILED_EVENT, mEventHandler);
+ WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
+ WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler);
}
@Override
@@ -115,6 +111,7 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
capabilities.max_hotlist_bssids = 0;
capabilities.max_significant_wifi_change_aps = 0;
// TODO reenable once scan results handlers are enabled again
+ // NOTE: this only disables background scan requests
return false;
}
@@ -255,7 +252,8 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
}
Set<Integer> freqs = new HashSet<>();
- LastScanSettings newScanSettings = new LastScanSettings(SystemClock.elapsedRealtime());
+ final LastScanSettings newScanSettings =
+ new LastScanSettings(SystemClock.elapsedRealtime());
// Update scan settings if there is a pending scan
if (!mBackgroundScanPaused) {
@@ -358,8 +356,7 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
}
if (freqs.size() > 0) {
- boolean success = mWifiNative.scan(
- WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, freqs);
+ boolean success = mWifiNative.scan(freqs);
if (success) {
// TODO handle scan timeout
Log.d(TAG, "Starting wifi scan for " + freqs.size() + " freqs"
@@ -367,8 +364,18 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
+ ", single=" + newScanSettings.singleScanActive);
mLastScanSettings = newScanSettings;
} else {
- Log.w(TAG, "Failed starting wifi scan for " + freqs.size() + " freqs");
- // TODO indicate failure for single and background scans
+ Log.e(TAG, "Failed to start scan, freqs=" + freqs);
+ // indicate scan failure async
+ mEventHandler.post(new Runnable() {
+ public void run() {
+ newScanSettings.singleScanActive = false;
+ if (newScanSettings.singleScanEventHandler != null) {
+ newScanSettings.singleScanEventHandler
+ .onScanStatus(WifiNative.WIFI_SCAN_DISABLED);
+ }
+ }
+ });
+ // TODO if scans fail enough background scans should be failed as well
}
}
}
@@ -457,7 +464,8 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
/ 100)
|| mBackgroundScanBuffer.size()
>= mLastScanSettings.reportNumScansThreshold))) {
- mBackgroundScanEventHandler.onScanStatus();
+ mBackgroundScanEventHandler
+ .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
}
}
@@ -484,7 +492,8 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
Collections.sort(singleScanResults, SCAN_RESULT_SORT_COMPARATOR);
mLatestSingleScanResult = new WifiScanner.ScanData(mLastScanSettings.scanId, 0,
singleScanResults.toArray(new ScanResult[singleScanResults.size()]));
- mLastScanSettings.singleScanEventHandler.onScanResultsAvailable();
+ mLastScanSettings.singleScanEventHandler
+ .onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
}
mLastScanSettings = null;
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 8166328dc..0560345f6 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -324,12 +324,9 @@ public class WifiNative {
}
- public static final int SCAN_WITHOUT_CONNECTION_SETUP = 1;
- public static final int SCAN_WITH_CONNECTION_SETUP = 2;
-
- public boolean scan(int type, Set<Integer> freqs) {
+ public boolean scan(Set<Integer> freqs) {
if(freqs == null) {
- return scan(type, (String)null);
+ return scan((String) null);
}
else if (freqs.size() != 0) {
StringBuilder freqList = new StringBuilder();
@@ -340,22 +337,18 @@ public class WifiNative {
freqList.append(freq.toString());
first = false;
}
- return scan(type, freqList.toString());
+ return scan(freqList.toString());
}
else {
return false;
}
}
- private boolean scan(int type, String freqList) {
- if (type == SCAN_WITHOUT_CONNECTION_SETUP) {
- if (freqList == null) return doBooleanCommand("SCAN TYPE=ONLY");
- else return doBooleanCommand("SCAN TYPE=ONLY freq=" + freqList);
- } else if (type == SCAN_WITH_CONNECTION_SETUP) {
- if (freqList == null) return doBooleanCommand("SCAN");
- else return doBooleanCommand("SCAN freq=" + freqList);
+ private boolean scan(String freqList) {
+ if (freqList == null) {
+ return doBooleanCommand("SCAN TYPE=ONLY"); // Scan all channels
} else {
- throw new IllegalArgumentException("Invalid scan type");
+ return doBooleanCommand("SCAN TYPE=ONLY freq=" + freqList);
}
}
@@ -677,6 +670,7 @@ public class WifiNative {
ScanDetail scan = new ScanDetail(networkDetail, wifiSsid, bssid, flags,
level, freq, tsf);
scan.getScanResult().informationElements = infoElements;
+ scan.getScanResult().anqpLines = anqpLines;
results.add(scan);
} catch (IllegalArgumentException iae) {
Log.d(TAG, "Failed to parse information elements: " + iae);
@@ -1731,18 +1725,17 @@ public class WifiNative {
}
public static interface ScanEventHandler {
- void onScanResultsAvailable();
void onFullScanResult(ScanResult fullScanResult);
- void onScanStatus();
+ void onScanStatus(int event);
void onScanPaused(WifiScanner.ScanData[] data);
void onScanRestarted();
}
/* scan status, keep these values in sync with gscan.h */
- private static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
- private static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
- private static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
- private static final int WIFI_SCAN_DISABLED = 3;
+ public static final int WIFI_SCAN_RESULTS_AVAILABLE = 0;
+ public static final int WIFI_SCAN_THRESHOLD_NUM_SCANS = 1;
+ public static final int WIFI_SCAN_THRESHOLD_PERCENT = 2;
+ public static final int WIFI_SCAN_DISABLED = 3;
// Callback from native
private static void onScanStatus(int id, int event) {
@@ -1751,7 +1744,7 @@ public class WifiNative {
|| event == WIFI_SCAN_THRESHOLD_PERCENT) {
if (handler != null) {
// TODO pass event back to framework
- handler.onScanStatus();
+ handler.onScanStatus(event);
}
}
else if (event == WIFI_SCAN_DISABLED) {
diff --git a/service/java/com/android/server/wifi/WifiScanningScheduler.java b/service/java/com/android/server/wifi/WifiScanningScheduler.java
index 7b36b9918..744afd55c 100644
--- a/service/java/com/android/server/wifi/WifiScanningScheduler.java
+++ b/service/java/com/android/server/wifi/WifiScanningScheduler.java
@@ -28,17 +28,17 @@ import java.util.Collection;
*/
public abstract class WifiScanningScheduler {
- private static final int DEFAULT_MAX_BUCKETS = 8;
- private static final int DEFAULT_MAX_CHANNELS = 32;
+ static final int DEFAULT_MAX_BUCKETS = 8;
+ static final int DEFAULT_MAX_CHANNELS = 32;
// anecdotally, some chipsets will fail without explanation with a higher batch size, and
// there is apparently no way to retrieve the maximum batch size
- private static final int DEFAULT_MAX_SCANS_TO_BATCH = 10;
- private static final int DEFAULT_MAX_AP_PER_SCAN = 32;
+ static final int DEFAULT_MAX_SCANS_TO_BATCH = 10;
+ static final int DEFAULT_MAX_AP_PER_SCAN = 32;
- private static int mMaxBuckets = DEFAULT_MAX_BUCKETS;
- private static int mMaxChannels = DEFAULT_MAX_CHANNELS;
- private static int mMaxBatch = DEFAULT_MAX_SCANS_TO_BATCH;
- private static int mMaxApPerScan = DEFAULT_MAX_AP_PER_SCAN;
+ private int mMaxBuckets = DEFAULT_MAX_BUCKETS;
+ private int mMaxChannels = DEFAULT_MAX_CHANNELS;
+ private int mMaxBatch = DEFAULT_MAX_SCANS_TO_BATCH;
+ private int mMaxApPerScan = DEFAULT_MAX_AP_PER_SCAN;
int getMaxBuckets() {
return mMaxBuckets;
diff --git a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
index 777b3f9b6..3d61c1a63 100644
--- a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
@@ -43,6 +43,8 @@ import android.os.WorkSource;
import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
+import android.util.Pair;
+import android.util.SparseIntArray;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
@@ -190,13 +192,15 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
case WifiScanner.CMD_CONFIGURE_WIFI_CHANGE:
case WifiScanner.CMD_START_TRACKING_CHANGE:
case WifiScanner.CMD_STOP_TRACKING_CHANGE:
+ mStateMachine.sendMessage(Message.obtain(msg));
+ break;
case WifiScanner.CMD_START_SINGLE_SCAN:
case WifiScanner.CMD_STOP_SINGLE_SCAN:
- mStateMachine.sendMessage(Message.obtain(msg));
- return;
+ mSingleScanStateMachine.sendMessage(Message.obtain(msg));
+ break;
default:
replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "Invalid request");
- return;
+ break;
}
}
}
@@ -213,7 +217,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
private static final int CMD_DRIVER_UNLOADED = BASE + 7;
private static final int CMD_SCAN_PAUSED = BASE + 8;
private static final int CMD_SCAN_RESTARTED = BASE + 9;
- private static final int CMD_STOP_SCAN_INTERNAL = BASE + 10;
+ private static final int CMD_SCAN_DISABLED = BASE + 10;
private final Context mContext;
private final Looper mLooper;
@@ -224,6 +228,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
private WifiNative.ScanSettings mPreviousSchedule;
private WifiScanningStateMachine mStateMachine;
+ private WifiSingleScanStateMachine mSingleScanStateMachine;
private ClientHandler mClientHandler;
private final IBatteryStats mBatteryStats;
@@ -243,6 +248,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
mClientHandler = new ClientHandler(mLooper);
mStateMachine = new WifiScanningStateMachine(mLooper);
mWifiChangeStateMachine = new WifiChangeStateMachine(mLooper);
+ mSingleScanStateMachine = new WifiSingleScanStateMachine(mLooper);
mContext.registerReceiver(
new BroadcastReceiver() {
@@ -253,16 +259,342 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
if (DBG) localLog("SCAN_AVAILABLE : " + state);
if (state == WifiManager.WIFI_STATE_ENABLED) {
mStateMachine.sendMessage(CMD_DRIVER_LOADED);
+ mSingleScanStateMachine.sendMessage(CMD_DRIVER_LOADED);
} else if (state == WifiManager.WIFI_STATE_DISABLED) {
mStateMachine.sendMessage(CMD_DRIVER_UNLOADED);
+ mSingleScanStateMachine.sendMessage(CMD_DRIVER_UNLOADED);
}
}
}, new IntentFilter(WifiManager.WIFI_SCAN_AVAILABLE));
mStateMachine.start();
mWifiChangeStateMachine.start();
+ mSingleScanStateMachine.start();
+ }
+
+ /**
+ * A map of objects of a WifiScanner client and handler id to an object of type T
+ */
+ private static class ClientHandlerMap<T> extends HashMap<Pair<ClientInfo, Integer>, T> {
+ public ClientHandlerMap(int initialSize) {
+ super(initialSize);
+ }
+
+ public T put(ClientInfo ci, int handler, T value) {
+ return put(Pair.create(ci, handler), value);
+ }
+
+ public T get(ClientInfo ci, int handler) {
+ return get(Pair.create(ci, handler));
+ }
+
+ public T remove(ClientInfo ci, int handler) {
+ return remove(Pair.create(ci, handler));
+ }
}
+ /**
+ * State machine that holds the state of single scans. Scans should only be active in the
+ * ScanningState. The pending scans and active scans maps are swaped when entering
+ * ScanningState. Any requests queued while scanning will be placed in the pending queue and
+ * executed after transitioning back to NotScanningState.
+ */
+ class WifiSingleScanStateMachine extends StateMachine implements WifiNative.ScanEventHandler {
+ private final DefaultState mDefaultState = new DefaultState();
+ private final DriverStartedState mDriverStartedState = new DriverStartedState();
+ private final NotScanningState mNotScanningState = new NotScanningState();
+ private final ScanningState mScanningState = new ScanningState();
+
+ private ClientHandlerMap<ScanSettings> mActiveScans = new ClientHandlerMap<>(4);
+ private ClientHandlerMap<ScanSettings> mPendingScans = new ClientHandlerMap<>(4);
+
+ public WifiSingleScanStateMachine(Looper looper) {
+ super("WifiSingleScanStateMachine", looper);
+
+ setLogRecSize(128);
+ setLogOnlyTransitions(false);
+
+ // CHECKSTYLE:OFF IndentationCheck
+ addState(mDefaultState);
+ addState(mDriverStartedState, mDefaultState);
+ addState(mNotScanningState, mDriverStartedState);
+ addState(mScanningState, mDriverStartedState);
+ // CHECKSTYLE:ON IndentationCheck
+
+ setInitialState(mDefaultState);
+ }
+
+ /**
+ * Called to indicate a change in state for the current scan.
+ * Will dispatch a coresponding event to the state machine
+ */
+ @Override
+ public void onScanStatus(int event) {
+ if (DBG) localLog("onScanStatus event received, event=" + event);
+ switch(event) {
+ case WifiNative.WIFI_SCAN_RESULTS_AVAILABLE:
+ case WifiNative.WIFI_SCAN_THRESHOLD_NUM_SCANS:
+ case WifiNative.WIFI_SCAN_THRESHOLD_PERCENT:
+ sendMessage(CMD_SCAN_RESULTS_AVAILABLE);
+ break;
+ case WifiNative.WIFI_SCAN_DISABLED:
+ sendMessage(CMD_SCAN_DISABLED);
+ break;
+ default:
+ Log.e(TAG, "Unknown scan status event: " + event);
+ break;
+ }
+ }
+
+ /**
+ * Called for each full scan result if requested
+ */
+ @Override
+ public void onFullScanResult(ScanResult fullScanResult) {
+ if (DBG) localLog("onFullScanResult received");
+ sendMessage(CMD_FULL_SCAN_RESULTS, 0, 0, fullScanResult);
+ }
+
+ @Override
+ public void onScanPaused(ScanData scanData[]) {
+ // should not happen for single scan
+ Log.e(TAG, "Got scan paused for single scan");
+ }
+
+ @Override
+ public void onScanRestarted() {
+ // should not happen for single scan
+ Log.e(TAG, "Got scan restarted for single scan");
+ }
+
+ class DefaultState extends State {
+ @Override
+ public void enter() {
+ mActiveScans.clear();
+ mPendingScans.clear();
+ }
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_DRIVER_LOADED:
+ transitionTo(mNotScanningState);
+ return HANDLED;
+ case CMD_DRIVER_UNLOADED:
+ transitionTo(mDefaultState);
+ return HANDLED;
+ case WifiScanner.CMD_START_SINGLE_SCAN:
+ case WifiScanner.CMD_STOP_SINGLE_SCAN:
+ replyFailed(msg, WifiScanner.REASON_UNSPECIFIED, "not available");
+ return HANDLED;
+ case CMD_SCAN_RESULTS_AVAILABLE:
+ if (DBG) localLog("ignored scan results available event");
+ return HANDLED;
+ case CMD_FULL_SCAN_RESULTS:
+ if (DBG) localLog("ignored full scan result event");
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+
+ }
+ }
+
+ /**
+ * State representing when the driver is running. This state is not meant to be transitioned
+ * directly, but is instead indented as a parent state of ScanningState and NotScanningState
+ * to hold common functionality and handle cleaning up scans when the driver is shut down.
+ */
+ class DriverStartedState extends State {
+ @Override
+ public void exit() {
+ sendOpFailedToAll(mPendingScans, WifiScanner.REASON_UNSPECIFIED,
+ "Scan was interrupted");
+ mPendingScans.clear();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ ClientInfo ci = mClients.get(msg.replyTo);
+
+ switch (msg.what) {
+ case WifiScanner.CMD_START_SINGLE_SCAN:
+ if (validateAndAddToScanQueue(ci, msg.arg2, (ScanSettings) msg.obj)) {
+ replySucceeded(msg);
+ // if were not currently scanning then try to start
+ if (getCurrentState() != mScanningState) {
+ tryToStartNewScan();
+ }
+ } else {
+ replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");
+ }
+ return HANDLED;
+ case WifiScanner.CMD_STOP_SINGLE_SCAN:
+ removeSingleScanRequest(ci, msg.arg2);
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ class NotScanningState extends State {
+ @Override
+ public void enter() {
+ tryToStartNewScan();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ return NOT_HANDLED;
+ }
+ }
+
+ class ScanningState extends State {
+ @Override
+ public void exit() {
+ // if any scans are still active (never got results available then indicate failure
+ sendOpFailedToAll(mActiveScans, WifiScanner.REASON_UNSPECIFIED,
+ "Scan was interrupted");
+ mActiveScans.clear();
+ }
+
+ // TODO correctly handle battery blaming
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_SCAN_RESULTS_AVAILABLE:
+ reportScanResults(mScannerImpl.getLatestSingleScanResults());
+ mActiveScans.clear();
+ transitionTo(mNotScanningState);
+ return HANDLED;
+ case CMD_FULL_SCAN_RESULTS:
+ reportFullScanResult((ScanResult) msg.obj);
+ return HANDLED;
+ case CMD_SCAN_DISABLED:
+ sendOpFailedToAll(mActiveScans, WifiScanner.REASON_UNSPECIFIED,
+ "Scan was interrupted");
+ mActiveScans.clear();
+ transitionTo(mNotScanningState);
+ return HANDLED;
+ default:
+ return NOT_HANDLED;
+ }
+ }
+ }
+
+ boolean validateAndAddToScanQueue(ClientInfo ci, int handler, ScanSettings settings) {
+ if (ci == null) {
+ Log.d(TAG, "Failing single scan request ClientInfo not found " + handler);
+ return false;
+ }
+ ChannelSpec[] channels = WifiChannelHelper.getChannelsForScanSettings(settings);
+ if (channels.length == 0) {
+ Log.d(TAG, "Failing single scan because channel list was empty");
+ return false;
+ }
+ logScanRequest("validateSingleScanAndAddToScanQueue", ci, handler, settings);
+ mPendingScans.put(ci, handler, settings);
+ return true;
+ }
+
+ void removeSingleScanRequest(ClientInfo ci, int handler) {
+ if (ci != null) {
+ logScanRequest("removeSingleScanRequest", ci, handler, null);
+ mPendingScans.remove(ci, handler);
+ mActiveScans.remove(ci, handler);
+ }
+ }
+
+ void tryToStartNewScan() {
+ // TODO move merging logic to a scheduler
+ int reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
+ ArrayList<Integer> allChannels = new ArrayList<>();
+ for (ScanSettings settings : mPendingScans.values()) {
+ ChannelSpec[] channels = WifiChannelHelper.getChannelsForScanSettings(settings);
+ for (int i = 0; i < channels.length; ++i) {
+ allChannels.add(channels[i].frequency);
+ }
+ if ((settings.reportEvents & WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) != 0) {
+ reportEvents |= WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
+ }
+ }
+ if (allChannels.size() > 0) {
+ WifiNative.ScanSettings settings = new WifiNative.ScanSettings();
+ settings.num_buckets = 1;
+ WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
+ bucketSettings.bucket = 0;
+ bucketSettings.period_ms = 0;
+ bucketSettings.report_events = reportEvents;
+ bucketSettings.num_channels = allChannels.size();
+ bucketSettings.channels = new WifiNative.ChannelSettings[allChannels.size()];
+ for (int i = 0; i < bucketSettings.channels.length; ++i) {
+ bucketSettings.channels[i] = new WifiNative.ChannelSettings();
+ bucketSettings.channels[i].frequency = allChannels.get(i);
+ }
+ settings.buckets = new WifiNative.BucketSettings[] {bucketSettings};
+ if (mScannerImpl.startSingleScan(settings, this)) {
+ // swap pending and active scan requests
+ ClientHandlerMap<ScanSettings> tmp = mActiveScans;
+ mActiveScans = mPendingScans;
+ mPendingScans = tmp;
+ // make sure that the pending list is clear
+ mPendingScans.clear();
+ transitionTo(mScanningState);
+ } else {
+ // notify and cancel failed scans
+ sendOpFailedToAll(mPendingScans, WifiScanner.REASON_UNSPECIFIED,
+ "Failed to start single scan");
+ mPendingScans.clear();
+ }
+ } else {
+ // notify and cancel failed scans
+ sendOpFailedToAll(mPendingScans, WifiScanner.REASON_INVALID_REQUEST,
+ "No channels specified");
+ mPendingScans.clear();
+ }
+ }
+
+ void sendOpFailedToAll(ClientHandlerMap<?> clientHandlers, int reason, String description) {
+ for (Pair<ClientInfo, Integer> key : clientHandlers.keySet()) {
+ ClientInfo ci = key.first;
+ int handler = key.second;
+ ci.sendMessage(WifiScanner.CMD_OP_FAILED, 0, handler,
+ new WifiScanner.OperationResult(reason, description));
+ }
+ }
+
+ // TODO fix shouldReport checks
+ // currently these checks work becuase the shouldReport methods don't yet rely on the
+ // internal state of the scheduler.
+ void reportFullScanResult(ScanResult result) {
+ for (Map.Entry<Pair<ClientInfo, Integer>, ScanSettings> entry
+ : mActiveScans.entrySet()) {
+ ClientInfo ci = entry.getKey().first;
+ int handler = entry.getKey().second;
+ ScanSettings settings = entry.getValue();
+ if (mScheduler.shouldReportFullScanResultForSettings(result, settings)) {
+ ci.sendMessage(WifiScanner.CMD_FULL_SCAN_RESULT, 0, handler, result);
+ }
+ }
+ }
+
+ void reportScanResults(ScanData results) {
+ for (Map.Entry<Pair<ClientInfo, Integer>, ScanSettings> entry
+ : mActiveScans.entrySet()) {
+ ClientInfo ci = entry.getKey().first;
+ int handler = entry.getKey().second;
+ ScanSettings settings = entry.getValue();
+ ScanData[] resultsArray = new ScanData[] {results};
+ ScanData[] resultsToDeliver =
+ mScheduler.filterResultsForSettings(resultsArray, settings);
+ WifiScanner.ParcelableScanData parcelableScanData =
+ new WifiScanner.ParcelableScanData(resultsToDeliver);
+ ci.sendMessage(WifiScanner.CMD_SCAN_RESULT, 0, handler, parcelableScanData);
+ }
+ }
+ }
+
+
class WifiScanningStateMachine extends StateMachine implements WifiNative.ScanEventHandler,
WifiNative.HotlistEventHandler, WifiNative.SignificantWifiChangeEventHandler {
@@ -276,23 +608,31 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
setLogRecSize(512);
setLogOnlyTransitions(false);
+ // CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState);
addState(mStartedState, mDefaultState);
addState(mPausedState, mDefaultState);
+ // CHECKSTYLE:ON IndentationCheck
setInitialState(mDefaultState);
}
@Override
- public void onScanResultsAvailable() {
- if (DBG) localLog("onScanResultAvailable event received");
- sendMessage(CMD_SCAN_RESULTS_AVAILABLE);
- }
-
- @Override
- public void onScanStatus() {
- if (DBG) localLog("onScanStatus event received");
- sendMessage(CMD_SCAN_RESULTS_AVAILABLE);
+ public void onScanStatus(int event) {
+ if (DBG) localLog("onScanStatus event received, event=" + event);
+ switch(event) {
+ case WifiNative.WIFI_SCAN_RESULTS_AVAILABLE:
+ case WifiNative.WIFI_SCAN_THRESHOLD_NUM_SCANS:
+ case WifiNative.WIFI_SCAN_THRESHOLD_PERCENT:
+ sendMessage(CMD_SCAN_RESULTS_AVAILABLE);
+ break;
+ case WifiNative.WIFI_SCAN_DISABLED:
+ sendMessage(CMD_SCAN_DISABLED);
+ break;
+ default:
+ Log.e(TAG, "Unknown scan status event: " + event);
+ break;
+ }
}
@Override
@@ -340,6 +680,9 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_DRIVER_LOADED:
+ // TODO this should be moved to a common location since it is used outside
+ // of this state machine. It is ok right now becuase the driver loaded event
+ // is sent to this state machine first.
if (mScannerImpl == null) {
mScannerImpl = mScannerImplFactory.create(mContext, mLooper);
}
@@ -408,33 +751,19 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
case CMD_DRIVER_UNLOADED:
return NOT_HANDLED;
case WifiScanner.CMD_START_BACKGROUND_SCAN:
- if (addScanRequest(ci, msg.arg2, (ScanSettings) msg.obj)) {
+ if (addBackgroundScanRequest(ci, msg.arg2, (ScanSettings) msg.obj)) {
replySucceeded(msg);
} else {
replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");
}
break;
case WifiScanner.CMD_STOP_BACKGROUND_SCAN:
- removeScanRequest(ci, msg.arg2);
+ removeBackgroundScanRequest(ci, msg.arg2);
break;
case WifiScanner.CMD_GET_SCAN_RESULTS:
reportScanResults(mScannerImpl.getLatestBatchedScanResults(true));
replySucceeded(msg);
break;
- case WifiScanner.CMD_START_SINGLE_SCAN:
- if (addSingleScanRequest(ci, msg.arg2, (ScanSettings) msg.obj)) {
- replySucceeded(msg);
- } else {
- replyFailed(msg, WifiScanner.REASON_INVALID_REQUEST, "bad request");
- }
- break;
- case WifiScanner.CMD_STOP_SINGLE_SCAN:
- removeScanRequest(ci, msg.arg2);
- break;
- case CMD_STOP_SCAN_INTERNAL:
- localLog("Removing single shot scan");
- removeScanRequest((ClientInfo) msg.obj, msg.arg2);
- break;
case WifiScanner.CMD_SET_HOTLIST:
setHotlist(ci, msg.arg2, (WifiScanner.HotlistSettings) msg.obj);
replySucceeded(msg);
@@ -491,6 +820,10 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
reportScanResults((ScanData[]) msg.obj);
transitionTo(mPausedState);
break;
+ case CMD_SCAN_DISABLED:
+ // TODO handle this gracefully (currently no implementations are know to
+ // report this)
+ break;
default:
return NOT_HANDLED;
}
@@ -523,8 +856,14 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
private class ClientInfo {
private final AsyncChannel mChannel;
+ /**
+ * Indicates if the client is still connected
+ * If the client is no longer connected then messages to it will be signlently dropped
+ */
+ private boolean mDisconnected = false;
private final int mUid;
private final WorkSource mWorkSource;
+
private boolean mScanWorkReported = false;
ClientInfo(int uid, AsyncChannel c) {
@@ -534,6 +873,12 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
if (DBG) localLog("New client, channel: " + c);
}
+ void sendMessage(int what, int arg1, int arg2, Object obj) {
+ if (!mDisconnected) {
+ mChannel.sendMessage(what, arg1, arg2, obj);
+ }
+ }
+
void reportBatchedScanStart() {
if (mUid == 0)
return;
@@ -560,7 +905,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
int getCsph() {
int csph = 0;
- for (ScanSettings settings : getScanSettings()) {
+ for (ScanSettings settings : getBackgroundScanSettings()) {
int num_channels = WifiChannelHelper.getChannelsForScanSettings(settings).length;
int scans_per_Hour = settings.periodInMs == 0 ? 1 : (3600 * 1000) /
settings.periodInMs;
@@ -575,7 +920,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
reportBatchedScanStop();
mScanWorkReported = false;
}
- if (mScanSettings.isEmpty() == false) {
+ if (mBackgroundScanSettings.isEmpty()) {
reportBatchedScanStart();
mScanWorkReported = true;
}
@@ -583,14 +928,15 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
@Override
public String toString() {
- return "ClientInfo[uid=" + mUid + ", channel=" + mChannel + "]";
+ return "ClientInfo[uid=" + mUid + "]";
}
void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
StringBuilder sb = new StringBuilder();
sb.append(toString());
- Iterator<Map.Entry<Integer, ScanSettings>> it = mScanSettings.entrySet().iterator();
+ Iterator<Map.Entry<Integer, ScanSettings>> it =
+ mBackgroundScanSettings.entrySet().iterator();
for (; it.hasNext(); ) {
Map.Entry<Integer, ScanSettings> entry = it.next();
sb.append("ScanId ").append(entry.getKey()).append("\n");
@@ -603,33 +949,26 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
pw.println(sb.toString());
}
- HashMap<Integer, ScanSettings> mScanSettings = new HashMap<Integer, ScanSettings>(4);
- HashMap<Integer, Integer> mScanPeriods = new HashMap<Integer, Integer>(4);
+ private final Map<Integer, ScanSettings> mBackgroundScanSettings =
+ new HashMap<Integer, ScanSettings>(4);
+ private final SparseIntArray mBackgroundScanPeriods = new SparseIntArray(4);
- void addScanRequest(ScanSettings settings, int id) {
- mScanSettings.put(id, settings);
+ void addBackgroundScanRequest(ScanSettings settings, int id) {
+ mBackgroundScanSettings.put(id, settings);
reportScanWorkUpdate();
}
- void removeScanRequest(int id) {
- ScanSettings settings = mScanSettings.remove(id);
- if (settings != null && settings.periodInMs == 0) {
- /* this was a single shot scan */
- mChannel.sendMessage(WifiScanner.CMD_SINGLE_SCAN_COMPLETED, 0, id);
- }
+ void removeBackgroundScanRequest(int id) {
+ mBackgroundScanSettings.remove(id);
reportScanWorkUpdate();
}
- Iterator<Map.Entry<Integer, ScanSettings>> getScans() {
- return mScanSettings.entrySet().iterator();
- }
-
- Collection<ScanSettings> getScanSettings() {
- return mScanSettings.values();
+ Collection<ScanSettings> getBackgroundScanSettings() {
+ return mBackgroundScanSettings.values();
}
void reportScanResults(ScanData[] results) {
- Iterator<Integer> it = mScanSettings.keySet().iterator();
+ Iterator<Integer> it = mBackgroundScanSettings.keySet().iterator();
while (it.hasNext()) {
int handler = it.next();
reportScanResults(results, handler);
@@ -637,7 +976,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
void reportScanResults(ScanData[] results, int handler) {
- ScanSettings settings = mScanSettings.get(handler);
+ ScanSettings settings = mBackgroundScanSettings.get(handler);
ScanData[] resultsToDeliver = mScheduler.filterResultsForSettings(results, settings);
@@ -646,11 +985,6 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
deliverScanResults(handler, resultsToDeliver);
}
-
- if (settings.periodInMs == 0) {
- /* this is a single shot scan; stop the scan now */
- mStateMachine.sendMessage(CMD_STOP_SCAN_INTERNAL, 0, handler, this);
- }
}
void deliverScanResults(int handler, ScanData results[]) {
@@ -660,10 +994,10 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
void reportFullScanResult(ScanResult result) {
- Iterator<Integer> it = mScanSettings.keySet().iterator();
+ Iterator<Integer> it = mBackgroundScanSettings.keySet().iterator();
while (it.hasNext()) {
int handler = it.next();
- ScanSettings settings = mScanSettings.get(handler);
+ ScanSettings settings = mBackgroundScanSettings.get(handler);
if (mScheduler.shouldReportFullScanResultForSettings(result, settings)) {
ScanResult newResult = new ScanResult(result);
if (result.informationElements != null) {
@@ -678,18 +1012,18 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
void reportPeriodChanged(int handler, ScanSettings settings, int newPeriodInMs) {
- Integer prevPeriodObject = mScanPeriods.get(handler);
- int prevPeriodInMs = settings.periodInMs;
- if (prevPeriodObject != null) {
- prevPeriodInMs = prevPeriodObject;
+ int prevPeriodInMs = mBackgroundScanPeriods.get(handler, 0);
+ if (prevPeriodInMs == 0) {
+ prevPeriodInMs = settings.periodInMs;
}
if (prevPeriodInMs != newPeriodInMs) {
+ mBackgroundScanPeriods.put(handler, newPeriodInMs);
mChannel.sendMessage(WifiScanner.CMD_PERIOD_CHANGED, newPeriodInMs, handler);
}
}
- private final HashMap<Integer, WifiScanner.HotlistSettings> mHotlistSettings =
+ private final Map<Integer, WifiScanner.HotlistSettings> mHotlistSettings =
new HashMap<Integer, WifiScanner.HotlistSettings>();
void addHostlistSettings(WifiScanner.HotlistSettings settings, int handler) {
@@ -780,7 +1114,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
void cleanup() {
- mScanSettings.clear();
+ mDisconnected = true;
+ mBackgroundScanSettings.clear();
updateSchedule();
mHotlistSettings.clear();
@@ -829,7 +1164,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
private boolean updateSchedule() {
ArrayList<ScanSettings> settings = new ArrayList<>();
for (ClientInfo client : mClients.values()) {
- settings.addAll(client.getScanSettings());
+ settings.addAll(client.getBackgroundScanSettings());
}
mScheduler.updateSchedule(settings);
@@ -897,7 +1232,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
localLog(sb.toString());
}
- boolean addScanRequest(ClientInfo ci, int handler, ScanSettings settings) {
+ boolean addBackgroundScanRequest(ClientInfo ci, int handler, ScanSettings settings) {
// sanity check the input
if (ci == null) {
Log.d(TAG, "Failing scan request ClientInfo not found " + handler);
@@ -941,48 +1276,22 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
}
- logScanRequest("addScanRequest", ci, handler, settings);
- ci.addScanRequest(settings, handler);
-
- if (updateSchedule()) {
- return true;
- } else {
- ci.removeScanRequest(handler);
- localLog("Failing scan request because failed to reset scan");
- return false;
- }
- }
-
- boolean addSingleScanRequest(ClientInfo ci, int handler, ScanSettings settings) {
- if (ci == null) {
- Log.d(TAG, "Failing single scan request ClientInfo not found " + handler);
- return false;
- }
- if (settings.reportEvents == 0) {
- settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
- }
- if (settings.periodInMs == 0) {
- settings.periodInMs = 10000; // 10s - although second scan should never happen
- }
-
- logScanRequest("addSingleScanRequest", ci, handler, settings);
- ci.addScanRequest(settings, handler);
+ logScanRequest("addBackgroundScanRequest", ci, handler, settings);
+ ci.addBackgroundScanRequest(settings, handler);
if (updateSchedule()) {
- /* reset periodInMs to 0 to indicate single shot scan */
- settings.periodInMs = 0;
return true;
} else {
- ci.removeScanRequest(handler);
+ ci.removeBackgroundScanRequest(handler);
localLog("Failing scan request because failed to reset scan");
return false;
}
}
- void removeScanRequest(ClientInfo ci, int handler) {
+ void removeBackgroundScanRequest(ClientInfo ci, int handler) {
if (ci != null) {
- logScanRequest("removeScanRequest", ci, handler, null);
- ci.removeScanRequest(handler);
+ logScanRequest("removeBackgroundScanRequest", ci, handler, null);
+ ci.removeBackgroundScanRequest(handler);
updateSchedule();
}
}
@@ -1125,9 +1434,11 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
mClients.put(null, mClientInfo);
+ // CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState);
- addState(mStationaryState, mDefaultState);
- addState(mMovingState, mDefaultState);
+ addState(mStationaryState, mDefaultState);
+ addState(mMovingState, mDefaultState);
+ // CHECKSTYLE:ON IndentationCheck
setInitialState(mDefaultState);
}
@@ -1531,7 +1842,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
pw.println("listeners:");
for (ClientInfo client : mClients.values()) {
- for (ScanSettings settings : client.getScanSettings()) {
+ for (ScanSettings settings : client.getBackgroundScanSettings()) {
pw.println(" " + toString(client.mUid, settings));
}
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index d94af1516..ceb6ac39d 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -1400,8 +1400,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT,
getHandler());
- mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_FAILED_EVENT, getHandler());
- mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_RESULTS_EVENT, getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_REENABLED, getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_TEMP_DISABLED, getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler());
@@ -1997,7 +1995,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
}
- private void handleScanRequest(int type, Message message) {
+ private void handleScanRequest(Message message) {
ScanSettings settings = null;
WorkSource workSource = null;
@@ -2018,7 +2016,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
// call wifi native to start the scan
- if (startScanNative(type, freqs)) {
+ if (startScanNative(freqs)) {
// only count battery consumption if scan request is accepted
noteScanStart(message.arg1, workSource);
// a full scan covers everything, clearing scan request buffer
@@ -2069,17 +2067,57 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
+ // TODO this is a temporary measure to bridge between WifiScanner and WifiStateMachine until
+ // scan functionality is refactored out of WifiStateMachine.
+ private WifiScanner.ScanListener mLastNativeScanListener = null;
+ private volatile ArrayList<ScanDetail> mLastNativeScanResults = new ArrayList<ScanDetail>();
/**
* return true iff scan request is accepted
*/
- private boolean startScanNative(int type, Set<Integer> freqs) {
- if (mWifiNative.scan(type, freqs)) {
- mIsScanOngoing = true;
- mIsFullScanOngoing = (freqs == null);
- lastScanFreqs = freqs;
- return true;
+ private boolean startScanNative(Set<Integer> freqs) {
+ if (mLastNativeScanListener != null) {
+ mWifiScanner.stopScan(mLastNativeScanListener);
+ mLastNativeScanListener = null;
+ }
+ WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings();
+ if (freqs == null) {
+ settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
+ } else {
+ settings.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
+ int index = 0;
+ settings.channels = new WifiScanner.ChannelSpec[freqs.size()];
+ for (Integer freq : freqs) {
+ settings.channels[index++] = new WifiScanner.ChannelSpec(freq);
+ }
}
- return false;
+ settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
+ | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
+ mLastNativeScanListener = new WifiScanner.ScanListener() {
+ private final ArrayList<ScanDetail> mNewScanResults = new ArrayList<>();
+
+ public void onSuccess() {
+ // the scan started successfully, but has not completed yet
+ }
+ public void onFailure(int reason, String description) {
+ Log.e(TAG, "Scan failed: reason=" + reason + ", " + description);
+ sendMessage(WifiMonitor.SCAN_FAILED_EVENT);
+ }
+ public void onResults(WifiScanner.ScanData[] results) {
+ mLastNativeScanResults = mNewScanResults;
+ sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
+ }
+ public void onFullResult(ScanResult fullScanResult) {
+ mNewScanResults.add(ScanDetailUtil.toScanDetail(fullScanResult));
+ }
+ public void onPeriodChanged(int periodInMs) {
+ // does not occur for single scan
+ }
+ };
+ mWifiScanner.startScan(settings, mLastNativeScanListener);
+ mIsScanOngoing = true;
+ mIsFullScanOngoing = (freqs == null);
+ lastScanFreqs = freqs;
+ return true;
}
/**
@@ -3911,7 +3949,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mNumScanResultsKnown = 0;
mNumScanResultsReturned = 0;
- ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults();
+ ArrayList<ScanDetail> scanResults = mLastNativeScanResults;
if (scanResults.isEmpty()) {
mScanResults = new ArrayList<>();
@@ -4965,13 +5003,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
mDhcpActive = false;
}
- void connectScanningService() {
-
- if (mWifiScanner == null) {
- mWifiScanner = (WifiScanner) mContext.getSystemService(Context.WIFI_SCANNING_SERVICE);
- }
- }
-
private void handleIPv4Success(DhcpResults dhcpResults, int reason) {
if (PDBG) {
@@ -6111,11 +6142,17 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class DriverStartedState extends State {
@Override
public void enter() {
-
if (PDBG) {
logd("DriverStartedState enter");
}
+ // We can't do this in the constructor because WifiStateMachine is created before the
+ // wifi scanning service is initialized
+ if (mWifiScanner == null) {
+ mWifiScanner =
+ (WifiScanner) mContext.getSystemService(Context.WIFI_SCANNING_SERVICE);
+ }
+
mWifiLogger.startLogging(mVerboseLoggingLevel > 0);
mIsRunning = true;
updateBatteryWorkSource(null);
@@ -6208,7 +6245,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
switch(message.what) {
case CMD_START_SCAN:
- handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ handleScanRequest(message);
break;
case CMD_SET_FREQUENCY_BAND:
int band = message.arg1;
@@ -6221,7 +6258,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Flush old data - like scan results
mWifiNative.bssFlush();
// Fetch the latest scan results when frequency band is set
-// startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, null);
+ // startScanNative(null);
if (PDBG) logd("done set frequency band " + band);
@@ -6497,7 +6534,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
// Handle scan. All the connection related commands are
// handled only in ConnectModeState
case CMD_START_SCAN:
- handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ handleScanRequest(message);
break;
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
SupplicantState state = handleSupplicantStateChange(message);
@@ -6995,11 +7032,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
class ConnectModeState extends State {
@Override
- public void enter() {
- connectScanningService();
- }
-
- @Override
public boolean processMessage(Message message) {
WifiConfiguration config;
int netId;
@@ -8045,8 +8077,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
logd("starting scan for " + config.configKey() + " with " + freqs);
//}
// Call wifi native to start the scan
- if (startScanNative(
- WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, freqs)) {
+ if (startScanNative(freqs)) {
// Only count battery consumption if scan request is accepted
noteScanStart(SCAN_ALARM_SOURCE, null);
messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK;
@@ -8339,8 +8370,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
+ fullBandConnectedTimeIntervalMilli);
}
}
- handleScanRequest(
- WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ handleScanRequest(message);
} else {
if (!startScanForConfiguration(
currentConfiguration, restrictChannelList)) {
@@ -8361,8 +8391,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
+ fullBandConnectedTimeIntervalMilli);
}
}
- handleScanRequest(
- WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ handleScanRequest(message);
}
}
@@ -9309,7 +9338,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno
}
/* Disable background scan temporarily during a regular scan */
enableBackgroundScan(false);
- handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
+ handleScanRequest(message);
ret = HANDLED;
} else {
diff --git a/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java b/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java
index 0ff439152..9a21843f4 100644
--- a/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/BaseWifiScannerImplTest.java
@@ -25,7 +25,6 @@ import static com.android.server.wifi.ScanTestUtil.setupMockChannels;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -140,7 +139,7 @@ public abstract class BaseWifiScannerImplTest {
WifiNative.ScanEventHandler eventHandler2 = mock(WifiNative.ScanEventHandler.class);
// scan start succeeds
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
assertTrue(mScanner.startSingleScan(settings, eventHandler));
assertFalse("second scan while first scan running should fail immediately",
@@ -164,12 +163,13 @@ public abstract class BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// scan fails
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(false);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(false);
// start scan
assertTrue(mScanner.startSingleScan(settings, eventHandler));
- // TODO expect failure callback once implemented
+ mLooper.dispatchAll();
+ order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_DISABLED);
verifyNoMoreInteractions(eventHandler);
}
@@ -213,7 +213,7 @@ public abstract class BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// scans succeed
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// start first scan
assertTrue(mScanner.startSingleScan(settings, eventHandler));
@@ -257,7 +257,7 @@ public abstract class BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// scan succeeds
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// start scan
assertTrue(mScanner.startSingleScan(settings, eventHandler));
@@ -270,8 +270,7 @@ public abstract class BaseWifiScannerImplTest {
protected void expectSuccessfulSingleScan(InOrder order,
WifiNative.ScanEventHandler eventHandler, Set<Integer> expectedScan,
ScanResults results, boolean expectFullResults) {
- order.verify(mWifiNative).scan(eq(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP),
- eq(expectedScan));
+ order.verify(mWifiNative).scan(eq(expectedScan));
when(mWifiNative.getScanResults()).thenReturn(results.getScanDetailArrayList());
@@ -286,7 +285,7 @@ public abstract class BaseWifiScannerImplTest {
}
}
- order.verify(eventHandler).onScanResultsAvailable();
+ order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
assertScanDataEquals(results.getScanData(), mScanner.getLatestSingleScanResults());
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/HalWifiScannerTest.java b/tests/wifitests/src/com/android/server/wifi/HalWifiScannerTest.java
index 162fc2c0c..d253ff723 100644
--- a/tests/wifitests/src/com/android/server/wifi/HalWifiScannerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/HalWifiScannerTest.java
@@ -16,13 +16,10 @@
package com.android.server.wifi;
-import android.os.Handler;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Before;
-import java.lang.reflect.Field;
-
/**
* Unit tests for {@link com.android.server.wifi.HalWifiScannerImpl}.
*/
@@ -32,14 +29,5 @@ public class HalWifiScannerTest extends BaseWifiScannerImplTest {
@Before
public void setUp() throws Exception {
mScanner = new HalWifiScannerImpl(WifiNative.getWlanNativeInterface(), mLooper.getLooper());
-
- // TODO remove this once HalWifiScannerImpl wifi monitor registration is enabled
- Field eventHandlerField = HalWifiScannerImpl.class.getDeclaredField("mEventHandler");
- eventHandlerField.setAccessible(true);
- Handler eventHandler = (Handler) eventHandlerField.get(mScanner);
- WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- WifiMonitor.SCAN_FAILED_EVENT, eventHandler);
- WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- WifiMonitor.SCAN_RESULTS_EVENT, eventHandler);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/MultiClientSchedulerTest.java b/tests/wifitests/src/com/android/server/wifi/MultiClientSchedulerTest.java
index 97da4a473..94ce31d38 100644
--- a/tests/wifitests/src/com/android/server/wifi/MultiClientSchedulerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/MultiClientSchedulerTest.java
@@ -16,6 +16,8 @@
package com.android.server.wifi;
+import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder;
+import static com.android.server.wifi.ScanTestUtil.assertNativeScanSettingsEquals;
import static com.android.server.wifi.ScanTestUtil.channelsToSpec;
import static com.android.server.wifi.ScanTestUtil.createRequest;
import static com.android.server.wifi.ScanTestUtil.getAllChannels;
@@ -44,7 +46,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
-import java.util.Set;
/**
* Unit tests for {@link com.android.server.wifi.MultiClientScheduler}.
@@ -459,43 +460,23 @@ public class MultiClientSchedulerTest {
mScheduler.updateSchedule(requests);
WifiNative.ScanSettings schedule = mScheduler.getSchedule();
- assertEquals("base_period_ms", computeExpectedPeriod(settings.periodInMs),
- schedule.base_period_ms);
- assertBuckets(schedule, 1);
+ int expectedPeriod = computeExpectedPeriod(settings.periodInMs);
+ NativeScanSettingsBuilder expectedBuilder = new NativeScanSettingsBuilder()
+ .withBasePeriod(expectedPeriod)
+ .withMaxApPerScan(settings.numBssidsPerScan == 0
+ ? DEFAULT_MAX_AP_PER_SCAN
+ : settings.numBssidsPerScan)
+ .withMaxScansToCache(settings.maxScansToCache == 0
+ ? DEFAULT_MAX_BATCH
+ : settings.maxScansToCache);
- if (settings.numBssidsPerScan == 0) {
- assertEquals("bssids per scan", DEFAULT_MAX_AP_PER_SCAN, schedule.max_ap_per_scan);
- } else {
- assertEquals("bssids per scan", settings.numBssidsPerScan, schedule.max_ap_per_scan);
- }
- if (settings.maxScansToCache == 0) {
- assertEquals("scans to cache", DEFAULT_MAX_BATCH,
- schedule.report_threshold_num_scans);
- } else {
- assertEquals("scans to cache", settings.maxScansToCache,
- schedule.report_threshold_num_scans);
- }
- assertEquals("reportEvents", settings.reportEvents, schedule.buckets[0].report_events);
- assertEquals("period", computeExpectedPeriod(settings.periodInMs),
- schedule.buckets[0].period_ms);
if (settings.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
- assertEquals("band", settings.band, schedule.buckets[0].band);
- Set<Integer> expectedChannels = new HashSet<>();
- for (ChannelSpec channel : getAllChannels(settings)) {
- expectedChannels.add(channel.frequency);
- }
- Set<Integer> actualChannels = new HashSet<>();
- for (ChannelSpec channel : getAllChannels(schedule.buckets[0])) {
- actualChannels.add(channel.frequency);
- }
- assertEquals("channels", expectedChannels, actualChannels);
- }
- else {
- assertEquals("band", settings.band, schedule.buckets[0].band);
- assertEquals("num_channels", 0, schedule.buckets[0].num_channels);
- assertTrue("channels", schedule.buckets[0].channels == null
- || schedule.buckets[0].channels.length == 0);
+ expectedBuilder.addBucketWithChannels(expectedPeriod, settings.reportEvents,
+ getAllChannels(settings));
+ } else {
+ expectedBuilder.addBucketWithBand(expectedPeriod, settings.reportEvents, settings.band);
}
+ assertNativeScanSettingsEquals(expectedBuilder.build(), schedule);
}
private void assertBuckets(WifiNative.ScanSettings schedule, int numBuckets) {
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanResults.java b/tests/wifitests/src/com/android/server/wifi/ScanResults.java
index d418451fc..b6007b26c 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanResults.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanResults.java
@@ -28,7 +28,9 @@ import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
import java.util.Random;
/**
@@ -39,6 +41,29 @@ public class ScanResults {
private final ScanData mScanData;
private final ScanResult[] mScanResults;
+ private ScanResults(ArrayList<ScanDetail> scanDetails, ScanData scanData,
+ ScanResult[] scanResults) {
+ mScanDetails.addAll(scanDetails);
+ mScanData = scanData;
+ mScanResults = scanResults;
+ }
+
+ public static ScanResults merge(ScanResults... others) {
+ ArrayList<ScanDetail> scanDetails = new ArrayList<>();
+ ArrayList<ScanResult> scanDataResults = new ArrayList<>();
+ ArrayList<ScanResult> rawScanResults = new ArrayList<>();
+ for (ScanResults other : others) {
+ scanDetails.addAll(other.getScanDetailArrayList());
+ scanDataResults.addAll(Arrays.asList(other.getScanData().getResults()));
+ rawScanResults.addAll(Arrays.asList(other.getRawScanResults()));
+ }
+ Collections.sort(scanDataResults, SCAN_RESULT_RSSI_COMPARATOR);
+ int id = others[0].getScanData().getId();
+ return new ScanResults(scanDetails, new ScanData(id, 0, scanDataResults
+ .toArray(new ScanResult[scanDataResults.size()])),
+ rawScanResults.toArray(new ScanResult[rawScanResults.size()]));
+ }
+
private static String generateBssid(Random r) {
return String.format("%02X:%02X:%02X:%02X:%02X:%02X",
r.nextInt(256), r.nextInt(256), r.nextInt(256),
@@ -102,11 +127,14 @@ public class ScanResults {
int rssi = r.nextInt(40) - 99; // -99 to -60
ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
ie[0] = generateSsidIe(ssid);
- NetworkDetail nd = new NetworkDetail(bssid, ie, new ArrayList<String>(), freq);
+ List<String> anqpLines = new ArrayList<>();
+ NetworkDetail nd = new NetworkDetail(bssid, ie, anqpLines, freq);
ScanDetail detail = new ScanDetail(nd, WifiSsid.createFromAsciiEncoded(ssid),
bssid, "", rssi, freq,
Long.MAX_VALUE); /* needed so that scan results aren't rejected because
there older than scan start */
+ detail.getScanResult().informationElements = ie;
+ detail.getScanResult().anqpLines = anqpLines;
results[i] = detail;
}
return results;
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java b/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java
index 3b06c0386..cc583e420 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java
@@ -18,6 +18,7 @@ package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.net.wifi.ScanResult;
@@ -27,8 +28,6 @@ import android.net.wifi.WifiScanner.ScanData;
import android.net.wifi.WifiScanner.ScanSettings;
import android.net.wifi.WifiSsid;
-import com.android.server.wifi.WifiNative.BucketSettings;
-
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
@@ -115,6 +114,10 @@ public class ScanTestUtil {
mSettings.report_threshold_num_scans = maxScans;
return this;
}
+ public NativeScanSettingsBuilder withMaxPercentToCache(int percent) {
+ mSettings.report_threshold_percent = percent;
+ return this;
+ }
public NativeScanSettingsBuilder addBucketWithBand(
int period, int reportEvents, int band) {
@@ -128,6 +131,11 @@ public class ScanTestUtil {
public NativeScanSettingsBuilder addBucketWithChannels(
int period, int reportEvents, int... channels) {
+ return addBucketWithChannels(period, reportEvents, channelsToSpec(channels));
+ }
+
+ public NativeScanSettingsBuilder addBucketWithChannels(
+ int period, int reportEvents, ChannelSpec... channels) {
WifiNative.BucketSettings bucket = new WifiNative.BucketSettings();
bucket.bucket = mSettings.num_buckets;
bucket.band = WifiScanner.WIFI_BAND_UNSPECIFIED;
@@ -135,7 +143,7 @@ public class ScanTestUtil {
bucket.channels = new WifiNative.ChannelSettings[channels.length];
for (int i = 0; i < channels.length; ++i) {
bucket.channels[i] = new WifiNative.ChannelSettings();
- bucket.channels[i].frequency = channels[i];
+ bucket.channels[i].frequency = channels[i].frequency;
}
bucket.period_ms = period;
bucket.report_events = reportEvents;
@@ -154,6 +162,26 @@ public class ScanTestUtil {
}
}
+ public static WifiNative.ScanSettings computeSingleScanNativeSettings(
+ WifiScanner.ScanSettings requestSettings) {
+ return createSingleScanNativeSettings(requestSettings.reportEvents,
+ getAllChannels(requestSettings));
+ }
+
+ public static WifiNative.ScanSettings createSingleScanNativeSettings(
+ int reportEvents, ChannelSpec... channels) {
+ // TODO requests using bands should be scheduled using the band, but are currently
+ // converted to channels before scheduling. This should probably change
+ return new NativeScanSettingsBuilder()
+ .withBasePeriod(0)
+ .withMaxApPerScan(0)
+ .withMaxPercentToCache(0)
+ .withMaxScansToCache(0)
+ .addBucketWithChannels(0,
+ reportEvents | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channels)
+ .build();
+ }
+
public static Set<Integer> createFreqSet(int... elements) {
Set<Integer> set = new HashSet<>();
for (int e : elements) {
@@ -237,7 +265,46 @@ public class ScanTestUtil {
return channelSpecs;
}
- public static ChannelSpec[] getAllChannels(BucketSettings bucket) {
+ public static void assertNativeScanSettingsEquals(WifiNative.ScanSettings expected,
+ WifiNative.ScanSettings actual) {
+ assertEquals("bssids per scan", expected.max_ap_per_scan, actual.max_ap_per_scan);
+ assertEquals("scans to cache", expected.report_threshold_num_scans,
+ actual.report_threshold_num_scans);
+ assertEquals("percent to cache", expected.report_threshold_percent,
+ actual.report_threshold_percent);
+ assertEquals("base period", expected.base_period_ms, actual.base_period_ms);
+
+ assertEquals("number of buckets", expected.num_buckets, actual.num_buckets);
+ assertNotNull("buckets was null", actual.buckets);
+ for (int i = 0; i < expected.buckets.length; ++i) {
+ assertNotNull("buckets[" + i + "] was null", actual.buckets[i]);
+ assertEquals("buckets[" + i + "].period",
+ expected.buckets[i].period_ms, actual.buckets[i].period_ms);
+ assertEquals("buckets[" + i + "].reportEvents",
+ expected.buckets[i].report_events, actual.buckets[i].report_events);
+
+ assertEquals("buckets[" + i + "].band",
+ expected.buckets[i].band, actual.buckets[i].band);
+ if (expected.buckets[i].band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
+ Set<Integer> expectedChannels = new HashSet<>();
+ for (ChannelSpec channel : getAllChannels(expected.buckets[i])) {
+ expectedChannels.add(channel.frequency);
+ }
+ Set<Integer> actualChannels = new HashSet<>();
+ for (ChannelSpec channel : getAllChannels(actual.buckets[i])) {
+ actualChannels.add(channel.frequency);
+ }
+ assertEquals("channels", expectedChannels, actualChannels);
+ } else {
+ assertEquals("buckets[" + i + "].num_channels", 0, actual.buckets[i].num_channels);
+ assertTrue("buckets[" + i + "].channels",
+ actual.buckets[i].channels == null
+ || actual.buckets[i].channels.length == 0);
+ }
+ }
+ }
+
+ public static ChannelSpec[] getAllChannels(WifiNative.BucketSettings bucket) {
if (bucket.band == WifiScanner.WIFI_BAND_UNSPECIFIED) {
ChannelSpec[] channels = new ChannelSpec[bucket.num_channels];
for (int i = 0; i < bucket.num_channels; i++) {
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java
index b08e52dc8..94b9dc330 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantWifiScannerTest.java
@@ -22,7 +22,6 @@ import static com.android.server.wifi.ScanTestUtil.createFreqSet;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -32,14 +31,12 @@ import static org.mockito.Mockito.when;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
-import android.os.Handler;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Set;
@@ -53,15 +50,6 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
public void setup() throws Exception {
mScanner = new SupplicantWifiScannerImpl(mContext, WifiNative.getWlanNativeInterface(),
mLooper.getLooper());
-
- // TODO remove this once SupplicantWifiScannerImpl wifi monitor registration is enabled
- Field eventHandlerField = SupplicantWifiScannerImpl.class.getDeclaredField("mEventHandler");
- eventHandlerField.setAccessible(true);
- Handler eventHandler = (Handler) eventHandlerField.get(mScanner);
- WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- WifiMonitor.SCAN_FAILED_EVENT, eventHandler);
- WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),
- WifiMonitor.SCAN_RESULTS_EVENT, eventHandler);
}
@Test
@@ -332,7 +320,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// All scans fail
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(false);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(false);
// Start scan
mScanner.startBatchedScan(settings, eventHandler);
@@ -367,7 +355,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// All scan starts succeed
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// Start scan
mScanner.startBatchedScan(settings, eventHandler);
@@ -412,7 +400,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// All scan starts succeed
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// Start scan
mScanner.startBatchedScan(settings, eventHandler);
@@ -467,7 +455,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// All scan starts succeed
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// Start scan
mScanner.startBatchedScan(settings, eventHandler);
@@ -477,8 +465,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
// alarm for next period
assertEquals(1, mAlarmManager.getPendingCount());
- order.verify(mWifiNative).scan(eq(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP),
- eq(expectedPeriods[0].getScanFreqs()));
+ order.verify(mWifiNative).scan(eq(expectedPeriods[0].getScanFreqs()));
mScanner.pauseBatchedScan();
@@ -544,7 +531,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// All scan starts succeed
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// Start scan
mScanner.startBatchedScan(settings, eventHandler);
@@ -583,7 +570,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
InOrder order = inOrder(eventHandler, mWifiNative);
// All scans succeed
- when(mWifiNative.scan(anyInt(), any(Set.class))).thenReturn(true);
+ when(mWifiNative.scan(any(Set.class))).thenReturn(true);
// Start scan
mScanner.startBatchedScan(settings, eventHandler);
@@ -643,7 +630,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
ArrayList<ScanDetail> nativeResults, WifiScanner.ScanData[] expectedScanResults,
ScanResult[] fullResults, int periodId) {
// Verify scan started
- order.verify(mWifiNative).scan(eq(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP), eq(scanFreqs));
+ order.verify(mWifiNative).scan(eq(scanFreqs));
// Setup scan results
when(mWifiNative.getScanResults()).thenReturn(nativeResults);
@@ -660,7 +647,7 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
if (expectedScanResults != null) {
// Verify scan results delivered
- order.verify(eventHandler).onScanStatus();
+ order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
assertScanDatasEquals("period[" + periodId + "].", expectedScanResults,
mScanner.getLatestBatchedScanResults(true));
}
@@ -669,22 +656,26 @@ public class SupplicantWifiScannerTest extends BaseWifiScannerImplTest {
private void expectFailedScanStart(InOrder order, WifiNative.ScanEventHandler eventHandler,
Set<Integer> scanFreqs) {
// Verify scan started
- order.verify(mWifiNative).scan(eq(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP), eq(scanFreqs));
+ order.verify(mWifiNative).scan(eq(scanFreqs));
+
+ // TODO verify failure event
}
private void expectFailedEventScan(InOrder order, WifiNative.ScanEventHandler eventHandler,
Set<Integer> scanFreqs) {
// Verify scan started
- order.verify(mWifiNative).scan(eq(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP), eq(scanFreqs));
+ order.verify(mWifiNative).scan(eq(scanFreqs));
// Notify scan has failed
mWifiMonitor.sendMessage(mWifiNative.getInterfaceName(), WifiMonitor.SCAN_FAILED_EVENT);
assertEquals("dispatch message after results event", 1, mLooper.dispatchAll());
+
+ // TODO verify failure event
}
private void dispatchOnlyAlarm() {
assertEquals("dispatch only one alarm", 1, mAlarmManager.dispatchAll());
- assertEquals("dispatch only one message", 1, mLooper.dispatchAll());
+ mLooper.dispatchAll();
}
private static class ScanPeriod {
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScanningServiceTest.java
index 4093936b6..42d89525a 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiScanningServiceTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiScanningServiceTest.java
@@ -16,12 +16,21 @@
package com.android.server.wifi;
+import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder;
+import static com.android.server.wifi.ScanTestUtil.assertNativeScanSettingsEquals;
+import static com.android.server.wifi.ScanTestUtil.assertScanDatasEquals;
+import static com.android.server.wifi.ScanTestUtil.channelsToSpec;
+import static com.android.server.wifi.ScanTestUtil.computeSingleScanNativeSettings;
import static com.android.server.wifi.ScanTestUtil.createRequest;
+import static com.android.server.wifi.ScanTestUtil.createSingleScanNativeSettings;
import static com.android.server.wifi.ScanTestUtil.installWlanWifiNative;
import static com.android.server.wifi.ScanTestUtil.setupMockChannels;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.validateMockitoUsage;
@@ -48,6 +57,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -89,13 +99,16 @@ public class WifiScanningServiceTest {
}
- ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
+ /**
+ * Internal BroadcastReceiver that WifiScanningServiceImpl uses to listen for broadcasts
+ * this is initialized by calling startServiceAndLoadDriver
+ */
+ BroadcastReceiver mBroadcastReceiver;
private void sendWifiScanAvailable(int scanAvailable) {
Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, scanAvailable);
- mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
+ mBroadcastReceiver.onReceive(mContext, intent);
}
private WifiScanner.ScanSettings generateValidScanSettings() {
@@ -112,45 +125,96 @@ public class WifiScanningServiceTest {
return controlChannel;
}
- private Message sendRequest(BidirectionalAsyncChannel controlChannel, Handler handler,
- Message msg) {
- controlChannel.sendMessage(msg);
- mLooper.dispatchAll();
+ private Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler) {
ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
- verify(handler).handleMessage(messageCaptor.capture());
+ order.verify(handler).handleMessage(messageCaptor.capture());
return messageCaptor.getValue();
}
- private void sendAndAssertSuccessfulyBackgroundScan(BidirectionalAsyncChannel controlChannel,
- Handler handler, int scanRequestId, WifiScanner.ScanSettings settings) {
- Message response = sendRequest(controlChannel, handler,
- Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0, scanRequestId,
- settings));
- assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what);
- assertEquals("response.arg2", scanRequestId, response.arg2);
- assertEquals("response.obj", null, response.obj);
+ private void verifyScanResultsRecieved(InOrder order, Handler handler, int listenerId,
+ WifiScanner.ScanData... expected) {
+ Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler);
+ assertScanResultsMessage(listenerId, expected, scanResultMessage);
+ }
+
+ private void assertScanResultsMessage(int listenerId, WifiScanner.ScanData[] expected,
+ Message scanResultMessage) {
+ assertEquals("what", WifiScanner.CMD_SCAN_RESULT, scanResultMessage.what);
+ assertEquals("listenerId", listenerId, scanResultMessage.arg2);
+ assertScanDatasEquals(expected,
+ ((WifiScanner.ParcelableScanData) scanResultMessage.obj).getResults());
+ }
+
+ private void sendBackgroundScanRequest(BidirectionalAsyncChannel controlChannel,
+ int scanRequestId, WifiScanner.ScanSettings settings) {
+ controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0,
+ scanRequestId, settings));
+ }
+
+ private void sendSingleScanRequest(BidirectionalAsyncChannel controlChannel,
+ int scanRequestId, WifiScanner.ScanSettings settings) {
+ controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN, 0,
+ scanRequestId, settings));
+ }
+
+ private void verifySuccessfulResponse(InOrder order, Handler handler, int arg2) {
+ Message response = verifyHandleMessageAndGetMessage(order, handler);
+ assertSuccessfulResponse(arg2, response);
+ }
+
+ private void assertSuccessfulResponse(int arg2, Message response) {
+ if (response.what == WifiScanner.CMD_OP_FAILED) {
+ WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
+ fail("response indicates failure, reason=" + result.reason
+ + ", description=" + result.description);
+ } else {
+ assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what);
+ assertEquals("response.arg2", arg2, response.arg2);
+ }
}
- private void sendAndAssertFailedBackgroundScan(BidirectionalAsyncChannel controlChannel,
- Handler handler, int scanRequestId, WifiScanner.ScanSettings settings,
+ private void verifyFailedResponse(InOrder order, Handler handler, int arg2,
int expectedErrorReason, String expectedErrorDescription) {
- Message response = sendRequest(controlChannel, handler,
- Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0, scanRequestId,
- settings));
- assertFailedResponse(scanRequestId, expectedErrorReason, expectedErrorDescription,
- response);
+ Message response = verifyHandleMessageAndGetMessage(order, handler);
+ assertFailedResponse(arg2, expectedErrorReason, expectedErrorDescription, response);
}
private void assertFailedResponse(int arg2, int expectedErrorReason,
String expectedErrorDescription, Message response) {
- assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what);
- assertEquals("response.arg2", arg2, response.arg2);
- assertEquals("response.obj.reason",
- expectedErrorReason, ((WifiScanner.OperationResult) response.obj).reason);
- assertEquals("response.obj.description",
- expectedErrorDescription, ((WifiScanner.OperationResult) response.obj).description);
+ if (response.what == WifiScanner.CMD_OP_SUCCEEDED) {
+ fail("response indicates success");
+ } else {
+ assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what);
+ assertEquals("response.arg2", arg2, response.arg2);
+ WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
+ assertEquals("response.obj.reason",
+ expectedErrorReason, result.reason);
+ assertEquals("response.obj.description",
+ expectedErrorDescription, result.description);
+ }
}
+ private WifiNative.ScanEventHandler verifyStartSingleScan(InOrder order,
+ WifiNative.ScanSettings expected) {
+ ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
+ ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
+ ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
+ ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
+ order.verify(mWifiScannerImpl).startSingleScan(scanSettingsCaptor.capture(),
+ scanEventHandlerCaptor.capture());
+ assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
+ return scanEventHandlerCaptor.getValue();
+ }
+
+ private void verifyStartBackgroundScan(InOrder order, WifiNative.ScanSettings expected) {
+ ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
+ ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
+ order.verify(mWifiScannerImpl).startBatchedScan(scanSettingsCaptor.capture(),
+ any(WifiNative.ScanEventHandler.class));
+ assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
+ }
+
+ private static final int MAX_AP_PER_SCAN = 16;
private void startServiceAndLoadDriver() {
mWifiScanningServiceImpl.startService();
when(mWifiScannerImpl.getScanCapabilities(any(WifiNative.ScanCapabilities.class)))
@@ -158,7 +222,7 @@ public class WifiScanningServiceTest {
public boolean answer(WifiNative.ScanCapabilities capabilities) {
capabilities.max_scan_cache_size = Integer.MAX_VALUE;
capabilities.max_scan_buckets = 8;
- capabilities.max_ap_cache_per_scan = 16;
+ capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN;
capabilities.max_rssi_sample_size = 8;
capabilities.max_scan_reporting_threshold = 10;
capabilities.max_hotlist_bssids = 0;
@@ -166,8 +230,12 @@ public class WifiScanningServiceTest {
return true;
}
});
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mContext)
- .registerReceiver(mBroadcastReceiverCaptor.capture(), any(IntentFilter.class));
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class));
+ mBroadcastReceiver = broadcastReceiverCaptor.getValue();
+
sendWifiScanAvailable(WifiManager.WIFI_STATE_ENABLED);
mLooper.dispatchAll();
}
@@ -185,8 +253,10 @@ public class WifiScanningServiceTest {
Handler handler = mock(Handler.class);
BidirectionalAsyncChannel controlChannel = connectChannel(handler);
- sendAndAssertFailedBackgroundScan(controlChannel, handler, 122, generateValidScanSettings(),
- WifiScanner.REASON_UNSPECIFIED, "not available");
+ InOrder order = inOrder(handler);
+ sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings());
+ mLooper.dispatchAll();
+ verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
}
@Test
@@ -196,10 +266,12 @@ public class WifiScanningServiceTest {
Handler handler = mock(Handler.class);
BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder order = inOrder(handler);
when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
any(WifiNative.ScanEventHandler.class))).thenReturn(true);
- sendAndAssertSuccessfulyBackgroundScan(controlChannel, handler, 192,
- generateValidScanSettings());
+ sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings());
+ mLooper.dispatchAll();
+ verifySuccessfulResponse(order, handler, 192);
}
@Test
@@ -208,9 +280,368 @@ public class WifiScanningServiceTest {
Handler handler = mock(Handler.class);
BidirectionalAsyncChannel controlChannel = connectChannel(handler);
- Message response = sendRequest(controlChannel, handler,
- Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
- assertFailedResponse(0, WifiScanner.REASON_INVALID_REQUEST, "Invalid request", response);
+ InOrder order = inOrder(handler, mWifiScannerImpl);
+ controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
+ mLooper.dispatchAll();
+ verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST,
+ "Invalid request");
+ }
+
+ private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings,
+ WifiNative.ScanSettings nativeSettings, ScanResults results) {
+ int requestId = 12;
+ startServiceAndLoadDriver();
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder order = inOrder(handler, mWifiScannerImpl);
+
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+
+ sendSingleScanRequest(controlChannel, requestId, requestSettings);
+
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
+ verifySuccessfulResponse(order, handler, requestId);
+
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results.getScanData());
+ eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(order, handler, 12, results.getScanData());
+ verifyNoMoreInteractions(handler);
+ }
+
+ @Test
+ public void sendSingleScanBandRequest() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
+ ScanResults.create(0, 2400, 5150, 5175));
+ }
+
+ @Test
+ public void sendSingleScanChannelsRequest() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
+ ScanResults.create(0, 2400, 2400, 2400));
}
+ @Test
+ public void sendSingleScanRequestWhichFailsToStart() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId = 33;
+
+ startServiceAndLoadDriver();
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder order = inOrder(handler, mWifiScannerImpl);
+
+ // scan fails
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(false);
+
+ sendSingleScanRequest(controlChannel, requestId, requestSettings);
+
+ mLooper.dispatchAll();
+ // Scan is successfully queue, but then fails to execute
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
+ assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0));
+ assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED,
+ "Failed to start single scan", messageCaptor.getAllValues().get(1));
+ }
+
+ @Test
+ public void sendSingleScanRequestWhichFailsAfterStart() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId = 33;
+
+ startServiceAndLoadDriver();
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder order = inOrder(handler, mWifiScannerImpl);
+
+ // successful start
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+
+ sendSingleScanRequest(controlChannel, requestId, requestSettings);
+
+ // Scan is successfully queue
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler =
+ verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings));
+ verifySuccessfulResponse(order, handler, requestId);
+
+ // but then fails to execute
+ eventHandler.onScanStatus(WifiNative.WIFI_SCAN_DISABLED);
+ mLooper.dispatchAll();
+ verifyFailedResponse(order, handler, requestId,
+ WifiScanner.REASON_UNSPECIFIED, "Scan was interrupted");
+ }
+
+ // TODO Add more single scan tests
+ // * disable wifi while scanning
+ // * disable wifi while scanning with pending scan
+
+ @Test
+ public void sendSingleScanRequestAfterPreviousCompletes() {
+ WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId1 = 12;
+ ScanResults results1 = ScanResults.create(0, 2400);
+
+
+ WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId2 = 13;
+ ScanResults results2 = ScanResults.create(0, 2450);
+
+
+ startServiceAndLoadDriver();
+
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder order = inOrder(handler, mWifiScannerImpl);
+
+ // Run scan 1
+ sendSingleScanRequest(controlChannel, requestId1, requestSettings1);
+
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
+ computeSingleScanNativeSettings(requestSettings1));
+ verifySuccessfulResponse(order, handler, requestId1);
+
+ // dispatch scan 1 results
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results1.getScanData());
+ eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(order, handler, requestId1, results1.getScanData());
+
+ // Run scan 2
+ sendSingleScanRequest(controlChannel, requestId2, requestSettings2);
+
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
+ computeSingleScanNativeSettings(requestSettings2));
+ verifySuccessfulResponse(order, handler, requestId2);
+
+ // dispatch scan 2 results
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results2.getScanData());
+ eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(order, handler, requestId2, results2.getScanData());
+ }
+
+ @Test
+ public void sendSingleScanRequestWhilePreviousScanRunning() {
+ WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId1 = 12;
+ ScanResults results1 = ScanResults.create(0, 2400);
+
+ WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId2 = 13;
+ ScanResults results2 = ScanResults.create(0, 2450);
+
+
+ startServiceAndLoadDriver();
+
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder handlerOrder = inOrder(handler);
+ InOrder nativeOrder = inOrder(mWifiScannerImpl);
+
+ // Run scan 1
+ sendSingleScanRequest(controlChannel, requestId1, requestSettings1);
+
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
+ computeSingleScanNativeSettings(requestSettings1));
+ verifySuccessfulResponse(handlerOrder, handler, requestId1);
+
+ // Queue scan 2 (will not run because previous is in progress)
+ sendSingleScanRequest(controlChannel, requestId2, requestSettings2);
+ mLooper.dispatchAll();
+ verifySuccessfulResponse(handlerOrder, handler, requestId2);
+
+ // dispatch scan 1 results
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results1.getScanData());
+ eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
+
+ // now that the first scan completed we expect the second one to start
+ WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
+ computeSingleScanNativeSettings(requestSettings2));
+
+ // dispatch scan 2 results
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results2.getScanData());
+ eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(handlerOrder, handler, requestId2, results2.getScanData());
+ }
+
+
+
+ @Test
+ public void sendMultipleSingleScanRequestWhilePreviousScanRunning() {
+ WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId1 = 12;
+ ScanResults results1 = ScanResults.create(0, 2400);
+
+ WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId2 = 13;
+ ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
+
+ WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId3 = 15;
+ ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
+
+ WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettings(
+ WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
+ ScanResults results2and3 = ScanResults.merge(results2, results3);
+
+
+ startServiceAndLoadDriver();
+
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder handlerOrder = inOrder(handler);
+ InOrder nativeOrder = inOrder(mWifiScannerImpl);
+
+ // Run scan 1
+ sendSingleScanRequest(controlChannel, requestId1, requestSettings1);
+
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
+ computeSingleScanNativeSettings(requestSettings1));
+ verifySuccessfulResponse(handlerOrder, handler, requestId1);
+
+ // Queue scan 2 (will not run because previous is in progress)
+ sendSingleScanRequest(controlChannel, requestId2, requestSettings2);
+ mLooper.dispatchAll();
+ verifySuccessfulResponse(handlerOrder, handler, requestId2);
+
+ // Queue scan 3 (will not run because previous is in progress)
+ sendSingleScanRequest(controlChannel, requestId3, requestSettings3);
+ mLooper.dispatchAll();
+ verifySuccessfulResponse(handlerOrder, handler, requestId3);
+
+ // dispatch scan 1 results
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results1.getScanData());
+ eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
+
+ // now that the first scan completed we expect the second and third ones to start
+ WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
+ nativeSettings2and3);
+
+ // dispatch scan 2 and 3 results
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results2and3.getScanData());
+ eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+
+ mLooper.dispatchAll();
+
+ // unfortunatally the order that these events are dispatched is dependant on the order which
+ // they are iterated through internally
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ handlerOrder.verify(handler, times(2)).handleMessage(messageCaptor.capture());
+ int firstListenerId = messageCaptor.getAllValues().get(0).arg2;
+ assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId3,
+ firstListenerId == requestId2 || firstListenerId == requestId3);
+ if (firstListenerId == requestId2) {
+ assertScanResultsMessage(requestId2,
+ new WifiScanner.ScanData[] {results2.getScanData()},
+ messageCaptor.getAllValues().get(0));
+ assertScanResultsMessage(requestId3,
+ new WifiScanner.ScanData[] {results3.getScanData()},
+ messageCaptor.getAllValues().get(1));
+ } else {
+ assertScanResultsMessage(requestId3,
+ new WifiScanner.ScanData[] {results3.getScanData()},
+ messageCaptor.getAllValues().get(0));
+ assertScanResultsMessage(requestId2,
+ new WifiScanner.ScanData[] {results2.getScanData()},
+ messageCaptor.getAllValues().get(1));
+ }
+ }
+
+ private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings,
+ WifiNative.ScanSettings nativeSettings) {
+ startServiceAndLoadDriver();
+
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ InOrder order = inOrder(handler, mWifiScannerImpl);
+
+ when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+
+ sendBackgroundScanRequest(controlChannel, 12, requestSettings);
+ mLooper.dispatchAll();
+ verifyStartBackgroundScan(order, nativeSettings);
+ verifySuccessfulResponse(order, handler, 12);
+ verifyNoMoreInteractions(handler);
+ }
+
+ @Test
+ public void sendBackgroundScanBandRequest() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 20000,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
+ .withBasePeriod(20000)
+ .withMaxApPerScan(MAX_AP_PER_SCAN)
+ .withMaxScansToCache(WifiScanningScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
+ .addBucketWithBand(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
+ WifiScanner.WIFI_BAND_BOTH)
+ .build();
+ doSuccessfulBackgroundScan(requestSettings, nativeSettings);
+ }
+
+ @Test
+ public void sendBackgroundScanChannelsRequest() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5150), 20000,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
+ .withBasePeriod(20000)
+ .withMaxApPerScan(MAX_AP_PER_SCAN)
+ .withMaxScansToCache(WifiScanningScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
+ .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5150)
+ .build();
+ doSuccessfulBackgroundScan(requestSettings, nativeSettings);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index fa7d36da1..80667b58d 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -41,6 +41,7 @@ import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
import android.net.wifi.p2p.IWifiP2pManager;
import android.os.BatteryStats;
@@ -74,6 +75,7 @@ import com.android.server.wifi.p2p.WifiP2pServiceImpl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -84,6 +86,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -193,6 +196,8 @@ public class WifiStateMachineTest {
when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
mock(ConnectivityManager.class));
+ when(context.getSystemService(Context.WIFI_SCANNING_SERVICE)).thenReturn(mWifiScanner);
+
return context;
}
@@ -257,16 +262,20 @@ public class WifiStateMachineTest {
ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
Long.MAX_VALUE /* needed so that scan results aren't rejected because
there older than scan start */);
+ detail.getScanResult().informationElements = ie;
+ detail.getScanResult().anqpLines = new ArrayList<String>();
return detail;
}
- private ArrayList<ScanDetail> getMockScanResults() {
+ private ScanResult[] getMockScanResults() {
ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
- ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
+ // copy generated results and add space on the end for one more
+ ScanResult[] results = Arrays.copyOf(sr.getScanData().getResults(),
+ sr.getScanData().getResults().length + 1);
int rssi = -65;
- list.add(getGoogleGuestScanDetail(rssi));
- return list;
+ results[results.length - 1] = getGoogleGuestScanDetail(rssi).getScanResult();
+ return results;
}
static final String sSSID = "\"GoogleGuest\"";
@@ -284,6 +293,7 @@ public class WifiStateMachineTest {
MockWifiMonitor mWifiMonitor;
@Mock WifiNative mWifiNative;
+ @Mock WifiScanner mWifiScanner;
@Mock SupplicantStateTracker mSupplicantStateTracker;
@Mock WifiMetrics mWifiMetrics;
@@ -511,14 +521,27 @@ public class WifiStateMachineTest {
mWsm.startScan(-1, 0, null, null);
wait(200);
- verify(mWifiNative).scan(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, null);
-
- when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
- mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
+ ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor =
+ ArgumentCaptor.forClass(WifiScanner.ScanSettings.class);
+ ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor =
+ ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
+ verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture());
+ assertEquals("band", WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
+ scanSettingsCaptor.getValue().band);
+ assertEquals("reportEvents", WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
+ | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT,
+ scanSettingsCaptor.getValue().reportEvents);
+
+ ScanResult[] results = getMockScanResults();
+ for (ScanResult result : results) {
+ scanListenerCaptor.getValue().onFullResult(result);
+ }
+ scanListenerCaptor.getValue().onResults(
+ new WifiScanner.ScanData[] {new WifiScanner.ScanData(0, 0, results)});
wait(200);
- List<ScanResult> results = mWsm.syncGetScanResultsList();
- assertEquals(8, results.size());
+ List<ScanResult> reportedResults = mWsm.syncGetScanResultsList();
+ assertEquals(8, reportedResults.size());
}
@Test