summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Chen <stewchen@google.com>2017-08-08 17:55:21 -0700
committerStephen Chen <stewchen@google.com>2017-09-05 11:40:23 -0700
commitb280c399d7be7d04a245c5fc2d2897f0ddc9cc0a (patch)
tree7af445cadaed0b7bd6bfbb3584c18011d6534456
parent69fa2e7fa12b8f4c24a27b3291a0744cd808a324 (diff)
downloadwifi-b280c399d7be7d04a245c5fc2d2897f0ddc9cc0a.tar.gz
ONA: Implement SSID blacklist handling for dismissed networks.
When ONA notifications are dismissed by the user, the recommended network ssid is permanently blacklisted. This change also removes the use of currentRecommendation in the recommendation logic, because the extra stickiness is not neccesary due to the slow scan rate that triggers a recommendation update. Bug: 64091575 Bug: 37357441 Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: I27fc667ae51f9dbc4665ba9d15b18ed3e6daa058
-rw-r--r--service/java/com/android/server/wifi/OpenNetworkNotifier.java43
-rw-r--r--service/java/com/android/server/wifi/OpenNetworkRecommender.java24
-rw-r--r--service/java/com/android/server/wifi/SsidSetStoreData.java131
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java2
-rw-r--r--tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java105
-rw-r--r--tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java30
-rw-r--r--tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java202
7 files changed, 469 insertions, 68 deletions
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
index fc144c139..692c8e22c 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.Looper;
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 com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
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 @@ public class OpenNetworkNotifier {
/** 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 @@ public class OpenNetworkNotifier {
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 @@ public class OpenNetworkNotifier {
}
mRecommendedNetwork = mOpenNetworkRecommender.recommendNetwork(
- availableNetworks, mRecommendedNetwork);
+ availableNetworks, new ArraySet<>(mBlacklistedSsids));
postNotification(availableNetworks.size());
}
@@ -201,8 +221,14 @@ public class OpenNetworkNotifier {
.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 @@ public class OpenNetworkNotifier {
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 cd460e58b..5ceeddded 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.annotation.NonNull;
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 @@ public class OpenNetworkRecommender {
*
* @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 000000000..daed26a6a
--- /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/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 60c5d2fb9..26d702477 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -233,7 +233,7 @@ public class WifiInjector {
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/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
index 29c068ddc..957fc2294 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.UserHandle;
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 org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Unit tests for {@link OpenNetworkNotifier}.
@@ -60,6 +62,8 @@ public class OpenNetworkNotifierTest {
@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 @@ public class OpenNetworkNotifierTest {
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 @@ public class OpenNetworkNotifierTest {
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 @@ public class OpenNetworkNotifierTest {
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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
@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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
*/
@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 @@ public class OpenNetworkNotifierTest {
}
/**
+ * 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 @@ public class OpenNetworkNotifierTest {
// 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 @@ public class OpenNetworkNotifierTest {
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 @@ public class OpenNetworkNotifierTest {
/** 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 becc1d2e8..720ec3797 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 @@ public class OpenNetworkRecommenderTest {
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 @@ public class OpenNetworkRecommenderTest {
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 @@ public class OpenNetworkRecommenderTest {
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 000000000..606b825ee
--- /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 */);
+ }
+}