summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Pasanen <invisiblek@cyanogenmod.org>2016-12-05 20:50:00 -0600
committerDan Pasanen <invisiblek@cyanogenmod.org>2016-12-05 20:50:00 -0600
commit7e4f2af516a1f603411cd02336dfa58d1b7a8bfe (patch)
treef29cca780378fa43a2d778e289d2dfca54b431eb
parentad493b0bff4a913f728464da462d5f6083f85299 (diff)
parent4da98e32a7c53663b1af4d979b27df214a3d3b46 (diff)
downloadandroid_frameworks_opt_net_wifi-cm-14.1_prerebase.tar.gz
android_frameworks_opt_net_wifi-cm-14.1_prerebase.tar.bz2
android_frameworks_opt_net_wifi-cm-14.1_prerebase.zip
Merge tag 'android-7.1.1_r4' into cm-14.1cm-14.1_prerebase
Android 7.1.1 release 4 Change-Id: If876f7e629a09a1a82dcaea05381c0af2408cefb
-rw-r--r--service/Android.mk6
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java47
-rw-r--r--service/java/com/android/server/wifi/WifiConnectivityManager.java30
-rw-r--r--service/java/com/android/server/wifi/WifiLastResortWatchdog.java6
-rw-r--r--service/java/com/android/server/wifi/WifiLoggerHal.java5
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java205
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java18
-rw-r--r--service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java6
-rw-r--r--service/java/com/android/server/wifi/WifiScoreReport.java4
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java129
-rw-r--r--service/java/com/android/server/wifi/hotspot2/NetworkDetail.java39
-rw-r--r--service/java/com/android/server/wifi/scanner/ChannelHelper.java4
-rw-r--r--service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java6
-rw-r--r--service/java/com/android/server/wifi/scanner/NoBandChannelHelper.java5
-rw-r--r--service/java/com/android/server/wifi/scanner/SupplicantWifiScannerImpl.java47
-rw-r--r--service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java4
-rw-r--r--service/java/com/android/server/wifi/util/InformationElementUtil.java2
-rw-r--r--service/jni/com_android_server_wifi_WifiNative.cpp33
-rw-r--r--service/proto/wifi.proto63
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ScanResults.java23
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java4
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java60
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java56
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java208
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java55
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java16
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java25
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java30
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/NoBandChannelHelperTest.java12
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/SupplicantPnoScannerTest.java163
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java83
31 files changed, 1195 insertions, 199 deletions
diff --git a/service/Android.mk b/service/Android.mk
index c1ba4a886..cdee104a4 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -145,6 +145,12 @@ LOCAL_MODULE_TAGS :=
LOCAL_MODULE := wifi-service
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
+LOCAL_EMMA_INSTRUMENT := true
+endif
+
+LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.server.wifi.*
+
include $(BUILD_JAVA_LIBRARY)
endif
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 7f3a8eebd..24409aebb 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -190,7 +190,7 @@ public class WifiConfigManager {
*/
private static final int[] NETWORK_SELECTION_DISABLE_THRESHOLD = {
-1, // threshold for NETWORK_SELECTION_ENABLE
- 1, // threshold for DISABLED_BAD_LINK
+ 1, // threshold for DISABLED_BAD_LINK (deprecated)
5, // threshold for DISABLED_ASSOCIATION_REJECTION
5, // threshold for DISABLED_AUTHENTICATION_FAILURE
5, // threshold for DISABLED_DHCP_FAILURE
@@ -206,7 +206,7 @@ public class WifiConfigManager {
*/
private static final int[] NETWORK_SELECTION_DISABLE_TIMEOUT = {
Integer.MAX_VALUE, // threshold for NETWORK_SELECTION_ENABLE
- 15, // threshold for DISABLED_BAD_LINK
+ 15, // threshold for DISABLED_BAD_LINK (deprecated)
5, // threshold for DISABLED_ASSOCIATION_REJECTION
5, // threshold for DISABLED_AUTHENTICATION_FAILURE
5, // threshold for DISABLED_DHCP_FAILURE
@@ -243,11 +243,6 @@ public class WifiConfigManager {
public AtomicInteger mBandAward5Ghz = new AtomicInteger();
/**
- * If Connectivity Service has triggered an unwanted network disconnect
- */
- public long mLastUnwantedNetworkDisconnectTimestamp = 0;
-
- /**
* Framework keeps a list of ephemeral SSIDs that where deleted by user,
* so as, framework knows not to autojoin again those SSIDs based on scorer input.
* The list is never cleared up.
@@ -1669,6 +1664,7 @@ public class WifiConfigManager {
// 2) mConfiguredNetworks caches a Passpoint network's FQDN the moment the network is added.
// Thus, we had to load the FQDNs first.
mConfiguredNetworks.clear();
+ mScanDetailCaches.clear();
for (Map.Entry<String, WifiConfiguration> entry : configs.entrySet()) {
final String configKey = entry.getKey();
final WifiConfiguration config = entry.getValue();
@@ -2472,20 +2468,8 @@ public class WifiConfigManager {
}
private Map<HomeSP, PasspointMatch> matchPasspointNetworks(ScanDetail scanDetail) {
+ // Nothing to do if no Hotspot 2.0 provider is configured.
if (!mMOManager.isConfigured()) {
- if (mEnableOsuQueries) {
- NetworkDetail networkDetail = scanDetail.getNetworkDetail();
- List<Constants.ANQPElementType> querySet =
- ANQPFactory.buildQueryList(networkDetail, false, true);
-
- if (networkDetail.queriable(querySet)) {
- querySet = mAnqpCache.initiate(networkDetail, querySet);
- if (querySet != null) {
- mSupplicantBridge.startANQP(scanDetail, querySet);
- }
- updateAnqpCache(scanDetail, networkDetail.getANQPElements());
- }
- }
return null;
}
NetworkDetail networkDetail = scanDetail.getNetworkDetail();
@@ -3233,29 +3217,6 @@ public class WifiConfigManager {
}
}
- /** called when CS ask WiFistateMachine to disconnect the current network
- * because the score is bad.
- */
- void handleBadNetworkDisconnectReport(int netId, WifiInfo info) {
- /* TODO verify the bad network is current */
- WifiConfiguration config = mConfiguredNetworks.getForCurrentUser(netId);
- if (config != null) {
- if ((info.is24GHz() && info.getRssi()
- <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_24G_BAND)
- || (info.is5GHz() && info.getRssi()
- <= WifiQualifiedNetworkSelector.QUALIFIED_RSSI_5G_BAND)) {
- // We do not block due to bad RSSI since network selection should not select bad
- // RSSI candidate
- } else {
- // We got disabled but RSSI is good, so disable hard
- updateNetworkSelectionStatus(config,
- WifiConfiguration.NetworkSelectionStatus.DISABLED_BAD_LINK);
- }
- }
- // Record last time Connectivity Service switched us away from WiFi and onto Cell
- mLastUnwantedNetworkDisconnectTimestamp = mClock.currentTimeMillis();
- }
-
int getMaxDhcpRetries() {
return mFacade.getIntegerSetting(mContext,
Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index bdd931e4e..1cdfb692a 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -150,6 +150,7 @@ public class WifiConnectivityManager {
private long mLastPeriodicSingleScanTimeStamp = RESET_TIME_STAMP;
private boolean mPnoScanStarted = false;
private boolean mPeriodicScanTimerSet = false;
+ private boolean mWaitForFullBandScanResults = false;
// PNO settings
private int mMin5GHzRssi;
@@ -229,6 +230,7 @@ public class WifiConnectivityManager {
mStateMachine.isSupplicantTransientState());
mWifiLastResortWatchdog.updateAvailableNetworks(
mQualifiedNetworkSelector.getFilteredScanDetails());
+ mWifiMetrics.countScanResults(scanDetails);
if (candidate != null) {
localLog(listenerName + ": QNS candidate-" + candidate.SSID);
connectToNetwork(candidate);
@@ -327,9 +329,21 @@ public class WifiConnectivityManager {
public void onResults(WifiScanner.ScanData[] results) {
if (!mWifiEnabled || !mWifiConnectivityManagerEnabled) {
clearScanDetails();
+ mWaitForFullBandScanResults = false;
return;
}
+ // Full band scan results only.
+ if (mWaitForFullBandScanResults) {
+ if (!results[0].isAllChannelsScanned()) {
+ localLog("AllSingleScanListener waiting for full band scan results.");
+ clearScanDetails();
+ return;
+ } else {
+ mWaitForFullBandScanResults = false;
+ }
+ }
+
boolean wasConnectAttempted = handleScanResults(mScanDetails, "AllSingleScanListener");
clearScanDetails();
@@ -513,7 +527,7 @@ public class WifiConnectivityManager {
public WifiConnectivityManager(Context context, WifiStateMachine stateMachine,
WifiScanner scanner, WifiConfigManager configManager, WifiInfo wifiInfo,
WifiQualifiedNetworkSelector qualifiedNetworkSelector,
- WifiInjector wifiInjector, Looper looper) {
+ WifiInjector wifiInjector, Looper looper, boolean enable) {
mStateMachine = stateMachine;
mScanner = scanner;
mConfigManager = configManager;
@@ -548,7 +562,10 @@ public class WifiConnectivityManager {
// Register for all single scan results
mScanner.registerScanListener(mAllSingleScanListener);
- Log.i(TAG, "ConnectivityScanManager initialized ");
+ mWifiConnectivityManagerEnabled = enable;
+
+ Log.i(TAG, "ConnectivityScanManager initialized and "
+ + (enable ? "enabled" : "disabled"));
}
/**
@@ -1077,7 +1094,8 @@ public class WifiConnectivityManager {
public void forceConnectivityScan() {
Log.i(TAG, "forceConnectivityScan");
- startConnectivityScan(SCAN_IMMEDIATELY);
+ mWaitForFullBandScanResults = true;
+ startSingleScan(true);
}
/**
@@ -1121,6 +1139,9 @@ public class WifiConnectivityManager {
stopConnectivityScan();
resetLastPeriodicSingleScanTimeStamp();
mLastConnectionAttemptBssid = null;
+ mWaitForFullBandScanResults = false;
+ } else if (mWifiConnectivityManagerEnabled) {
+ startConnectivityScan(SCAN_IMMEDIATELY);
}
}
@@ -1136,6 +1157,9 @@ public class WifiConnectivityManager {
stopConnectivityScan();
resetLastPeriodicSingleScanTimeStamp();
mLastConnectionAttemptBssid = null;
+ mWaitForFullBandScanResults = false;
+ } else if (mWifiEnabled) {
+ startConnectivityScan(SCAN_IMMEDIATELY);
}
}
diff --git a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java
index 558b50ef1..0885e46fd 100644
--- a/service/java/com/android/server/wifi/WifiLastResortWatchdog.java
+++ b/service/java/com/android/server/wifi/WifiLastResortWatchdog.java
@@ -209,6 +209,12 @@ public class WifiLastResortWatchdog {
public void connectedStateTransition(boolean isEntering) {
if (VDBG) Log.v(TAG, "connectedStateTransition: isEntering = " + isEntering);
mWifiIsConnected = isEntering;
+
+ if (!mWatchdogAllowedToTrigger) {
+ // WiFi has connected after a Watchdog trigger, without any new networks becoming
+ // available, log a Watchdog success in wifi metrics
+ mWifiMetrics.incrementNumLastResortWatchdogSuccesses();
+ }
if (isEntering) {
// We connected to something! Reset failure counts for everything
clearAllFailureCounts();
diff --git a/service/java/com/android/server/wifi/WifiLoggerHal.java b/service/java/com/android/server/wifi/WifiLoggerHal.java
index 8a0276480..0294e9bf7 100644
--- a/service/java/com/android/server/wifi/WifiLoggerHal.java
+++ b/service/java/com/android/server/wifi/WifiLoggerHal.java
@@ -46,4 +46,9 @@ public class WifiLoggerHal {
public static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8;
public static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9;
public static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10;
+
+ /** These aren't formally part of the HAL. But they probably should be, eventually. */
+ public static final byte WIFI_ALERT_REASON_RESERVED = 0;
+ public static final byte WIFI_ALERT_REASON_MIN = 0;
+ public static final byte WIFI_ALERT_REASON_MAX = 64;
}
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 4ef29f6f8..fcb6301b6 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -16,6 +16,7 @@
package com.android.server.wifi;
+import android.net.NetworkAgent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.util.Base64;
@@ -47,6 +48,8 @@ public class WifiMetrics {
*/
private static final int MAX_RSSI_POLL = 0;
private static final int MIN_RSSI_POLL = -127;
+ private static final int MIN_WIFI_SCORE = 0;
+ private static final int MAX_WIFI_SCORE = NetworkAgent.WIFI_BASE_SCORE;
private final Object mLock = new Object();
private static final int MAX_CONNECTION_EVENTS = 256;
private Clock mClock;
@@ -76,13 +79,17 @@ public class WifiMetrics {
* combination. Indexed by WifiLog.WifiState * (1 + screenOn)
*/
private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray();
+ /** Mapping of RSSI values to counts. */
+ private final SparseIntArray mRssiPollCounts = new SparseIntArray();
+ /** Mapping of alert reason to the respective alert count. */
+ private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray();
/**
* Records the elapsedRealtime (in seconds) that represents the beginning of data
* capture for for this WifiMetricsProto
*/
- private final SparseIntArray mRssiPollCounts = new SparseIntArray();
private long mRecordStartTimeSec;
-
+ /** Mapping of Wifi Scores to counts */
+ private final SparseIntArray mWifiScoreCounts = new SparseIntArray();
class RouterFingerPrint {
private WifiMetricsProto.RouterFingerPrint mRouterFingerPrintProto;
RouterFingerPrint() {
@@ -127,6 +134,8 @@ public class WifiMetrics {
mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
.authentication = WifiMetricsProto.RouterFingerPrint.AUTH_PERSONAL;
}
+ mCurrentConnectionEvent.mRouterFingerPrint.mRouterFingerPrintProto
+ .passpoint = config.isPasspoint();
// If there's a ScanResult candidate associated with this config already, get it and
// log (more accurate) metrics from it
ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
@@ -512,6 +521,18 @@ public class WifiMetrics {
}
}
+ void setNumHiddenNetworks(int num) {
+ synchronized (mLock) {
+ mWifiLogProto.numHiddenNetworks = num;
+ }
+ }
+
+ void setNumPasspointNetworks(int num) {
+ synchronized (mLock) {
+ mWifiLogProto.numPasspointNetworks = num;
+ }
+ }
+
void setNumNetworksAddedByUser(int num) {
synchronized (mLock) {
mWifiLogProto.numNetworksAddedByUser = num;
@@ -806,10 +827,105 @@ public class WifiMetrics {
}
}
+ /**
+ * Increment count of Watchdog successes.
+ */
+ public void incrementNumLastResortWatchdogSuccesses() {
+ synchronized (mLock) {
+ mWifiLogProto.numLastResortWatchdogSuccesses++;
+ }
+ }
+
+ /**
+ * Increments the count of alerts by alert reason.
+ *
+ * @param reason The cause of the alert. The reason values are driver-specific.
+ */
+ public void incrementAlertReasonCount(int reason) {
+ if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX
+ || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) {
+ reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED;
+ }
+ synchronized (mLock) {
+ int alertCount = mWifiAlertReasonCounts.get(reason);
+ mWifiAlertReasonCounts.put(reason, alertCount + 1);
+ }
+ }
+
+ /**
+ * Counts all the different types of networks seen in a set of scan results
+ */
+ public void countScanResults(List<ScanDetail> scanDetails) {
+ if (scanDetails == null) {
+ return;
+ }
+ int totalResults = 0;
+ int openNetworks = 0;
+ int personalNetworks = 0;
+ int enterpriseNetworks = 0;
+ int hiddenNetworks = 0;
+ int hotspot2r1Networks = 0;
+ int hotspot2r2Networks = 0;
+ for (ScanDetail scanDetail : scanDetails) {
+ NetworkDetail networkDetail = scanDetail.getNetworkDetail();
+ ScanResult scanResult = scanDetail.getScanResult();
+ totalResults++;
+ if (networkDetail != null) {
+ if (networkDetail.isHiddenBeaconFrame()) {
+ hiddenNetworks++;
+ }
+ if (networkDetail.getHSRelease() != null) {
+ if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R1) {
+ hotspot2r1Networks++;
+ } else if (networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2) {
+ hotspot2r2Networks++;
+ }
+ }
+ }
+ if (scanResult != null && scanResult.capabilities != null) {
+ if (scanResult.capabilities.contains("EAP")) {
+ enterpriseNetworks++;
+ } else if (scanResult.capabilities.contains("PSK")
+ || scanResult.capabilities.contains("WEP")) {
+ personalNetworks++;
+ } else {
+ openNetworks++;
+ }
+ }
+ }
+ synchronized (mLock) {
+ mWifiLogProto.numTotalScanResults += totalResults;
+ mWifiLogProto.numOpenNetworkScanResults += openNetworks;
+ mWifiLogProto.numPersonalNetworkScanResults += personalNetworks;
+ mWifiLogProto.numEnterpriseNetworkScanResults += enterpriseNetworks;
+ mWifiLogProto.numHiddenNetworkScanResults += hiddenNetworks;
+ mWifiLogProto.numHotspot2R1NetworkScanResults += hotspot2r1Networks;
+ mWifiLogProto.numHotspot2R2NetworkScanResults += hotspot2r2Networks;
+ mWifiLogProto.numScans++;
+ }
+ }
+
+ /**
+ * Increments occurence of a particular wifi score calculated
+ * in WifiScoreReport by current connected network. Scores are bounded
+ * within [MIN_WIFI_SCORE, MAX_WIFI_SCORE] to limit size of SparseArray
+ */
+ public void incrementWifiScoreCount(int score) {
+ if (score < MIN_WIFI_SCORE || score > MAX_WIFI_SCORE) {
+ return;
+ }
+ synchronized (mLock) {
+ int count = mWifiScoreCounts.get(score);
+ mWifiScoreCounts.put(score, count + 1);
+ }
+ }
+
public static final String PROTO_DUMP_ARG = "wifiMetricsProto";
+ public static final String CLEAN_DUMP_ARG = "clean";
+
/**
* Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager
- * at this time
+ * at this time.
*
* @param fd unused
* @param pw PrintWriter for writing dump to
@@ -817,9 +933,8 @@ public class WifiMetrics {
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mLock) {
- pw.println("WifiMetrics:");
if ((args != null) && args.length > 0 && PROTO_DUMP_ARG.equals(args[0])) {
- //Dump serialized WifiLog proto
+ // Dump serialized WifiLog proto
consolidateProto(true);
for (ConnectionEvent event : mConnectionEventList) {
if (mCurrentConnectionEvent != event) {
@@ -830,10 +945,18 @@ public class WifiMetrics {
}
byte[] wifiMetricsProto = WifiMetricsProto.WifiLog.toByteArray(mWifiLogProto);
String metricsProtoDump = Base64.encodeToString(wifiMetricsProto, Base64.DEFAULT);
- pw.println(metricsProtoDump);
- pw.println("EndWifiMetrics");
+ if (args.length > 1 && CLEAN_DUMP_ARG.equals(args[1])) {
+ // Output metrics proto bytes (base64) and nothing else
+ pw.print(metricsProtoDump);
+ } else {
+ // Tag the start and end of the metrics proto bytes
+ pw.println("WifiMetrics:");
+ pw.println(metricsProtoDump);
+ pw.println("EndWifiMetrics");
+ }
clear();
} else {
+ pw.println("WifiMetrics:");
pw.println("mConnectionEvents:");
for (ConnectionEvent event : mConnectionEventList) {
String eventLine = event.toString();
@@ -848,6 +971,9 @@ public class WifiMetrics {
+ mWifiLogProto.numPersonalNetworks);
pw.println("mWifiLogProto.numEnterpriseNetworks="
+ mWifiLogProto.numEnterpriseNetworks);
+ pw.println("mWifiLogProto.numHiddenNetworks=" + mWifiLogProto.numHiddenNetworks);
+ pw.println("mWifiLogProto.numPasspointNetworks="
+ + mWifiLogProto.numPasspointNetworks);
pw.println("mWifiLogProto.isLocationEnabled=" + mWifiLogProto.isLocationEnabled);
pw.println("mWifiLogProto.isScanningAlwaysEnabled="
+ mWifiLogProto.isScanningAlwaysEnabled);
@@ -921,6 +1047,8 @@ public class WifiMetrics {
+ mWifiLogProto.numLastResortWatchdogTriggersWithBadDhcp);
pw.println("mWifiLogProto.numLastResortWatchdogTriggersWithBadOther="
+ mWifiLogProto.numLastResortWatchdogTriggersWithBadOther);
+ pw.println("mWifiLogProto.numLastResortWatchdogSuccesses="
+ + mWifiLogProto.numLastResortWatchdogSuccesses);
pw.println("mWifiLogProto.recordDurationSec="
+ ((mClock.elapsedRealtime() / 1000) - mRecordStartTimeSec));
pw.println("mWifiLogProto.rssiPollRssiCount: Printing counts for [" + MIN_RSSI_POLL
@@ -930,6 +1058,42 @@ public class WifiMetrics {
sb.append(mRssiPollCounts.get(i) + " ");
}
pw.println(" " + sb.toString());
+ pw.print("mWifiLogProto.alertReasonCounts=");
+ sb.setLength(0);
+ for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN;
+ i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) {
+ int count = mWifiAlertReasonCounts.get(i);
+ if (count > 0) {
+ sb.append("(" + i + "," + count + "),");
+ }
+ }
+ if (sb.length() > 1) {
+ sb.setLength(sb.length() - 1); // strip trailing comma
+ pw.println(sb.toString());
+ } else {
+ pw.println("()");
+ }
+ pw.println("mWifiLogProto.numTotalScanResults="
+ + mWifiLogProto.numTotalScanResults);
+ pw.println("mWifiLogProto.numOpenNetworkScanResults="
+ + mWifiLogProto.numOpenNetworkScanResults);
+ pw.println("mWifiLogProto.numPersonalNetworkScanResults="
+ + mWifiLogProto.numPersonalNetworkScanResults);
+ pw.println("mWifiLogProto.numEnterpriseNetworkScanResults="
+ + mWifiLogProto.numEnterpriseNetworkScanResults);
+ pw.println("mWifiLogProto.numHiddenNetworkScanResults="
+ + mWifiLogProto.numHiddenNetworkScanResults);
+ pw.println("mWifiLogProto.numHotspot2R1NetworkScanResults="
+ + mWifiLogProto.numHotspot2R1NetworkScanResults);
+ pw.println("mWifiLogProto.numHotspot2R2NetworkScanResults="
+ + mWifiLogProto.numHotspot2R2NetworkScanResults);
+ pw.println("mWifiLogProto.numScans=" + mWifiLogProto.numScans);
+ pw.println("mWifiLogProto.WifiScoreCount: [" + MIN_WIFI_SCORE + ", "
+ + MAX_WIFI_SCORE + "]");
+ for (int i = 0; i <= MAX_WIFI_SCORE; i++) {
+ pw.print(mWifiScoreCounts.get(i) + " ");
+ }
+ pw.print("\n");
}
}
}
@@ -943,6 +1107,8 @@ public class WifiMetrics {
private void consolidateProto(boolean incremental) {
List<WifiMetricsProto.ConnectionEvent> events = new ArrayList<>();
List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>();
+ List<WifiMetricsProto.AlertReasonCount> alertReasons = new ArrayList<>();
+ List<WifiMetricsProto.WifiScoreCount> scores = new ArrayList<>();
synchronized (mLock) {
for (ConnectionEvent event : mConnectionEventList) {
// If this is not incremental, dump full ConnectionEvent list
@@ -1000,6 +1166,29 @@ public class WifiMetrics {
rssis.add(keyVal);
}
mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount);
+
+ /**
+ * Convert the SparseIntArray of alert reasons and counts to the proto's repeated
+ * IntKeyVal array.
+ */
+ for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) {
+ WifiMetricsProto.AlertReasonCount keyVal = new WifiMetricsProto.AlertReasonCount();
+ keyVal.reason = mWifiAlertReasonCounts.keyAt(i);
+ keyVal.count = mWifiAlertReasonCounts.valueAt(i);
+ alertReasons.add(keyVal);
+ }
+ mWifiLogProto.alertReasonCount = alertReasons.toArray(mWifiLogProto.alertReasonCount);
+ /**
+ * Convert the SparseIntArray of Wifi Score and counts to proto's repeated
+ * IntKeyVal array.
+ */
+ for (int score = 0; score < mWifiScoreCounts.size(); score++) {
+ WifiMetricsProto.WifiScoreCount keyVal = new WifiMetricsProto.WifiScoreCount();
+ keyVal.score = mWifiScoreCounts.keyAt(score);
+ keyVal.count = mWifiScoreCounts.valueAt(score);
+ scores.add(keyVal);
+ }
+ mWifiLogProto.wifiScoreCount = scores.toArray(mWifiLogProto.wifiScoreCount);
}
}
@@ -1016,6 +1205,8 @@ public class WifiMetrics {
mWifiSystemStateEntries.clear();
mRecordStartTimeSec = mClock.elapsedRealtime() / 1000;
mRssiPollCounts.clear();
+ mWifiAlertReasonCounts.clear();
+ mWifiScoreCounts.clear();
mWifiLogProto.clear();
}
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index 7ed0409f9..f6931c1fe 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -78,6 +78,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
@@ -1716,6 +1717,19 @@ public class WifiNative {
public int priority;
public byte flags;
public byte auth_bit_field;
+
+ @Override
+ public boolean equals(Object otherObj) {
+ if (this == otherObj) {
+ return true;
+ } else if (otherObj == null || getClass() != otherObj.getClass()) {
+ return false;
+ }
+ PnoNetwork other = (PnoNetwork) otherObj;
+ return ((Objects.equals(ssid, other.ssid)) && (networkId == other.networkId)
+ && (priority == other.priority) && (flags == other.flags)
+ && (auth_bit_field == other.auth_bit_field));
+ }
}
/**
@@ -2193,13 +2207,12 @@ public class WifiNative {
synchronized (sLock) {
if (isHalStarted()) {
if (sRttCmdId != 0) {
- Log.v("TAG", "Last one is still under measurement!");
+ Log.w(TAG, "Last one is still under measurement!");
return false;
} else {
sRttCmdId = getNewCmdIdLocked();
}
sRttEventHandler = handler;
- Log.v(TAG, "native issue RTT request");
return requestRangeNative(sWlan0Index, sRttCmdId, params);
} else {
return false;
@@ -2218,7 +2231,6 @@ public class WifiNative {
if (cancelRangeRequestNative(sWlan0Index, sRttCmdId, params)) {
sRttEventHandler = null;
- Log.v(TAG, "RTT cancel Request Successfully");
return true;
} else {
Log.e(TAG, "RTT cancel Request failed");
diff --git a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
index 7ad44c875..00fffdb4b 100644
--- a/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiQualifiedNetworkSelector.java
@@ -626,9 +626,9 @@ public class WifiQualifiedNetworkSelector {
mWifiConfigManager.getWifiConfiguration(mWifiInfo.getNetworkId());
}
- if (mCurrentBssid == null) {
- mCurrentBssid = mWifiInfo.getBSSID();
- }
+ // Always get the current BSSID from WifiInfo in case that firmware initiated roaming
+ // happened.
+ mCurrentBssid = mWifiInfo.getBSSID();
if (!forceSelectNetwork && !needQualifiedNetworkSelection(isLinkDebouncing, isConnected,
isDisconnected, isSupplicantTransient)) {
diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java
index 50e28bf28..d32c72299 100644
--- a/service/java/com/android/server/wifi/WifiScoreReport.java
+++ b/service/java/com/android/server/wifi/WifiScoreReport.java
@@ -97,7 +97,8 @@ public class WifiScoreReport {
WifiConfigManager wifiConfigManager,
NetworkAgent networkAgent,
WifiScoreReport lastReport,
- int aggressiveHandover) {
+ int aggressiveHandover,
+ WifiMetrics wifiMetrics) {
boolean debugLogging = false;
if (wifiConfigManager.mEnableVerboseLogging.get() > 0) {
debugLogging = true;
@@ -370,6 +371,7 @@ public class WifiScoreReport {
networkAgent.sendNetworkScore(score);
}
}
+ wifiMetrics.incrementWifiScoreCount(score);
return new WifiScoreReport(sb.toString(), badLinkspeedcount);
}
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 180fd82f8..e34385352 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -98,6 +98,7 @@ import android.util.SparseArray;
import android.os.SystemProperties;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
@@ -551,10 +552,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
private WifiScanner mWifiScanner;
- private int mConnectionRequests = 0;
+ @GuardedBy("mWifiReqCountLock")
+ private int mConnectionReqCount = 0;
private WifiNetworkFactory mNetworkFactory;
+ @GuardedBy("mWifiReqCountLock")
+ private int mUntrustedReqCount = 0;
private UntrustedWifiNetworkFactory mUntrustedNetworkFactory;
private WifiNetworkAgent mNetworkAgent;
+ private final Object mWifiReqCountLock = new Object();
private String[] mWhiteListedSsids = null;
@@ -2372,6 +2377,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (args.length > 1 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0])
+ && WifiMetrics.CLEAN_DUMP_ARG.equals(args[1])) {
+ // Dump only wifi metrics serialized proto bytes (base64)
+ updateWifiMetrics();
+ mWifiMetrics.dump(fd, pw, args);
+ return;
+ }
super.dump(fd, pw, args);
mSupplicantStateTracker.dump(fd, pw, args);
pw.println("mLinkProperties " + mLinkProperties);
@@ -2620,7 +2632,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
sb.append(" known=").append(mNumScanResultsKnown);
sb.append(" got=").append(mNumScanResultsReturned);
sb.append(String.format(" bcn=%d", mRunningBeaconCount));
- sb.append(String.format(" con=%d", mConnectionRequests));
+ sb.append(String.format(" con=%d", mConnectionReqCount));
+ sb.append(String.format(" untrustedcn=%d", mUntrustedReqCount));
key = mWifiConfigManager.getLastSelectedConfiguration();
if (key != null) {
sb.append(" last=").append(key);
@@ -3989,23 +4002,33 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
@Override
protected void needNetworkFor(NetworkRequest networkRequest, int score) {
- ++mConnectionRequests;
+ synchronized (mWifiReqCountLock) {
+ if (++mConnectionReqCount == 1) {
+ if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) {
+ mWifiConnectivityManager.enable(true);
+ }
+ }
+ }
}
@Override
protected void releaseNetworkFor(NetworkRequest networkRequest) {
- --mConnectionRequests;
+ synchronized (mWifiReqCountLock) {
+ if (--mConnectionReqCount == 0) {
+ if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) {
+ mWifiConnectivityManager.enable(false);
+ }
+ }
+ }
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("mConnectionRequests " + mConnectionRequests);
+ pw.println("mConnectionReqCount " + mConnectionReqCount);
}
}
private class UntrustedWifiNetworkFactory extends NetworkFactory {
- private int mUntrustedReqCount;
-
public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) {
super(l, c, tag, f);
}
@@ -4014,9 +4037,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
protected void needNetworkFor(NetworkRequest networkRequest, int score) {
if (!networkRequest.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_TRUSTED)) {
- if (++mUntrustedReqCount == 1) {
- if (mWifiConnectivityManager != null) {
- mWifiConnectivityManager.setUntrustedConnectionAllowed(true);
+ synchronized (mWifiReqCountLock) {
+ if (++mUntrustedReqCount == 1) {
+ if (mWifiConnectivityManager != null) {
+ if (mConnectionReqCount == 0) {
+ mWifiConnectivityManager.enable(true);
+ }
+ mWifiConnectivityManager.setUntrustedConnectionAllowed(true);
+ }
}
}
}
@@ -4026,9 +4054,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
protected void releaseNetworkFor(NetworkRequest networkRequest) {
if (!networkRequest.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_TRUSTED)) {
- if (--mUntrustedReqCount == 0) {
- if (mWifiConnectivityManager != null) {
- mWifiConnectivityManager.setUntrustedConnectionAllowed(false);
+ synchronized (mWifiReqCountLock) {
+ if (--mUntrustedReqCount == 0) {
+ if (mWifiConnectivityManager != null) {
+ mWifiConnectivityManager.setUntrustedConnectionAllowed(false);
+ if (mConnectionReqCount == 0) {
+ mWifiConnectivityManager.enable(false);
+ }
+ }
}
}
}
@@ -4234,7 +4267,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
case CMD_FIRMWARE_ALERT:
if (mWifiLogger != null) {
byte[] buffer = (byte[])message.obj;
- mWifiLogger.captureAlertData(message.arg1, buffer);
+ int alertReason = message.arg1;
+ mWifiLogger.captureAlertData(alertReason, buffer);
+ mWifiMetrics.incrementAlertReasonCount(alertReason);
}
break;
case CMD_GET_LINK_LAYER_STATS:
@@ -4779,10 +4814,13 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
if (mWifiScanner == null) {
mWifiScanner = mFacade.makeWifiScanner(mContext, getHandler().getLooper());
- mWifiConnectivityManager = new WifiConnectivityManager(mContext,
- WifiStateMachine.this, mWifiScanner, mWifiConfigManager, mWifiInfo,
- mWifiQualifiedNetworkSelector, mWifiInjector,
- getHandler().getLooper());
+ synchronized (mWifiReqCountLock) {
+ mWifiConnectivityManager = new WifiConnectivityManager(mContext,
+ WifiStateMachine.this, mWifiScanner, mWifiConfigManager, mWifiInfo,
+ mWifiQualifiedNetworkSelector, mWifiInjector,
+ getHandler().getLooper(), hasConnectionRequests());
+ mWifiConnectivityManager.setUntrustedConnectionAllowed(mUntrustedReqCount > 0);
+ }
}
mWifiLogger.startLogging(DBG);
@@ -5671,8 +5709,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
config, disableOthers, message.sendingUid);
if (!ok) {
messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
- } else if (disableOthers) {
- mTargetNetworkId = netId;
+ } else {
+ if (disableOthers) {
+ mTargetNetworkId = netId;
+ }
+ mWifiConnectivityManager.forceConnectivityScan();
}
replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
@@ -6756,7 +6797,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mWifiConfigManager,
mNetworkAgent,
mWifiScoreReport,
- mAggressiveHandover);
+ mAggressiveHandover,
+ mWifiMetrics);
}
sendMessageDelayed(obtainMessage(CMD_RSSI_POLL,
mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
@@ -7223,8 +7265,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
break;
case CMD_UNWANTED_NETWORK:
if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) {
- mWifiConfigManager.handleBadNetworkDisconnectReport(
- mLastNetworkId, mWifiInfo);
mWifiNative.disconnect();
transitionTo(mDisconnectingState);
} else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN ||
@@ -7369,18 +7409,16 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
config = mWifiConfigManager.getWifiConfiguration(netId);
}
+ setTargetBssid(config, bssid);
+ mTargetNetworkId = netId;
+
logd("CMD_AUTO_ROAM sup state "
+ mSupplicantStateTracker.getSupplicantStateName()
+ " my state " + getCurrentState().getName()
+ " nid=" + Integer.toString(netId)
+ " config " + config.configKey()
- + " roam=" + Integer.toString(message.arg2)
- + " to " + bssid
+ " targetRoamBSSID " + mTargetRoamBSSID);
- setTargetBssid(config, bssid);
- mTargetNetworkId = netId;
-
/* Determine if this is a regular roam (between BSSIDs sharing the same SSID),
or a DBDC roam (between 2.4 & 5GHz networks on different SSID's, but with
matching 16 byte BSSID prefixes):
@@ -8251,7 +8289,11 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
* @param bssid BSSID of the network
*/
public void autoConnectToNetwork(int networkId, String bssid) {
- sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid);
+ synchronized (mWifiReqCountLock) {
+ if (hasConnectionRequests()) {
+ sendMessage(CMD_AUTO_CONNECT, networkId, 0, bssid);
+ }
+ }
}
/**
@@ -8302,6 +8344,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
int numEnterpriseNetworks = 0;
int numNetworksAddedByUser = 0;
int numNetworksAddedByApps = 0;
+ int numHiddenNetworks = 0;
+ int numPasspoint = 0;
for (WifiConfiguration config : mWifiConfigManager.getSavedNetworks()) {
if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
numOpenNetworks++;
@@ -8315,6 +8359,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
} else {
numNetworksAddedByApps++;
}
+ if (config.hiddenSSID) {
+ numHiddenNetworks++;
+ }
+ if (config.isPasspoint()) {
+ numPasspoint++;
+ }
}
mWifiMetrics.setNumSavedNetworks(numSavedNetworks);
mWifiMetrics.setNumOpenNetworks(numOpenNetworks);
@@ -8322,17 +8372,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks);
mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser);
mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps);
-
- /* <TODO> decide how to access WifiServiecImpl.isLocationEnabled() or if to do it manually
- mWifiMetrics.setIsLocationEnabled(Settings.Secure.getInt(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
- != Settings.Secure.LOCATION_MODE_OFF);
- */
-
- /* <TODO> decide how statemachine will access WifiSettingsStore
- mWifiMetrics.setIsScanningAlwaysEnabled(mSettingsStore.isScanningAlwaysAvailable());
- */
+ mWifiMetrics.setNumHiddenNetworks(numHiddenNetworks);
+ mWifiMetrics.setNumPasspointNetworks(numPasspoint);
}
private static String getLinkPropertiesSummary(LinkProperties lp) {
@@ -8431,4 +8472,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
}
}
}
+
+ /**
+ * Check if there is any connection request for WiFi network.
+ * Note, caller of this helper function must acquire mWifiReqCountLock.
+ */
+ private boolean hasConnectionRequests() {
+ return mConnectionReqCount > 0 || mUntrustedReqCount > 0;
+ }
}
diff --git a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
index 402c0a869..321254c72 100644
--- a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
+++ b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
@@ -59,6 +59,8 @@ public class NetworkDetail {
private final String mSSID;
private final long mHESSID;
private final long mBSSID;
+ // True if the SSID is potentially from a hidden network
+ private final boolean mIsHiddenSsid;
// BSS Load element:
private final int mStationCount;
@@ -131,6 +133,7 @@ public class NetworkDetail {
mBSSID = Utils.parseMac(bssid);
String ssid = null;
+ boolean isHiddenSsid = false;
byte[] ssidOctets = null;
InformationElementUtil.BssLoad bssLoad = new InformationElementUtil.BssLoad();
@@ -236,10 +239,18 @@ public class NetworkDetail {
ssid = new String(ssidOctets, StandardCharsets.ISO_8859_1);
}
}
+ isHiddenSsid = true;
+ for (byte byteVal : ssidOctets) {
+ if (byteVal != 0) {
+ isHiddenSsid = false;
+ break;
+ }
+ }
}
mSSID = ssid;
mHESSID = interworking.hessid;
+ mIsHiddenSsid = isHiddenSsid;
mStationCount = bssLoad.stationCount;
mChannelUtilization = bssLoad.channelUtilization;
mCapacity = bssLoad.capacity;
@@ -268,7 +279,9 @@ public class NetworkDetail {
}
// If trafficIndicationMap is not valid, mDtimPeriod will be negative
- mDtimInterval = trafficIndicationMap.mDtimPeriod;
+ if (trafficIndicationMap.isValid()) {
+ mDtimInterval = trafficIndicationMap.mDtimPeriod;
+ }
int maxRateA = 0;
int maxRateB = 0;
@@ -318,6 +331,7 @@ public class NetworkDetail {
private NetworkDetail(NetworkDetail base, Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
mSSID = base.mSSID;
+ mIsHiddenSsid = base.mIsHiddenSsid;
mBSSID = base.mBSSID;
mHESSID = base.mHESSID;
mStationCount = base.mStationCount;
@@ -515,6 +529,28 @@ public class NetworkDetail {
return toMACString(mBSSID);
}
+ /**
+ * Evaluates the ScanResult this NetworkDetail is built from
+ * returns true if built from a Beacon Frame
+ * returns false if built from a Probe Response
+ */
+ public boolean isBeaconFrame() {
+ // Beacon frames have a 'Traffic Indication Map' Information element
+ // Probe Responses do not. This is indicated by a DTIM period > 0
+ return mDtimInterval > 0;
+ }
+
+ /**
+ * Evaluates the ScanResult this NetworkDetail is built from
+ * returns true if built from a hidden Beacon Frame
+ * returns false if not hidden or not a Beacon
+ */
+ public boolean isHiddenBeaconFrame() {
+ // Hidden networks are not 80211 standard, but it is common for a hidden network beacon
+ // frame to either send zero-value bytes as the SSID, or to send no bytes at all.
+ return isBeaconFrame() && mIsHiddenSsid;
+ }
+
public static String toMACString(long mac) {
StringBuilder sb = new StringBuilder();
boolean first = true;
@@ -528,5 +564,4 @@ public class NetworkDetail {
}
return sb.toString();
}
-
}
diff --git a/service/java/com/android/server/wifi/scanner/ChannelHelper.java b/service/java/com/android/server/wifi/scanner/ChannelHelper.java
index d4168123d..acb0ac820 100644
--- a/service/java/com/android/server/wifi/scanner/ChannelHelper.java
+++ b/service/java/com/android/server/wifi/scanner/ChannelHelper.java
@@ -100,6 +100,10 @@ public abstract class ChannelHelper {
*/
public abstract boolean isEmpty();
/**
+ * @return true if the collection contains all available channels
+ */
+ public abstract boolean isAllChannels();
+ /**
* Remove all channels from the collection
*/
public abstract void clear();
diff --git a/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java b/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java
index b180da71d..acddc26c6 100644
--- a/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java
+++ b/service/java/com/android/server/wifi/scanner/KnownBandsChannelHelper.java
@@ -198,6 +198,12 @@ public class KnownBandsChannelHelper extends ChannelHelper {
}
@Override
+ public boolean isAllChannels() {
+ return getAvailableScanChannels(WifiScanner.WIFI_BAND_BOTH_WITH_DFS).length ==
+ mChannels.size();
+ }
+
+ @Override
public void clear() {
mAllBands = 0;
mExactBands = 0;
diff --git a/service/java/com/android/server/wifi/scanner/NoBandChannelHelper.java b/service/java/com/android/server/wifi/scanner/NoBandChannelHelper.java
index 7b1602008..4f8373b30 100644
--- a/service/java/com/android/server/wifi/scanner/NoBandChannelHelper.java
+++ b/service/java/com/android/server/wifi/scanner/NoBandChannelHelper.java
@@ -112,6 +112,11 @@ public class NoBandChannelHelper extends ChannelHelper {
}
@Override
+ public boolean isAllChannels() {
+ return mAllChannels;
+ }
+
+ @Override
public void clear() {
mAllChannels = false;
mChannels.clear();
diff --git a/service/java/com/android/server/wifi/scanner/SupplicantWifiScannerImpl.java b/service/java/com/android/server/wifi/scanner/SupplicantWifiScannerImpl.java
index ab013b1e0..ac5db5a4f 100644
--- a/service/java/com/android/server/wifi/scanner/SupplicantWifiScannerImpl.java
+++ b/service/java/com/android/server/wifi/scanner/SupplicantWifiScannerImpl.java
@@ -330,6 +330,11 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
processPendingScans();
}
+ private boolean isDifferentPnoScanSettings(LastScanSettings newScanSettings) {
+ return (mLastScanSettings == null || !Arrays.equals(
+ newScanSettings.pnoNetworkList, mLastScanSettings.pnoNetworkList));
+ }
+
private void processPendingScans() {
synchronized (mSettingsLock) {
// Wait for the active scan result to come back to reschedule other scans,
@@ -460,8 +465,16 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
// TODO(b/27769665) background scans should be failed too if scans fail enough
}
} else if (isHwPnoScanRequired()) {
- newScanSettings.setHwPnoScan(mPnoEventHandler);
- if (startHwPnoScan()) {
+ newScanSettings.setHwPnoScan(mPnoSettings.networkList, mPnoEventHandler);
+ boolean status;
+ // If the PNO network list has changed from the previous request, ensure that
+ // we bypass the debounce logic and restart PNO scan.
+ if (isDifferentPnoScanSettings(newScanSettings)) {
+ status = restartHwPnoScan();
+ } else {
+ status = startHwPnoScan();
+ }
+ if (status) {
mLastScanSettings = newScanSettings;
} else {
Log.e(TAG, "Failed to start PNO scan");
@@ -625,7 +638,8 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
}
}
Collections.sort(singleScanResults, SCAN_RESULT_SORT_COMPARATOR);
- mLatestSingleScanResult = new WifiScanner.ScanData(mLastScanSettings.scanId, 0,
+ mLatestSingleScanResult = new WifiScanner.ScanData(mLastScanSettings.scanId, 0, 0,
+ mLastScanSettings.singleScanFreqs.isAllChannels(),
singleScanResults.toArray(new ScanResult[singleScanResults.size()]));
mLastScanSettings.singleScanEventHandler
.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
@@ -695,6 +709,11 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
mHwPnoDebouncer.forceStopPnoScan();
}
+ private boolean restartHwPnoScan() {
+ mHwPnoDebouncer.forceStopPnoScan();
+ return mHwPnoDebouncer.startPnoScan(mHwPnoDebouncerListener);
+ }
+
/**
* Hw Pno Scan is required only for disconnected PNO when the device supports it.
* @param isConnectedPno Whether this is connected PNO vs disconnected PNO.
@@ -826,10 +845,14 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
}
public boolean hwPnoScanActive = false;
+ public WifiNative.PnoNetwork[] pnoNetworkList;
public WifiNative.PnoEventHandler pnoScanEventHandler;
- public void setHwPnoScan(WifiNative.PnoEventHandler pnoScanEventHandler) {
+ public void setHwPnoScan(
+ WifiNative.PnoNetwork[] pnoNetworkList,
+ WifiNative.PnoEventHandler pnoScanEventHandler) {
hwPnoScanActive = true;
+ this.pnoNetworkList = pnoNetworkList;
this.pnoScanEventHandler = pnoScanEventHandler;
}
}
@@ -1050,7 +1073,6 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
if (DBG) Log.d(TAG, "PNO state is already " + enable);
return true;
}
-
mLastPnoChangeTimeStamp = mClock.elapsedRealtime();
if (mWifiNative.setPnoScan(enable)) {
Log.d(TAG, "Changed PNO state from " + mCurrentPnoState + " to " + enable);
@@ -1058,6 +1080,7 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
return true;
} else {
Log.e(TAG, "PNO state change to " + enable + " failed");
+ mCurrentPnoState = false;
return false;
}
}
@@ -1125,15 +1148,13 @@ public class SupplicantWifiScannerImpl extends WifiScannerImpl implements Handle
* scan immediately.
*/
public void forceStopPnoScan() {
- if (mCurrentPnoState) {
- if (DBG) Log.d(TAG, "Force stopping Pno scan");
- // Cancel the debounce timer and stop PNO scan.
- if (mWaitForTimer) {
- mAlarmManager.cancel(mAlarmListener);
- mWaitForTimer = false;
- }
- updatePnoState(false);
+ if (DBG) Log.d(TAG, "Force stopping Pno scan");
+ // Cancel the debounce timer and stop PNO scan.
+ if (mWaitForTimer) {
+ mAlarmManager.cancel(mAlarmListener);
+ mWaitForTimer = false;
}
+ updatePnoState(false);
}
}
}
diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index 6ae223717..9f8fb2f58 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -164,7 +164,9 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub {
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
ExternalClientInfo client = (ExternalClientInfo) mClients.get(msg.replyTo);
- if (client != null) {
+ if (client != null && msg.arg1 != AsyncChannel.STATUS_SEND_UNSUCCESSFUL
+ && msg.arg1
+ != AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED) {
localLog("client disconnected: " + client + ", reason: " + msg.arg1);
client.cleanup();
}
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index 6e6dfcc77..d3e2fea90 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -600,7 +600,7 @@ public class InformationElementUtil {
} catch (BufferUnderflowException e) {
return;
}
- if (mLength <= MAX_TIM_LENGTH) {
+ if (mLength <= MAX_TIM_LENGTH && mDtimPeriod > 0) {
mValid = true;
}
}
diff --git a/service/jni/com_android_server_wifi_WifiNative.cpp b/service/jni/com_android_server_wifi_WifiNative.cpp
index e33512f11..7e70d95a7 100644
--- a/service/jni/com_android_server_wifi_WifiNative.cpp
+++ b/service/jni/com_android_server_wifi_WifiNative.cpp
@@ -854,6 +854,13 @@ static jboolean android_net_wifi_setHotlist(
return false;
}
+ if (params.num_bssid >
+ static_cast<int>(sizeof(params.ap) / sizeof(params.ap[0]))) {
+ ALOGE("setHotlist array length is too long");
+ android_errorWriteLog(0x534e4554, "31856351");
+ return false;
+ }
+
for (int i = 0; i < params.num_bssid; i++) {
JNIObject<jobject> objAp = helper.getObjectArrayElement(array, i);
@@ -1180,7 +1187,7 @@ static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_resu
JNIHelper helper(mVM);
- ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls);
+ if (DBG) ALOGD("onRttResults called, vm = %p, obj = %p", mVM, mCls);
JNIObject<jobjectArray> rttResults = helper.newObjectArray(
num_results, "android/net/wifi/RttManager$RttResult", NULL);
@@ -1227,14 +1234,12 @@ static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_resu
JNIObject<jobject> LCI = helper.createObject(
"android/net/wifi/RttManager$WifiInformationElement");
if (result->LCI != NULL && result->LCI->len > 0) {
- ALOGD("Add LCI in result");
helper.setByteField(LCI, "id", result->LCI->id);
JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
jbyte *bytes = (jbyte *)&(result->LCI->data[0]);
helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
helper.setObjectField(LCI, "data", "[B", elements);
} else {
- ALOGD("No LCI in result");
helper.setByteField(LCI, "id", (byte)(0xff));
}
helper.setObjectField(rttResult, "LCI",
@@ -1243,14 +1248,12 @@ static void onRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_resu
JNIObject<jobject> LCR = helper.createObject(
"android/net/wifi/RttManager$WifiInformationElement");
if (result->LCR != NULL && result->LCR->len > 0) {
- ALOGD("Add LCR in result");
helper.setByteField(LCR, "id", result->LCR->id);
JNIObject<jbyteArray> elements = helper.newByteArray(result->LCI->len);
jbyte *bytes = (jbyte *)&(result->LCR->data[0]);
helper.setByteArrayRegion(elements, 0, result->LCI->len, bytes);
helper.setObjectField(LCR, "data", "[B", elements);
} else {
- ALOGD("No LCR in result");
helper.setByteField(LCR, "id", (byte)(0xff));
}
helper.setObjectField(rttResult, "LCR",
@@ -1271,7 +1274,7 @@ static jboolean android_net_wifi_requestRange(
JNIHelper helper(env);
wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
- ALOGD("sending rtt request [%d] = %p", id, handle);
+ if (DBG) ALOGD("sending rtt request [%d] = %p", id, handle);
if (params == NULL) {
ALOGE("ranging params are empty");
return false;
@@ -1289,7 +1292,7 @@ static jboolean android_net_wifi_requestRange(
JNIObject<jobject> param = helper.getObjectArrayElement((jobjectArray)params, i);
if (param == NULL) {
- ALOGD("could not get element %d", i);
+ ALOGW("could not get element %d", i);
continue;
}
@@ -1314,18 +1317,6 @@ static jboolean android_net_wifi_requestRange(
config.burst_duration = (unsigned) helper.getIntField(param, "burstTimeout");
config.preamble = (wifi_rtt_preamble) helper.getIntField(param, "preamble");
config.bw = (wifi_rtt_bw) helper.getIntField(param, "bandwidth");
-
- ALOGD("RTT request destination %d: type is %d, peer is %d, bw is %d, center_freq is %d ", i,
- config.type,config.peer, config.channel.width, config.channel.center_freq);
- ALOGD("center_freq0 is %d, center_freq1 is %d, num_burst is %d,interval is %d",
- config.channel.center_freq0, config.channel.center_freq1, config.num_burst,
- config.burst_period);
- ALOGD("frames_per_burst is %d, retries of measurement frame is %d, retries_per_ftmr is %d",
- config.num_frames_per_burst, config.num_retries_per_rtt_frame,
- config.num_retries_per_ftmr);
- ALOGD("LCI_requestis %d, LCR_request is %d, burst_timeout is %d, preamble is %d, bw is %d",
- config.LCI_request, config.LCR_request, config.burst_duration, config.preamble,
- config.bw);
}
wifi_rtt_event_handler handler;
@@ -1339,7 +1330,7 @@ static jboolean android_net_wifi_cancelRange(
JNIHelper helper(env);
wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
- ALOGD("cancelling rtt request [%d] = %p", id, handle);
+ if (DBG) ALOGD("cancelling rtt request [%d] = %p", id, handle);
if (params == NULL) {
ALOGE("ranging params are empty");
@@ -1358,7 +1349,7 @@ static jboolean android_net_wifi_cancelRange(
JNIObject<jobject> param = helper.getObjectArrayElement(params, i);
if (param == NULL) {
- ALOGD("could not get element %d", i);
+ ALOGW("could not get element %d", i);
continue;
}
diff --git a/service/proto/wifi.proto b/service/proto/wifi.proto
index 3b0e8544b..8128ec115 100644
--- a/service/proto/wifi.proto
+++ b/service/proto/wifi.proto
@@ -189,6 +189,46 @@ message WifiLog {
// Counts the occurrences of each individual RSSI poll level
repeated RssiPollCount rssi_poll_rssi_count = 35;
+
+ // Total number of times WiFi connected immediately after a Last Resort Watchdog trigger,
+ // without new networks becoming available.
+ optional int32 num_last_resort_watchdog_successes = 36;
+
+ // Counts the occurrences of each alert reason.
+ repeated AlertReasonCount alert_reason_count = 47;
+
+ // Total number of saved hidden networks
+ optional int32 num_hidden_networks = 37;
+
+ // Total number of saved passpoint / hotspot 2.0 networks
+ optional int32 num_passpoint_networks = 38;
+
+ // Total number of scan results
+ optional int32 num_total_scan_results = 39;
+
+ // Total number of scan results for open networks
+ optional int32 num_open_network_scan_results = 40;
+
+ // Total number of scan results for personal networks
+ optional int32 num_personal_network_scan_results = 41;
+
+ // Total number of scan results for enterprise networks
+ optional int32 num_enterprise_network_scan_results = 42;
+
+ // Total number of scan results for hidden networks
+ optional int32 num_hidden_network_scan_results = 43;
+
+ // Total number of scan results for hotspot 2.0 r1 networks
+ optional int32 num_hotspot2_r1_network_scan_results = 44;
+
+ // Total number of scan results for hotspot 2.0 r2 networks
+ optional int32 num_hotspot2_r2_network_scan_results = 45;
+
+ // Total number of scans handled by framework (oneshot or otherwise)
+ optional int32 num_scans = 46;
+
+ // Counts the occurrences of each Wifi score
+ repeated WifiScoreCount wifi_score_count = 48;
}
// Information that gets logged for every WiFi connection.
@@ -260,7 +300,7 @@ message RouterFingerPrint {
// Authentication scheme of the router.
optional Auth authentication = 4;
- // If the router is hidded.
+ // If the router is hidden.
optional bool hidden = 5;
// Channel information.
@@ -268,6 +308,9 @@ message RouterFingerPrint {
// whether ipv6 is supported.
optional bool supports_ipv6 = 7;
+
+ // If the router is a passpoint / hotspot 2.0 network
+ optional bool passpoint = 8;
}
message ConnectionEvent {
@@ -349,3 +392,21 @@ message RssiPollCount {
// Number of RSSI polls with 'rssi'
optional int32 count = 2;
}
+
+// Number of occurrences of a specific alert reason value
+message AlertReasonCount {
+ // Alert reason
+ optional int32 reason = 1;
+
+ // Number of alerts with |reason|.
+ optional int32 count = 2;
+}
+
+// Counts the number of instances of a specific Wifi Score calculated by WifiScoreReport
+message WifiScoreCount {
+ // Wifi Score
+ optional int32 score = 1;
+
+ // Number of Wifi score reports with this score
+ optional int32 count = 2;
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanResults.java b/tests/wifitests/src/com/android/server/wifi/ScanResults.java
index 160902081..fc532701f 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanResults.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanResults.java
@@ -138,21 +138,29 @@ public class ScanResults {
* @see #generateNativeResults for more details on how results are generated
*/
public static ScanResults create(int id, int... freqs) {
- return new ScanResults(id, -1, generateNativeResults(id, freqs));
+ return create(id, generateNativeResults(id, freqs));
+ }
+ public static ScanResults create(int id, boolean allChannelsScanned, int... freqs) {
+ return create(id, allChannelsScanned, generateNativeResults(id, freqs));
}
/**
* Create a ScanResults with no IE information.
*/
public static ScanResults createWithNoIE(int id, int... freqs) {
- return new ScanResults(id, -1, generateNativeResults(false, id, freqs));
+ return create(id, generateNativeResults(false, id, freqs));
}
/**
* Create a ScanResults with the given ScanDetails
*/
public static ScanResults create(int id, ScanDetail... nativeResults) {
- return new ScanResults(id, -1, nativeResults);
+ return new ScanResults(id, false, -1, nativeResults);
+ }
+
+ public static ScanResults create(int id, boolean allChannelsScanned,
+ ScanDetail... nativeResults) {
+ return new ScanResults(id, allChannelsScanned, -1, nativeResults);
}
/**
@@ -162,10 +170,11 @@ public class ScanResults {
*/
public static ScanResults createOverflowing(int id, int maxResults,
ScanDetail... nativeResults) {
- return new ScanResults(id, maxResults, nativeResults);
+ return new ScanResults(id, false, maxResults, nativeResults);
}
- private ScanResults(int id, int maxResults, ScanDetail... nativeResults) {
+ private ScanResults(int id, boolean allChannelsScanned, int maxResults,
+ ScanDetail... nativeResults) {
mScanResults = new ScanResult[nativeResults.length];
for (int i = 0; i < nativeResults.length; ++i) {
mScanDetails.add(nativeResults[i]);
@@ -173,13 +182,13 @@ public class ScanResults {
}
ScanResult[] sortedScanResults = Arrays.copyOf(mScanResults, mScanResults.length);
Arrays.sort(sortedScanResults, SCAN_RESULT_RSSI_COMPARATOR);
- mRawScanData = new ScanData(id, 0, sortedScanResults);
+ mRawScanData = new ScanData(id, 0, 0, allChannelsScanned, sortedScanResults);
if (maxResults == -1) {
mScanData = mRawScanData;
} else {
ScanResult[] reducedScanResults = Arrays.copyOf(sortedScanResults,
Math.min(sortedScanResults.length, maxResults));
- mScanData = new ScanData(id, 0, reducedScanResults);
+ mScanData = new ScanData(id, 0, 0, allChannelsScanned, reducedScanResults);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java b/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java
index 8228118d8..7a1bdd20b 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanTestUtil.java
@@ -217,7 +217,7 @@ public class ScanTestUtil {
for (int i = 0; i < freqs.length; ++i) {
results[i] = createScanResult(freqs[i]);
}
- return new ScanData(0, 0, bucketsScanned, results);
+ return new ScanData(0, 0, bucketsScanned, false, results);
}
public static ScanData[] createScanDatas(int[][] freqs, int[] bucketsScanned) {
@@ -272,6 +272,8 @@ public class ScanTestUtil {
assertNotNull(prefix + "actual ScanData was null", actual);
assertEquals(prefix + "id", expected.getId(), actual.getId());
assertEquals(prefix + "flags", expected.getFlags(), actual.getFlags());
+ assertEquals(prefix + "all channels", expected.isAllChannelsScanned(),
+ actual.isAllChannelsScanned());
assertScanResultsEquals(prefix, expected.getResults(), actual.getResults());
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index 022997d67..281ffa163 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -33,6 +33,7 @@ import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiScanner.PnoScanListener;
import android.net.wifi.WifiScanner.PnoSettings;
+import android.net.wifi.WifiScanner.ScanData;
import android.net.wifi.WifiScanner.ScanListener;
import android.net.wifi.WifiScanner.ScanSettings;
import android.net.wifi.WifiSsid;
@@ -71,11 +72,12 @@ public class WifiConnectivityManagerTest {
mWifiStateMachine = mockWifiStateMachine();
mWifiConfigManager = mockWifiConfigManager();
mWifiInfo = getWifiInfo();
+ mScanData = mockScanData();
mWifiScanner = mockWifiScanner();
mWifiQNS = mockWifiQualifiedNetworkSelector();
mWifiConnectivityManager = new WifiConnectivityManager(mContext, mWifiStateMachine,
mWifiScanner, mWifiConfigManager, mWifiInfo, mWifiQNS, mWifiInjector,
- mLooper.getLooper());
+ mLooper.getLooper(), true);
mWifiConnectivityManager.setWifiEnabled(true);
when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
}
@@ -96,6 +98,7 @@ public class WifiConnectivityManagerTest {
private WifiQualifiedNetworkSelector mWifiQNS;
private WifiStateMachine mWifiStateMachine;
private WifiScanner mWifiScanner;
+ private ScanData mScanData;
private WifiConfigManager mWifiConfigManager;
private WifiInfo mWifiInfo;
private Clock mClock = mock(Clock.class);
@@ -128,6 +131,14 @@ public class WifiConnectivityManagerTest {
return context;
}
+ ScanData mockScanData() {
+ ScanData scanData = mock(ScanData.class);
+
+ when(scanData.isAllChannelsScanned()).thenReturn(true);
+
+ return scanData;
+ }
+
WifiScanner mockWifiScanner() {
WifiScanner scanner = mock(WifiScanner.class);
ArgumentCaptor<ScanListener> allSingleScanListenerCaptor =
@@ -135,9 +146,8 @@ public class WifiConnectivityManagerTest {
doNothing().when(scanner).registerScanListener(allSingleScanListenerCaptor.capture());
- // dummy scan results. QNS PeriodicScanListener bulids scanDetails from
- // the fullScanResult and doesn't really use results
- final WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1];
+ ScanData[] scanDatas = new ScanData[1];
+ scanDatas[0] = mScanData;
// do a synchronous answer for the ScanListener callbacks
doAnswer(new AnswerWithArguments() {
@@ -756,8 +766,9 @@ public class WifiConnectivityManagerTest {
currentTimeStamp += 2000;
when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp);
- // Force a connectivity scan
- mWifiConnectivityManager.forceConnectivityScan();
+ // Allow untrusted networks so WifiConnectivityManager starts a periodic scan
+ // immediately.
+ mWifiConnectivityManager.setUntrustedConnectionAllowed(true);
// Get the second periodic scan actual time stamp. Note, this scan is not
// started from the AlarmManager.
@@ -944,4 +955,41 @@ public class WifiConnectivityManagerTest {
verify(mWifiStateMachine).autoConnectToNetwork(
CANDIDATE_NETWORK_ID, CANDIDATE_BSSID);
}
+
+ /**
+ * Verify that a forced connectivity scan waits for full band scan
+ * results.
+ *
+ * Expected behavior: WifiConnectivityManager doesn't invoke
+ * WifiStateMachine.autoConnectToNetwork() when full band scan
+ * results are not available.
+ */
+ @Test
+ public void waitForFullBandScanResults() {
+ // Set WiFi to connected state.
+ mWifiConnectivityManager.handleConnectionStateChanged(
+ WifiConnectivityManager.WIFI_STATE_CONNECTED);
+
+ // Set up as partial scan results.
+ when(mScanData.isAllChannelsScanned()).thenReturn(false);
+
+ // Force a connectivity scan which enables WifiConnectivityManager
+ // to wait for full band scan results.
+ mWifiConnectivityManager.forceConnectivityScan();
+
+ // No roaming because no full band scan results.
+ verify(mWifiStateMachine, times(0)).autoConnectToNetwork(
+ CANDIDATE_NETWORK_ID, CANDIDATE_BSSID);
+
+ // Set up as full band scan results.
+ when(mScanData.isAllChannelsScanned()).thenReturn(true);
+
+ // Force a connectivity scan which enables WifiConnectivityManager
+ // to wait for full band scan results.
+ mWifiConnectivityManager.forceConnectivityScan();
+
+ // Roaming attempt because full band scan results are available.
+ verify(mWifiStateMachine).autoConnectToNetwork(
+ CANDIDATE_NETWORK_ID, CANDIDATE_BSSID);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java
index 237fc666d..08163e7f2 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiLastResortWatchdogTest.java
@@ -1440,7 +1440,7 @@ public class WifiLastResortWatchdogTest {
int[] levels = {-60, -86, -50, -62, -60};
boolean[] isEphemeral = {false, false, false, false, false};
boolean[] hasEverConnected = {true, false, false, false, false};
- // Buffer potential candidates 1,2,3 & 4
+ // Buffer potential candidates 1,2,3,4 & 5
List<Pair<ScanDetail, WifiConfiguration>> candidates = createFilteredQnsCandidates(ssids,
bssids, frequencies, caps, levels, isEphemeral, hasEverConnected);
mLastResortWatchdog.updateAvailableNetworks(candidates);
@@ -1450,7 +1450,7 @@ public class WifiLastResortWatchdogTest {
assertFailureCountEquals(bssids[i], 0, 0, 0);
}
- //Increment failure count for the first test network ssid & bssid
+ //Increment failure counts
for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) {
mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
ssids[1], bssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION);
@@ -1478,6 +1478,58 @@ public class WifiLastResortWatchdogTest {
verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadAssociation();
verify(mWifiMetrics, times(1)).addCountToNumLastResortWatchdogBadDhcpNetworksTotal(3);
verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogTriggersWithBadDhcp();
+
+ // Simulate wifi connecting after triggering
+ mLastResortWatchdog.connectedStateTransition(true);
+
+ // Verify that WifiMetrics counted this as a Watchdog success
+ verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses();
+
+ // Simulate wifi disconnecting
+ mLastResortWatchdog.connectedStateTransition(false);
+
+ // Verify that WifiMetrics has still only counted one success
+ verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses();
+
+ // Remove the fifth network from candidates
+ candidates = createFilteredQnsCandidates(Arrays.copyOfRange(mSsids, 0, 4),
+ Arrays.copyOfRange(mBssids, 0, 4),
+ Arrays.copyOfRange(mFrequencies, 0, 4),
+ Arrays.copyOfRange(mCaps, 0, 4),
+ Arrays.copyOfRange(mLevels, 0, 4),
+ Arrays.copyOfRange(mIsEphemeral, 0, 4));
+
+ // Age out the fifth network
+ for (int i = 0; i < WifiLastResortWatchdog.MAX_BSSID_AGE; i++) {
+ mLastResortWatchdog.updateAvailableNetworks(candidates);
+ }
+
+ //Increment failure counts
+ for (int i = 0; i < WifiLastResortWatchdog.FAILURE_THRESHOLD; i++) {
+ mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
+ ssids[1], bssids[1], WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION);
+ mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
+ ssids[2], bssids[2], WifiLastResortWatchdog.FAILURE_CODE_DHCP);
+ mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
+ ssids[3], bssids[3], WifiLastResortWatchdog.FAILURE_CODE_DHCP);
+ mLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
+ ssids[0], bssids[0], WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION);
+ }
+
+ // Add network #5 back into the candidates
+ candidates = createFilteredQnsCandidates(ssids,
+ bssids, frequencies, caps, levels, isEphemeral, hasEverConnected);
+
+ // LastResortWatchdog should reactivate because there is a new network (#5) available,
+ // Not because it was successful
+ mLastResortWatchdog.updateAvailableNetworks(candidates);
+
+ // Simulate wifi connecting
+ mLastResortWatchdog.connectedStateTransition(true);
+
+ // Verify that WifiMetrics did not count another success, as the connection could be due
+ // to the newly available network #5
+ verify(mWifiMetrics, times(1)).incrementNumLastResortWatchdogSuccesses();
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 011682b81..15a5327d6 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
+import android.net.NetworkAgent;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.test.suitebuilder.annotation.SmallTest;
@@ -33,6 +34,8 @@ import org.mockito.MockitoAnnotations;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -104,15 +107,51 @@ public class WifiMetricsTest {
mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
}
- @Test
- public void dumpHumanReadable() throws Exception {
+ /**
+ * Gets the 'clean dump' proto bytes from mWifiMetrics & deserializes it into
+ * mDeserializedWifiMetrics
+ */
+ public void cleanDumpProtoAndDeserialize() throws Exception {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
PrintWriter writer = new PrintWriter(stream);
String[] args = new String[0];
+
+ when(mClock.elapsedRealtime()).thenReturn(TEST_RECORD_DURATION_MILLIS);
+ //Test proto dump, by passing in proto arg option
+ args = new String[]{WifiMetrics.PROTO_DUMP_ARG, WifiMetrics.CLEAN_DUMP_ARG};
mWifiMetrics.dump(null, writer, args);
writer.flush();
- assertTrue("stream.toString().contains(\"WifiMetrics\")",
- stream.toString().contains("WifiMetrics"));
+ String protoByteString = stream.toString();
+ byte[] protoBytes = Base64.decode(protoByteString, Base64.DEFAULT);
+ mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes);
+ }
+
+ /** Verifies that dump() includes the expected header */
+ @Test
+ public void stateDumpIncludesHeader() throws Exception {
+ assertStringContains(getStateDump(), "WifiMetrics");
+ }
+
+ /** Verifies that dump() includes correct alert count when there are no alerts. */
+ @Test
+ public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception {
+ assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()");
+ }
+
+ /** Verifies that dump() includes correct alert count when there is one alert. */
+ @Test
+ public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception {
+ mWifiMetrics.incrementAlertReasonCount(1);
+ assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)");
+ }
+
+ /** Verifies that dump() includes correct alert count when there are multiple alerts. */
+ @Test
+ public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception {
+ mWifiMetrics.incrementAlertReasonCount(1);
+ mWifiMetrics.incrementAlertReasonCount(1);
+ mWifiMetrics.incrementAlertReasonCount(16);
+ assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)");
}
@Test
@@ -126,6 +165,8 @@ public class WifiMetricsTest {
private static final int NUM_OPEN_NETWORKS = 2;
private static final int NUM_PERSONAL_NETWORKS = 3;
private static final int NUM_ENTERPRISE_NETWORKS = 5;
+ private static final int NUM_HIDDEN_NETWORKS = 3;
+ private static final int NUM_PASSPOINT_NETWORKS = 4;
private static final boolean TEST_VAL_IS_LOCATION_ENABLED = true;
private static final boolean IS_SCANNING_ALWAYS_ENABLED = true;
private static final int NUM_NEWTORKS_ADDED_BY_USER = 13;
@@ -154,8 +195,53 @@ public class WifiMetricsTest {
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_AUTHENTICATION = 8;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_DHCP = 9;
private static final int NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER = 10;
+ private static final int NUM_LAST_RESORT_WATCHDOG_SUCCESSES = 5;
private static final int NUM_RSSI_LEVELS_TO_INCREMENT = 20;
private static final int FIRST_RSSI_LEVEL = -80;
+ private static final int NUM_OPEN_NETWORK_SCAN_RESULTS = 1;
+ private static final int NUM_PERSONAL_NETWORK_SCAN_RESULTS = 4;
+ private static final int NUM_ENTERPRISE_NETWORK_SCAN_RESULTS = 3;
+ private static final int NUM_HIDDEN_NETWORK_SCAN_RESULTS = 1;
+ private static final int NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS = 1;
+ private static final int NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS = 2;
+ private static final int NUM_SCANS = 5;
+ private static final int NUM_TOTAL_SCAN_RESULTS = 8;
+ private static final int MIN_RSSI_LEVEL = -127;
+ private static final int MAX_RSSI_LEVEL = 0;
+ private static final int WIFI_SCORE_RANGE_MIN = 0;
+ private static final int NUM_WIFI_SCORES_TO_INCREMENT = 20;
+ private static final int WIFI_SCORE_RANGE_MAX = 60;
+ private static final int NUM_OUT_OF_BOUND_ENTRIES = 10;
+
+ private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
+ String capabilities) {
+ ScanDetail mockScanDetail = mock(ScanDetail.class);
+ NetworkDetail mockNetworkDetail = mock(NetworkDetail.class);
+ ScanResult mockScanResult = mock(ScanResult.class);
+ when(mockScanDetail.getNetworkDetail()).thenReturn(mockNetworkDetail);
+ when(mockScanDetail.getScanResult()).thenReturn(mockScanResult);
+ when(mockNetworkDetail.isHiddenBeaconFrame()).thenReturn(hidden);
+ when(mockNetworkDetail.getHSRelease()).thenReturn(hSRelease);
+ mockScanResult.capabilities = capabilities;
+ return mockScanDetail;
+ }
+
+ private List<ScanDetail> buildMockScanDetailList() {
+ List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>();
+ mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]"));
+ mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]"));
+ mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]"));
+ mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]"));
+ mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]"));
+ mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
+ "[WPA-EAP-CCMP]"));
+ mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
+ "[WPA2-EAP+FT/EAP-CCMP]"));
+ mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1,
+ "[WPA-EAP-CCMP]"));
+ return mockScanDetails;
+ }
+
/**
* Set simple metrics, increment others
*/
@@ -164,6 +250,8 @@ public class WifiMetricsTest {
mWifiMetrics.setNumOpenNetworks(NUM_OPEN_NETWORKS);
mWifiMetrics.setNumPersonalNetworks(NUM_PERSONAL_NETWORKS);
mWifiMetrics.setNumEnterpriseNetworks(NUM_ENTERPRISE_NETWORKS);
+ mWifiMetrics.setNumHiddenNetworks(NUM_HIDDEN_NETWORKS);
+ mWifiMetrics.setNumPasspointNetworks(NUM_PASSPOINT_NETWORKS);
mWifiMetrics.setNumNetworksAddedByUser(NUM_NEWTORKS_ADDED_BY_USER);
mWifiMetrics.setNumNetworksAddedByApps(NUM_NEWTORKS_ADDED_BY_APPS);
mWifiMetrics.setIsLocationEnabled(TEST_VAL_IS_LOCATION_ENABLED);
@@ -238,11 +326,43 @@ public class WifiMetricsTest {
for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER; i++) {
mWifiMetrics.incrementNumLastResortWatchdogTriggersWithBadOther();
}
+ for (int i = 0; i < NUM_LAST_RESORT_WATCHDOG_SUCCESSES; i++) {
+ mWifiMetrics.incrementNumLastResortWatchdogSuccesses();
+ }
for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
for (int j = 0; j <= i; j++) {
- mWifiMetrics.incrementRssiPollRssiCount(FIRST_RSSI_LEVEL + i);
+ mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL + i);
}
}
+ for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
+ mWifiMetrics.incrementRssiPollRssiCount(MIN_RSSI_LEVEL - i);
+ }
+ for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
+ mWifiMetrics.incrementRssiPollRssiCount(MAX_RSSI_LEVEL + i);
+ }
+ // Test alert-reason clamping.
+ mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1);
+ mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1);
+ // Simple cases for alert reason.
+ mWifiMetrics.incrementAlertReasonCount(1);
+ mWifiMetrics.incrementAlertReasonCount(1);
+ mWifiMetrics.incrementAlertReasonCount(1);
+ mWifiMetrics.incrementAlertReasonCount(2);
+ List<ScanDetail> mockScanDetails = buildMockScanDetailList();
+ for (int i = 0; i < NUM_SCANS; i++) {
+ mWifiMetrics.countScanResults(mockScanDetails);
+ }
+ for (int score = WIFI_SCORE_RANGE_MIN; score < NUM_WIFI_SCORES_TO_INCREMENT; score++) {
+ for (int offset = 0; offset <= score; offset++) {
+ mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN + score);
+ }
+ }
+ for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
+ mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MIN - i);
+ }
+ for (int i = 1; i < NUM_OUT_OF_BOUND_ENTRIES; i++) {
+ mWifiMetrics.incrementWifiScoreCount(WIFI_SCORE_RANGE_MAX + i);
+ }
}
/**
@@ -261,6 +381,8 @@ public class WifiMetricsTest {
assertEquals("mDeserializedWifiMetrics.numNetworksAddedByUser "
+ "== NUM_NEWTORKS_ADDED_BY_USER",
mDeserializedWifiMetrics.numNetworksAddedByUser, NUM_NEWTORKS_ADDED_BY_USER);
+ assertEquals(NUM_HIDDEN_NETWORKS, mDeserializedWifiMetrics.numHiddenNetworks);
+ assertEquals(NUM_PASSPOINT_NETWORKS, mDeserializedWifiMetrics.numPasspointNetworks);
assertEquals("mDeserializedWifiMetrics.numNetworksAddedByApps "
+ "== NUM_NEWTORKS_ADDED_BY_APPS",
mDeserializedWifiMetrics.numNetworksAddedByApps, NUM_NEWTORKS_ADDED_BY_APPS);
@@ -318,12 +440,53 @@ public class WifiMetricsTest {
mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadDhcp);
assertEquals(NUM_LAST_RESORT_WATCHDOG_TRIGGERS_WITH_BAD_OTHER,
mDeserializedWifiMetrics.numLastResortWatchdogTriggersWithBadOther);
+ assertEquals(NUM_LAST_RESORT_WATCHDOG_SUCCESSES,
+ mDeserializedWifiMetrics.numLastResortWatchdogSuccesses);
assertEquals(TEST_RECORD_DURATION_SEC,
mDeserializedWifiMetrics.recordDurationSec);
for (int i = 0; i < NUM_RSSI_LEVELS_TO_INCREMENT; i++) {
- assertEquals(FIRST_RSSI_LEVEL + i, mDeserializedWifiMetrics.rssiPollRssiCount[i].rssi);
+ assertEquals(MIN_RSSI_LEVEL + i, mDeserializedWifiMetrics.rssiPollRssiCount[i].rssi);
assertEquals(i + 1, mDeserializedWifiMetrics.rssiPollRssiCount[i].count);
}
+ StringBuilder sb_rssi = new StringBuilder();
+ sb_rssi.append("Number of RSSIs = " + mDeserializedWifiMetrics.rssiPollRssiCount.length);
+ assertTrue(sb_rssi.toString(), (mDeserializedWifiMetrics.rssiPollRssiCount.length
+ <= (MAX_RSSI_LEVEL - MIN_RSSI_LEVEL + 1)));
+ assertEquals(2, mDeserializedWifiMetrics.alertReasonCount[0].count); // Clamped reasons.
+ assertEquals(3, mDeserializedWifiMetrics.alertReasonCount[1].count);
+ assertEquals(1, mDeserializedWifiMetrics.alertReasonCount[2].count);
+ assertEquals(3, mDeserializedWifiMetrics.alertReasonCount.length);
+ assertEquals(NUM_TOTAL_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numTotalScanResults);
+ assertEquals(NUM_OPEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numOpenNetworkScanResults);
+ assertEquals(NUM_PERSONAL_NETWORK_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numPersonalNetworkScanResults);
+ assertEquals(NUM_ENTERPRISE_NETWORK_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numEnterpriseNetworkScanResults);
+ assertEquals(NUM_HIDDEN_NETWORK_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numHiddenNetworkScanResults);
+ assertEquals(NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numHotspot2R1NetworkScanResults);
+ assertEquals(NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS * NUM_SCANS,
+ mDeserializedWifiMetrics.numHotspot2R2NetworkScanResults);
+ assertEquals(NUM_SCANS,
+ mDeserializedWifiMetrics.numScans);
+ for (int score_index = 0; score_index < NUM_WIFI_SCORES_TO_INCREMENT; score_index++) {
+ assertEquals(WIFI_SCORE_RANGE_MIN + score_index,
+ mDeserializedWifiMetrics.wifiScoreCount[score_index].score);
+ assertEquals(score_index + 1,
+ mDeserializedWifiMetrics.wifiScoreCount[score_index].count);
+ }
+ StringBuilder sb_wifi_score = new StringBuilder();
+ sb_wifi_score.append("Number of wifi_scores = "
+ + mDeserializedWifiMetrics.wifiScoreCount.length);
+ assertTrue(sb_wifi_score.toString(), (mDeserializedWifiMetrics.wifiScoreCount.length
+ <= (WIFI_SCORE_RANGE_MAX - WIFI_SCORE_RANGE_MIN + 1)));
+ StringBuilder sb_wifi_limits = new StringBuilder();
+ sb_wifi_limits.append("Wifi Score limit is " + NetworkAgent.WIFI_BASE_SCORE
+ + ">= " + WIFI_SCORE_RANGE_MAX);
+ assertTrue(sb_wifi_limits.toString(), NetworkAgent.WIFI_BASE_SCORE <= WIFI_SCORE_RANGE_MAX);
}
/**
@@ -461,6 +624,8 @@ public class WifiMetricsTest {
dumpProtoAndDeserialize();
//Check there are only 3 connection events
assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 4);
+ assertEquals(mDeserializedWifiMetrics.rssiPollRssiCount.length, 0);
+ assertEquals(mDeserializedWifiMetrics.alertReasonCount.length, 0);
// Create 2 ConnectionEvents
mWifiMetrics.startConnectionEvent(null, "BLUE",
@@ -479,4 +644,35 @@ public class WifiMetricsTest {
//Check there are only 2 connection events
assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 2);
}
+
+ /**
+ * Tests that after setting metrics values they can be serialized and deserialized with the
+ * $ adb shell dumpsys wifi wifiMetricsProto clean
+ */
+ @Test
+ public void testClearMetricsDump() throws Exception {
+ setAndIncrementMetrics();
+ startAndEndConnectionEventSucceeds();
+ cleanDumpProtoAndDeserialize();
+ assertDeserializedMetricsCorrect();
+ assertEquals("mDeserializedWifiMetrics.connectionEvent.length",
+ 2, mDeserializedWifiMetrics.connectionEvent.length);
+ }
+
+ private void assertStringContains(
+ String actualString, String expectedSubstring) {
+ assertTrue("Expected text not found in: " + actualString,
+ actualString.contains(expectedSubstring));
+ }
+
+ private String getStateDump() {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(stream);
+ String[] args = new String[0];
+ mWifiMetrics.dump(null, writer, args);
+ writer.flush();
+ return stream.toString();
+ }
}
+
+
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
index 92de7d48b..1726e7d32 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiQualifiedNetworkSelectorTest.java
@@ -2270,4 +2270,59 @@ public class WifiQualifiedNetworkSelectorTest {
verifySelectedResult(chosenScanResult, candidate);
}
+
+ /**
+ * Case #47 Choose the currently connected BSSID after a firmware initiated roaming.
+ *
+ * In this test. we simulate following scenario:
+ * Two APs are found in scan results
+ * BSSID1 is @ 2.4GHz with RSSI -78
+ * BSSID2 is @ 2.4Ghz with RSSI -77
+ * BSSID2 is chosen because of stronger RSSI. Then firmware initiates
+ * a roaming to BSSID1. QNS now selects BSSID1 because of the bonus for currently
+ * connected network even if BSSID 2 has slightly stronger signal strengh.
+ *
+ * expect BSSID2 to be chosen after firmware roaming
+ */
+ @Test
+ public void chooseCurrentlyConnectedBssid() {
+ String[] ssids = {"\"test1\"", "\"test1\""};
+ String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+ int[] frequencies = {2437, 2437};
+ String[] caps = {"[ESS]", "[ESS]"};
+ int[] levels = {-78, -77};
+ int[] security = {SECURITY_NONE, SECURITY_NONE};
+
+ List<ScanDetail> scanDetails = getScanDetails(ssids, bssids, frequencies, caps, levels);
+ WifiConfiguration[] savedConfigs = generateWifiConfigurations(ssids, security);
+ prepareConfigStore(savedConfigs);
+
+ final List<WifiConfiguration> savedNetwork = Arrays.asList(savedConfigs);
+ when(mWifiConfigManager.getSavedNetworks()).thenReturn(savedNetwork);
+ scanResultLinkConfiguration(savedConfigs, scanDetails);
+
+ // Choose BSSID2 as it has stronger RSSI
+ ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
+ WifiConfiguration candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(false,
+ false, scanDetails, false, false, true, false);
+ verifySelectedResult(chosenScanResult, candidate);
+ when(mWifiInfo.getBSSID()).thenReturn(bssids[1]);
+ when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true);
+
+ // Choose BSSID2 as it has stronger RSSI and it is the currently connected BSSID
+ chosenScanResult = scanDetails.get(1).getScanResult();
+ candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true,
+ false, scanDetails, false, true, false, false);
+ verifySelectedResult(chosenScanResult, candidate);
+
+ // Pretend firmware roamed the device to BSSID1
+ when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
+
+ // Choose BSSID1 as it is the currently connected BSSID even if BSSID2 has slightly
+ // higher RSSI value.
+ chosenScanResult = scanDetails.get(0).getScanResult();
+ candidate = mWifiQualifiedNetworkSelector.selectQualifiedNetwork(true,
+ false, scanDetails, false, true, false, false);
+ verifySelectedResult(chosenScanResult, candidate);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
index 53d8f46aa..a881d8f04 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiStateMachineTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import android.app.ActivityManager;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -41,6 +42,7 @@ import android.net.wifi.WifiSsid;
import android.net.wifi.p2p.IWifiP2pManager;
import android.os.BatteryStats;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -56,6 +58,8 @@ import android.os.UserManager;
import android.provider.Settings;
import android.security.KeyStore;
import android.telephony.TelephonyManager;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
import android.util.Log;
@@ -218,13 +222,19 @@ public class WifiStateMachineTest {
Context context = mock(Context.class);
when(context.getPackageManager()).thenReturn(pkgMgr);
- when(context.getContentResolver()).thenReturn(mock(ContentResolver.class));
MockResources resources = new com.android.server.wifi.MockResources();
when(context.getResources()).thenReturn(resources);
- ContentResolver cr = mock(ContentResolver.class);
- when(context.getContentResolver()).thenReturn(cr);
+ MockContentResolver mockContentResolver = new MockContentResolver();
+ mockContentResolver.addProvider(Settings.AUTHORITY,
+ new MockContentProvider(context) {
+ @Override
+ public Bundle call(String method, String arg, Bundle extras) {
+ return new Bundle();
+ }
+ });
+ when(context.getContentResolver()).thenReturn(mockContentResolver);
when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
new PowerManager(context, mock(IPowerManager.class), new Handler()));
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java
index 1355961c1..767cddfea 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java
@@ -89,6 +89,12 @@ public abstract class BaseWifiScannerImplTest {
when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime());
}
+ protected boolean isAllChannelsScanned(int band) {
+ ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection();
+ collection.addBand(band);
+ return collection.isAllChannels();
+ }
+
protected Set<Integer> expectedBandScanFreqs(int band) {
ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection();
collection.addBand(band);
@@ -115,7 +121,8 @@ public abstract class BaseWifiScannerImplTest {
doSuccessfulSingleScanTest(settings, expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ),
new HashSet<Integer>(),
- ScanResults.create(0, 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), false);
+ ScanResults.create(0, isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ),
+ 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), false);
}
@Test
@@ -144,7 +151,8 @@ public abstract class BaseWifiScannerImplTest {
doSuccessfulSingleScanTest(settings, expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ),
new HashSet<Integer>(),
- ScanResults.create(0, 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), true);
+ ScanResults.create(0, isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ),
+ 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), true);
}
/**
@@ -346,7 +354,7 @@ public abstract class BaseWifiScannerImplTest {
.withBasePeriod(10000)
.withMaxApPerScan(10)
.addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
- WifiScanner.WIFI_BAND_5_GHZ)
+ WifiScanner.WIFI_BAND_BOTH_WITH_DFS)
.build();
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
@@ -361,15 +369,17 @@ public abstract class BaseWifiScannerImplTest {
expectSuccessfulSingleScan(order, eventHandler,
expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ),
new HashSet<Integer>(),
- ScanResults.create(0, 2400, 2450, 2450), false);
+ ScanResults.create(0, isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ),
+ 2400, 2450, 2450), false);
// start second scan
assertTrue(mScanner.startSingleScan(settings2, eventHandler));
expectSuccessfulSingleScan(order, eventHandler,
- expectedBandScanFreqs(WifiScanner.WIFI_BAND_5_GHZ),
+ expectedBandScanFreqs(WifiScanner.WIFI_BAND_BOTH_WITH_DFS),
new HashSet<Integer>(),
- ScanResults.create(0, 5150, 5175), false);
+ ScanResults.create(0, true,
+ 5150, 5175), false);
verifyNoMoreInteractions(eventHandler);
}
@@ -412,7 +422,8 @@ public abstract class BaseWifiScannerImplTest {
}
ArrayList<ScanResult> scanDataResults = new ArrayList<>(fullResults);
Collections.sort(scanDataResults, ScanResults.SCAN_RESULT_RSSI_COMPARATOR);
- ScanData scanData = new ScanData(0, 0,
+ ScanData scanData = new ScanData(0, 0, 0,
+ isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ),
scanDataResults.toArray(new ScanResult[scanDataResults.size()]));
Set<Integer> expectedScan = expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ);
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java
index ed466835d..3e482a9fe 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/KnownBandsChannelHelperTest.java
@@ -290,6 +290,7 @@ public class KnownBandsChannelHelperTest {
assertTrue(mChannelCollection.isEmpty());
assertFalse(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -310,6 +311,7 @@ public class KnownBandsChannelHelperTest {
assertTrue(mChannelCollection.isEmpty());
assertFalse(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -329,6 +331,7 @@ public class KnownBandsChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -348,6 +351,7 @@ public class KnownBandsChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -368,6 +372,7 @@ public class KnownBandsChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -388,6 +393,7 @@ public class KnownBandsChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -408,6 +414,7 @@ public class KnownBandsChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertTrue(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -428,6 +435,7 @@ public class KnownBandsChannelHelperTest {
assertTrue(mChannelCollection.containsChannel(2400));
assertTrue(mChannelCollection.containsChannel(5150));
assertTrue(mChannelCollection.containsChannel(5600));
+ assertTrue(mChannelCollection.isAllChannels());
}
/**
@@ -442,6 +450,7 @@ public class KnownBandsChannelHelperTest {
WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
mChannelCollection.fillBucketSettings(bucketSettings, 2);
assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -456,6 +465,27 @@ public class KnownBandsChannelHelperTest {
WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
mChannelCollection.fillBucketSettings(bucketSettings, 2);
assertThat(bucketSettings, bandIs(WifiScanner.WIFI_BAND_BOTH));
+ assertFalse(mChannelCollection.isAllChannels());
+ }
+
+
+ /**
+ * Add enough channels across all bands that the max channels is exceeded
+ */
+ @Test
+ public void addChannel_addAllAvailableChannels() {
+ mChannelCollection.addChannel(2400);
+ mChannelCollection.addChannel(2450);
+ mChannelCollection.addChannel(5150);
+ mChannelCollection.addChannel(5175);
+ mChannelCollection.addChannel(5600);
+ mChannelCollection.addChannel(5650);
+ mChannelCollection.addChannel(5660);
+
+ WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
+ mChannelCollection.fillBucketSettings(bucketSettings, Integer.MAX_VALUE);
+ assertThat(bucketSettings, channelsAre(2400, 2450, 5150, 5175, 5600, 5650, 5660));
+ assertTrue(mChannelCollection.isAllChannels());
}
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/NoBandChannelHelperTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/NoBandChannelHelperTest.java
index cbf6fe5d1..2863b9f90 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/NoBandChannelHelperTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/NoBandChannelHelperTest.java
@@ -199,7 +199,7 @@ public class NoBandChannelHelperTest {
* {@link com.android.server.wifi.scanner.NoBandChannelHelper.NoBandChannelCollection}.
*/
@SmallTest
- public static class KnownBandsChannelCollectionTest {
+ public static class NoBandsChannelCollectionTest {
ChannelHelper.ChannelCollection mChannelCollection;
/**
@@ -225,6 +225,7 @@ public class NoBandChannelHelperTest {
assertTrue(mChannelCollection.isEmpty());
assertFalse(mChannelCollection.containsChannel(2400));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -244,6 +245,7 @@ public class NoBandChannelHelperTest {
assertTrue(mChannelCollection.isEmpty());
assertFalse(mChannelCollection.containsChannel(2400));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -262,6 +264,7 @@ public class NoBandChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertTrue(mChannelCollection.containsChannel(5150));
+ assertTrue(mChannelCollection.isAllChannels());
}
/**
@@ -281,6 +284,7 @@ public class NoBandChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -301,6 +305,7 @@ public class NoBandChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertFalse(mChannelCollection.containsChannel(5150));
+ assertFalse(mChannelCollection.isAllChannels());
}
/**
@@ -320,6 +325,7 @@ public class NoBandChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertTrue(mChannelCollection.containsChannel(5150));
+ assertTrue(mChannelCollection.isAllChannels());
}
/**
@@ -339,6 +345,7 @@ public class NoBandChannelHelperTest {
assertFalse(mChannelCollection.isEmpty());
assertTrue(mChannelCollection.containsChannel(2400));
assertTrue(mChannelCollection.containsChannel(5150));
+ assertTrue(mChannelCollection.isAllChannels());
}
/**
@@ -359,6 +366,7 @@ public class NoBandChannelHelperTest {
assertTrue(mChannelCollection.containsChannel(2400));
assertTrue(mChannelCollection.containsChannel(5150));
assertTrue(mChannelCollection.containsChannel(5600));
+ assertTrue(mChannelCollection.isAllChannels());
}
/**
@@ -373,6 +381,7 @@ public class NoBandChannelHelperTest {
WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
mChannelCollection.fillBucketSettings(bucketSettings, 2);
assertThat(bucketSettings, bandIs(ALL_BANDS));
+ assertFalse(mChannelCollection.isAllChannels()); // can't determine from just channels
}
/**
@@ -387,6 +396,7 @@ public class NoBandChannelHelperTest {
WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
mChannelCollection.fillBucketSettings(bucketSettings, 2);
assertThat(bucketSettings, bandIs(ALL_BANDS));
+ assertFalse(mChannelCollection.isAllChannels()); // can't determine from just channels
}
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/SupplicantPnoScannerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/SupplicantPnoScannerTest.java
index 39709f84d..560710f79 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/SupplicantPnoScannerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/SupplicantPnoScannerTest.java
@@ -45,6 +45,7 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -90,7 +91,7 @@ public class SupplicantPnoScannerTest {
WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class);
WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false);
- ScanResults scanResults = createDummyScanResults();
+ ScanResults scanResults = createDummyScanResults(false);
InOrder order = inOrder(pnoEventHandler, mWifiNative);
// Start PNO scan
@@ -111,7 +112,7 @@ public class SupplicantPnoScannerTest {
WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
WifiNative.ScanSettings settings = createDummyScanSettings();
- ScanResults scanResults = createDummyScanResults();
+ ScanResults scanResults = createDummyScanResults(true);
InOrder order = inOrder(eventHandler, mWifiNative);
// Start PNO scan
@@ -181,7 +182,7 @@ public class SupplicantPnoScannerTest {
WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
WifiNative.ScanSettings settings = createDummyScanSettings();
- ScanResults scanResults = createDummyScanResults();
+ ScanResults scanResults = createDummyScanResults(true);
InOrder order = inOrder(eventHandler, mWifiNative);
// Start PNO scan
@@ -214,12 +215,126 @@ public class SupplicantPnoScannerTest {
verifyNoMoreInteractions(pnoEventHandler);
}
+ /**
+ * Verify that the HW PNO scan stop failure still resets the PNO scan state.
+ * 1. Start Hw PNO.
+ * 2. Stop Hw PNO scan which raises a stop command to WifiNative which is failed.
+ * 3. Now restart a new PNO scan to ensure that the failure was cleanly handled.
+ */
+ @Test
+ public void ignoreHwDisconnectedPnoScanStopFailure() {
+ createScannerWithHwPnoScanSupport();
+
+ WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class);
+ WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false);
+
+ // Start PNO scan
+ startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler);
+
+ // Fail the PNO stop.
+ when(mWifiNative.setPnoScan(false)).thenReturn(false);
+ assertTrue(mScanner.resetHwPnoList());
+ assertTrue("dispatch pno monitor alarm",
+ mAlarmManager.dispatch(
+ SupplicantWifiScannerImpl.HwPnoDebouncer.PNO_DEBOUNCER_ALARM_TAG));
+ mLooper.dispatchAll();
+ verify(mWifiNative).setPnoScan(false);
+
+ // Add a new PNO scan request and ensure it runs successfully.
+ startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler);
+ assertTrue("dispatch pno monitor alarm",
+ mAlarmManager.dispatch(
+ SupplicantWifiScannerImpl.HwPnoDebouncer.PNO_DEBOUNCER_ALARM_TAG));
+ mLooper.dispatchAll();
+ InOrder order = inOrder(pnoEventHandler, mWifiNative);
+ ScanResults scanResults = createDummyScanResults(false);
+ expectSuccessfulHwDisconnectedPnoScan(order, pnoSettings, pnoEventHandler, scanResults);
+ verifyNoMoreInteractions(pnoEventHandler);
+ }
+
+ /**
+ * Verify that the HW PNO scan is forcefully stopped (bypass debounce logic) and restarted when
+ * settings change.
+ * 1. Start Hw PNO.
+ * 2. Stop Hw PNO .
+ * 3. Now restart a new PNO scan with different settings.
+ * 4. Ensure that the stop was issued before we start again.
+ */
+ @Test
+ public void forceRestartHwDisconnectedPnoScanWhenSettingsChange() {
+ createScannerWithHwPnoScanSupport();
+
+ WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class);
+ WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false);
+ InOrder order = inOrder(pnoEventHandler, mWifiNative);
+
+ // Start PNO scan
+ startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler);
+ expectHwDisconnectedPnoScanStart(order, pnoSettings);
+
+ // Stop PNO now. This should trigger the debounce timer and not stop PNO.
+ assertTrue(mScanner.resetHwPnoList());
+ assertTrue(mAlarmManager.isPending(
+ SupplicantWifiScannerImpl.HwPnoDebouncer.PNO_DEBOUNCER_ALARM_TAG));
+ order.verify(mWifiNative, never()).setPnoScan(false);
+
+ // Now restart PNO scan with an extra network in settings.
+ pnoSettings.networkList =
+ Arrays.copyOf(pnoSettings.networkList, pnoSettings.networkList.length + 1);
+ pnoSettings.networkList[pnoSettings.networkList.length - 1] =
+ createDummyPnoNetwork("ssid_pno_new", 6, 6);
+ startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler);
+
+ // This should bypass the debounce timer and stop PNO scan immediately and then start
+ // a new debounce timer for the start.
+ order.verify(mWifiNative).setPnoScan(false);
+
+ // Trigger the debounce timer and ensure we start PNO scan again.
+ mAlarmManager.dispatch(SupplicantWifiScannerImpl.HwPnoDebouncer.PNO_DEBOUNCER_ALARM_TAG);
+ mLooper.dispatchAll();
+ order.verify(mWifiNative).setPnoScan(true);
+ }
+
+ /**
+ * Verify that the HW PNO scan is not forcefully stopped (bypass debounce logic) when
+ * settings don't change.
+ * 1. Start Hw PNO.
+ * 2. Stop Hw PNO .
+ * 3. Now restart a new PNO scan with same settings.
+ * 4. Ensure that the stop was never issued.
+ */
+ @Test
+ public void noForceRestartHwDisconnectedPnoScanWhenNoSettingsChange() {
+ createScannerWithHwPnoScanSupport();
+
+ WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class);
+ WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(false);
+ InOrder order = inOrder(pnoEventHandler, mWifiNative);
+
+ // Start PNO scan
+ startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler);
+ expectHwDisconnectedPnoScanStart(order, pnoSettings);
+
+ // Stop PNO now. This should trigger the debounce timer and not stop PNO.
+ assertTrue(mScanner.resetHwPnoList());
+ assertTrue(mAlarmManager.isPending(
+ SupplicantWifiScannerImpl.HwPnoDebouncer.PNO_DEBOUNCER_ALARM_TAG));
+ order.verify(mWifiNative, never()).setPnoScan(false);
+
+ // Now restart PNO scan with the same settings.
+ startSuccessfulPnoScan(null, pnoSettings, null, pnoEventHandler);
+
+ // Trigger the debounce timer and ensure that we neither stop/start.
+ mLooper.dispatchAll();
+ order.verify(mWifiNative, never()).setPnoScan(anyBoolean());
+ }
+
private void doSuccessfulSwPnoScanTest(boolean isConnectedPno) {
WifiNative.PnoEventHandler pnoEventHandler = mock(WifiNative.PnoEventHandler.class);
WifiNative.PnoSettings pnoSettings = createDummyPnoSettings(isConnectedPno);
WifiNative.ScanEventHandler scanEventHandler = mock(WifiNative.ScanEventHandler.class);
WifiNative.ScanSettings scanSettings = createDummyScanSettings();
- ScanResults scanResults = createDummyScanResults();
+ ScanResults scanResults = createDummyScanResults(false);
InOrder order = inOrder(scanEventHandler, mWifiNative);
@@ -243,18 +358,20 @@ public class SupplicantPnoScannerTest {
new SupplicantWifiScannerImpl(mContext, mWifiNative, mLooper.getLooper(), mClock);
}
+ private WifiNative.PnoNetwork createDummyPnoNetwork(String ssid, int networkId, int priority) {
+ WifiNative.PnoNetwork pnoNetwork = new WifiNative.PnoNetwork();
+ pnoNetwork.ssid = ssid;
+ pnoNetwork.networkId = networkId;
+ pnoNetwork.priority = priority;
+ return pnoNetwork;
+ }
+
private WifiNative.PnoSettings createDummyPnoSettings(boolean isConnected) {
WifiNative.PnoSettings pnoSettings = new WifiNative.PnoSettings();
pnoSettings.isConnected = isConnected;
pnoSettings.networkList = new WifiNative.PnoNetwork[2];
- pnoSettings.networkList[0] = new WifiNative.PnoNetwork();
- pnoSettings.networkList[0].ssid = "ssid_pno_1";
- pnoSettings.networkList[0].networkId = 1;
- pnoSettings.networkList[0].priority = 1;
- pnoSettings.networkList[1] = new WifiNative.PnoNetwork();
- pnoSettings.networkList[1].ssid = "ssid_pno_2";
- pnoSettings.networkList[1].networkId = 2;
- pnoSettings.networkList[1].priority = 2;
+ pnoSettings.networkList[0] = createDummyPnoNetwork("ssid_pno_1", 1, 1);
+ pnoSettings.networkList[1] = createDummyPnoNetwork("ssid_pno_2", 2, 2);
return pnoSettings;
}
@@ -268,13 +385,15 @@ public class SupplicantPnoScannerTest {
return settings;
}
- private ScanResults createDummyScanResults() {
- return ScanResults.create(0, 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450);
+ private ScanResults createDummyScanResults(boolean allChannelsScanned) {
+ return ScanResults.create(0, allChannelsScanned, 2400, 2450, 2450, 2400, 2450, 2450, 2400,
+ 2450, 2450);
}
private void startSuccessfulPnoScan(WifiNative.ScanSettings scanSettings,
WifiNative.PnoSettings pnoSettings, WifiNative.ScanEventHandler scanEventHandler,
WifiNative.PnoEventHandler pnoEventHandler) {
+ reset(mWifiNative);
when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true);
when(mWifiNative.enableNetworkWithoutConnect(anyInt())).thenReturn(true);
// Scans succeed
@@ -300,9 +419,8 @@ public class SupplicantPnoScannerTest {
/**
* Verify that the PNO scan was successfully started.
*/
- private void expectSuccessfulHwDisconnectedPnoScan(InOrder order,
- WifiNative.PnoSettings pnoSettings, WifiNative.PnoEventHandler eventHandler,
- ScanResults scanResults) {
+ private void expectHwDisconnectedPnoScanStart(InOrder order,
+ WifiNative.PnoSettings pnoSettings) {
for (int i = 0; i < pnoSettings.networkList.length; i++) {
WifiNative.PnoNetwork network = pnoSettings.networkList[i];
order.verify(mWifiNative).setNetworkVariable(network.networkId,
@@ -311,6 +429,17 @@ public class SupplicantPnoScannerTest {
}
// Verify HW PNO scan started
order.verify(mWifiNative).setPnoScan(true);
+ }
+
+ /**
+ *
+ * 1. Verify that the PNO scan was successfully started.
+ * 2. Send scan results and ensure that the |onPnoNetworkFound| callback was called.
+ */
+ private void expectSuccessfulHwDisconnectedPnoScan(InOrder order,
+ WifiNative.PnoSettings pnoSettings, WifiNative.PnoEventHandler eventHandler,
+ ScanResults scanResults) {
+ expectHwDisconnectedPnoScanStart(order, pnoSettings);
// Setup scan results
when(mWifiNative.getScanResults()).thenReturn(scanResults.getScanDetailArrayList());
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
index 03a11dceb..3498b53fc 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
@@ -1,4 +1,4 @@
-/*
+ /*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -371,7 +371,7 @@ public class WifiScanningServiceTest {
assertTrue("dump did not contain log with type=" + type + ", id=" + id +
": " + serviceDump + "\n",
logLineRegex.matcher(serviceDump).find());
- }
+ }
private void assertDumpContainsCallbackLog(String callback, int id, String extra) {
String serviceDump = dumpService();
@@ -382,7 +382,7 @@ public class WifiScanningServiceTest {
assertTrue("dump did not contain callback log with callback=" + callback + ", id=" + id +
", extra=" + extra + ": " + serviceDump + "\n",
logLineRegex.matcher(serviceDump).find());
- }
+ }
@Test
public void construct() throws Exception {
@@ -507,10 +507,10 @@ public class WifiScanningServiceTest {
*/
@Test
public void sendSingleScanBandRequest() throws Exception {
- WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
- 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
+ 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
- ScanResults.create(0, 2400, 5150, 5175));
+ ScanResults.create(0, true, 2400, 5150, 5175));
}
/**
@@ -518,13 +518,25 @@ public class WifiScanningServiceTest {
*/
@Test
public void sendSingleScanChannelsRequest() throws Exception {
- WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
- 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400, 5150, 5175),
+ 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
ScanResults.create(0, 2400, 5150, 5175));
}
/**
+ * Do a single scan for a list of all channels and verify that it is successful.
+ */
+ @Test
+ public void sendSingleScanAllChannelsRequest() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(
+ channelsToSpec(2400, 2450, 5150, 5175, 5600, 5650, 5660),
+ 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
+ ScanResults.create(0, true, 2400, 5150, 5175));
+ }
+
+ /**
* Do a single scan with no results and verify that it is successful.
*/
@Test
@@ -1655,8 +1667,8 @@ public class WifiScanningServiceTest {
sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
// Can't call |disconnect| here because that sends |CMD_CHANNEL_DISCONNECT| followed by
// |CMD_CHANNEL_DISCONNECTED|.
- controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED, 0,
- 0, null));
+ controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED,
+ AsyncChannel.STATUS_REMOTE_DISCONNECTION, 0, null));
// Now process the above 2 actions. This should result in first processing the single scan
// request (which forwards the request to SingleScanStateMachine) and then processing the
@@ -1671,4 +1683,55 @@ public class WifiScanningServiceTest {
logLineRegex.matcher(serviceDump).find());
}
+ /**
+ * Tries to simulate the race scenario where a client is disconnected immediately after single
+ * scan request is sent to |SingleScanStateMachine|.
+ */
+ @Test
+ public void sendScanRequestAfterUnsuccessfulSend() throws Exception {
+ WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
+ 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
+ int requestId = 9;
+
+ startServiceAndLoadDriver();
+ Handler handler = mock(Handler.class);
+ BidirectionalAsyncChannel controlChannel = connectChannel(handler);
+ mLooper.dispatchAll();
+
+ when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
+ any(WifiNative.ScanEventHandler.class))).thenReturn(true);
+ ScanResults results = ScanResults.create(0, 2400);
+ when(mWifiScannerImpl.getLatestSingleScanResults())
+ .thenReturn(results.getRawScanData());
+
+ InOrder order = inOrder(mWifiScannerImpl, handler);
+
+ sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
+ computeSingleScanNativeSettings(requestSettings));
+ verifySuccessfulResponse(order, handler, requestId);
+
+ eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(order, handler, requestId, results.getScanData());
+ verifySingleScanCompletedRecieved(order, handler, requestId);
+ verifyNoMoreInteractions(handler);
+
+ controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED,
+ AsyncChannel.STATUS_SEND_UNSUCCESSFUL, 0, null));
+ mLooper.dispatchAll();
+
+ sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
+ mLooper.dispatchAll();
+ WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
+ computeSingleScanNativeSettings(requestSettings));
+ verifySuccessfulResponse(order, handler, requestId);
+
+ eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
+ mLooper.dispatchAll();
+ verifyScanResultsRecieved(order, handler, requestId, results.getScanData());
+ verifySingleScanCompletedRecieved(order, handler, requestId);
+ verifyNoMoreInteractions(handler);
+ }
}