Merge "WifiConfigStore: Remove legacy modules" into oc-mr1-dev
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
index fc144c1..692c8e2 100644
--- a/service/java/com/android/server/wifi/OpenNetworkNotifier.java
+++ b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
@@ -29,6 +29,8 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.util.ArraySet;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -36,18 +38,25 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
+import java.util.Set;
/**
* Takes care of handling the "open wi-fi network available" notification
+ *
+ * NOTE: These API's are not thread safe and should only be used from WifiStateMachine thread.
* @hide
*/
public class OpenNetworkNotifier {
+ private static final String TAG = "OpenNetworkNotifier";
+
static final String ACTION_USER_DISMISSED_NOTIFICATION =
"com.android.server.wifi.OpenNetworkNotifier.USER_DISMISSED_NOTIFICATION";
static final String ACTION_USER_TAPPED_CONTENT =
"com.android.server.wifi.OpenNetworkNotifier.USER_TAPPED_CONTENT";
+ /** Identifier of the {@link SsidSetStoreData}. */
+ private static final String STORE_DATA_IDENTIFIER = "OpenNetworkNotifierBlacklist";
/**
* The {@link Clock#getWallClockMillis()} must be at least this value for us
* to show the notification again.
@@ -68,10 +77,14 @@
/** Whether the screen is on or not. */
private boolean mScreenOn;
+ /** List of SSIDs blacklisted from recommendation. */
+ private final Set<String> mBlacklistedSsids;
+
private final Context mContext;
private final Handler mHandler;
private final FrameworkFacade mFrameworkFacade;
private final Clock mClock;
+ private final WifiConfigManager mConfigManager;
private final OpenNetworkRecommender mOpenNetworkRecommender;
private final OpenNetworkNotificationBuilder mOpenNetworkNotificationBuilder;
@@ -82,15 +95,22 @@
Looper looper,
FrameworkFacade framework,
Clock clock,
+ WifiConfigManager wifiConfigManager,
+ WifiConfigStore wifiConfigStore,
OpenNetworkRecommender openNetworkRecommender) {
mContext = context;
mHandler = new Handler(looper);
mFrameworkFacade = framework;
mClock = clock;
+ mConfigManager = wifiConfigManager;
mOpenNetworkRecommender = openNetworkRecommender;
mOpenNetworkNotificationBuilder = new OpenNetworkNotificationBuilder(context, framework);
mScreenOn = false;
+ mBlacklistedSsids = new ArraySet<>();
+ wifiConfigStore.registerStoreData(new SsidSetStoreData(
+ STORE_DATA_IDENTIFIER, new OpenNetworkNotifierStoreData()));
+
// Setting is in seconds
mNotificationRepeatDelay = mFrameworkFacade.getIntegerSetting(context,
Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
@@ -165,7 +185,7 @@
}
mRecommendedNetwork = mOpenNetworkRecommender.recommendNetwork(
- availableNetworks, mRecommendedNetwork);
+ availableNetworks, new ArraySet<>(mBlacklistedSsids));
postNotification(availableNetworks.size());
}
@@ -201,8 +221,14 @@
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
- /** A delay is set before the next shown notification after user dismissal. */
private void handleUserDismissedAction() {
+ if (mRecommendedNetwork != null) {
+ // blacklist dismissed network
+ mBlacklistedSsids.add(mRecommendedNetwork.SSID);
+ mConfigManager.saveToStore(false /* forceWrite */);
+ Log.d(TAG, "Network is added to the open network notification blacklist: "
+ + mRecommendedNetwork.SSID);
+ }
mNotificationShown = false;
}
@@ -213,6 +239,19 @@
pw.println("currentTime: " + mClock.getWallClockMillis());
pw.println("mNotificationRepeatTime: " + mNotificationRepeatTime);
pw.println("mNotificationShown: " + mNotificationShown);
+ pw.println("mBlacklistedSsids: " + mBlacklistedSsids.toString());
+ }
+
+ private class OpenNetworkNotifierStoreData implements SsidSetStoreData.DataSource {
+ @Override
+ public Set<String> getSsids() {
+ return new ArraySet<>(mBlacklistedSsids);
+ }
+
+ @Override
+ public void setSsids(Set<String> ssidList) {
+ mBlacklistedSsids.addAll(ssidList);
+ }
}
private class NotificationEnabledSettingObserver extends ContentObserver {
diff --git a/service/java/com/android/server/wifi/OpenNetworkRecommender.java b/service/java/com/android/server/wifi/OpenNetworkRecommender.java
index cd460e5..5ceeddd 100644
--- a/service/java/com/android/server/wifi/OpenNetworkRecommender.java
+++ b/service/java/com/android/server/wifi/OpenNetworkRecommender.java
@@ -20,9 +20,12 @@
import android.net.wifi.ScanResult;
import java.util.List;
+import java.util.Set;
/**
* Helps recommend the best available network for {@link OpenNetworkNotifier}.
+ *
+ * NOTE: These API's are not thread safe and should only be used from WifiStateMachine thread.
* @hide
*/
public class OpenNetworkRecommender {
@@ -32,31 +35,24 @@
*
* @param networks List of scan details to pick a recommendation. This list should not be null
* or empty.
- * @param currentRecommendation The currently recommended network.
+ * @param blacklistedSsids The list of SSIDs that should not be recommended.
*/
- public ScanResult recommendNetwork(
- @NonNull List<ScanDetail> networks, ScanResult currentRecommendation) {
- ScanResult currentUpdatedRecommendation = null;
+ public ScanResult recommendNetwork(@NonNull List<ScanDetail> networks,
+ @NonNull Set<String> blacklistedSsids) {
ScanResult result = null;
int highestRssi = Integer.MIN_VALUE;
for (ScanDetail scanDetail : networks) {
ScanResult scanResult = scanDetail.getScanResult();
- if (currentRecommendation != null
- && currentRecommendation.SSID.equals(scanResult.SSID)) {
- currentUpdatedRecommendation = scanResult;
- }
-
if (scanResult.level > highestRssi) {
result = scanResult;
highestRssi = scanResult.level;
}
}
- if (currentUpdatedRecommendation != null
- && currentUpdatedRecommendation.level >= result.level) {
- return currentUpdatedRecommendation;
- } else {
- return result;
+
+ if (result != null && blacklistedSsids.contains(result.SSID)) {
+ result = null;
}
+ return result;
}
}
diff --git a/service/java/com/android/server/wifi/SsidSetStoreData.java b/service/java/com/android/server/wifi/SsidSetStoreData.java
new file mode 100644
index 0000000..daed26a
--- /dev/null
+++ b/service/java/com/android/server/wifi/SsidSetStoreData.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import android.text.TextUtils;
+
+import com.android.server.wifi.util.XmlUtil;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Store data for network notifiers.
+ *
+ * Below are the current configuration data for each respective store file:
+ *
+ * Share Store (system wide configurations)
+ * - No data
+ *
+ * User Store (user specific configurations)
+ * - Set of blacklisted SSIDs
+ */
+public class SsidSetStoreData implements WifiConfigStore.StoreData {
+ private static final String XML_TAG_SECTION_HEADER_SUFFIX = "ConfigData";
+ private static final String XML_TAG_SSID_SET = "SSIDSet";
+
+ private final String mTagName;
+ private final DataSource mDataSource;
+
+ /**
+ * Interface define the data source for the notifier store data.
+ */
+ public interface DataSource {
+ /**
+ * Retrieve the SSID set from the data source.
+ *
+ * @return Set of SSIDs
+ */
+ Set<String> getSsids();
+
+ /**
+ * Update the SSID set in the data source.
+ *
+ * @param ssidSet The set of SSIDs
+ */
+ void setSsids(Set<String> ssidSet);
+ }
+
+ /**
+ * Creates the SSID Set store data.
+ *
+ * @param name Identifier of the SSID set.
+ * @param dataSource The DataSource that implements the update and retrieval of the SSID set.
+ */
+ SsidSetStoreData(String name, DataSource dataSource) {
+ mTagName = name + XML_TAG_SECTION_HEADER_SUFFIX;
+ mDataSource = dataSource;
+ }
+
+ @Override
+ public void serializeData(XmlSerializer out, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ throw new XmlPullParserException("Share data not supported");
+ }
+ Set<String> ssidSet = mDataSource.getSsids();
+ if (ssidSet != null && !ssidSet.isEmpty()) {
+ XmlUtil.writeNextValue(out, XML_TAG_SSID_SET, mDataSource.getSsids());
+ }
+ }
+
+ @Override
+ public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ throw new XmlPullParserException("Share data not supported");
+ }
+
+ while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
+ String[] valueName = new String[1];
+ Object value = XmlUtil.readCurrentValue(in, valueName);
+ if (TextUtils.isEmpty(valueName[0])) {
+ throw new XmlPullParserException("Missing value name");
+ }
+ switch (valueName[0]) {
+ case XML_TAG_SSID_SET:
+ mDataSource.setSsids((Set<String>) value);
+ break;
+ default:
+ throw new XmlPullParserException("Unknown tag under "
+ + mTagName + ": " + valueName[0]);
+ }
+ }
+ }
+
+ @Override
+ public void resetData(boolean shared) {
+ if (!shared) {
+ mDataSource.setSsids(new HashSet<>());
+ }
+ }
+
+ @Override
+ public String getName() {
+ return mTagName;
+ }
+
+ @Override
+ public boolean supportShareData() {
+ return false;
+ }
+}
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 93db5ab..e417fde 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -512,6 +512,8 @@
}
@Override
public void onSavedNetworkUpdated(int networkId) {
+ // User might have changed meteredOverride, so update capabilties
+ mStateMachine.updateCapabilities();
updatePnoScan();
}
@Override
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 719bed7..734c28d 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -226,7 +226,7 @@
mCertManager = new WifiCertManager(mContext);
mOpenNetworkNotifier = new OpenNetworkNotifier(mContext,
mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade, mClock,
- new OpenNetworkRecommender());
+ mWifiConfigManager, mWifiConfigStore, new OpenNetworkRecommender());
mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore,
mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade);
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 7dfdb86..5db5ee6 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -37,6 +37,7 @@
import com.android.server.wifi.hotspot2.PasspointMatch;
import com.android.server.wifi.hotspot2.PasspointProvider;
import com.android.server.wifi.nano.WifiMetricsProto;
+import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics;
import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
import com.android.server.wifi.nano.WifiMetricsProto.StaEvent.ConfigInfo;
import com.android.server.wifi.util.InformationElementUtil;
@@ -86,6 +87,7 @@
private boolean mScreenOn;
private int mWifiState;
private WifiAwareMetrics mWifiAwareMetrics;
+ private final PnoScanMetrics mPnoScanMetrics = new PnoScanMetrics();
private Handler mHandler;
private WifiConfigManager mWifiConfigManager;
private WifiNetworkSelector mWifiNetworkSelector;
@@ -407,6 +409,51 @@
mPasspointManager = passpointManager;
}
+ /**
+ * Increment total number of attempts to start a pno scan
+ */
+ public void incrementPnoScanStartAttempCount() {
+ synchronized (mLock) {
+ mPnoScanMetrics.numPnoScanAttempts++;
+ }
+ }
+
+ /**
+ * Increment total number of attempts with pno scan failed
+ */
+ public void incrementPnoScanFailedCount() {
+ synchronized (mLock) {
+ mPnoScanMetrics.numPnoScanFailed++;
+ }
+ }
+
+ /**
+ * Increment number of pno scans started successfully over offload
+ */
+ public void incrementPnoScanStartedOverOffloadCount() {
+ synchronized (mLock) {
+ mPnoScanMetrics.numPnoScanStartedOverOffload++;
+ }
+ }
+
+ /**
+ * Increment number of pno scans failed over offload
+ */
+ public void incrementPnoScanFailedOverOffloadCount() {
+ synchronized (mLock) {
+ mPnoScanMetrics.numPnoScanFailedOverOffload++;
+ }
+ }
+
+ /**
+ * Increment number of times pno scan found a result
+ */
+ public void incrementPnoFoundNetworkEventCount() {
+ synchronized (mLock) {
+ mPnoScanMetrics.numPnoFoundNetworkEvents++;
+ }
+ }
+
// Values used for indexing SystemStateEntries
private static final int SCREEN_ON = 1;
private static final int SCREEN_OFF = 0;
@@ -1388,8 +1435,8 @@
pw.println("mWifiLogProto.numWifiOnFailureDueToWificond="
+ mWifiLogProto.numWifiOnFailureDueToWificond);
pw.println("StaEventList:");
- for (StaEvent event : mStaEventList) {
- pw.println(staEventToString(event));
+ for (StaEventWithTime event : mStaEventList) {
+ pw.println(event);
}
pw.println("mWifiLogProto.numPasspointProviders="
@@ -1430,6 +1477,17 @@
+ mWifiLogProto.fullBandAllSingleScanListenerResults);
pw.println("mWifiAwareMetrics:");
mWifiAwareMetrics.dump(fd, pw, args);
+
+ pw.println("mPnoScanMetrics.numPnoScanAttempts="
+ + mPnoScanMetrics.numPnoScanAttempts);
+ pw.println("mPnoScanMetrics.numPnoScanFailed="
+ + mPnoScanMetrics.numPnoScanFailed);
+ pw.println("mPnoScanMetrics.numPnoScanStartedOverOffload="
+ + mPnoScanMetrics.numPnoScanStartedOverOffload);
+ pw.println("mPnoScanMetrics.numPnoScanFailedOverOffload="
+ + mPnoScanMetrics.numPnoScanFailedOverOffload);
+ pw.println("mPnoScanMetrics.numPnoFoundNetworkEvents="
+ + mPnoScanMetrics.numPnoFoundNetworkEvents);
}
}
}
@@ -1605,6 +1663,14 @@
mWifiLogProto.softApReturnCode[sapCode].count =
mSoftApManagerReturnCodeCounts.valueAt(sapCode);
}
+
+ /**
+ * Convert StaEventList to array of StaEvents
+ */
+ mWifiLogProto.staEventList = new StaEvent[mStaEventList.size()];
+ for (int i = 0; i < mStaEventList.size(); i++) {
+ mWifiLogProto.staEventList[i] = mStaEventList.get(i).staEvent;
+ }
mWifiLogProto.totalSsidsInScanHistogram =
makeNumConnectableNetworksBucketArray(mTotalSsidsInScanHistogram);
mWifiLogProto.totalBssidsInScanHistogram =
@@ -1629,8 +1695,9 @@
mWifiLogProto.availableSavedPasspointProviderBssidsInScanHistogram =
makeNumConnectableNetworksBucketArray(
mAvailableSavedPasspointProviderBssidsInScanHistogram);
- mWifiLogProto.staEventList = mStaEventList.toArray(mWifiLogProto.staEventList);
mWifiLogProto.wifiAwareLog = mWifiAwareMetrics.consolidateProto();
+
+ mWifiLogProto.pnoScanMetrics = mPnoScanMetrics;
}
}
@@ -1679,6 +1746,7 @@
mAvailableOpenOrSavedBssidsInScanHistogram.clear();
mAvailableSavedPasspointProviderProfilesInScanHistogram.clear();
mAvailableSavedPasspointProviderBssidsInScanHistogram.clear();
+ mPnoScanMetrics.clear();
}
}
@@ -1826,7 +1894,7 @@
mLastPollRssi = -127;
mLastPollFreq = -1;
mLastPollLinkSpeed = -1;
- mStaEventList.add(staEvent);
+ mStaEventList.add(new StaEventWithTime(staEvent, mClock.getWallClockMillis()));
// Prune StaEventList if it gets too long
if (mStaEventList.size() > MAX_STA_EVENTS) mStaEventList.remove();
}
@@ -1903,7 +1971,7 @@
private static String supplicantStateChangesBitmaskToString(int mask) {
StringBuilder sb = new StringBuilder();
- sb.append("SUPPLICANT_STATE_CHANGE_EVENTS: {");
+ sb.append("supplicantStateChangeEvents: {");
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");
@@ -1928,58 +1996,56 @@
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:")
+ 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)
+ 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:");
+ sb.append("NETWORK_CONNECTION_EVENT");
break;
case StaEvent.TYPE_NETWORK_DISCONNECTION_EVENT:
- sb.append("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:");
+ sb.append("CMD_ASSOCIATED_BSSID");
break;
case StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL:
- sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL:");
+ sb.append("CMD_IP_CONFIGURATION_SUCCESSFUL");
break;
case StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST:
- sb.append("CMD_IP_CONFIGURATION_LOST:");
+ sb.append("CMD_IP_CONFIGURATION_LOST");
break;
case StaEvent.TYPE_CMD_IP_REACHABILITY_LOST:
- sb.append("CMD_IP_REACHABILITY_LOST:");
+ sb.append("CMD_IP_REACHABILITY_LOST");
break;
case StaEvent.TYPE_CMD_TARGET_BSSID:
- sb.append("CMD_TARGET_BSSID:");
+ sb.append("CMD_TARGET_BSSID");
break;
case StaEvent.TYPE_CMD_START_CONNECT:
- sb.append("CMD_START_CONNECT:");
+ sb.append("CMD_START_CONNECT");
break;
case StaEvent.TYPE_CMD_START_ROAM:
- sb.append("CMD_START_ROAM:");
+ sb.append("CMD_START_ROAM");
break;
case StaEvent.TYPE_CONNECT_NETWORK:
- sb.append("CONNECT_NETWORK:");
+ sb.append("CONNECT_NETWORK");
break;
case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
- sb.append("NETWORK_AGENT_VALID_NETWORK:");
+ sb.append("NETWORK_AGENT_VALID_NETWORK");
break;
case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
- sb.append("FRAMEWORK_DISCONNECT:")
+ sb.append("FRAMEWORK_DISCONNECT")
.append(" reason=")
.append(frameworkDisconnectReasonToString(event.frameworkDisconnectReason));
break;
@@ -1991,11 +2057,11 @@
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(
+ sb.append(", ").append(supplicantStateChangesBitmaskToString(
event.supplicantStateChangesBitmask));
}
if (event.configInfo != null) {
- sb.append("\n ").append(configInfoToString(event.configInfo));
+ sb.append(", ").append(configInfoToString(event.configInfo));
}
return sb.toString();
@@ -2053,7 +2119,7 @@
}
public static final int MAX_STA_EVENTS = 512;
- private LinkedList<StaEvent> mStaEventList = new LinkedList<StaEvent>();
+ private LinkedList<StaEventWithTime> mStaEventList = new LinkedList<StaEventWithTime>();
private int mLastPollRssi = -127;
private int mLastPollLinkSpeed = -1;
private int mLastPollFreq = -1;
@@ -2085,4 +2151,27 @@
int count = sia.get(element);
sia.put(element, count + 1);
}
+
+ private static class StaEventWithTime {
+ public StaEvent staEvent;
+ public long wallClockMillis;
+
+ StaEventWithTime(StaEvent event, long wallClockMillis) {
+ staEvent = event;
+ this.wallClockMillis = wallClockMillis;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(wallClockMillis);
+ if (wallClockMillis != 0) {
+ sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
+ } else {
+ sb.append(" ");
+ }
+ sb.append(" ").append(staEventToString(staEvent));
+ return sb.toString();
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 49be0e8..38c767f 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -1913,9 +1913,13 @@
public List<WifiConfiguration> syncGetConfiguredNetworks(int uuid, AsyncChannel channel) {
Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS, uuid);
- List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
- resultMsg.recycle();
- return result;
+ if (resultMsg == null) { // an error has occurred
+ return null;
+ } else {
+ List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
+ resultMsg.recycle();
+ return result;
+ }
}
public List<WifiConfiguration> syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) {
@@ -3482,14 +3486,14 @@
final WifiConfiguration config = getCurrentWifiConfiguration();
if (config != null) {
mWifiInfo.setEphemeral(config.ephemeral);
-
- // Set meteredHint if DHCP result says network is metered
- if (dhcpResults.hasMeteredHint()) {
- mWifiInfo.setMeteredHint(true);
- }
}
- updateCapabilities();
+ // Set meteredHint if DHCP result says network is metered
+ if (dhcpResults.hasMeteredHint()) {
+ mWifiInfo.setMeteredHint(true);
+ }
+
+ updateCapabilities(config);
}
private void handleSuccessfulIpConfiguration() {
@@ -3501,7 +3505,7 @@
WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
// Tell the framework whether the newly connected network is trusted or untrusted.
- updateCapabilities();
+ updateCapabilities(c);
}
if (c != null) {
ScanResult result = getCurrentScanResult();
@@ -5503,7 +5507,11 @@
}
}
- private void updateCapabilities() {
+ public void updateCapabilities() {
+ updateCapabilities(getCurrentWifiConfiguration());
+ }
+
+ private void updateCapabilities(WifiConfiguration config) {
final NetworkCapabilities result = new NetworkCapabilities(mDfltNetworkCapabilities);
if (mWifiInfo != null && !mWifiInfo.isEphemeral()) {
@@ -5512,7 +5520,7 @@
result.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
}
- if (mWifiInfo != null && !mWifiInfo.getMeteredHint()) {
+ if (mWifiInfo != null && !WifiConfiguration.isMetered(config, mWifiInfo)) {
result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
} else {
result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
@@ -5524,7 +5532,9 @@
result.setSignalStrength(NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED);
}
- mNetworkAgent.sendNetworkCapabilities(result);
+ if (mNetworkAgent != null) {
+ mNetworkAgent.sendNetworkCapabilities(result);
+ }
}
/**
@@ -6139,7 +6149,9 @@
if (mVerboseLoggingEnabled) {
log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected);
}
- mNetworkAgent.explicitlySelected(config.noInternetAccessExpected);
+ if (mNetworkAgent != null) {
+ mNetworkAgent.explicitlySelected(config.noInternetAccessExpected);
+ }
}
}
@@ -6511,13 +6523,17 @@
dstMac = NativeUtil.macAddressToByteArray(dstMacStr);
} catch (NullPointerException | IllegalArgumentException e) {
loge("Can't find MAC address for next hop to " + pkt.dstAddress);
- mNetworkAgent.onPacketKeepaliveEvent(slot,
- ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
+ if (mNetworkAgent != null) {
+ mNetworkAgent.onPacketKeepaliveEvent(slot,
+ ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS);
+ }
break;
}
pkt.dstMac = dstMac;
int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds);
- mNetworkAgent.onPacketKeepaliveEvent(slot, result);
+ if (mNetworkAgent != null) {
+ mNetworkAgent.onPacketKeepaliveEvent(slot, result);
+ }
break;
}
default:
diff --git a/service/java/com/android/server/wifi/WificondControl.java b/service/java/com/android/server/wifi/WificondControl.java
index 70ecabc..056777f 100644
--- a/service/java/com/android/server/wifi/WificondControl.java
+++ b/service/java/com/android/server/wifi/WificondControl.java
@@ -99,24 +99,25 @@
public void OnPnoNetworkFound() {
Log.d(TAG, "Pno scan result event");
mWifiMonitor.broadcastPnoScanResultEvent(mClientInterfaceName);
+ mWifiInjector.getWifiMetrics().incrementPnoFoundNetworkEventCount();
}
@Override
public void OnPnoScanFailed() {
Log.d(TAG, "Pno Scan failed event");
- // Nothing to do for now.
+ mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
}
@Override
public void OnPnoScanOverOffloadStarted() {
Log.d(TAG, "Pno scan over offload started");
- // Update metrics
+ mWifiInjector.getWifiMetrics().incrementPnoScanStartedOverOffloadCount();
}
@Override
public void OnPnoScanOverOffloadFailed(int reason) {
Log.d(TAG, "Pno scan over offload failed");
- // Update metrics
+ mWifiInjector.getWifiMetrics().incrementPnoScanFailedOverOffloadCount();
}
}
@@ -475,9 +476,14 @@
}
try {
- return mWificondScanner.startPnoScan(settings);
+ boolean success = mWificondScanner.startPnoScan(settings);
+ mWifiInjector.getWifiMetrics().incrementPnoScanStartAttempCount();
+ if (!success) {
+ mWifiInjector.getWifiMetrics().incrementPnoScanFailedCount();
+ }
+ return success;
} catch (RemoteException e1) {
- Log.e(TAG, "Failed to stop pno scan due to remote exception");
+ Log.e(TAG, "Failed to start pno scan due to remote exception");
}
return false;
}
diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
index ab2a5dc..4b8e284 100644
--- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java
@@ -2129,20 +2129,21 @@
pw.println();
pw.println("Latest scan results:");
List<ScanResult> scanResults = mSingleScanStateMachine.getCachedScanResultsAsList();
- long nowMs = System.currentTimeMillis();
+ long nowMs = mClock.getElapsedSinceBootMillis();
if (scanResults != null && scanResults.size() != 0) {
pw.println(" BSSID Frequency RSSI Age(sec) SSID "
+ " Flags");
for (ScanResult r : scanResults) {
+ long timeStampMs = r.timestamp / 1000;
String age;
- if (r.seen <= 0) {
+ if (timeStampMs <= 0) {
age = "___?___";
- } else if (nowMs < r.seen) {
+ } else if (nowMs < timeStampMs) {
age = " 0.000";
- } else if (r.seen < nowMs - 1000000) {
+ } else if (timeStampMs < nowMs - 1000000) {
age = ">1000.0";
} else {
- age = String.format("%3.3f", (nowMs - r.seen) / 1000.0);
+ age = String.format("%3.3f", (nowMs - timeStampMs) / 1000.0);
}
String ssid = r.SSID == null ? "" : r.SSID;
pw.printf(" %17s %9d %5d %7s %-32s %s\n",
diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
index 29c068d..957fc22 100644
--- a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
@@ -37,6 +37,7 @@
import android.os.UserManager;
import android.os.test.TestLooper;
import android.provider.Settings;
+import android.util.ArraySet;
import org.junit.Before;
import org.junit.Test;
@@ -47,6 +48,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Unit tests for {@link OpenNetworkNotifier}.
@@ -60,6 +62,8 @@
@Mock private Resources mResources;
@Mock private FrameworkFacade mFrameworkFacade;
@Mock private Clock mClock;
+ @Mock private WifiConfigStore mWifiConfigStore;
+ @Mock private WifiConfigManager mWifiConfigManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder;
@Mock private NotificationManager mNotificationManager;
@Mock private OpenNetworkRecommender mOpenNetworkRecommender;
@@ -67,6 +71,8 @@
private OpenNetworkNotifier mNotificationController;
private BroadcastReceiver mBroadcastReceiver;
private ScanResult mDummyNetwork;
+ private List<ScanDetail> mOpenNetworks;
+ private Set<String> mBlacklistedSsids;
/** Initialize objects before each test run. */
@@ -90,11 +96,14 @@
mDummyNetwork.capabilities = "[ESS]";
mDummyNetwork.level = MIN_RSSI_LEVEL;
when(mOpenNetworkRecommender.recommendNetwork(any(), any())).thenReturn(mDummyNetwork);
+ mOpenNetworks = new ArrayList<>();
+ mOpenNetworks.add(new ScanDetail(mDummyNetwork, null /* networkDetail */));
+ mBlacklistedSsids = new ArraySet<>();
TestLooper mock_looper = new TestLooper();
mNotificationController = new OpenNetworkNotifier(
- mContext, mock_looper.getLooper(), mFrameworkFacade,
- mClock, mOpenNetworkRecommender);
+ mContext, mock_looper.getLooper(), mFrameworkFacade, mClock, mWifiConfigManager,
+ mWifiConfigStore, mOpenNetworkRecommender);
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
@@ -102,20 +111,14 @@
mNotificationController.handleScreenStateChanged(true);
}
- private List<ScanDetail> createOpenScanResults() {
- List<ScanDetail> scanResults = new ArrayList<>();
- scanResults.add(new ScanDetail(mDummyNetwork, null /* networkDetail */));
- return scanResults;
- }
-
/**
* When scan results with open networks are handled, a notification is posted.
*/
@Test
public void handleScanResults_hasOpenNetworks_notificationDisplayed() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
}
@@ -136,9 +139,9 @@
*/
@Test
public void handleScanResults_notificationShown_emptyList_notificationCleared() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.handleScanResults(new ArrayList<>());
@@ -151,9 +154,9 @@
*/
@Test
public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.handleScreenStateChanged(false);
@@ -167,10 +170,10 @@
*/
@Test
public void handleScanResults_notificationShowing_doesNotRepostNotification() {
- mNotificationController.handleScanResults(createOpenScanResults());
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
}
@@ -180,9 +183,9 @@
*/
@Test
public void clearPendingNotification_clearsNotificationIfOneIsShowing() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.clearPendingNotification(true);
@@ -208,7 +211,7 @@
@Test
public void screenOff_handleScanResults_notificationNotDisplayed() {
mNotificationController.handleScreenStateChanged(false);
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
verify(mNotificationManager, never()).notify(anyInt(), any());
@@ -220,17 +223,18 @@
*/
@Test
public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.clearPendingNotification(false);
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
// Recommendation made twice but no new notification posted.
- verify(mOpenNetworkRecommender, times(2)).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
+ mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
verify(mNotificationManager).cancel(anyInt());
}
@@ -241,16 +245,17 @@
*/
@Test
public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.clearPendingNotification(true);
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender, times(2)).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
+ mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager, times(2)).notify(anyInt(), any());
}
@@ -259,9 +264,9 @@
*/
@Test
public void notificationTap_opensWifiSettings() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mBroadcastReceiver.onReceive(
@@ -271,14 +276,37 @@
}
/**
+ * When user dismissed notification and there is a recommended network, network ssid should be
+ * blacklisted.
+ */
+ @Test
+ public void userDismissedNotification_shouldBlacklistNetwork() {
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationManager).notify(anyInt(), any());
+
+ mBroadcastReceiver.onReceive(
+ mContext, new Intent(OpenNetworkNotifier.ACTION_USER_DISMISSED_NOTIFICATION));
+
+ verify(mWifiConfigManager).saveToStore(false /* forceWrite */);
+
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ Set<String> expectedBlacklist = new ArraySet<>();
+ expectedBlacklist.add(mDummyNetwork.SSID);
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, expectedBlacklist);
+ }
+
+ /**
* When a notification is posted and cleared without reseting delay, after the delay has passed
* the next scan with open networks should post a notification.
*/
@Test
public void delaySet_delayPassed_shouldPostNotification() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.clearPendingNotification(false);
@@ -286,9 +314,10 @@
// twice the delay time passed
when(mClock.getWallClockMillis()).thenReturn(DEFAULT_REPEAT_DELAY_SEC * 1000L * 2);
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender, times(2)).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
+ mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager, times(2)).notify(anyInt(), any());
}
@@ -298,7 +327,7 @@
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
.thenReturn(true);
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
verify(mNotificationManager, never()).notify(anyInt(), any());
@@ -307,15 +336,15 @@
/** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} clears the showing notification. */
@Test
public void userHasDisallowConfigWifiRestriction_showingNotificationIsCleared() {
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
verify(mNotificationManager).notify(anyInt(), any());
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
.thenReturn(true);
- mNotificationController.handleScanResults(createOpenScanResults());
+ mNotificationController.handleScanResults(mOpenNetworks);
verify(mNotificationManager).cancel(anyInt());
}
diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java
index becc1d2..720ec37 100644
--- a/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java
@@ -17,14 +17,18 @@
package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import android.net.wifi.ScanResult;
+import android.util.ArraySet;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Tests for {@link OpenNetworkRecommender}.
@@ -36,10 +40,13 @@
private static final int MIN_RSSI_LEVEL = -127;
private OpenNetworkRecommender mOpenNetworkRecommender;
+ private Set<String> mBlacklistedSsids;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mOpenNetworkRecommender = new OpenNetworkRecommender();
+ mBlacklistedSsids = new ArraySet<>();
}
private List<ScanDetail> createOpenScanResults(String... ssids) {
@@ -59,7 +66,8 @@
List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1);
scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL;
- ScanResult actual = mOpenNetworkRecommender.recommendNetwork(scanResults, null);
+ ScanResult actual = mOpenNetworkRecommender.recommendNetwork(
+ scanResults, mBlacklistedSsids);
ScanResult expected = scanResults.get(0).getScanResult();
assertEquals(expected, actual);
}
@@ -71,28 +79,24 @@
scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL;
scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL + 1;
- ScanResult actual = mOpenNetworkRecommender.recommendNetwork(scanResults, null);
+ ScanResult actual = mOpenNetworkRecommender.recommendNetwork(
+ scanResults, mBlacklistedSsids);
ScanResult expected = scanResults.get(1).getScanResult();
assertEquals(expected, actual);
}
/**
- * If the current recommended network is present in the list for the next recommendation and has
- * an equal RSSI, the recommendation should not change.
+ * If the best available open network is blacklisted, no networks should be recommended.
*/
@Test
- public void currentRecommendationHasEquallyHighRssi_shouldNotChangeRecommendation() {
+ public void blacklistBestNetworkSsid_shouldNeverRecommendNetwork() {
List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1, TEST_SSID_2);
scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL + 1;
- scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL + 1;
+ scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL;
+ mBlacklistedSsids.add(TEST_SSID_1);
- ScanResult currentRecommendation = new ScanResult(scanResults.get(1).getScanResult());
- // next recommendation does not depend on the rssi of the input recommendation.
- currentRecommendation.level = MIN_RSSI_LEVEL;
-
- ScanResult expected = scanResults.get(1).getScanResult();
ScanResult actual = mOpenNetworkRecommender.recommendNetwork(
- scanResults, currentRecommendation);
- assertEquals(expected, actual);
+ scanResults, mBlacklistedSsids);
+ assertNull(actual);
}
}
diff --git a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java
new file mode 100644
index 0000000..606b825
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.SsidSetStoreData}.
+ */
+public class SsidSetStoreDataTest {
+ private static final String TEST_NOTIFIER_NAME = "TestNetwork";
+ private static final String TEST_SSID1 = "SSID 1";
+ private static final String TEST_SSID2 = "SSID 2";
+ private static final String TEST_SSID_SET_XML_STRING =
+ "<set name=\"SSIDSet\">\n"
+ + "<string>" + TEST_SSID1 + "</string>\n"
+ + "<string>" + TEST_SSID2 + "</string>\n"
+ + "</set>\n";
+ private static final byte[] TEST_SSID_SET_XML_BYTES =
+ TEST_SSID_SET_XML_STRING.getBytes(StandardCharsets.UTF_8);
+
+ @Mock SsidSetStoreData.DataSource mDataSource;
+ SsidSetStoreData mSsidSetStoreData;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mSsidSetStoreData = new SsidSetStoreData(TEST_NOTIFIER_NAME, mDataSource);
+ }
+
+ /**
+ * Helper function for serializing configuration data to a XML block.
+ *
+ * @param shared Flag indicating serializing shared or user configurations
+ * @return byte[] of the XML data
+ * @throws Exception
+ */
+ private byte[] serializeData(boolean shared) throws Exception {
+ final XmlSerializer out = new FastXmlSerializer();
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+ mSsidSetStoreData.serializeData(out, shared);
+ out.flush();
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Helper function for parsing configuration data from a XML block.
+ *
+ * @param data XML data to parse from
+ * @param shared Flag indicating parsing of shared or user configurations
+ * @throws Exception
+ */
+ private void deserializeData(byte[] data, boolean shared) throws Exception {
+ final XmlPullParser in = Xml.newPullParser();
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+ in.setInput(inputStream, StandardCharsets.UTF_8.name());
+ mSsidSetStoreData.deserializeData(in, in.getDepth(), shared);
+ }
+
+ /**
+ * Verify that a XmlPullParserException will be thrown when attempting to serialize data
+ * to the share store.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void serializeShareData() throws Exception {
+ serializeData(true /* shared */);
+ }
+
+ /**
+ * Verify that a XmlPullParserException will be thrown when attempting to deserialize
+ * data from the share store.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void deserializeShareData() throws Exception {
+ deserializeData(new byte[0], true /* shared */);
+ }
+
+ /**
+ * Verify that serializing the user store data without any configuration doesn't cause any
+ * crash and no data should be serialized.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeEmptyConfigs() throws Exception {
+ when(mDataSource.getSsids()).thenReturn(new HashSet<String>());
+ assertEquals(0, serializeData(false /* shared */).length);
+ }
+
+ /**
+ * Verify that parsing an empty data doesn't cause any crash and no configuration should
+ * be deserialized.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void deserializeEmptyStoreData() throws Exception {
+ deserializeData(new byte[0], false /* shared */);
+ verify(mDataSource, never()).setSsids(any(Set.class));
+ }
+
+ /**
+ * Verify that {@link SsidSetStoreData} does not support share data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void supportShareData() throws Exception {
+ assertFalse(mSsidSetStoreData.supportShareData());
+ }
+
+ /**
+ * Verify that the store data is serialized correctly, matches the predefined test XML data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeSsidSet() throws Exception {
+ Set<String> ssidSet = new HashSet<>();
+ ssidSet.add(TEST_SSID1);
+ ssidSet.add(TEST_SSID2);
+ when(mDataSource.getSsids()).thenReturn(ssidSet);
+ byte[] actualData = serializeData(false /* shared */);
+ assertTrue(Arrays.equals(TEST_SSID_SET_XML_BYTES, actualData));
+ }
+
+ /**
+ * Verify that the store data is deserialized correctly using the predefined test XML data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void deserializeSsidSet() throws Exception {
+ Set<String> ssidSet = new HashSet<>();
+ ssidSet.add(TEST_SSID1);
+ ssidSet.add(TEST_SSID2);
+ deserializeData(TEST_SSID_SET_XML_BYTES, false /* shared */);
+ verify(mDataSource).setSsids(eq(ssidSet));
+ }
+
+ /**
+ * Verify that a XmlPullParserException will be thrown when parsing a SSIDSet set with an
+ * unknown tag.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void parseSetWithUnknownTag() throws Exception {
+ String ssidSet =
+ "<set name=\"SSIDSet\">\n"
+ + "<string>" + TEST_SSID1 + "</string>\n"
+ + "<string>" + TEST_SSID2 + "</string>\n"
+ + "<Unknown>" + "badInput" + "</Unknown>" // Unknown tag.
+ + "</set>\n";
+ deserializeData(ssidSet.getBytes(StandardCharsets.UTF_8), false /* shared */);
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 5a13928..10ad3c6 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -16,6 +16,7 @@
package com.android.server.wifi;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
@@ -37,6 +38,7 @@
import com.android.server.wifi.hotspot2.PasspointMatch;
import com.android.server.wifi.hotspot2.PasspointProvider;
import com.android.server.wifi.nano.WifiMetricsProto;
+import com.android.server.wifi.nano.WifiMetricsProto.PnoScanMetrics;
import com.android.server.wifi.nano.WifiMetricsProto.StaEvent;
import org.junit.Before;
@@ -252,6 +254,11 @@
private static final int NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS = 2;
private static final int NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED = 1;
private static final int NUM_PARTIAL_SCAN_RESULTS = 73;
+ private static final int NUM_PNO_SCAN_ATTEMPTS = 20;
+ private static final int NUM_PNO_SCAN_FAILED = 5;
+ private static final int NUM_PNO_SCAN_STARTED_OVER_OFFLOAD = 17;
+ private static final int NUM_PNO_SCAN_FAILED_OVER_OFFLOAD = 8;
+ private static final int NUM_PNO_FOUND_NETWORK_EVENTS = 10;
private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
String capabilities) {
@@ -474,6 +481,23 @@
for (int i = 0; i < NUM_PASSPOINT_PROVIDER_UNINSTALL_SUCCESS; i++) {
mWifiMetrics.incrementNumPasspointProviderUninstallSuccess();
}
+
+ // increment pno scan metrics
+ for (int i = 0; i < NUM_PNO_SCAN_ATTEMPTS; i++) {
+ mWifiMetrics.incrementPnoScanStartAttempCount();
+ }
+ for (int i = 0; i < NUM_PNO_SCAN_FAILED; i++) {
+ mWifiMetrics.incrementPnoScanFailedCount();
+ }
+ for (int i = 0; i < NUM_PNO_SCAN_STARTED_OVER_OFFLOAD; i++) {
+ mWifiMetrics.incrementPnoScanStartedOverOffloadCount();
+ }
+ for (int i = 0; i < NUM_PNO_SCAN_FAILED_OVER_OFFLOAD; i++) {
+ mWifiMetrics.incrementPnoScanFailedOverOffloadCount();
+ }
+ for (int i = 0; i < NUM_PNO_FOUND_NETWORK_EVENTS; i++) {
+ mWifiMetrics.incrementPnoFoundNetworkEventCount();
+ }
}
/**
@@ -618,6 +642,14 @@
mDecodedProto.numPasspointProviderUninstallSuccess);
assertEquals(NUM_PASSPOINT_PROVIDERS_SUCCESSFULLY_CONNECTED,
mDecodedProto.numPasspointProvidersSuccessfullyConnected);
+
+ PnoScanMetrics pno_metrics = mDecodedProto.pnoScanMetrics;
+ assertNotNull(pno_metrics);
+ assertEquals(NUM_PNO_SCAN_ATTEMPTS, pno_metrics.numPnoScanAttempts);
+ assertEquals(NUM_PNO_SCAN_FAILED, pno_metrics.numPnoScanFailed);
+ assertEquals(NUM_PNO_SCAN_STARTED_OVER_OFFLOAD, pno_metrics.numPnoScanStartedOverOffload);
+ assertEquals(NUM_PNO_SCAN_FAILED_OVER_OFFLOAD, pno_metrics.numPnoScanFailedOverOffload);
+ assertEquals(NUM_PNO_FOUND_NETWORK_EVENTS, pno_metrics.numPnoFoundNetworkEvents);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java
index 24d3afa..6f01c8e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java
@@ -48,6 +48,18 @@
private static final int CELLULAR_THRESHOLD_SCORE = 50;
+ class FakeClock extends Clock {
+ long mWallClockMillis = 1500000000000L;
+ int mStepMillis = 1001;
+
+ @Override
+ public long getWallClockMillis() {
+ mWallClockMillis += mStepMillis;
+ return mWallClockMillis;
+ }
+ }
+
+ FakeClock mClock;
WifiConfiguration mWifiConfiguration;
WifiScoreReport mWifiScoreReport;
ScanDetailCache mScanDetailCache;
@@ -122,7 +134,8 @@
when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt()))
.thenReturn(mScanDetailCache);
when(mContext.getResources()).thenReturn(mResources);
- mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager, new Clock());
+ mClock = new FakeClock();
+ mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager, mClock);
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java b/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java
index 164f759..cca2045 100644
--- a/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WificondControlTest.java
@@ -66,6 +66,7 @@
public class WificondControlTest {
private WifiInjector mWifiInjector;
private WifiMonitor mWifiMonitor;
+ private WifiMetrics mWifiMetrics;
private CarrierNetworkConfig mCarrierNetworkConfig;
private WificondControl mWificondControl;
private static final String TEST_INTERFACE_NAME = "test_wlan_if";
@@ -145,6 +146,8 @@
public void setUp() throws Exception {
mWifiInjector = mock(WifiInjector.class);
mWifiMonitor = mock(WifiMonitor.class);
+ mWifiMetrics = mock(WifiMetrics.class);
+ when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
mCarrierNetworkConfig = mock(CarrierNetworkConfig.class);
mWificondControl = new WificondControl(mWifiInjector, mWifiMonitor, mCarrierNetworkConfig);
}
@@ -660,7 +663,7 @@
/**
* Verifies that WificondControl can invoke WifiMonitor broadcast methods upon pno scan
- * reuslt event.
+ * result event.
*/
@Test
public void testPnoScanResultEvent() throws Exception {
@@ -671,11 +674,48 @@
IPnoScanEvent pnoScanEvent = messageCaptor.getValue();
assertNotNull(pnoScanEvent);
pnoScanEvent.OnPnoNetworkFound();
-
verify(mWifiMonitor).broadcastPnoScanResultEvent(any(String.class));
}
/**
+ * Verifies that WificondControl can invoke WifiMetrics pno scan count methods upon pno event.
+ */
+ @Test
+ public void testPnoScanEventsForMetrics() throws Exception {
+ IWifiScannerImpl scanner = setupClientInterfaceAndCreateMockWificondScanner();
+
+ ArgumentCaptor<IPnoScanEvent> messageCaptor = ArgumentCaptor.forClass(IPnoScanEvent.class);
+ verify(scanner).subscribePnoScanEvents(messageCaptor.capture());
+ IPnoScanEvent pnoScanEvent = messageCaptor.getValue();
+ assertNotNull(pnoScanEvent);
+
+ pnoScanEvent.OnPnoNetworkFound();
+ verify(mWifiMetrics).incrementPnoFoundNetworkEventCount();
+
+ pnoScanEvent.OnPnoScanFailed();
+ verify(mWifiMetrics).incrementPnoScanFailedCount();
+
+ pnoScanEvent.OnPnoScanOverOffloadStarted();
+ verify(mWifiMetrics).incrementPnoScanStartedOverOffloadCount();
+
+ pnoScanEvent.OnPnoScanOverOffloadFailed(0);
+ verify(mWifiMetrics).incrementPnoScanFailedOverOffloadCount();
+ }
+
+ /**
+ * Verifies that startPnoScan() can invoke WifiMetrics pno scan count methods correctly.
+ */
+ @Test
+ public void testStartPnoScanForMetrics() throws Exception {
+ IWifiScannerImpl scanner = setupClientInterfaceAndCreateMockWificondScanner();
+
+ when(scanner.startPnoScan(any(PnoSettings.class))).thenReturn(false);
+ assertFalse(mWificondControl.startPnoScan(TEST_PNO_SETTINGS));
+ verify(mWifiMetrics).incrementPnoScanStartAttempCount();
+ verify(mWifiMetrics).incrementPnoScanFailedCount();
+ }
+
+ /**
* Verifies that abortScan() calls underlying wificond.
*/
@Test