summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java4
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java404
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java50
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java213
-rw-r--r--tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java2
5 files changed, 664 insertions, 9 deletions
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 3d444a448..a977a4693 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -88,7 +88,7 @@ public class WifiInjector {
private final WifiController mWifiController;
private final WificondControl mWificondControl;
private final Clock mClock = new Clock();
- private final WifiMetrics mWifiMetrics = new WifiMetrics(mClock);
+ private final WifiMetrics mWifiMetrics;
private final WifiLastResortWatchdog mWifiLastResortWatchdog;
private final PropertyService mPropertyService = new SystemPropertyService();
private final BuildProperties mBuildProperties = new SystemBuildProperties();
@@ -151,7 +151,7 @@ public class WifiInjector {
mWifiStateMachineHandlerThread = new HandlerThread("WifiStateMachine");
mWifiStateMachineHandlerThread.start();
Looper wifiStateMachineLooper = mWifiStateMachineHandlerThread.getLooper();
-
+ mWifiMetrics = new WifiMetrics(mClock, wifiStateMachineLooper);
// Modules interacting with Native.
mWifiMonitor = new WifiMonitor(this);
mHalDeviceManager = new HalDeviceManager();
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 934a4c64f..411d7d7e1 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -16,23 +16,33 @@
package com.android.server.wifi;
+import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
import android.net.NetworkAgent;
import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.util.Base64;
import android.util.Log;
import android.util.SparseIntArray;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.nano.WifiMetricsProto;
+import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
+import com.android.server.wifi.nano.WifiMetricsProto.StaEvent.ConfigInfo;
import com.android.server.wifi.util.InformationElementUtil;
import com.android.server.wifi.util.ScanResultUtil;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Calendar;
+import java.util.LinkedList;
import java.util.List;
/**
@@ -62,6 +72,7 @@ public class WifiMetrics {
private Clock mClock;
private boolean mScreenOn;
private int mWifiState;
+ private Handler mHandler;
/**
* Metrics are stored within an instance of the WifiLog proto during runtime,
* The ConnectionEvent, SystemStateEntries & ScanReturnEntries metrics are stored during
@@ -333,12 +344,20 @@ public class WifiMetrics {
}
}
- public WifiMetrics(Clock clock) {
+ public WifiMetrics(Clock clock, Looper looper) {
mClock = clock;
mCurrentConnectionEvent = null;
mScreenOn = true;
mWifiState = WifiMetricsProto.WifiLog.WIFI_DISABLED;
mRecordStartTimeSec = mClock.getElapsedSinceBootMillis() / 1000;
+
+ mHandler = new Handler(looper) {
+ public void handleMessage(Message msg) {
+ synchronized (mLock) {
+ processMessage(msg);
+ }
+ }
+ };
}
// Values used for indexing SystemStateEntries
@@ -796,6 +815,16 @@ public class WifiMetrics {
}
/**
+ * Increment various poll related metrics, and cache performance data for StaEvent logging
+ */
+ public void handlePollResult(WifiInfo wifiInfo) {
+ mLastPollRssi = wifiInfo.getRssi();
+ mLastPollLinkSpeed = wifiInfo.getLinkSpeed();
+ mLastPollFreq = wifiInfo.getFrequency();
+ incrementRssiPollRssiCount(mLastPollRssi);
+ }
+
+ /**
* Increment occurence count of RSSI level from RSSI poll.
* Ignores rssi values outside the bounds of [MIN_RSSI_POLL, MAX_RSSI_POLL]
*/
@@ -1146,6 +1175,10 @@ public class WifiMetrics {
pw.println(" FAILED_NO_CHANNEL: " + mSoftApManagerReturnCodeCounts.get(
WifiMetricsProto.SoftApReturnCodeCount.SOFT_AP_FAILED_NO_CHANNEL));
pw.print("\n");
+ pw.println("StaEventList:");
+ for (StaEvent event : mStaEventList) {
+ pw.println(staEventToString(event));
+ }
}
}
}
@@ -1308,6 +1341,8 @@ public class WifiMetrics {
mWifiLogProto.softApReturnCode[sapCode].count =
mSoftApManagerReturnCodeCounts.valueAt(sapCode);
}
+
+ mWifiLogProto.staEventList = mStaEventList.toArray(mWifiLogProto.staEventList);
}
}
@@ -1330,6 +1365,7 @@ public class WifiMetrics {
mWifiLogProto.clear();
mScanResultRssiTimestampMillis = -1;
mSoftApManagerReturnCodeCounts.clear();
+ mStaEventList.clear();
}
}
@@ -1350,4 +1386,370 @@ public class WifiMetrics {
mWifiState = wifiState;
}
}
+
+ /**
+ * Message handler for interesting WifiMonitor messages. Generates StaEvents
+ */
+ private void processMessage(Message msg) {
+ StaEvent event = new StaEvent();
+ boolean logEvent = true;
+ switch (msg.what) {
+ case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
+ event.type = StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT;
+ event.associationTimedOut = msg.arg1 > 0 ? true : false;
+ event.status = msg.arg2;
+ break;
+ case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
+ event.type = StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT;
+ switch (msg.arg2) {
+ case WifiManager.ERROR_AUTH_FAILURE_NONE:
+ event.authFailureReason = StaEvent.AUTH_FAILURE_NONE;
+ break;
+ case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT:
+ event.authFailureReason = StaEvent.AUTH_FAILURE_TIMEOUT;
+ break;
+ case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD:
+ event.authFailureReason = StaEvent.AUTH_FAILURE_WRONG_PSWD;
+ break;
+ case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE:
+ event.authFailureReason = StaEvent.AUTH_FAILURE_EAP_FAILURE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case WifiMonitor.NETWORK_CONNECTION_EVENT:
+ event.type = StaEvent.TYPE_NETWORK_CONNECTION_EVENT;
+ break;
+ case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
+ event.type = StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT;
+ event.reason = msg.arg2;
+ event.localGen = msg.arg1 == 0 ? false : true;
+ break;
+ case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+ logEvent = false;
+ StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
+ mSupplicantStateChangeBitmask |= supplicantStateToBit(stateChangeResult.state);
+ break;
+ case WifiStateMachine.CMD_ASSOCIATED_BSSID:
+ event.type = StaEvent.TYPE_CMD_ASSOCIATED_BSSID;
+ break;
+ case WifiStateMachine.CMD_TARGET_BSSID:
+ event.type = StaEvent.TYPE_CMD_TARGET_BSSID;
+ break;
+ default:
+ return;
+ }
+ if (logEvent) {
+ addStaEvent(event);
+ }
+ }
+ /**
+ * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant
+ * generated event types, which are logged through 'sendMessage'
+ * @param type StaEvent.EventType describing the event
+ */
+ public void logStaEvent(int type) {
+ logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, null);
+ }
+ /**
+ * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant
+ * generated event types, which are logged through 'sendMessage'
+ * @param type StaEvent.EventType describing the event
+ * @param config WifiConfiguration for a framework initiated connection attempt
+ */
+ public void logStaEvent(int type, WifiConfiguration config) {
+ logStaEvent(type, StaEvent.DISCONNECT_UNKNOWN, config);
+ }
+ /**
+ * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant
+ * generated event types, which are logged through 'sendMessage'
+ * @param type StaEvent.EventType describing the event
+ * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework
+ * initiated a FRAMEWORK_DISCONNECT
+ */
+ public void logStaEvent(int type, int frameworkDisconnectReason) {
+ logStaEvent(type, frameworkDisconnectReason, null);
+ }
+ /**
+ * Log a StaEvent from WifiStateMachine. The StaEvent must not be one of the supplicant
+ * generated event types, which are logged through 'sendMessage'
+ * @param type StaEvent.EventType describing the event
+ * @param frameworkDisconnectReason StaEvent.FrameworkDisconnectReason explaining why framework
+ * initiated a FRAMEWORK_DISCONNECT
+ * @param config WifiConfiguration for a framework initiated connection attempt
+ */
+ public void logStaEvent(int type, int frameworkDisconnectReason, WifiConfiguration config) {
+ switch (type) {
+ case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
+ case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
+ case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
+ case StaEvent.TYPE_CMD_START_CONNECT:
+ case StaEvent.TYPE_CMD_START_ROAM:
+ case StaEvent.TYPE_CONNECT_NETWORK:
+ case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
+ case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
+ break;
+ default:
+ Log.e(TAG, "Unknown StaEvent:" + type);
+ return;
+ }
+ StaEvent event = new StaEvent();
+ event.type = type;
+ if (frameworkDisconnectReason != StaEvent.DISCONNECT_UNKNOWN) {
+ event.frameworkDisconnectReason = frameworkDisconnectReason;
+ }
+ event.configInfo = createConfigInfo(config);
+ addStaEvent(event);
+ }
+
+ private void addStaEvent(StaEvent staEvent) {
+ staEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
+ staEvent.lastRssi = mLastPollRssi;
+ staEvent.lastFreq = mLastPollFreq;
+ staEvent.lastLinkSpeed = mLastPollLinkSpeed;
+ staEvent.supplicantStateChangesBitmask = mSupplicantStateChangeBitmask;
+ mSupplicantStateChangeBitmask = 0;
+ mLastPollRssi = -127;
+ mLastPollFreq = -1;
+ mLastPollLinkSpeed = -1;
+ mStaEventList.add(staEvent);
+ // Prune StaEventList if it gets too long
+ if (mStaEventList.size() > MAX_STA_EVENTS) mStaEventList.remove();
+ }
+
+ private ConfigInfo createConfigInfo(WifiConfiguration config) {
+ if (config == null) return null;
+ ConfigInfo info = new ConfigInfo();
+ info.allowedKeyManagement = bitSetToInt(config.allowedKeyManagement);
+ info.allowedProtocols = bitSetToInt(config.allowedProtocols);
+ info.allowedAuthAlgorithms = bitSetToInt(config.allowedAuthAlgorithms);
+ info.allowedPairwiseCiphers = bitSetToInt(config.allowedPairwiseCiphers);
+ info.allowedGroupCiphers = bitSetToInt(config.allowedGroupCiphers);
+ info.hiddenSsid = config.hiddenSSID;
+ info.isPasspoint = config.isPasspoint();
+ info.isEphemeral = config.isEphemeral();
+ info.hasEverConnected = config.getNetworkSelectionStatus().getHasEverConnected();
+ ScanResult candidate = config.getNetworkSelectionStatus().getCandidate();
+ if (candidate != null) {
+ info.scanRssi = candidate.level;
+ info.scanFreq = candidate.frequency;
+ }
+ return info;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ // Rather than generate a StaEvent for each SUPPLICANT_STATE_CHANGE, cache these in a bitmask
+ // and attach it to the next event which is generated.
+ private int mSupplicantStateChangeBitmask = 0;
+
+ /**
+ * Converts a SupplicantState value to a single bit, with position defined by
+ * {@code StaEvent.SupplicantState}
+ */
+ public static int supplicantStateToBit(SupplicantState state) {
+ switch(state) {
+ case DISCONNECTED:
+ return 1 << StaEvent.STATE_DISCONNECTED;
+ case INTERFACE_DISABLED:
+ return 1 << StaEvent.STATE_INTERFACE_DISABLED;
+ case INACTIVE:
+ return 1 << StaEvent.STATE_INACTIVE;
+ case SCANNING:
+ return 1 << StaEvent.STATE_SCANNING;
+ case AUTHENTICATING:
+ return 1 << StaEvent.STATE_AUTHENTICATING;
+ case ASSOCIATING:
+ return 1 << StaEvent.STATE_ASSOCIATING;
+ case ASSOCIATED:
+ return 1 << StaEvent.STATE_ASSOCIATED;
+ case FOUR_WAY_HANDSHAKE:
+ return 1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE;
+ case GROUP_HANDSHAKE:
+ return 1 << StaEvent.STATE_GROUP_HANDSHAKE;
+ case COMPLETED:
+ return 1 << StaEvent.STATE_COMPLETED;
+ case DORMANT:
+ return 1 << StaEvent.STATE_DORMANT;
+ case UNINITIALIZED:
+ return 1 << StaEvent.STATE_UNINITIALIZED;
+ case INVALID:
+ return 1 << StaEvent.STATE_INVALID;
+ default:
+ Log.wtf(TAG, "Got unknown supplicant state: " + state.ordinal());
+ return 0;
+ }
+ }
+
+ private static String supplicantStateChangesBitmaskToString(int mask) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("SUPPLICANT_STATE_CHANGE_EVENTS: {");
+ if ((mask & (1 << StaEvent.STATE_DISCONNECTED)) > 0) sb.append(" DISCONNECTED");
+ if ((mask & (1 << StaEvent.STATE_INTERFACE_DISABLED)) > 0) sb.append(" INTERFACE_DISABLED");
+ if ((mask & (1 << StaEvent.STATE_INACTIVE)) > 0) sb.append(" INACTIVE");
+ if ((mask & (1 << StaEvent.STATE_SCANNING)) > 0) sb.append(" SCANNING");
+ if ((mask & (1 << StaEvent.STATE_AUTHENTICATING)) > 0) sb.append(" AUTHENTICATING");
+ if ((mask & (1 << StaEvent.STATE_ASSOCIATING)) > 0) sb.append(" ASSOCIATING");
+ if ((mask & (1 << StaEvent.STATE_ASSOCIATED)) > 0) sb.append(" ASSOCIATED");
+ if ((mask & (1 << StaEvent.STATE_FOUR_WAY_HANDSHAKE)) > 0) sb.append(" FOUR_WAY_HANDSHAKE");
+ if ((mask & (1 << StaEvent.STATE_GROUP_HANDSHAKE)) > 0) sb.append(" GROUP_HANDSHAKE");
+ if ((mask & (1 << StaEvent.STATE_COMPLETED)) > 0) sb.append(" COMPLETED");
+ if ((mask & (1 << StaEvent.STATE_DORMANT)) > 0) sb.append(" DORMANT");
+ if ((mask & (1 << StaEvent.STATE_UNINITIALIZED)) > 0) sb.append(" UNINITIALIZED");
+ if ((mask & (1 << StaEvent.STATE_INVALID)) > 0) sb.append(" INVALID");
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * Returns a human readable string from a Sta Event. Only adds information relevant to the event
+ * type.
+ */
+ public static String staEventToString(StaEvent event) {
+ if (event == null) return "<NULL>";
+ StringBuilder sb = new StringBuilder();
+ Long time = event.startTimeMillis;
+ sb.append(String.format("%9d ", time.longValue())).append(" ");
+ switch (event.type) {
+ case StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT:
+ sb.append("ASSOCIATION_REJECTION_EVENT:")
+ .append(" timedOut=").append(event.associationTimedOut)
+ .append(" status=").append(event.status).append(":")
+ .append(ISupplicantStaIfaceCallback.StatusCode.toString(event.status));
+ break;
+ case StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT:
+ sb.append("AUTHENTICATION_FAILURE_EVENT: reason=").append(event.authFailureReason)
+ .append(":").append(authFailureReasonToString(event.authFailureReason));
+ break;
+ case StaEvent.TYPE_NETWORK_CONNECTION_EVENT:
+ sb.append("NETWORK_CONNECTION_EVENT:");
+ break;
+ case StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT:
+ sb.append("NETWORK_DISCONNECTION_EVENT:")
+ .append(" local_gen=").append(event.localGen)
+ .append(" reason=").append(event.reason).append(":")
+ .append(ISupplicantStaIfaceCallback.ReasonCode.toString(
+ (event.reason >= 0 ? event.reason : -1 * event.reason)));
+ break;
+ case StaEvent.TYPE_CMD_ASSOCIATED_BSSID:
+ sb.append("CMD_ASSOCIATED_BSSID:");
+ break;
+ case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
+ sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL:");
+ break;
+ case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
+ sb.append("CMD_IP_CONFIGURATION_LOST:");
+ break;
+ case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
+ sb.append("CMD_IP_REACHABILITY_LOST:");
+ break;
+ case StaEvent.TYPE_CMD_TARGET_BSSID:
+ sb.append("CMD_TARGET_BSSID:");
+ break;
+ case StaEvent.TYPE_CMD_START_CONNECT:
+ sb.append("CMD_START_CONNECT:");
+ break;
+ case StaEvent.TYPE_CMD_START_ROAM:
+ sb.append("CMD_START_ROAM:");
+ break;
+ case StaEvent.TYPE_CONNECT_NETWORK:
+ sb.append("CONNECT_NETWORK:");
+ break;
+ case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
+ sb.append("NETWORK_AGENT_VALID_NETWORK:");
+ break;
+ case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
+ sb.append("FRAMEWORK_DISCONNECT:")
+ .append(" reason=")
+ .append(frameworkDisconnectReasonToString(event.frameworkDisconnectReason));
+ break;
+ default:
+ sb.append("UNKNOWN " + event.type + ":");
+ break;
+ }
+ if (event.lastRssi != -127) sb.append(" lastRssi=").append(event.lastRssi);
+ if (event.lastFreq != -1) sb.append(" lastFreq=").append(event.lastFreq);
+ if (event.lastLinkSpeed != -1) sb.append(" lastLinkSpeed=").append(event.lastLinkSpeed);
+ if (event.supplicantStateChangesBitmask != 0) {
+ sb.append("\n ").append(supplicantStateChangesBitmaskToString(
+ event.supplicantStateChangesBitmask));
+ }
+ if (event.configInfo != null) {
+ sb.append("\n ").append(configInfoToString(event.configInfo));
+ }
+
+ return sb.toString();
+ }
+
+ private static String authFailureReasonToString(int authFailureReason) {
+ switch (authFailureReason) {
+ case StaEvent.AUTH_FAILURE_NONE:
+ return "ERROR_AUTH_FAILURE_NONE";
+ case StaEvent.AUTH_FAILURE_TIMEOUT:
+ return "ERROR_AUTH_FAILURE_TIMEOUT";
+ case StaEvent.AUTH_FAILURE_WRONG_PSWD:
+ return "ERROR_AUTH_FAILURE_WRONG_PSWD";
+ case StaEvent.AUTH_FAILURE_EAP_FAILURE:
+ return "ERROR_AUTH_FAILURE_EAP_FAILURE";
+ default:
+ return "";
+ }
+ }
+
+ private static String frameworkDisconnectReasonToString(int frameworkDisconnectReason) {
+ switch (frameworkDisconnectReason) {
+ case StaEvent.DISCONNECT_API:
+ return "DISCONNECT_API";
+ case StaEvent.DISCONNECT_GENERIC:
+ return "DISCONNECT_GENERIC";
+ case StaEvent.DISCONNECT_UNWANTED:
+ return "DISCONNECT_UNWANTED";
+ case StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER:
+ return "DISCONNECT_ROAM_WATCHDOG_TIMER";
+ case StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST:
+ return "DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST";
+ case StaEvent.DISCONNECT_RESET_SIM_NETWORKS:
+ return "DISCONNECT_RESET_SIM_NETWORKS";
+ default:
+ return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason;
+ }
+ }
+
+ private static String configInfoToString(ConfigInfo info) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("ConfigInfo:")
+ .append(" allowed_key_management=").append(info.allowedKeyManagement)
+ .append(" allowed_protocols=").append(info.allowedProtocols)
+ .append(" allowed_auth_algorithms=").append(info.allowedAuthAlgorithms)
+ .append(" allowed_pairwise_ciphers=").append(info.allowedPairwiseCiphers)
+ .append(" allowed_group_ciphers=").append(info.allowedGroupCiphers)
+ .append(" hidden_ssid=").append(info.hiddenSsid)
+ .append(" is_passpoint=").append(info.isPasspoint)
+ .append(" is_ephemeral=").append(info.isEphemeral)
+ .append(" has_ever_connected=").append(info.hasEverConnected)
+ .append(" scan_rssi=").append(info.scanRssi)
+ .append(" scan_freq=").append(info.scanFreq);
+ return sb.toString();
+ }
+
+ public static final int MAX_STA_EVENTS = 512;
+ private LinkedList<StaEvent> mStaEventList = new LinkedList<StaEvent>();
+ private int mLastPollRssi = -127;
+ private int mLastPollLinkSpeed = -1;
+ private int mLastPollFreq = -1;
+
+ /**
+ * Converts the first 31 bits of a BitSet to a little endian int
+ */
+ private static int bitSetToInt(BitSet bits) {
+ int value = 0;
+ int nBits = bits.length() < 31 ? bits.length() : 31;
+ for (int i = 0; i < nBits; i++) {
+ value += bits.get(i) ? (1 << i) : 0;
+ }
+ return value;
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index d90962157..eaac5560a 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -114,6 +114,7 @@ import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.hotspot2.Utils;
import com.android.server.wifi.hotspot2.WnmData;
import com.android.server.wifi.nano.WifiMetricsProto;
+import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.p2p.WifiP2pServiceImpl;
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.TelephonyUtil;
@@ -1072,6 +1073,21 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_SUCCESS_EVENT, getHandler());
mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_TIMEOUT_EVENT, getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT,
+ mWifiMetrics.getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
+ mWifiMetrics.getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT,
+ mWifiMetrics.getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT,
+ mWifiMetrics.getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
+ mWifiMetrics.getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, CMD_ASSOCIATED_BSSID,
+ mWifiMetrics.getHandler());
+ mWifiMonitor.registerHandler(mInterfaceName, CMD_TARGET_BSSID,
+ mWifiMetrics.getHandler());
+
final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
@@ -1103,12 +1119,14 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
@Override
public void onProvisioningSuccess(LinkProperties newLp) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL);
sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);
}
@Override
public void onProvisioningFailure(LinkProperties newLp) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST);
sendMessage(CMD_IP_CONFIGURATION_LOST);
}
@@ -1119,6 +1137,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
@Override
public void onReachabilityLost(String logMsg) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_REACHABILITY_LOST);
sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);
}
@@ -2884,10 +2903,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
if (newRssi > 0) newRssi -= 256;
mWifiInfo.setRssi(newRssi);
/*
- * Log the rssi poll value in metrics
- */
- mWifiMetrics.incrementRssiPollRssiCount(newRssi);
- /*
* Rather then sending the raw RSSI out every time it
* changes, we precalculate the signal level that would
* be displayed in the status bar, and only send the
@@ -2921,6 +2936,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mWifiInfo.setFrequency(newFrequency);
}
mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo);
+ /*
+ * Increment various performance metrics
+ */
+ if (newRssi != null && newLinkSpeed != null && newFrequency != null) {
+ mWifiMetrics.handlePollResult(mWifiInfo);
+ }
}
// Polling has completed, hence we wont have a score anymore
@@ -4818,6 +4839,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
break;
case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
if (message.arg1 == 1) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
mWifiNative.disconnect();
mTemporarilyDisconnectWifi = true;
} else {
@@ -4913,6 +4936,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
WifiConfiguration.NetworkSelectionStatus
.DISABLED_AUTHENTICATION_NO_CREDENTIALS);
}
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_GENERIC);
mWifiNative.disconnect();
}
break;
@@ -4972,6 +4997,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
reportConnectionAttemptStart(config, mTargetRoamBSSID,
WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED);
if (mWifiNative.connectToNetwork(config)) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config);
lastConnectAttemptTimestamp = mClock.getWallClockMillis();
targetWificonfiguration = config;
mIsAutoRoaming = false;
@@ -5039,6 +5065,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
WifiManager.NOT_AUTHORIZED);
break;
}
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CONNECT_NETWORK, config);
broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config);
replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED);
break;
@@ -5332,6 +5359,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
log("WifiNetworkAgent -> Wifi networkStatus valid, score= "
+ Integer.toString(mWifiInfo.score));
}
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK);
doNetworkStatus(status);
}
}
@@ -5594,11 +5622,15 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
}
break;
case CMD_DISCONNECT:
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_UNKNOWN);
mWifiNative.disconnect();
transitionTo(mDisconnectingState);
break;
case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
if (message.arg1 == 1) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
mWifiNative.disconnect();
mTemporarilyDisconnectWifi = true;
transitionTo(mDisconnectingState);
@@ -5731,6 +5763,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
WifiConfiguration config =
mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
if (TelephonyUtil.isSimConfig(config)) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_RESET_SIM_NETWORKS);
mWifiNative.disconnect();
transitionTo(mDisconnectingState);
}
@@ -5946,6 +5980,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
WifiMetricsProto.ConnectionEvent.HLF_NONE);
mRoamFailCount++;
handleNetworkDisconnect();
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER);
mWifiNative.disconnect();
transitionTo(mDisconnectedState);
}
@@ -6060,6 +6096,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
switch (message.what) {
case CMD_UNWANTED_NETWORK:
if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_UNWANTED);
mWifiNative.disconnect();
transitionTo(mDisconnectingState);
} else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN ||
@@ -6202,6 +6240,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
lastConnectAttemptTimestamp = mClock.getWallClockMillis();
targetWificonfiguration = config;
mIsAutoRoaming = true;
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_ROAM, config);
transitionTo(mRoamingState);
} else {
loge("CMD_START_ROAM Failed to start roaming to network " + config);
@@ -6315,6 +6354,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
class DisconnectedState extends State {
@Override
public void enter() {
+ Log.i(TAG, "disconnectedstate enter");
// We dont scan frequently if this is a temporary disconnect
// due to p2p
if (mTemporarilyDisconnectWifi) {
@@ -6387,6 +6427,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
}
break;
case CMD_DISCONNECT:
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
+ StaEvent.DISCONNECT_UNKNOWN);
mWifiNative.disconnect();
break;
/* Ignore network disconnect */
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 38d2062e0..22744b63b 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -21,13 +21,19 @@ import static org.mockito.Mockito.*;
import android.net.NetworkAgent;
import android.net.wifi.ScanResult;
+import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
+import android.os.Handler;
+import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
+
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.nano.WifiMetricsProto;
+import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
import org.junit.Before;
import org.junit.Test;
@@ -37,6 +43,7 @@ import org.mockito.MockitoAnnotations;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -49,6 +56,7 @@ public class WifiMetricsTest {
WifiMetrics mWifiMetrics;
WifiMetricsProto.WifiLog mDeserializedWifiMetrics;
+ TestLooper mTestLooper;
@Mock Clock mClock;
@Before
@@ -56,7 +64,8 @@ public class WifiMetricsTest {
MockitoAnnotations.initMocks(this);
mDeserializedWifiMetrics = null;
when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 0);
- mWifiMetrics = new WifiMetrics(mClock);
+ mTestLooper = new TestLooper();
+ mWifiMetrics = new WifiMetrics(mClock, mTestLooper.getLooper());
}
/**
@@ -847,6 +856,156 @@ public class WifiMetricsTest {
assertEquals(0, mDeserializedWifiMetrics.rssiPollDeltaCount.length);
}
+ private static final int DEAUTH_REASON = 7;
+ private static final int ASSOC_STATUS = 11;
+ private static final int ASSOC_TIMEOUT = 1;
+ private static final int LOCAL_GEN = 1;
+ private static final int AUTH_FAILURE_REASON = WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD;
+ private static final int NUM_TEST_STA_EVENTS = 14;
+ private static final String sSSID = "\"SomeTestSsid\"";
+ private static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
+ private static final String sBSSID = "01:02:03:04:05:06";
+
+ private final StateChangeResult mStateDisconnected =
+ new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED);
+ private final StateChangeResult mStateCompleted =
+ new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED);
+ // Test bitmasks of supplicant state changes
+ private final int mSupBm1 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state);
+ private final int mSupBm2 = WifiMetrics.supplicantStateToBit(mStateDisconnected.state)
+ | WifiMetrics.supplicantStateToBit(mStateCompleted.state);
+ // An invalid but interesting wifiConfiguration that exercises the StaEvent.ConfigInfo encoding
+ private final WifiConfiguration mTestWifiConfig = createComplexWifiConfig();
+ // <msg.what> <msg.arg1> <msg.arg2>
+ private int[][] mTestStaMessageInts = {
+ {WifiMonitor.ASSOCIATION_REJECTION_EVENT, ASSOC_TIMEOUT, ASSOC_STATUS},
+ {WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, AUTH_FAILURE_REASON},
+ {WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0},
+ {WifiMonitor.NETWORK_DISCONNECTION_EVENT, LOCAL_GEN, DEAUTH_REASON},
+ {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0},
+ {WifiStateMachine.CMD_ASSOCIATED_BSSID, 0, 0},
+ {WifiStateMachine.CMD_TARGET_BSSID, 0, 0},
+ {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0},
+ {WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0}
+ };
+ private Object[] mTestStaMessageObjs = {
+ null,
+ null,
+ null,
+ null,
+ mStateDisconnected,
+ null,
+ null,
+ mStateDisconnected,
+ mStateCompleted
+ };
+ // Values used to generate the StaEvent log calls from WifiStateMachine
+ // <StaEvent.Type>, <StaEvent.FrameworkDisconnectReason>, <1|0>(testWifiConfiguration, null)
+ private int[][] mTestStaLogInts = {
+ {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, 0, 0},
+ {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, 0, 0},
+ {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, 0, 0},
+ {StaEvent.TYPE_CMD_START_CONNECT, 0, 1},
+ {StaEvent.TYPE_CMD_START_ROAM, 0, 1},
+ {StaEvent.TYPE_CONNECT_NETWORK, 0, 1},
+ {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, 0, 0},
+ {StaEvent.TYPE_FRAMEWORK_DISCONNECT, StaEvent.DISCONNECT_API, 0}
+ };
+ // Values used to generate the StaEvent log calls from WifiMonitor
+ // <type>, <reason>, <status>, <local_gen>,
+ // <auth_fail_reason>, <assoc_timed_out> <supplicantStateChangeBitmask> <1|0>(has ConfigInfo)
+ private int[][] mExpectedValues = {
+ {StaEvent.TYPE_ASSOCIATION_REJECTION_EVENT, -1, ASSOC_STATUS, 0,
+ /**/ 0, ASSOC_TIMEOUT, 0, 0}, /**/
+ {StaEvent.TYPE_AUTHENTICATION_FAILURE_EVENT, -1, -1, 0,
+ /**/StaEvent.AUTH_FAILURE_WRONG_PSWD, 0, 0, 0}, /**/
+ {StaEvent.TYPE_NETWORK_CONNECTION_EVENT, -1, -1, 0,
+ /**/ 0, 0, 0, 0}, /**/
+ {StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT, DEAUTH_REASON, -1, LOCAL_GEN,
+ /**/ 0, 0, 0, 0}, /**/
+ {StaEvent.TYPE_CMD_ASSOCIATED_BSSID, -1, -1, 0,
+ /**/ 0, 0, mSupBm1, 0}, /**/
+ {StaEvent.TYPE_CMD_TARGET_BSSID, -1, -1, 0,
+ /**/ 0, 0, 0, 0}, /**/
+ {StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL, -1, -1, 0,
+ /**/ 0, 0, mSupBm2, 0}, /**/
+ {StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST, -1, -1, 0,
+ /**/ 0, 0, 0, 0}, /**/
+ {StaEvent.TYPE_CMD_IP_REACHABILITY_LOST, -1, -1, 0,
+ /**/ 0, 0, 0, 0}, /**/
+ {StaEvent.TYPE_CMD_START_CONNECT, -1, -1, 0,
+ /**/ 0, 0, 0, 1}, /**/
+ {StaEvent.TYPE_CMD_START_ROAM, -1, -1, 0,
+ /**/ 0, 0, 0, 1}, /**/
+ {StaEvent.TYPE_CONNECT_NETWORK, -1, -1, 0,
+ /**/ 0, 0, 0, 1}, /**/
+ {StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK, -1, -1, 0,
+ /**/ 0, 0, 0, 0}, /**/
+ {StaEvent.TYPE_FRAMEWORK_DISCONNECT, -1, -1, 0,
+ /**/ 0, 0, 0, 0} /**/
+ };
+
+ /**
+ * Generates events from all the rows in mTestStaMessageInts, and then mTestStaLogInts
+ */
+ private void generateStaEvents(WifiMetrics wifiMetrics) {
+ Handler handler = wifiMetrics.getHandler();
+ for (int i = 0; i < mTestStaMessageInts.length; i++) {
+ int[] mia = mTestStaMessageInts[i];
+ handler.sendMessage(
+ handler.obtainMessage(mia[0], mia[1], mia[2], mTestStaMessageObjs[i]));
+ }
+ mTestLooper.dispatchAll();
+ for (int i = 0; i < mTestStaLogInts.length; i++) {
+ int[] lia = mTestStaLogInts[i];
+ wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null);
+ }
+ }
+ private void verifyDeserializedStaEvents(WifiMetricsProto.WifiLog wifiLog) {
+ assertEquals(NUM_TEST_STA_EVENTS, wifiLog.staEventList.length);
+ int j = 0; // De-serialized event index
+ for (int i = 0; i < mTestStaMessageInts.length; i++) {
+ StaEvent event = wifiLog.staEventList[j];
+ int[] mia = mTestStaMessageInts[i];
+ int[] evs = mExpectedValues[j];
+ if (mia[0] != WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT) {
+ assertEquals(evs[0], event.type);
+ assertEquals(evs[1], event.reason);
+ assertEquals(evs[2], event.status);
+ assertEquals(evs[3] == 1 ? true : false, event.localGen);
+ assertEquals(evs[4], event.authFailureReason);
+ assertEquals(evs[5] == 1 ? true : false, event.associationTimedOut);
+ assertEquals(evs[6], event.supplicantStateChangesBitmask);
+ assertConfigInfoEqualsWifiConfig(
+ evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
+ j++;
+ }
+ }
+ }
+
+ /**
+ * Generate StaEvents of each type, ensure all the different values are logged correctly,
+ * and that they survive serialization & de-serialization
+ */
+ @Test
+ public void testStaEventsLogSerializeDeserialize() throws Exception {
+ generateStaEvents(mWifiMetrics);
+ dumpProtoAndDeserialize();
+ verifyDeserializedStaEvents(mDeserializedWifiMetrics);
+ }
+
+ /**
+ * Ensure the number of StaEvents does not exceed MAX_STA_EVENTS by generating lots of events
+ * and checking how many are deserialized
+ */
+ @Test
+ public void testStaEventBounding() throws Exception {
+ for (int i = 0; i < (WifiMetrics.MAX_STA_EVENTS + 10); i++) {
+ mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT);
+ }
+ dumpProtoAndDeserialize();
+ assertEquals(WifiMetrics.MAX_STA_EVENTS, mDeserializedWifiMetrics.staEventList.length);
+ }
/**
* Generate an RSSI delta event by creating a connection event and an RSSI poll within
* 'interArrivalTime' milliseconds of each other.
@@ -911,4 +1070,56 @@ public class WifiMetricsTest {
writer.flush();
return stream.toString();
}
+
+ private static final int TEST_ALLOWED_KEY_MANAGEMENT = 83;
+ private static final int TEST_ALLOWED_PROTOCOLS = 22;
+ private static final int TEST_ALLOWED_AUTH_ALGORITHMS = 11;
+ private static final int TEST_ALLOWED_PAIRWISE_CIPHERS = 67;
+ private static final int TEST_ALLOWED_GROUP_CIPHERS = 231;
+ private static final int TEST_CANDIDATE_LEVEL = -80;
+ private static final int TEST_CANDIDATE_FREQ = 2345;
+
+ private WifiConfiguration createComplexWifiConfig() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.allowedKeyManagement = intToBitSet(TEST_ALLOWED_KEY_MANAGEMENT);
+ config.allowedProtocols = intToBitSet(TEST_ALLOWED_PROTOCOLS);
+ config.allowedAuthAlgorithms = intToBitSet(TEST_ALLOWED_AUTH_ALGORITHMS);
+ config.allowedPairwiseCiphers = intToBitSet(TEST_ALLOWED_PAIRWISE_CIPHERS);
+ config.allowedGroupCiphers = intToBitSet(TEST_ALLOWED_GROUP_CIPHERS);
+ config.hiddenSSID = true;
+ config.ephemeral = true;
+ config.getNetworkSelectionStatus().setHasEverConnected(true);
+ ScanResult candidate = new ScanResult();
+ candidate.level = TEST_CANDIDATE_LEVEL;
+ candidate.frequency = TEST_CANDIDATE_FREQ;
+ config.getNetworkSelectionStatus().setCandidate(candidate);
+ return config;
+ }
+
+ private void assertConfigInfoEqualsWifiConfig(WifiConfiguration config,
+ StaEvent.ConfigInfo info) {
+ if (config == null && info == null) return;
+ assertEquals(config.allowedKeyManagement, intToBitSet(info.allowedKeyManagement));
+ assertEquals(config.allowedProtocols, intToBitSet(info.allowedProtocols));
+ assertEquals(config.allowedAuthAlgorithms, intToBitSet(info.allowedAuthAlgorithms));
+ assertEquals(config.allowedPairwiseCiphers, intToBitSet(info.allowedPairwiseCiphers));
+ assertEquals(config.allowedGroupCiphers, intToBitSet(info.allowedGroupCiphers));
+ assertEquals(config.hiddenSSID, info.hiddenSsid);
+ assertEquals(config.ephemeral, info.isEphemeral);
+ assertEquals(config.getNetworkSelectionStatus().getHasEverConnected(),
+ info.hasEverConnected);
+ assertEquals(config.getNetworkSelectionStatus().getCandidate().level, info.scanRssi);
+ assertEquals(config.getNetworkSelectionStatus().getCandidate().frequency, info.scanFreq);
+ }
+
+ /**
+ * Sets the values of bitSet to match an int mask
+ */
+ private static BitSet intToBitSet(int mask) {
+ BitSet bitSet = new BitSet();
+ for (int bitIndex = 0; mask > 0; mask >>>= 1, bitIndex++) {
+ if ((mask & 1) != 0) bitSet.set(bitIndex);
+ }
+ return bitSet;
+ }
}
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 3cd08439e..e7c5fa962 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java
@@ -105,7 +105,6 @@ public class WifiScanningServiceTest {
mAlarmManager = new TestAlarmManager();
when(mContext.getSystemService(Context.ALARM_SERVICE))
.thenReturn(mAlarmManager.getAlarmManager());
- mWifiMetrics = new WifiMetrics(mClock);
ChannelHelper channelHelper = new PresetKnownBandsChannelHelper(
new int[]{2400, 2450},
@@ -113,6 +112,7 @@ public class WifiScanningServiceTest {
new int[]{5600, 5650, 5660});
mLooper = new TestLooper();
+ mWifiMetrics = new WifiMetrics(mClock, mLooper.getLooper());
when(mWifiScannerImplFactory
.create(any(), any(), any()))
.thenReturn(mWifiScannerImpl);