summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-09-12 18:15:20 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-09-12 18:15:20 +0000
commit9ab1287775ac494293536c5954a49e668a6692cf (patch)
tree0618c4c1fc1d262b2638210df87732f57e662953
parentdd4b6e78d31c5bd73ec03cb01ff1579f1b054b63 (diff)
parentb94b47e8de99697600f79623d127e3d19e753106 (diff)
downloadandroid_frameworks_opt_net_wifi-9ab1287775ac494293536c5954a49e668a6692cf.tar.gz
android_frameworks_opt_net_wifi-9ab1287775ac494293536c5954a49e668a6692cf.tar.bz2
android_frameworks_opt_net_wifi-9ab1287775ac494293536c5954a49e668a6692cf.zip
release-request-dabd8cf7-7af2-48e9-a296-ccc6a71cc25d-for-git_oc-m2-release-4328410 snap-temp-L55300000101694322
Change-Id: I94462bad2c91443b518b27fbda53d23a057ed388
-rw-r--r--service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java146
-rw-r--r--service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java91
-rw-r--r--service/java/com/android/server/wifi/OpenNetworkNotifier.java257
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java50
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStoreLegacy.java354
-rw-r--r--service/java/com/android/server/wifi/WifiConnectivityManager.java13
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java13
-rw-r--r--service/java/com/android/server/wifi/WifiNetworkHistory.java630
-rw-r--r--service/java/com/android/server/wifi/WifiStateMachine.java9
-rw-r--r--service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfigParser.java513
-rw-r--r--tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java279
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java76
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigStoreLegacyTest.java273
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java49
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/LegacyPasspointConfigParserTest.java204
15 files changed, 657 insertions, 2300 deletions
diff --git a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
new file mode 100644
index 000000000..38c0ad058
--- /dev/null
+++ b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
@@ -0,0 +1,146 @@
+/*
+ * 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.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.wifi.ScanResult;
+
+import com.android.internal.R;
+import com.android.internal.notification.SystemNotificationChannels;
+
+/**
+ * Helper to create notifications for {@link OpenNetworkNotifier}.
+ */
+public class ConnectToNetworkNotificationBuilder {
+
+ /** Intent when user dismissed the "Connect to Network" notification. */
+ public static final String ACTION_USER_DISMISSED_NOTIFICATION =
+ "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION";
+
+ /** Intent when user tapped action button to connect to recommended network. */
+ public static final String ACTION_CONNECT_TO_NETWORK =
+ "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK";
+
+ /** Intent when user tapped action button to open Wi-Fi Settings. */
+ public static final String ACTION_PICK_WIFI_NETWORK =
+ "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK";
+
+ /** Intent when user tapped "Failed to connect" notification to open Wi-Fi Settings. */
+ public static final String ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE =
+ "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE";
+
+ private Context mContext;
+ private Resources mResources;
+ private FrameworkFacade mFrameworkFacade;
+
+ public ConnectToNetworkNotificationBuilder(
+ Context context,
+ FrameworkFacade framework) {
+ mContext = context;
+ mResources = context.getResources();
+ mFrameworkFacade = framework;
+ }
+
+ /**
+ * Creates the connect to network notification that alerts users of a recommended connectable
+ * network.
+ *
+ * There are two actions - "Options" link to the Wi-Fi picker activity, and "Connect" prompts
+ * the connection to the recommended network.
+ *
+ * @param network The network to be recommended
+ */
+ public Notification createConnectToNetworkNotification(ScanResult network) {
+ Notification.Action connectAction = new Notification.Action.Builder(
+ null /* icon */,
+ mResources.getText(R.string.wifi_available_action_connect),
+ getPrivateBroadcast(ACTION_CONNECT_TO_NETWORK)).build();
+ Notification.Action allNetworksAction = new Notification.Action.Builder(
+ null /* icon */,
+ mResources.getText(R.string.wifi_available_action_all_networks),
+ getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK)).build();
+ return createNotificationBuilder(
+ mContext.getText(R.string.wifi_available_title), network.SSID)
+ .addAction(connectAction)
+ .addAction(allNetworksAction)
+ .build();
+ }
+
+ /**
+ * Creates the notification that indicates the controller is attempting to connect to the
+ * recommended network.
+ *
+ * @param network The network to be recommended
+ */
+ public Notification createNetworkConnectingNotification(ScanResult network) {
+ return createNotificationBuilder(
+ mContext.getText(R.string.wifi_available_title_connecting), network.SSID)
+ .setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */)
+ .build();
+ }
+
+ /**
+ * Creates the notification that indicates the controller successfully connected to the
+ * recommended network.
+ *
+ * @param network The network to be recommended
+ */
+ public Notification createNetworkConnectedNotification(ScanResult network) {
+ return createNotificationBuilder(
+ mContext.getText(R.string.wifi_available_title_connected), network.SSID)
+ .build();
+ }
+
+ /**
+ * Creates the notification that indicates the controller failed to connect to the recommended
+ * network. Tapping this notification opens the wifi picker.
+ */
+ public Notification createNetworkFailedNotification() {
+ return createNotificationBuilder(
+ mContext.getText(R.string.wifi_available_title_failed_to_connect),
+ mContext.getText(R.string.wifi_available_content_failed_to_connect))
+ .setContentIntent(
+ getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE))
+ .setAutoCancel(true)
+ .build();
+ }
+
+ private Notification.Builder createNotificationBuilder(
+ CharSequence title, CharSequence content) {
+ return mFrameworkFacade.makeNotificationBuilder(mContext,
+ SystemNotificationChannels.NETWORK_AVAILABLE)
+ .setSmallIcon(R.drawable.stat_notify_wifi_in_range)
+ .setTicker(title)
+ .setContentTitle(title)
+ .setContentText(content)
+ .setDeleteIntent(getPrivateBroadcast(ACTION_USER_DISMISSED_NOTIFICATION))
+ .setShowWhen(false)
+ .setLocalOnly(true)
+ .setColor(mResources.getColor(R.color.system_notification_accent_color,
+ mContext.getTheme()));
+ }
+
+ private PendingIntent getPrivateBroadcast(String action) {
+ Intent intent = new Intent(action).setPackage("android");
+ return mFrameworkFacade.getBroadcast(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+}
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java b/service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java
deleted file mode 100644
index 5963b57a3..000000000
--- a/service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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 com.android.server.wifi.OpenNetworkNotifier.ACTION_USER_DISMISSED_NOTIFICATION;
-import static com.android.server.wifi.OpenNetworkNotifier.ACTION_USER_TAPPED_CONTENT;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-
-import com.android.internal.R;
-import com.android.internal.notification.SystemNotificationChannels;
-
-/**
- * Helper to create notifications for {@link OpenNetworkNotifier}.
- */
-public class OpenNetworkNotificationBuilder {
-
- private Context mContext;
- private Resources mResources;
- private FrameworkFacade mFrameworkFacade;
-
- public OpenNetworkNotificationBuilder(
- Context context,
- FrameworkFacade framework) {
- mContext = context;
- mResources = context.getResources();
- mFrameworkFacade = framework;
- }
-
- /**
- * Creates the open network available notification that alerts users there are open networks
- * nearby.
- */
- public Notification createOpenNetworkAvailableNotification(int numNetworks) {
-
- CharSequence title = mResources.getQuantityText(
- com.android.internal.R.plurals.wifi_available, numNetworks);
- CharSequence content = mResources.getQuantityText(
- com.android.internal.R.plurals.wifi_available_detailed, numNetworks);
-
- PendingIntent contentIntent =
- mFrameworkFacade.getBroadcast(
- mContext,
- 0,
- new Intent(ACTION_USER_TAPPED_CONTENT),
- PendingIntent.FLAG_UPDATE_CURRENT);
- return createNotificationBuilder(title, content)
- .setContentIntent(contentIntent)
- .build();
- }
-
- private Notification.Builder createNotificationBuilder(
- CharSequence title, CharSequence content) {
- PendingIntent deleteIntent =
- mFrameworkFacade.getBroadcast(
- mContext,
- 0,
- new Intent(ACTION_USER_DISMISSED_NOTIFICATION),
- PendingIntent.FLAG_UPDATE_CURRENT);
- return mFrameworkFacade.makeNotificationBuilder(mContext,
- SystemNotificationChannels.NETWORK_AVAILABLE)
- .setSmallIcon(R.drawable.stat_notify_wifi_in_range)
- .setAutoCancel(true)
- .setTicker(title)
- .setContentTitle(title)
- .setContentText(content)
- .setDeleteIntent(deleteIntent)
- .setShowWhen(false)
- .setLocalOnly(true)
- .setColor(mResources.getColor(R.color.system_notification_accent_color,
- mContext.getTheme()));
- }
-}
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotifier.java b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
index 692c8e22c..31ff44b72 100644
--- a/service/java/com/android/server/wifi/OpenNetworkNotifier.java
+++ b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
@@ -16,7 +16,14 @@
package com.android.server.wifi;
+import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK;
+import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK;
+import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE;
+import static com.android.server.wifi.ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION;
+
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -24,8 +31,12 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -34,9 +45,12 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.server.wifi.util.ScanResultUtil;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Set;
@@ -50,10 +64,39 @@ 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";
+ /** Time in milliseconds to display the Connecting notification. */
+ private static final int TIME_TO_SHOW_CONNECTING_MILLIS = 10000;
+
+ /** Time in milliseconds to display the Connected notification. */
+ private static final int TIME_TO_SHOW_CONNECTED_MILLIS = 5000;
+
+ /** Time in milliseconds to display the Failed To Connect notification. */
+ private static final int TIME_TO_SHOW_FAILED_MILLIS = 5000;
+
+ /** The state of the notification */
+ @IntDef({
+ STATE_NO_NOTIFICATION,
+ STATE_SHOWING_RECOMMENDATION_NOTIFICATION,
+ STATE_CONNECTING_IN_NOTIFICATION,
+ STATE_CONNECTED_NOTIFICATION,
+ STATE_CONNECT_FAILED_NOTIFICATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface State {}
+
+ /** No recommendation is made and no notifications are shown. */
+ private static final int STATE_NO_NOTIFICATION = 0;
+ /** The initial notification recommending an open network to connect to is shown. */
+ private static final int STATE_SHOWING_RECOMMENDATION_NOTIFICATION = 1;
+ /** The notification of status of connecting to the recommended network is shown. */
+ private static final int STATE_CONNECTING_IN_NOTIFICATION = 2;
+ /** The notification that the connection to the recommended network was successful is shown. */
+ private static final int STATE_CONNECTED_NOTIFICATION = 3;
+ /** The notification to show that connection to the recommended network failed is shown. */
+ private static final int STATE_CONNECT_FAILED_NOTIFICATION = 4;
+
+ /** Current state of the notification. */
+ @State private int mState = STATE_NO_NOTIFICATION;
/** Identifier of the {@link SsidSetStoreData}. */
private static final String STORE_DATA_IDENTIFIER = "OpenNetworkNotifierBlacklist";
@@ -72,8 +115,6 @@ public class OpenNetworkNotifier {
/** Whether the user has set the setting to show the 'available networks' notification. */
private boolean mSettingEnabled;
- /** Whether the notification is being shown. */
- private boolean mNotificationShown;
/** Whether the screen is on or not. */
private boolean mScreenOn;
@@ -85,8 +126,10 @@ public class OpenNetworkNotifier {
private final FrameworkFacade mFrameworkFacade;
private final Clock mClock;
private final WifiConfigManager mConfigManager;
+ private final WifiStateMachine mWifiStateMachine;
+ private final Messenger mSrcMessenger;
private final OpenNetworkRecommender mOpenNetworkRecommender;
- private final OpenNetworkNotificationBuilder mOpenNetworkNotificationBuilder;
+ private final ConnectToNetworkNotificationBuilder mNotificationBuilder;
private ScanResult mRecommendedNetwork;
@@ -97,15 +140,19 @@ public class OpenNetworkNotifier {
Clock clock,
WifiConfigManager wifiConfigManager,
WifiConfigStore wifiConfigStore,
- OpenNetworkRecommender openNetworkRecommender) {
+ WifiStateMachine wifiStateMachine,
+ OpenNetworkRecommender openNetworkRecommender,
+ ConnectToNetworkNotificationBuilder connectToNetworkNotificationBuilder) {
mContext = context;
mHandler = new Handler(looper);
mFrameworkFacade = framework;
mClock = clock;
mConfigManager = wifiConfigManager;
+ mWifiStateMachine = wifiStateMachine;
mOpenNetworkRecommender = openNetworkRecommender;
- mOpenNetworkNotificationBuilder = new OpenNetworkNotificationBuilder(context, framework);
+ mNotificationBuilder = connectToNetworkNotificationBuilder;
mScreenOn = false;
+ mSrcMessenger = new Messenger(new Handler(looper, mConnectionStateCallback));
mBlacklistedSsids = new ArraySet<>();
wifiConfigStore.registerStoreData(new SsidSetStoreData(
@@ -121,7 +168,9 @@ public class OpenNetworkNotifier {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USER_DISMISSED_NOTIFICATION);
- filter.addAction(ACTION_USER_TAPPED_CONTENT);
+ filter.addAction(ACTION_CONNECT_TO_NETWORK);
+ filter.addAction(ACTION_PICK_WIFI_NETWORK);
+ filter.addAction(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE);
mContext.registerReceiver(
mBroadcastReceiver, filter, null /* broadcastPermission */, mHandler);
}
@@ -130,28 +179,55 @@ public class OpenNetworkNotifier {
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (ACTION_USER_TAPPED_CONTENT.equals(intent.getAction())) {
- handleUserClickedContentAction();
- } else if (ACTION_USER_DISMISSED_NOTIFICATION.equals(intent.getAction())) {
- handleUserDismissedAction();
+ switch (intent.getAction()) {
+ case ACTION_USER_DISMISSED_NOTIFICATION:
+ handleUserDismissedAction();
+ break;
+ case ACTION_CONNECT_TO_NETWORK:
+ handleConnectToNetworkAction();
+ break;
+ case ACTION_PICK_WIFI_NETWORK:
+ handleSeeAllNetworksAction();
+ break;
+ case ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE:
+ handlePickWifiNetworkAfterConnectFailure();
+ break;
+ default:
+ Log.e(TAG, "Unknown action " + intent.getAction());
}
}
};
+ private final Handler.Callback mConnectionStateCallback = (Message msg) -> {
+ switch (msg.what) {
+ // Success here means that an attempt to connect to the network has been initiated.
+ // Successful connection updates are received via the
+ // WifiConnectivityManager#handleConnectionStateChanged() callback.
+ case WifiManager.CONNECT_NETWORK_SUCCEEDED:
+ break;
+ case WifiManager.CONNECT_NETWORK_FAILED:
+ handleConnectionFailure();
+ break;
+ default:
+ Log.e(TAG, "Unknown message " + msg.what);
+ }
+ return true;
+ };
+
/**
* Clears the pending notification. This is called by {@link WifiConnectivityManager} on stop.
*
- * @param resetRepeatDelay resets the time delay for repeated notification if true.
+ * @param resetRepeatTime resets the time delay for repeated notification if true.
*/
- public void clearPendingNotification(boolean resetRepeatDelay) {
- if (resetRepeatDelay) {
+ public void clearPendingNotification(boolean resetRepeatTime) {
+ if (resetRepeatTime) {
mNotificationRepeatTime = 0;
}
- if (mNotificationShown) {
+ if (mState != STATE_NO_NOTIFICATION) {
getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_AVAILABLE);
+ mState = STATE_NO_NOTIFICATION;
mRecommendedNetwork = null;
- mNotificationShown = false;
}
}
@@ -168,26 +244,37 @@ public class OpenNetworkNotifier {
*/
public void handleScanResults(@NonNull List<ScanDetail> availableNetworks) {
if (!isControllerEnabled()) {
- clearPendingNotification(true /* resetRepeatDelay */);
+ clearPendingNotification(true /* resetRepeatTime */);
return;
}
if (availableNetworks.isEmpty()) {
- clearPendingNotification(false /* resetRepeatDelay */);
+ clearPendingNotification(false /* resetRepeatTime */);
return;
}
- // Do not show or update the notification if screen is off. We want to avoid a race that
- // could occur between a user picking a network in settings and a network candidate picked
- // through network selection, which will happen because screen on triggers a new
- // connectivity scan.
- if (mNotificationShown || !mScreenOn) {
+ // Not enough time has passed to show a recommendation notification again
+ if (mState == STATE_NO_NOTIFICATION
+ && mClock.getWallClockMillis() < mNotificationRepeatTime) {
return;
}
- mRecommendedNetwork = mOpenNetworkRecommender.recommendNetwork(
- availableNetworks, new ArraySet<>(mBlacklistedSsids));
+ // Do nothing when the screen is off and no notification is showing.
+ if (mState == STATE_NO_NOTIFICATION && !mScreenOn) {
+ return;
+ }
- postNotification(availableNetworks.size());
+ // Only show a new or update an existing recommendation notification.
+ if (mState == STATE_NO_NOTIFICATION
+ || mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) {
+ ScanResult recommendation = mOpenNetworkRecommender.recommendNetwork(
+ availableNetworks, new ArraySet<>(mBlacklistedSsids));
+
+ if (recommendation != null) {
+ postInitialNotification(recommendation);
+ } else {
+ clearPendingNotification(false /* resetRepeatTime */);
+ }
+ }
}
/** Handles screen state changes. */
@@ -195,41 +282,121 @@ public class OpenNetworkNotifier {
mScreenOn = screenOn;
}
+ /**
+ * Called by {@link WifiConnectivityManager} when Wi-Fi is connected. If the notification
+ * was in the connecting state, update the notification to show that it has connected to the
+ * recommended network.
+ */
+ public void handleWifiConnected() {
+ if (mState != STATE_CONNECTING_IN_NOTIFICATION) {
+ clearPendingNotification(true /* resetRepeatTime */);
+ return;
+ }
+
+ postNotification(mNotificationBuilder.createNetworkConnectedNotification(
+ mRecommendedNetwork));
+ mState = STATE_CONNECTED_NOTIFICATION;
+ mHandler.postDelayed(
+ () -> {
+ if (mState == STATE_CONNECTED_NOTIFICATION) {
+ clearPendingNotification(true /* resetRepeatTime */);
+ }
+ },
+ TIME_TO_SHOW_CONNECTED_MILLIS);
+ }
+
+ /**
+ * Handles when a Wi-Fi connection attempt failed.
+ */
+ public void handleConnectionFailure() {
+ if (mState != STATE_CONNECTING_IN_NOTIFICATION) {
+ return;
+ }
+ postNotification(mNotificationBuilder.createNetworkFailedNotification());
+ mState = STATE_CONNECT_FAILED_NOTIFICATION;
+ mHandler.postDelayed(
+ () -> {
+ if (mState == STATE_CONNECT_FAILED_NOTIFICATION) {
+ clearPendingNotification(false /* resetRepeatTime */);
+ }
+ },
+ TIME_TO_SHOW_FAILED_MILLIS);
+ }
+
private NotificationManager getNotificationManager() {
return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
}
- private void postNotification(int numNetworks) {
- // Not enough time has passed to show the notification again
- if (mClock.getWallClockMillis() < mNotificationRepeatTime) {
+ private void postInitialNotification(ScanResult recommendedNetwork) {
+ postNotification(mNotificationBuilder.createConnectToNetworkNotification(
+ recommendedNetwork));
+ mState = STATE_SHOWING_RECOMMENDATION_NOTIFICATION;
+ mRecommendedNetwork = recommendedNetwork;
+ mNotificationRepeatTime = mClock.getWallClockMillis() + mNotificationRepeatDelay;
+ }
+
+ private void postNotification(Notification notification) {
+ getNotificationManager().notify(SystemMessage.NOTE_NETWORK_AVAILABLE, notification);
+ }
+
+ private void handleConnectToNetworkAction() {
+ if (mState != STATE_SHOWING_RECOMMENDATION_NOTIFICATION) {
return;
}
+ postNotification(mNotificationBuilder.createNetworkConnectingNotification(
+ mRecommendedNetwork));
+
+ Log.d(TAG, "User initiated connection to recommended network: " + mRecommendedNetwork.SSID);
+ WifiConfiguration network = ScanResultUtil.createNetworkFromScanResult(mRecommendedNetwork);
+ Message msg = Message.obtain();
+ msg.what = WifiManager.CONNECT_NETWORK;
+ msg.arg1 = WifiConfiguration.INVALID_NETWORK_ID;
+ msg.obj = network;
+ msg.replyTo = mSrcMessenger;
+ mWifiStateMachine.sendMessage(msg);
+
+ mState = STATE_CONNECTING_IN_NOTIFICATION;
+ mHandler.postDelayed(
+ () -> {
+ if (mState == STATE_CONNECTING_IN_NOTIFICATION) {
+ handleConnectionFailure();
+ }
+ },
+ TIME_TO_SHOW_CONNECTING_MILLIS);
+ }
- getNotificationManager().notify(
- SystemMessage.NOTE_NETWORK_AVAILABLE,
- mOpenNetworkNotificationBuilder.createOpenNetworkAvailableNotification(
- numNetworks));
- mNotificationShown = true;
- mNotificationRepeatTime = mClock.getWallClockMillis() + mNotificationRepeatDelay;
+ private void handleSeeAllNetworksAction() {
+ startWifiSettings();
}
- /** Opens Wi-Fi picker. */
- private void handleUserClickedContentAction() {
- mNotificationShown = false;
+ private void startWifiSettings() {
+ // Close notification drawer before opening the picker.
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
mContext.startActivity(
new Intent(Settings.ACTION_WIFI_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ clearPendingNotification(false /* resetRepeatTime */);
+ }
+
+ private void handlePickWifiNetworkAfterConnectFailure() {
+ startWifiSettings();
}
private void handleUserDismissedAction() {
- if (mRecommendedNetwork != null) {
+ if (mState == STATE_SHOWING_RECOMMENDATION_NOTIFICATION) {
// 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;
+ resetStateAndDelayNotification();
+ }
+
+ private void resetStateAndDelayNotification() {
+ mState = STATE_NO_NOTIFICATION;
+ mNotificationRepeatTime = System.currentTimeMillis() + mNotificationRepeatDelay;
+ mRecommendedNetwork = null;
}
/** Dump ONA controller state. */
@@ -238,7 +405,7 @@ public class OpenNetworkNotifier {
pw.println("mSettingEnabled " + mSettingEnabled);
pw.println("currentTime: " + mClock.getWallClockMillis());
pw.println("mNotificationRepeatTime: " + mNotificationRepeatTime);
- pw.println("mNotificationShown: " + mNotificationShown);
+ pw.println("mState: " + mState);
pw.println("mBlacklistedSsids: " + mBlacklistedSsids.toString());
}
@@ -269,7 +436,7 @@ public class OpenNetworkNotifier {
public void onChange(boolean selfChange) {
super.onChange(selfChange);
mSettingEnabled = getValue();
- clearPendingNotification(true /* resetRepeatDelay */);
+ clearPendingNotification(true /* resetRepeatTime */);
}
private boolean getValue() {
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 8180ab70b..75b39b261 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -47,7 +47,6 @@ import android.util.Log;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
-import com.android.server.wifi.WifiConfigStoreLegacy.WifiConfigStoreDataLegacy;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.util.TelephonyUtil;
import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -248,7 +247,6 @@ public class WifiConfigManager {
private final TelephonyManager mTelephonyManager;
private final WifiKeyStore mWifiKeyStore;
private final WifiConfigStore mWifiConfigStore;
- private final WifiConfigStoreLegacy mWifiConfigStoreLegacy;
private final WifiPermissionsUtil mWifiPermissionsUtil;
private final WifiPermissionsWrapper mWifiPermissionsWrapper;
/**
@@ -342,7 +340,7 @@ public class WifiConfigManager {
WifiConfigManager(
Context context, Clock clock, UserManager userManager,
TelephonyManager telephonyManager, WifiKeyStore wifiKeyStore,
- WifiConfigStore wifiConfigStore, WifiConfigStoreLegacy wifiConfigStoreLegacy,
+ WifiConfigStore wifiConfigStore,
WifiPermissionsUtil wifiPermissionsUtil,
WifiPermissionsWrapper wifiPermissionsWrapper,
NetworkListStoreData networkListStoreData,
@@ -354,7 +352,6 @@ public class WifiConfigManager {
mTelephonyManager = telephonyManager;
mWifiKeyStore = wifiKeyStore;
mWifiConfigStore = wifiConfigStore;
- mWifiConfigStoreLegacy = wifiConfigStoreLegacy;
mWifiPermissionsUtil = wifiPermissionsUtil;
mWifiPermissionsWrapper = wifiPermissionsWrapper;
@@ -2697,46 +2694,6 @@ public class WifiConfigManager {
}
/**
- * Migrate data from legacy store files. The function performs the following operations:
- * 1. Check if the legacy store files are present and the new store files are absent on device.
- * 2. Read all the data from the store files.
- * 3. Save it to the new store files.
- * 4. Delete the legacy store file.
- *
- * @return true if migration was successful or not needed (fresh install), false if it failed.
- */
- public boolean migrateFromLegacyStore() {
- if (!mWifiConfigStoreLegacy.areStoresPresent()) {
- Log.d(TAG, "Legacy store files not found. No migration needed!");
- return true;
- }
- if (mWifiConfigStore.areStoresPresent()) {
- Log.d(TAG, "New store files found. No migration needed!"
- + " Remove legacy store files");
- mWifiConfigStoreLegacy.removeStores();
- return true;
- }
- WifiConfigStoreDataLegacy storeData = mWifiConfigStoreLegacy.read();
- Log.d(TAG, "Reading from legacy store completed");
- loadInternalData(storeData.getConfigurations(), new ArrayList<WifiConfiguration>(),
- storeData.getDeletedEphemeralSSIDs());
-
- // Setup user store for the current user in case it have not setup yet, so that data
- // owned by the current user will be backed to the user store.
- if (mDeferredUserUnlockRead) {
- mWifiConfigStore.setUserStore(WifiConfigStore.createUserFile(mCurrentUserId));
- mDeferredUserUnlockRead = false;
- }
-
- if (!saveToStore(true)) {
- return false;
- }
- mWifiConfigStoreLegacy.removeStores();
- Log.d(TAG, "Migration from legacy store completed");
- return true;
- }
-
- /**
* Read the config store and load the in-memory lists from the store data retrieved and sends
* out the networks changed broadcast.
*
@@ -2750,10 +2707,7 @@ public class WifiConfigManager {
public boolean loadFromStore() {
if (!mWifiConfigStore.areStoresPresent()) {
Log.d(TAG, "New store files not found. No saved networks loaded!");
- if (!mWifiConfigStoreLegacy.areStoresPresent()) {
- // No legacy store files either, so reset the pending store read flag.
- mPendingStoreRead = false;
- }
+ mPendingStoreRead = false;
return true;
}
// If the user unlock comes in before we load from store, which means the user store have
diff --git a/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java b/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java
deleted file mode 100644
index 39e48a5cb..000000000
--- a/service/java/com/android/server/wifi/WifiConfigStoreLegacy.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wifi;
-
-import android.net.IpConfiguration;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiEnterpriseConfig;
-import android.os.Environment;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.server.net.IpConfigStore;
-import com.android.server.wifi.hotspot2.LegacyPasspointConfig;
-import com.android.server.wifi.hotspot2.LegacyPasspointConfigParser;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This class provides the API's to load network configurations from legacy store
- * mechanism (Pre O release).
- * This class loads network configurations from:
- * 1. /data/misc/wifi/networkHistory.txt
- * 2. /data/misc/wifi/wpa_supplicant.conf
- * 3. /data/misc/wifi/ipconfig.txt
- * 4. /data/misc/wifi/PerProviderSubscription.conf
- *
- * The order of invocation of the public methods during migration is the following:
- * 1. Check if legacy stores are present using {@link #areStoresPresent()}.
- * 2. Load all the store data using {@link #read()}
- * 3. Write the store data to the new store.
- * 4. Remove all the legacy stores using {@link #removeStores()}
- *
- * NOTE: This class should only be used from WifiConfigManager and is not thread-safe!
- *
- * TODO(b/31065385): Passpoint config store data migration & deletion.
- */
-public class WifiConfigStoreLegacy {
- /**
- * Log tag.
- */
- private static final String TAG = "WifiConfigStoreLegacy";
- /**
- * NetworkHistory config store file path.
- */
- private static final File NETWORK_HISTORY_FILE =
- new File(WifiNetworkHistory.NETWORK_HISTORY_CONFIG_FILE);
- /**
- * Passpoint config store file path.
- */
- private static final File PPS_FILE =
- new File(Environment.getDataMiscDirectory(), "wifi/PerProviderSubscription.conf");
- /**
- * IpConfig config store file path.
- */
- private static final File IP_CONFIG_FILE =
- new File(Environment.getDataMiscDirectory(), "wifi/ipconfig.txt");
- /**
- * List of external dependencies for WifiConfigManager.
- */
- private final WifiNetworkHistory mWifiNetworkHistory;
- private final WifiNative mWifiNative;
- private final IpConfigStore mIpconfigStore;
-
- private final LegacyPasspointConfigParser mPasspointConfigParser;
-
- WifiConfigStoreLegacy(WifiNetworkHistory wifiNetworkHistory,
- WifiNative wifiNative, IpConfigStore ipConfigStore,
- LegacyPasspointConfigParser passpointConfigParser) {
- mWifiNetworkHistory = wifiNetworkHistory;
- mWifiNative = wifiNative;
- mIpconfigStore = ipConfigStore;
- mPasspointConfigParser = passpointConfigParser;
- }
-
- /**
- * Helper function to lookup the WifiConfiguration object from configKey to WifiConfiguration
- * object map using the hashcode of the configKey.
- *
- * @param configurationMap Map of configKey to WifiConfiguration object.
- * @param hashCode hash code of the configKey to match.
- * @return
- */
- private static WifiConfiguration lookupWifiConfigurationUsingConfigKeyHash(
- Map<String, WifiConfiguration> configurationMap, int hashCode) {
- for (Map.Entry<String, WifiConfiguration> entry : configurationMap.entrySet()) {
- if (entry.getKey().hashCode() == hashCode) {
- return entry.getValue();
- }
- }
- return null;
- }
-
- /**
- * Helper function to load {@link IpConfiguration} data from the ip config store file and
- * populate the provided configuration map.
- *
- * @param configurationMap Map of configKey to WifiConfiguration object.
- */
- private void loadFromIpConfigStore(Map<String, WifiConfiguration> configurationMap) {
- // This is a map of the hash code of the network's configKey to the corresponding
- // IpConfiguration.
- SparseArray<IpConfiguration> ipConfigurations =
- mIpconfigStore.readIpAndProxyConfigurations(IP_CONFIG_FILE.getAbsolutePath());
- if (ipConfigurations == null || ipConfigurations.size() == 0) {
- Log.w(TAG, "No ip configurations found in ipconfig store");
- return;
- }
- for (int i = 0; i < ipConfigurations.size(); i++) {
- int id = ipConfigurations.keyAt(i);
- WifiConfiguration config =
- lookupWifiConfigurationUsingConfigKeyHash(configurationMap, id);
- // This is the only place the map is looked up through a (dangerous) hash-value!
- if (config == null || config.ephemeral) {
- Log.w(TAG, "configuration found for missing network, nid=" + id
- + ", ignored, networks.size=" + Integer.toString(ipConfigurations.size()));
- } else {
- config.setIpConfiguration(ipConfigurations.valueAt(i));
- }
- }
- }
-
- /**
- * Helper function to load {@link WifiConfiguration} data from networkHistory file and populate
- * the provided configuration map and deleted ephemeral ssid list.
- *
- * @param configurationMap Map of configKey to WifiConfiguration object.
- * @param deletedEphemeralSSIDs Map of configKey to WifiConfiguration object.
- */
- private void loadFromNetworkHistory(
- Map<String, WifiConfiguration> configurationMap, Set<String> deletedEphemeralSSIDs) {
- // TODO: Need to revisit the scan detail cache persistance. We're not doing it in the new
- // config store, so ignore it here as well.
- Map<Integer, ScanDetailCache> scanDetailCaches = new HashMap<>();
- mWifiNetworkHistory.readNetworkHistory(
- configurationMap, scanDetailCaches, deletedEphemeralSSIDs);
- }
-
- /**
- * Helper function to load {@link WifiConfiguration} data from wpa_supplicant and populate
- * the provided configuration map and network extras.
- *
- * This method needs to manually parse the wpa_supplicant.conf file to retrieve some of the
- * password fields like psk, wep_keys. password, etc.
- *
- * @param configurationMap Map of configKey to WifiConfiguration object.
- * @param networkExtras Map of network extras parsed from wpa_supplicant.
- */
- private void loadFromWpaSupplicant(
- Map<String, WifiConfiguration> configurationMap,
- SparseArray<Map<String, String>> networkExtras) {
- if (!mWifiNative.migrateNetworksFromSupplicant(configurationMap, networkExtras)) {
- Log.wtf(TAG, "Failed to load wifi configurations from wpa_supplicant");
- return;
- }
- if (configurationMap.isEmpty()) {
- Log.w(TAG, "No wifi configurations found in wpa_supplicant");
- return;
- }
- }
-
- /**
- * Helper function to update {@link WifiConfiguration} that represents a Passpoint
- * configuration.
- *
- * This method will manually parse PerProviderSubscription.conf file to retrieve missing
- * fields: provider friendly name, roaming consortium OIs, realm, IMSI.
- *
- * @param configurationMap Map of configKey to WifiConfiguration object.
- * @param networkExtras Map of network extras parsed from wpa_supplicant.
- */
- private void loadFromPasspointConfigStore(
- Map<String, WifiConfiguration> configurationMap,
- SparseArray<Map<String, String>> networkExtras) {
- Map<String, LegacyPasspointConfig> passpointConfigMap = null;
- try {
- passpointConfigMap = mPasspointConfigParser.parseConfig(PPS_FILE.getAbsolutePath());
- } catch (IOException e) {
- Log.w(TAG, "Failed to read/parse Passpoint config file: " + e.getMessage());
- }
-
- List<String> entriesToBeRemoved = new ArrayList<>();
- for (Map.Entry<String, WifiConfiguration> entry : configurationMap.entrySet()) {
- WifiConfiguration wifiConfig = entry.getValue();
- // Ignore non-Enterprise network since enterprise configuration is required for
- // Passpoint.
- if (wifiConfig.enterpriseConfig == null || wifiConfig.enterpriseConfig.getEapMethod()
- == WifiEnterpriseConfig.Eap.NONE) {
- continue;
- }
- // Ignore configuration without FQDN.
- Map<String, String> extras = networkExtras.get(wifiConfig.networkId);
- if (extras == null || !extras.containsKey(SupplicantStaNetworkHal.ID_STRING_KEY_FQDN)) {
- continue;
- }
- String fqdn = networkExtras.get(wifiConfig.networkId).get(
- SupplicantStaNetworkHal.ID_STRING_KEY_FQDN);
-
- // Remove the configuration if failed to find the matching configuration in the
- // Passpoint configuration file.
- if (passpointConfigMap == null || !passpointConfigMap.containsKey(fqdn)) {
- entriesToBeRemoved.add(entry.getKey());
- continue;
- }
-
- // Update the missing Passpoint configuration fields to this WifiConfiguration.
- LegacyPasspointConfig passpointConfig = passpointConfigMap.get(fqdn);
- wifiConfig.isLegacyPasspointConfig = true;
- wifiConfig.FQDN = fqdn;
- wifiConfig.providerFriendlyName = passpointConfig.mFriendlyName;
- if (passpointConfig.mRoamingConsortiumOis != null) {
- wifiConfig.roamingConsortiumIds = Arrays.copyOf(
- passpointConfig.mRoamingConsortiumOis,
- passpointConfig.mRoamingConsortiumOis.length);
- }
- if (passpointConfig.mImsi != null) {
- wifiConfig.enterpriseConfig.setPlmn(passpointConfig.mImsi);
- }
- if (passpointConfig.mRealm != null) {
- wifiConfig.enterpriseConfig.setRealm(passpointConfig.mRealm);
- }
- }
-
- // Remove any incomplete Passpoint configurations. Should never happen, in case it does
- // remove them to avoid maintaining any invalid Passpoint configurations.
- for (String key : entriesToBeRemoved) {
- Log.w(TAG, "Remove incomplete Passpoint configuration: " + key);
- configurationMap.remove(key);
- }
- }
-
- /**
- * Helper function to load from the different legacy stores:
- * 1. Read the network configurations from wpa_supplicant using {@link WifiNative}.
- * 2. Read the network configurations from networkHistory.txt using {@link WifiNetworkHistory}.
- * 3. Read the Ip configurations from ipconfig.txt using {@link IpConfigStore}.
- * 4. Read all the passpoint info from PerProviderSubscription.conf using
- * {@link LegacyPasspointConfigParser}.
- */
- public WifiConfigStoreDataLegacy read() {
- final Map<String, WifiConfiguration> configurationMap = new HashMap<>();
- final SparseArray<Map<String, String>> networkExtras = new SparseArray<>();
- final Set<String> deletedEphemeralSSIDs = new HashSet<>();
-
- loadFromWpaSupplicant(configurationMap, networkExtras);
- loadFromNetworkHistory(configurationMap, deletedEphemeralSSIDs);
- loadFromIpConfigStore(configurationMap);
- loadFromPasspointConfigStore(configurationMap, networkExtras);
-
- // Now create config store data instance to be returned.
- return new WifiConfigStoreDataLegacy(
- new ArrayList<>(configurationMap.values()), deletedEphemeralSSIDs);
- }
-
- /**
- * Function to check if the legacy store files are present and hence load from those stores and
- * then delete them.
- *
- * @return true if legacy store files are present, false otherwise.
- */
- public boolean areStoresPresent() {
- // We may have to keep the wpa_supplicant.conf file around. So, just use networkhistory.txt
- // as a check to see if we have not yet migrated or not. This should be the last file
- // that is deleted after migration.
- File file = new File(WifiNetworkHistory.NETWORK_HISTORY_CONFIG_FILE);
- return file.exists();
- }
-
- /**
- * Method to remove all the legacy store files. This should only be invoked once all
- * the data has been migrated to the new store file.
- * 1. Removes all networks from wpa_supplicant and saves it to wpa_supplicant.conf
- * 2. Deletes ipconfig.txt
- * 3. Deletes networkHistory.txt
- *
- * @return true if all the store files were deleted successfully, false otherwise.
- */
- public boolean removeStores() {
- // TODO(b/29352330): Delete wpa_supplicant.conf file instead.
- // First remove all networks from wpa_supplicant and save configuration.
- if (!mWifiNative.removeAllNetworks()) {
- Log.e(TAG, "Removing networks from wpa_supplicant failed");
- }
-
- // Now remove the ipconfig.txt file.
- if (!IP_CONFIG_FILE.delete()) {
- Log.e(TAG, "Removing ipconfig.txt failed");
- }
-
- // Now finally remove network history.txt
- if (!NETWORK_HISTORY_FILE.delete()) {
- Log.e(TAG, "Removing networkHistory.txt failed");
- }
-
- if (!PPS_FILE.delete()) {
- Log.e(TAG, "Removing PerProviderSubscription.conf failed");
- }
-
- Log.i(TAG, "All legacy stores removed!");
- return true;
- }
-
- /**
- * Interface used to set a masked value in the provided configuration. The masked value is
- * retrieved by parsing the wpa_supplicant.conf file.
- */
- private interface MaskedWpaSupplicantFieldSetter {
- void setValue(WifiConfiguration config, String value);
- }
-
- /**
- * Class used to encapsulate all the store data retrieved from the legacy (Pre O) store files.
- */
- public static class WifiConfigStoreDataLegacy {
- private List<WifiConfiguration> mConfigurations;
- private Set<String> mDeletedEphemeralSSIDs;
- // private List<HomeSP> mHomeSps;
-
- WifiConfigStoreDataLegacy(List<WifiConfiguration> configurations,
- Set<String> deletedEphemeralSSIDs) {
- mConfigurations = configurations;
- mDeletedEphemeralSSIDs = deletedEphemeralSSIDs;
- }
-
- public List<WifiConfiguration> getConfigurations() {
- return mConfigurations;
- }
-
- public Set<String> getDeletedEphemeralSSIDs() {
- return mDeletedEphemeralSSIDs;
- }
- }
-}
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index e417fde2c..7e730c838 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -1073,7 +1073,7 @@ public class WifiConnectivityManager {
mWifiState = state;
if (mWifiState == WIFI_STATE_CONNECTED) {
- mOpenNetworkNotifier.clearPendingNotification(false /* resetRepeatDelay */);
+ mOpenNetworkNotifier.handleWifiConnected();
}
// Reset BSSID of last connection attempt and kick off
@@ -1088,6 +1088,17 @@ public class WifiConnectivityManager {
}
/**
+ * Handler when a WiFi connection attempt ended.
+ *
+ * @param failureCode {@link WifiMetrics.ConnectionEvent} failure code.
+ */
+ public void handleConnectionAttemptEnded(int failureCode) {
+ if (failureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) {
+ mOpenNetworkNotifier.handleConnectionFailure();
+ }
+ }
+
+ /**
* Handler when user toggles whether untrusted connection is allowed
*/
public void setUntrustedConnectionAllowed(boolean allowed) {
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 26d702477..fc3af83e5 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -45,7 +45,6 @@ import com.android.server.am.BatteryStatsService;
import com.android.server.net.DelayedDiskWrite;
import com.android.server.net.IpConfigStore;
import com.android.server.wifi.aware.WifiAwareMetrics;
-import com.android.server.wifi.hotspot2.LegacyPasspointConfigParser;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.hotspot2.PasspointNetworkEvaluator;
import com.android.server.wifi.hotspot2.PasspointObjectFactory;
@@ -101,9 +100,7 @@ public class WifiInjector {
private final WifiMulticastLockManager mWifiMulticastLockManager;
private final WifiConfigStore mWifiConfigStore;
private final WifiKeyStore mWifiKeyStore;
- private final WifiNetworkHistory mWifiNetworkHistory;
private final IpConfigStore mIpConfigStore;
- private final WifiConfigStoreLegacy mWifiConfigStoreLegacy;
private final WifiConfigManager mWifiConfigManager;
private final WifiConnectivityHelper mWifiConnectivityHelper;
private final LocalLog mConnectivityLocalLog;
@@ -195,15 +192,11 @@ public class WifiInjector {
WifiConfigStore.createSharedFile());
// Legacy config store
DelayedDiskWrite writer = new DelayedDiskWrite();
- mWifiNetworkHistory = new WifiNetworkHistory(mContext, writer);
mIpConfigStore = new IpConfigStore(writer);
- mWifiConfigStoreLegacy = new WifiConfigStoreLegacy(
- mWifiNetworkHistory, mWifiNative, mIpConfigStore,
- new LegacyPasspointConfigParser());
// Config Manager
mWifiConfigManager = new WifiConfigManager(mContext, mClock,
UserManager.get(mContext), TelephonyManager.from(mContext),
- mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy, mWifiPermissionsUtil,
+ mWifiKeyStore, mWifiConfigStore, mWifiPermissionsUtil,
mWifiPermissionsWrapper, new NetworkListStoreData(),
new DeletedEphemeralSsidsStoreData());
mWifiMetrics.setWifiConfigManager(mWifiConfigManager);
@@ -233,7 +226,9 @@ public class WifiInjector {
mCertManager = new WifiCertManager(mContext);
mOpenNetworkNotifier = new OpenNetworkNotifier(mContext,
mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade, mClock,
- mWifiConfigManager, mWifiConfigStore, new OpenNetworkRecommender());
+ mWifiConfigManager, mWifiConfigStore, mWifiStateMachine,
+ new OpenNetworkRecommender(),
+ new ConnectToNetworkNotificationBuilder(mContext, mFrameworkFacade));
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/WifiNetworkHistory.java b/service/java/com/android/server/wifi/WifiNetworkHistory.java
deleted file mode 100644
index 282f6057d..000000000
--- a/service/java/com/android/server/wifi/WifiNetworkHistory.java
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wifi;
-
-import android.content.Context;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
-import android.net.wifi.WifiSsid;
-import android.os.Environment;
-import android.os.Process;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.server.net.DelayedDiskWrite;
-
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.text.DateFormat;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Provides an API to read and write the network history from WifiConfigurations to file
- * This is largely separate and extra to the supplicant config file.
- */
-public class WifiNetworkHistory {
- public static final String TAG = "WifiNetworkHistory";
- private static final boolean DBG = true;
- private static final boolean VDBG = true;
- static final String NETWORK_HISTORY_CONFIG_FILE = Environment.getDataDirectory()
- + "/misc/wifi/networkHistory.txt";
- /* Network History Keys */
- private static final String SSID_KEY = "SSID";
- static final String CONFIG_KEY = "CONFIG";
- private static final String CONFIG_BSSID_KEY = "CONFIG_BSSID";
- private static final String CHOICE_KEY = "CHOICE";
- private static final String CHOICE_TIME_KEY = "CHOICE_TIME";
- private static final String LINK_KEY = "LINK";
- private static final String BSSID_KEY = "BSSID";
- private static final String BSSID_KEY_END = "/BSSID";
- private static final String RSSI_KEY = "RSSI";
- private static final String FREQ_KEY = "FREQ";
- private static final String DATE_KEY = "DATE";
- private static final String MILLI_KEY = "MILLI";
- private static final String NETWORK_ID_KEY = "ID";
- private static final String PRIORITY_KEY = "PRIORITY";
- private static final String DEFAULT_GW_KEY = "DEFAULT_GW";
- private static final String AUTH_KEY = "AUTH";
- private static final String BSSID_STATUS_KEY = "BSSID_STATUS";
- private static final String SELF_ADDED_KEY = "SELF_ADDED";
- private static final String DID_SELF_ADD_KEY = "DID_SELF_ADD";
- private static final String PEER_CONFIGURATION_KEY = "PEER_CONFIGURATION";
- static final String CREATOR_UID_KEY = "CREATOR_UID_KEY";
- private static final String CONNECT_UID_KEY = "CONNECT_UID_KEY";
- private static final String UPDATE_UID_KEY = "UPDATE_UID";
- private static final String FQDN_KEY = "FQDN";
- private static final String SCORER_OVERRIDE_KEY = "SCORER_OVERRIDE";
- private static final String SCORER_OVERRIDE_AND_SWITCH_KEY = "SCORER_OVERRIDE_AND_SWITCH";
- private static final String VALIDATED_INTERNET_ACCESS_KEY = "VALIDATED_INTERNET_ACCESS";
- private static final String NO_INTERNET_ACCESS_REPORTS_KEY = "NO_INTERNET_ACCESS_REPORTS";
- private static final String NO_INTERNET_ACCESS_EXPECTED_KEY = "NO_INTERNET_ACCESS_EXPECTED";
- private static final String EPHEMERAL_KEY = "EPHEMERAL";
- private static final String USE_EXTERNAL_SCORES_KEY = "USE_EXTERNAL_SCORES";
- private static final String METERED_HINT_KEY = "METERED_HINT";
- private static final String METERED_OVERRIDE_KEY = "METERED_OVERRIDE";
- private static final String NUM_ASSOCIATION_KEY = "NUM_ASSOCIATION";
- private static final String DELETED_EPHEMERAL_KEY = "DELETED_EPHEMERAL";
- private static final String CREATOR_NAME_KEY = "CREATOR_NAME";
- private static final String UPDATE_NAME_KEY = "UPDATE_NAME";
- private static final String USER_APPROVED_KEY = "USER_APPROVED";
- private static final String CREATION_TIME_KEY = "CREATION_TIME";
- private static final String UPDATE_TIME_KEY = "UPDATE_TIME";
- static final String SHARED_KEY = "SHARED";
- private static final String NETWORK_SELECTION_STATUS_KEY = "NETWORK_SELECTION_STATUS";
- private static final String NETWORK_SELECTION_DISABLE_REASON_KEY =
- "NETWORK_SELECTION_DISABLE_REASON";
- private static final String HAS_EVER_CONNECTED_KEY = "HAS_EVER_CONNECTED";
-
- private static final String SEPARATOR = ": ";
- private static final String NL = "\n";
-
- protected final DelayedDiskWrite mWriter;
- Context mContext;
- /*
- * Lost config list, whenever we read a config from networkHistory.txt that was not in
- * wpa_supplicant.conf
- */
- HashSet<String> mLostConfigsDbg = new HashSet<String>();
-
- public WifiNetworkHistory(Context c, DelayedDiskWrite writer) {
- mContext = c;
- mWriter = writer;
- }
-
- /**
- * Write network history to file, for configured networks
- *
- * @param networks List of ConfiguredNetworks to write to NetworkHistory
- */
- public void writeKnownNetworkHistory(final List<WifiConfiguration> networks,
- final ConcurrentHashMap<Integer, ScanDetailCache> scanDetailCaches,
- final Set<String> deletedEphemeralSSIDs) {
-
- /* Make a copy */
- //final List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
-
- //for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
- // networks.add(new WifiConfiguration(config));
- //}
-
- mWriter.write(NETWORK_HISTORY_CONFIG_FILE, new DelayedDiskWrite.Writer() {
- public void onWriteCalled(DataOutputStream out) throws IOException {
- for (WifiConfiguration config : networks) {
- //loge("onWriteCalled write SSID: " + config.SSID);
- /* if (config.getLinkProperties() != null)
- loge(" lp " + config.getLinkProperties().toString());
- else
- loge("attempt config w/o lp");
- */
- NetworkSelectionStatus status = config.getNetworkSelectionStatus();
- if (VDBG) {
- int numlink = 0;
- if (config.linkedConfigurations != null) {
- numlink = config.linkedConfigurations.size();
- }
- String disableTime;
- if (config.getNetworkSelectionStatus().isNetworkEnabled()) {
- disableTime = "";
- } else {
- disableTime = "Disable time: " + DateFormat.getInstance().format(
- config.getNetworkSelectionStatus().getDisableTime());
- }
- logd("saving network history: " + config.configKey() + " gw: "
- + config.defaultGwMacAddress + " Network Selection-status: "
- + status.getNetworkStatusString()
- + disableTime + " ephemeral=" + config.ephemeral
- + " choice:" + status.getConnectChoice()
- + " link:" + numlink
- + " status:" + config.status
- + " nid:" + config.networkId
- + " hasEverConnected: " + status.getHasEverConnected());
- }
-
- if (!isValid(config)) {
- continue;
- }
-
- if (config.SSID == null) {
- if (VDBG) {
- logv("writeKnownNetworkHistory trying to write config with null SSID");
- }
- continue;
- }
- if (VDBG) {
- logv("writeKnownNetworkHistory write config " + config.configKey());
- }
- out.writeUTF(CONFIG_KEY + SEPARATOR + config.configKey() + NL);
-
- if (config.SSID != null) {
- out.writeUTF(SSID_KEY + SEPARATOR + config.SSID + NL);
- }
- if (config.BSSID != null) {
- out.writeUTF(CONFIG_BSSID_KEY + SEPARATOR + config.BSSID + NL);
- } else {
- out.writeUTF(CONFIG_BSSID_KEY + SEPARATOR + "null" + NL);
- }
- if (config.FQDN != null) {
- out.writeUTF(FQDN_KEY + SEPARATOR + config.FQDN + NL);
- }
-
- out.writeUTF(PRIORITY_KEY + SEPARATOR + Integer.toString(config.priority) + NL);
- out.writeUTF(NETWORK_ID_KEY + SEPARATOR
- + Integer.toString(config.networkId) + NL);
- out.writeUTF(SELF_ADDED_KEY + SEPARATOR
- + Boolean.toString(config.selfAdded) + NL);
- out.writeUTF(DID_SELF_ADD_KEY + SEPARATOR
- + Boolean.toString(config.didSelfAdd) + NL);
- out.writeUTF(NO_INTERNET_ACCESS_REPORTS_KEY + SEPARATOR
- + Integer.toString(config.numNoInternetAccessReports) + NL);
- out.writeUTF(VALIDATED_INTERNET_ACCESS_KEY + SEPARATOR
- + Boolean.toString(config.validatedInternetAccess) + NL);
- out.writeUTF(NO_INTERNET_ACCESS_EXPECTED_KEY + SEPARATOR +
- Boolean.toString(config.noInternetAccessExpected) + NL);
- out.writeUTF(EPHEMERAL_KEY + SEPARATOR
- + Boolean.toString(config.ephemeral) + NL);
- out.writeUTF(METERED_HINT_KEY + SEPARATOR
- + Boolean.toString(config.meteredHint) + NL);
- out.writeUTF(METERED_OVERRIDE_KEY + SEPARATOR
- + Integer.toString(config.meteredOverride) + NL);
- out.writeUTF(USE_EXTERNAL_SCORES_KEY + SEPARATOR
- + Boolean.toString(config.useExternalScores) + NL);
- if (config.creationTime != null) {
- out.writeUTF(CREATION_TIME_KEY + SEPARATOR + config.creationTime + NL);
- }
- if (config.updateTime != null) {
- out.writeUTF(UPDATE_TIME_KEY + SEPARATOR + config.updateTime + NL);
- }
- if (config.peerWifiConfiguration != null) {
- out.writeUTF(PEER_CONFIGURATION_KEY + SEPARATOR
- + config.peerWifiConfiguration + NL);
- }
- out.writeUTF(SCORER_OVERRIDE_KEY + SEPARATOR
- + Integer.toString(config.numScorerOverride) + NL);
- out.writeUTF(SCORER_OVERRIDE_AND_SWITCH_KEY + SEPARATOR
- + Integer.toString(config.numScorerOverrideAndSwitchedNetwork) + NL);
- out.writeUTF(NUM_ASSOCIATION_KEY + SEPARATOR
- + Integer.toString(config.numAssociation) + NL);
- out.writeUTF(CREATOR_UID_KEY + SEPARATOR
- + Integer.toString(config.creatorUid) + NL);
- out.writeUTF(CONNECT_UID_KEY + SEPARATOR
- + Integer.toString(config.lastConnectUid) + NL);
- out.writeUTF(UPDATE_UID_KEY + SEPARATOR
- + Integer.toString(config.lastUpdateUid) + NL);
- out.writeUTF(CREATOR_NAME_KEY + SEPARATOR
- + config.creatorName + NL);
- out.writeUTF(UPDATE_NAME_KEY + SEPARATOR
- + config.lastUpdateName + NL);
- out.writeUTF(USER_APPROVED_KEY + SEPARATOR
- + Integer.toString(config.userApproved) + NL);
- out.writeUTF(SHARED_KEY + SEPARATOR + Boolean.toString(config.shared) + NL);
- String allowedKeyManagementString =
- makeString(config.allowedKeyManagement,
- WifiConfiguration.KeyMgmt.strings);
- out.writeUTF(AUTH_KEY + SEPARATOR
- + allowedKeyManagementString + NL);
- out.writeUTF(NETWORK_SELECTION_STATUS_KEY + SEPARATOR
- + status.getNetworkSelectionStatus() + NL);
- out.writeUTF(NETWORK_SELECTION_DISABLE_REASON_KEY + SEPARATOR
- + status.getNetworkSelectionDisableReason() + NL);
-
- if (status.getConnectChoice() != null) {
- out.writeUTF(CHOICE_KEY + SEPARATOR + status.getConnectChoice() + NL);
- out.writeUTF(CHOICE_TIME_KEY + SEPARATOR
- + status.getConnectChoiceTimestamp() + NL);
- }
-
- if (config.linkedConfigurations != null) {
- log("writeKnownNetworkHistory write linked "
- + config.linkedConfigurations.size());
-
- for (String key : config.linkedConfigurations.keySet()) {
- out.writeUTF(LINK_KEY + SEPARATOR + key + NL);
- }
- }
-
- String macAddress = config.defaultGwMacAddress;
- if (macAddress != null) {
- out.writeUTF(DEFAULT_GW_KEY + SEPARATOR + macAddress + NL);
- }
-
- if (getScanDetailCache(config, scanDetailCaches) != null) {
- for (ScanDetail scanDetail : getScanDetailCache(config,
- scanDetailCaches).values()) {
- ScanResult result = scanDetail.getScanResult();
- out.writeUTF(BSSID_KEY + SEPARATOR
- + result.BSSID + NL);
- out.writeUTF(FREQ_KEY + SEPARATOR
- + Integer.toString(result.frequency) + NL);
-
- out.writeUTF(RSSI_KEY + SEPARATOR
- + Integer.toString(result.level) + NL);
-
- out.writeUTF(BSSID_KEY_END + NL);
- }
- }
- out.writeUTF(HAS_EVER_CONNECTED_KEY + SEPARATOR
- + Boolean.toString(status.getHasEverConnected()) + NL);
- out.writeUTF(NL);
- // Add extra blank lines for clarity
- out.writeUTF(NL);
- out.writeUTF(NL);
- }
- if (deletedEphemeralSSIDs != null && deletedEphemeralSSIDs.size() > 0) {
- for (String ssid : deletedEphemeralSSIDs) {
- out.writeUTF(DELETED_EPHEMERAL_KEY);
- out.writeUTF(ssid);
- out.writeUTF(NL);
- }
- }
- }
- });
- }
-
- /**
- * Adds information stored in networkHistory.txt to the given configs. The configs are provided
- * as a mapping from configKey to WifiConfiguration, because the WifiConfigurations themselves
- * do not contain sufficient information to compute their configKeys until after the information
- * that is stored in networkHistory.txt has been added to them.
- *
- * @param configs mapping from configKey to a WifiConfiguration that contains the information
- * information read from wpa_supplicant.conf
- */
- public void readNetworkHistory(Map<String, WifiConfiguration> configs,
- Map<Integer, ScanDetailCache> scanDetailCaches,
- Set<String> deletedEphemeralSSIDs) {
-
- try (DataInputStream in =
- new DataInputStream(new BufferedInputStream(
- new FileInputStream(NETWORK_HISTORY_CONFIG_FILE)))) {
-
- String bssid = null;
- String ssid = null;
-
- int freq = 0;
- int status = 0;
- long seen = 0;
- int rssi = WifiConfiguration.INVALID_RSSI;
- String caps = null;
-
- WifiConfiguration config = null;
- while (true) {
- String line = in.readUTF();
- if (line == null) {
- break;
- }
- int colon = line.indexOf(':');
- if (colon < 0) {
- continue;
- }
-
- String key = line.substring(0, colon).trim();
- String value = line.substring(colon + 1).trim();
-
- if (key.equals(CONFIG_KEY)) {
- config = configs.get(value);
-
- // skip reading that configuration data
- // since we don't have a corresponding network ID
- if (config == null) {
- Log.e(TAG, "readNetworkHistory didnt find netid for hash="
- + Integer.toString(value.hashCode())
- + " key: " + value);
- mLostConfigsDbg.add(value);
- continue;
- } else {
- // After an upgrade count old connections as owned by system
- if (config.creatorName == null || config.lastUpdateName == null) {
- config.creatorName =
- mContext.getPackageManager().getNameForUid(Process.SYSTEM_UID);
- config.lastUpdateName = config.creatorName;
-
- if (DBG) {
- Log.w(TAG, "Upgrading network " + config.networkId
- + " to " + config.creatorName);
- }
- }
- }
- } else if (config != null) {
- NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus();
- switch (key) {
- case SSID_KEY:
- if (config.isPasspoint()) {
- break;
- }
- ssid = value;
- if (config.SSID != null && !config.SSID.equals(ssid)) {
- loge("Error parsing network history file, mismatched SSIDs");
- config = null; //error
- ssid = null;
- } else {
- config.SSID = ssid;
- }
- break;
- case CONFIG_BSSID_KEY:
- config.BSSID = value.equals("null") ? null : value;
- break;
- case FQDN_KEY:
- // Check for literal 'null' to be backwards compatible.
- config.FQDN = value.equals("null") ? null : value;
- break;
- case DEFAULT_GW_KEY:
- config.defaultGwMacAddress = value;
- break;
- case SELF_ADDED_KEY:
- config.selfAdded = Boolean.parseBoolean(value);
- break;
- case DID_SELF_ADD_KEY:
- config.didSelfAdd = Boolean.parseBoolean(value);
- break;
- case NO_INTERNET_ACCESS_REPORTS_KEY:
- config.numNoInternetAccessReports = Integer.parseInt(value);
- break;
- case VALIDATED_INTERNET_ACCESS_KEY:
- config.validatedInternetAccess = Boolean.parseBoolean(value);
- break;
- case NO_INTERNET_ACCESS_EXPECTED_KEY:
- config.noInternetAccessExpected = Boolean.parseBoolean(value);
- break;
- case CREATION_TIME_KEY:
- config.creationTime = value;
- break;
- case UPDATE_TIME_KEY:
- config.updateTime = value;
- break;
- case EPHEMERAL_KEY:
- config.ephemeral = Boolean.parseBoolean(value);
- break;
- case METERED_HINT_KEY:
- config.meteredHint = Boolean.parseBoolean(value);
- break;
- case METERED_OVERRIDE_KEY:
- config.meteredOverride = Integer.parseInt(value);
- break;
- case USE_EXTERNAL_SCORES_KEY:
- config.useExternalScores = Boolean.parseBoolean(value);
- break;
- case CREATOR_UID_KEY:
- config.creatorUid = Integer.parseInt(value);
- break;
- case SCORER_OVERRIDE_KEY:
- config.numScorerOverride = Integer.parseInt(value);
- break;
- case SCORER_OVERRIDE_AND_SWITCH_KEY:
- config.numScorerOverrideAndSwitchedNetwork = Integer.parseInt(value);
- break;
- case NUM_ASSOCIATION_KEY:
- config.numAssociation = Integer.parseInt(value);
- break;
- case CONNECT_UID_KEY:
- config.lastConnectUid = Integer.parseInt(value);
- break;
- case UPDATE_UID_KEY:
- config.lastUpdateUid = Integer.parseInt(value);
- break;
- case PEER_CONFIGURATION_KEY:
- config.peerWifiConfiguration = value;
- break;
- case NETWORK_SELECTION_STATUS_KEY:
- int networkStatusValue = Integer.parseInt(value);
- // Reset temporarily disabled network status
- if (networkStatusValue ==
- NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED) {
- networkStatusValue =
- NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
- }
- networkStatus.setNetworkSelectionStatus(networkStatusValue);
- break;
- case NETWORK_SELECTION_DISABLE_REASON_KEY:
- networkStatus.setNetworkSelectionDisableReason(Integer.parseInt(value));
- break;
- case CHOICE_KEY:
- networkStatus.setConnectChoice(value);
- break;
- case CHOICE_TIME_KEY:
- networkStatus.setConnectChoiceTimestamp(Long.parseLong(value));
- break;
- case LINK_KEY:
- if (config.linkedConfigurations == null) {
- config.linkedConfigurations = new HashMap<>();
- } else {
- config.linkedConfigurations.put(value, -1);
- }
- break;
- case BSSID_KEY:
- status = 0;
- ssid = null;
- bssid = null;
- freq = 0;
- seen = 0;
- rssi = WifiConfiguration.INVALID_RSSI;
- caps = "";
- break;
- case RSSI_KEY:
- rssi = Integer.parseInt(value);
- break;
- case FREQ_KEY:
- freq = Integer.parseInt(value);
- break;
- case DATE_KEY:
- /*
- * when reading the configuration from file we don't update the date
- * so as to avoid reading back stale or non-sensical data that would
- * depend on network time.
- * The date of a WifiConfiguration should only come from actual scan
- * result.
- *
- String s = key.replace(FREQ_KEY, "");
- seen = Integer.getInteger(s);
- */
- break;
- case BSSID_KEY_END:
- if ((bssid != null) && (ssid != null)) {
- if (getScanDetailCache(config, scanDetailCaches) != null) {
- WifiSsid wssid = WifiSsid.createFromAsciiEncoded(ssid);
- ScanDetail scanDetail = new ScanDetail(wssid, bssid,
- caps, rssi, freq, (long) 0, seen);
- getScanDetailCache(config, scanDetailCaches).put(scanDetail);
- }
- }
- break;
- case DELETED_EPHEMERAL_KEY:
- if (!TextUtils.isEmpty(value)) {
- deletedEphemeralSSIDs.add(value);
- }
- break;
- case CREATOR_NAME_KEY:
- config.creatorName = value;
- break;
- case UPDATE_NAME_KEY:
- config.lastUpdateName = value;
- break;
- case USER_APPROVED_KEY:
- config.userApproved = Integer.parseInt(value);
- break;
- case SHARED_KEY:
- config.shared = Boolean.parseBoolean(value);
- break;
- case HAS_EVER_CONNECTED_KEY:
- networkStatus.setHasEverConnected(Boolean.parseBoolean(value));
- break;
- }
- }
- }
- } catch (EOFException e) {
- // do nothing
- } catch (FileNotFoundException e) {
- Log.i(TAG, "readNetworkHistory: no config file, " + e);
- } catch (NumberFormatException e) {
- Log.e(TAG, "readNetworkHistory: failed to parse, " + e, e);
- } catch (IOException e) {
- Log.e(TAG, "readNetworkHistory: failed to read, " + e, e);
- }
- }
-
- /**
- * Ported this out of WifiServiceImpl, I have no idea what it's doing
- * <TODO> figure out what/why this is doing
- * <TODO> Port it into WifiConfiguration, then remove all the silly business from ServiceImpl
- */
- public boolean isValid(WifiConfiguration config) {
- if (config.allowedKeyManagement == null) {
- return false;
- }
- if (config.allowedKeyManagement.cardinality() > 1) {
- if (config.allowedKeyManagement.cardinality() != 2) {
- return false;
- }
- if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)) {
- return false;
- }
- if ((!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X))
- && (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK))) {
- return false;
- }
- }
- return true;
- }
-
- private static String makeString(BitSet set, String[] strings) {
- StringBuffer buf = new StringBuffer();
- int nextSetBit = -1;
-
- /* Make sure all set bits are in [0, strings.length) to avoid
- * going out of bounds on strings. (Shouldn't happen, but...) */
- set = set.get(0, strings.length);
-
- while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
- buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
- }
-
- // remove trailing space
- if (set.cardinality() > 0) {
- buf.setLength(buf.length() - 1);
- }
-
- return buf.toString();
- }
-
- protected void logv(String s) {
- Log.v(TAG, s);
- }
- protected void logd(String s) {
- Log.d(TAG, s);
- }
- protected void log(String s) {
- Log.d(TAG, s);
- }
- protected void loge(String s) {
- loge(s, false);
- }
- protected void loge(String s, boolean stack) {
- if (stack) {
- Log.e(TAG, s + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
- + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
- + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
- + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
- } else {
- Log.e(TAG, s);
- }
- }
-
- private ScanDetailCache getScanDetailCache(WifiConfiguration config,
- Map<Integer, ScanDetailCache> scanDetailCaches) {
- if (config == null || scanDetailCaches == null) return null;
- ScanDetailCache cache = scanDetailCaches.get(config.networkId);
- if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) {
- cache =
- new ScanDetailCache(
- config, WifiConfigManager.SCAN_CACHE_ENTRIES_MAX_SIZE,
- WifiConfigManager.SCAN_CACHE_ENTRIES_TRIM_SIZE);
- scanDetailCaches.put(config.networkId, cache);
- }
- return cache;
- }
-}
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 1d26f0448..41a599451 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -3429,11 +3429,12 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
}
/**
- * Inform other components (WifiMetrics, WifiDiagnostics, etc.) that the current connection attempt
- * has concluded.
+ * Inform other components (WifiMetrics, WifiDiagnostics, WifiConnectivityManager, etc.) that
+ * the current connection attempt has concluded.
*/
private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode) {
mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode);
+ mWifiConnectivityManager.handleConnectionAttemptEnded(level2FailureCode);
switch (level2FailureCode) {
case WifiMetrics.ConnectionEvent.FAILURE_NONE:
// Ideally, we'd wait until IP reachability has been confirmed. this code falls
@@ -4274,10 +4275,6 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss
mLastSignalLevel = -1;
mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
- // Attempt to migrate data out of legacy store.
- if (!mWifiConfigManager.migrateFromLegacyStore()) {
- Log.e(TAG, "Failed to migrate from legacy config store");
- }
initializeWpsDetails();
sendSupplicantConnectionChangedBroadcast(true);
transitionTo(mSupplicantStartedState);
diff --git a/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfigParser.java b/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfigParser.java
deleted file mode 100644
index 31795f126..000000000
--- a/service/java/com/android/server/wifi/hotspot2/LegacyPasspointConfigParser.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * 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.hotspot2;
-
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Utility class for parsing legacy (N and older) Passpoint configuration file content
- * (/data/misc/wifi/PerProviderSubscription.conf). In N and older, only Release 1 is supported.
- *
- * This class only retrieve the relevant Release 1 configuration fields that are not backed
- * elsewhere. Below are relevant fields:
- * - FQDN (used for linking with configuration data stored elsewhere)
- * - Friendly Name
- * - Roaming Consortium
- * - Realm
- * - IMSI (for SIM credential)
- *
- * Below is an example content of a Passpoint configuration file:
- *
- * tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)
- * 8:MgmtTree+
- * 17:PerProviderSubscription+
- * 4:r1i1+
- * 6:HomeSP+
- * c:FriendlyName=d:Test Provider
- * 4:FQDN=8:test.net
- * 13:RoamingConsortiumOI=9:1234,5678
- * .
- * a:Credential+
- * 10:UsernamePassword+
- * 8:Username=4:user
- * 8:Password=4:pass
- *
- * 9:EAPMethod+
- * 7:EAPType=2:21
- * b:InnerMethod=3:PAP
- * .
- * .
- * 5:Realm=a:boingo.com
- * .
- * .
- * .
- * .
- *
- * Each string is prefixed with a "|StringBytesInHex|:".
- * '+' indicates start of a new internal node.
- * '.' indicates end of the current internal node.
- * '=' indicates "value" of a leaf node.
- *
- */
-public class LegacyPasspointConfigParser {
- private static final String TAG = "LegacyPasspointConfigParser";
-
- private static final String TAG_MANAGEMENT_TREE = "MgmtTree";
- private static final String TAG_PER_PROVIDER_SUBSCRIPTION = "PerProviderSubscription";
- private static final String TAG_HOMESP = "HomeSP";
- private static final String TAG_FQDN = "FQDN";
- private static final String TAG_FRIENDLY_NAME = "FriendlyName";
- private static final String TAG_ROAMING_CONSORTIUM_OI = "RoamingConsortiumOI";
- private static final String TAG_CREDENTIAL = "Credential";
- private static final String TAG_REALM = "Realm";
- private static final String TAG_SIM = "SIM";
- private static final String TAG_IMSI = "IMSI";
-
- private static final String LONG_ARRAY_SEPARATOR = ",";
- private static final String END_OF_INTERNAL_NODE_INDICATOR = ".";
- private static final char START_OF_INTERNAL_NODE_INDICATOR = '+';
- private static final char STRING_PREFIX_INDICATOR = ':';
- private static final char STRING_VALUE_INDICATOR = '=';
-
- /**
- * An abstraction for a node within a tree. A node can be an internal node (contained
- * children nodes) or a leaf node (contained a String value).
- */
- private abstract static class Node {
- private final String mName;
- Node(String name) {
- mName = name;
- }
-
- /**
- * @return the name of the node
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Applies for internal node only.
- *
- * @return the list of children nodes.
- */
- public abstract List<Node> getChildren();
-
- /**
- * Applies for leaf node only.
- *
- * @return the string value of the node
- */
- public abstract String getValue();
- }
-
- /**
- * Class representing an internal node of a tree. It contained a list of child nodes.
- */
- private static class InternalNode extends Node {
- private final List<Node> mChildren;
- InternalNode(String name, List<Node> children) {
- super(name);
- mChildren = children;
- }
-
- @Override
- public List<Node> getChildren() {
- return mChildren;
- }
-
- @Override
- public String getValue() {
- return null;
- }
- }
-
- /**
- * Class representing a leaf node of a tree. It contained a String type value.
- */
- private static class LeafNode extends Node {
- private final String mValue;
- LeafNode(String name, String value) {
- super(name);
- mValue = value;
- }
-
- @Override
- public List<Node> getChildren() {
- return null;
- }
-
- @Override
- public String getValue() {
- return mValue;
- }
- }
-
- public LegacyPasspointConfigParser() {}
-
- /**
- * Parse the legacy Passpoint configuration file content, only retrieve the relevant
- * configurations that are not saved elsewhere.
- *
- * For both N and M, only Release 1 is supported. Most of the configurations are saved
- * elsewhere as part of the {@link android.net.wifi.WifiConfiguration} data.
- * The configurations needed from the legacy Passpoint configuration file are:
- *
- * - FQDN - needed to be able to link to the associated {@link WifiConfiguration} data
- * - Friendly Name
- * - Roaming Consortium OIs
- * - Realm
- * - IMSI (for SIM credential)
- *
- * Make this function non-static so that it can be mocked during unit test.
- *
- * @param fileName The file name of the configuration file
- * @return Map of FQDN to {@link LegacyPasspointConfig}
- * @throws IOException
- */
- public Map<String, LegacyPasspointConfig> parseConfig(String fileName)
- throws IOException {
- Map<String, LegacyPasspointConfig> configs = new HashMap<>();
- BufferedReader in = new BufferedReader(new FileReader(fileName));
- in.readLine(); // Ignore the first line which contained the header.
-
- // Convert the configuration data to a management tree represented by a root {@link Node}.
- Node root = buildNode(in);
-
- if (root == null || root.getChildren() == null) {
- Log.d(TAG, "Empty configuration data");
- return configs;
- }
-
- // Verify root node name.
- if (!TextUtils.equals(TAG_MANAGEMENT_TREE, root.getName())) {
- throw new IOException("Unexpected root node: " + root.getName());
- }
-
- // Process and retrieve the configuration from each PPS (PerProviderSubscription) node.
- List<Node> ppsNodes = root.getChildren();
- for (Node ppsNode : ppsNodes) {
- LegacyPasspointConfig config = processPpsNode(ppsNode);
- configs.put(config.mFqdn, config);
- }
- return configs;
- }
-
- /**
- * Build a {@link Node} from the current line in the buffer. A node can be an internal
- * node (ends with '+') or a leaf node.
- *
- * @param in Input buffer to read data from
- * @return {@link Node} representing the current line
- * @throws IOException
- */
- private static Node buildNode(BufferedReader in) throws IOException {
- // Read until non-empty line.
- String currentLine = null;
- while ((currentLine = in.readLine()) != null) {
- if (!currentLine.isEmpty()) {
- break;
- }
- }
-
- // Return null if EOF is reached.
- if (currentLine == null) {
- return null;
- }
-
- // Remove the leading and the trailing whitespaces.
- currentLine = currentLine.trim();
-
- // Check for the internal node terminator.
- if (TextUtils.equals(END_OF_INTERNAL_NODE_INDICATOR, currentLine)) {
- return null;
- }
-
- // Parse the name-value of the current line. The value will be null if the current line
- // is not a leaf node (e.g. line ends with a '+').
- // Each line is encoded in UTF-8.
- Pair<String, String> nameValuePair =
- parseLine(currentLine.getBytes(StandardCharsets.UTF_8));
- if (nameValuePair.second != null) {
- return new LeafNode(nameValuePair.first, nameValuePair.second);
- }
-
- // Parse the children contained under this internal node.
- List<Node> children = new ArrayList<>();
- Node child = null;
- while ((child = buildNode(in)) != null) {
- children.add(child);
- }
- return new InternalNode(nameValuePair.first, children);
- }
-
- /**
- * Process a PPS (PerProviderSubscription) node to retrieve Passpoint configuration data.
- *
- * @param ppsNode The PPS node to process
- * @return {@link LegacyPasspointConfig}
- * @throws IOException
- */
- private static LegacyPasspointConfig processPpsNode(Node ppsNode) throws IOException {
- if (ppsNode.getChildren() == null || ppsNode.getChildren().size() != 1) {
- throw new IOException("PerProviderSubscription node should contain "
- + "one instance node");
- }
-
- if (!TextUtils.equals(TAG_PER_PROVIDER_SUBSCRIPTION, ppsNode.getName())) {
- throw new IOException("Unexpected name for PPS node: " + ppsNode.getName());
- }
-
- // Retrieve the PPS instance node.
- Node instanceNode = ppsNode.getChildren().get(0);
- if (instanceNode.getChildren() == null) {
- throw new IOException("PPS instance node doesn't contained any children");
- }
-
- // Process and retrieve the relevant configurations under the PPS instance node.
- LegacyPasspointConfig config = new LegacyPasspointConfig();
- for (Node node : instanceNode.getChildren()) {
- switch (node.getName()) {
- case TAG_HOMESP:
- processHomeSPNode(node, config);
- break;
- case TAG_CREDENTIAL:
- processCredentialNode(node, config);
- break;
- default:
- Log.d(TAG, "Ignore uninterested field under PPS instance: " + node.getName());
- break;
- }
- }
- if (config.mFqdn == null) {
- throw new IOException("PPS instance missing FQDN");
- }
- return config;
- }
-
- /**
- * Process a HomeSP node to retrieve configuration data into the given |config|.
- *
- * @param homeSpNode The HomeSP node to process
- * @param config The config object to fill in the data
- * @throws IOException
- */
- private static void processHomeSPNode(Node homeSpNode, LegacyPasspointConfig config)
- throws IOException {
- if (homeSpNode.getChildren() == null) {
- throw new IOException("HomeSP node should contain at least one child node");
- }
-
- for (Node node : homeSpNode.getChildren()) {
- switch (node.getName()) {
- case TAG_FQDN:
- config.mFqdn = getValue(node);
- break;
- case TAG_FRIENDLY_NAME:
- config.mFriendlyName = getValue(node);
- break;
- case TAG_ROAMING_CONSORTIUM_OI:
- config.mRoamingConsortiumOis = parseLongArray(getValue(node));
- break;
- default:
- Log.d(TAG, "Ignore uninterested field under HomeSP: " + node.getName());
- break;
- }
- }
- }
-
- /**
- * Process a Credential node to retrieve configuration data into the given |config|.
- *
- * @param credentialNode The Credential node to process
- * @param config The config object to fill in the data
- * @throws IOException
- */
- private static void processCredentialNode(Node credentialNode,
- LegacyPasspointConfig config)
- throws IOException {
- if (credentialNode.getChildren() == null) {
- throw new IOException("Credential node should contain at least one child node");
- }
-
- for (Node node : credentialNode.getChildren()) {
- switch (node.getName()) {
- case TAG_REALM:
- config.mRealm = getValue(node);
- break;
- case TAG_SIM:
- processSimNode(node, config);
- break;
- default:
- Log.d(TAG, "Ignore uninterested field under Credential: " + node.getName());
- break;
- }
- }
- }
-
- /**
- * Process a SIM node to retrieve configuration data into the given |config|.
- *
- * @param simNode The SIM node to process
- * @param config The config object to fill in the data
- * @throws IOException
- */
- private static void processSimNode(Node simNode, LegacyPasspointConfig config)
- throws IOException {
- if (simNode.getChildren() == null) {
- throw new IOException("SIM node should contain at least one child node");
- }
-
- for (Node node : simNode.getChildren()) {
- switch (node.getName()) {
- case TAG_IMSI:
- config.mImsi = getValue(node);
- break;
- default:
- Log.d(TAG, "Ignore uninterested field under SIM: " + node.getName());
- break;
- }
- }
- }
-
- /**
- * Parse the given line in the legacy Passpoint configuration file.
- * A line can be in the following formats:
- * 2:ab+ // internal node
- * 2:ab=2:bc // leaf node
- * . // end of internal node
- *
- * @param line The line to parse
- * @return name-value pair, a value of null indicates internal node
- * @throws IOException
- */
- private static Pair<String, String> parseLine(byte[] lineBytes) throws IOException {
- Pair<String, Integer> nameIndexPair = parseString(lineBytes, 0);
- int currentIndex = nameIndexPair.second;
- try {
- if (lineBytes[currentIndex] == START_OF_INTERNAL_NODE_INDICATOR) {
- return Pair.create(nameIndexPair.first, null);
- }
-
- if (lineBytes[currentIndex] != STRING_VALUE_INDICATOR) {
- throw new IOException("Invalid line - missing both node and value indicator: "
- + new String(lineBytes, StandardCharsets.UTF_8));
- }
- } catch (IndexOutOfBoundsException e) {
- throw new IOException("Invalid line - " + e.getMessage() + ": "
- + new String(lineBytes, StandardCharsets.UTF_8));
- }
- Pair<String, Integer> valueIndexPair = parseString(lineBytes, currentIndex + 1);
- return Pair.create(nameIndexPair.first, valueIndexPair.first);
- }
-
- /**
- * Parse a string value in the given line from the given start index.
- * A string value is in the following format:
- * |HexByteLength|:|String|
- *
- * The length value indicates the number of UTF-8 bytes in hex for the given string.
- *
- * For example: 3:abc
- *
- * @param lineBytes The UTF-8 bytes of the line to parse
- * @param startIndex The start index from the given line to parse from
- * @return Pair of a string value and an index pointed to character after the string value
- * @throws IOException
- */
- private static Pair<String, Integer> parseString(byte[] lineBytes, int startIndex)
- throws IOException {
- // Locate the index that separate length and the string value.
- int prefixIndex = -1;
- for (int i = startIndex; i < lineBytes.length; i++) {
- if (lineBytes[i] == STRING_PREFIX_INDICATOR) {
- prefixIndex = i;
- break;
- }
- }
- if (prefixIndex == -1) {
- throw new IOException("Invalid line - missing string prefix: "
- + new String(lineBytes, StandardCharsets.UTF_8));
- }
-
- try {
- String lengthStr = new String(lineBytes, startIndex, prefixIndex - startIndex,
- StandardCharsets.UTF_8);
- int length = Integer.parseInt(lengthStr, 16);
- int strStartIndex = prefixIndex + 1;
- // The length might account for bytes for the whitespaces, since the whitespaces are
- // already trimmed, ignore them.
- if ((strStartIndex + length) > lineBytes.length) {
- length = lineBytes.length - strStartIndex;
- }
- return Pair.create(
- new String(lineBytes, strStartIndex, length, StandardCharsets.UTF_8),
- strStartIndex + length);
- } catch (NumberFormatException | IndexOutOfBoundsException e) {
- throw new IOException("Invalid line - " + e.getMessage() + ": "
- + new String(lineBytes, StandardCharsets.UTF_8));
- }
- }
-
- /**
- * Parse a long array from the given string.
- *
- * @param str The string to parse
- * @return long[]
- * @throws IOException
- */
- private static long[] parseLongArray(String str)
- throws IOException {
- String[] strArray = str.split(LONG_ARRAY_SEPARATOR);
- long[] longArray = new long[strArray.length];
- for (int i = 0; i < longArray.length; i++) {
- try {
- longArray[i] = Long.parseLong(strArray[i], 16);
- } catch (NumberFormatException e) {
- throw new IOException("Invalid long integer value: " + strArray[i]);
- }
- }
- return longArray;
- }
-
- /**
- * Get the String value of the given node. An IOException will be thrown if the given
- * node doesn't contain a String value (internal node).
- *
- * @param node The node to get the value from
- * @return String
- * @throws IOException
- */
- private static String getValue(Node node) throws IOException {
- if (node.getValue() == null) {
- throw new IOException("Attempt to retreive value from non-leaf node: "
- + node.getName());
- }
- return node.getValue();
- }
-}
diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
index 957fc2294..46ec1597e 100644
--- a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
@@ -18,21 +18,23 @@ package com.android.server.wifi;
import static com.android.server.wifi.OpenNetworkNotifier.DEFAULT_REPEAT_DELAY_SEC;
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.wifi.ScanResult;
+import android.net.wifi.WifiManager;
+import android.os.Message;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.test.TestLooper;
@@ -41,7 +43,6 @@ import android.util.ArraySet;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -64,11 +65,13 @@ public class OpenNetworkNotifierTest {
@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 WifiStateMachine mWifiStateMachine;
@Mock private OpenNetworkRecommender mOpenNetworkRecommender;
+ @Mock private ConnectToNetworkNotificationBuilder mNotificationBuilder;
@Mock private UserManager mUserManager;
private OpenNetworkNotifier mNotificationController;
+ private TestLooper mLooper;
private BroadcastReceiver mBroadcastReceiver;
private ScanResult mDummyNetwork;
private List<ScanDetail> mOpenNetworks;
@@ -86,8 +89,6 @@ public class OpenNetworkNotifierTest {
when(mFrameworkFacade.getIntegerSetting(mContext,
Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, DEFAULT_REPEAT_DELAY_SEC))
.thenReturn(DEFAULT_REPEAT_DELAY_SEC);
- when(mFrameworkFacade.makeNotificationBuilder(any(), anyString()))
- .thenReturn(mNotificationBuilder);
when(mContext.getSystemService(Context.USER_SERVICE))
.thenReturn(mUserManager);
when(mContext.getResources()).thenReturn(mResources);
@@ -100,10 +101,10 @@ public class OpenNetworkNotifierTest {
mOpenNetworks.add(new ScanDetail(mDummyNetwork, null /* networkDetail */));
mBlacklistedSsids = new ArraySet<>();
- TestLooper mock_looper = new TestLooper();
+ mLooper = new TestLooper();
mNotificationController = new OpenNetworkNotifier(
- mContext, mock_looper.getLooper(), mFrameworkFacade, mClock, mWifiConfigManager,
- mWifiConfigStore, mOpenNetworkRecommender);
+ mContext, mLooper.getLooper(), mFrameworkFacade, mClock, mWifiConfigManager,
+ mWifiConfigStore, mWifiStateMachine, mOpenNetworkRecommender, mNotificationBuilder);
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
@@ -119,6 +120,7 @@ public class OpenNetworkNotifierTest {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
}
@@ -142,39 +144,48 @@ public class OpenNetworkNotifierTest {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.handleScanResults(new ArrayList<>());
verify(mNotificationManager).cancel(anyInt());
}
+
/**
- * When a notification is showing, screen is off, and scan results with no open networks are
- * handled, the notification is cleared.
+ * When a notification is showing and no recommendation is made for the new scan results, the
+ * notification is cleared.
*/
@Test
- public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() {
+ public void handleScanResults_notificationShown_noRecommendation_notificationCleared() {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
- mNotificationController.handleScreenStateChanged(false);
- mNotificationController.handleScanResults(new ArrayList<>());
+ when(mOpenNetworkRecommender.recommendNetwork(any(), any())).thenReturn(null);
+ mNotificationController.handleScanResults(mOpenNetworks);
verify(mNotificationManager).cancel(anyInt());
}
/**
- * If notification is showing, do not post another notification.
+ * When a notification is showing, screen is off, and scan results with no open networks are
+ * handled, the notification is cleared.
*/
@Test
- public void handleScanResults_notificationShowing_doesNotRepostNotification() {
- mNotificationController.handleScanResults(mOpenNetworks);
+ public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
+
+ mNotificationController.handleScreenStateChanged(false);
+ mNotificationController.handleScanResults(new ArrayList<>());
+
+ verify(mNotificationManager).cancel(anyInt());
}
/**
@@ -186,6 +197,7 @@ public class OpenNetworkNotifierTest {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.clearPendingNotification(true);
@@ -209,7 +221,7 @@ public class OpenNetworkNotifierTest {
* new scan results with open networks.
*/
@Test
- public void screenOff_handleScanResults_notificationNotDisplayed() {
+ public void screenOff_notificationNotShowing_handleScanResults_notificationNotDisplayed() {
mNotificationController.handleScreenStateChanged(false);
mNotificationController.handleScanResults(mOpenNetworks);
@@ -218,61 +230,69 @@ public class OpenNetworkNotifierTest {
}
/**
- * When a notification is posted and cleared without reseting delay, the next scan with open
- * networks should not post another notification.
+ * When screen is off and notification is displayed, the notification can be updated with a new
+ * recommendation.
*/
@Test
- public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() {
+ public void screenOff_notificationShowing_handleScanResults_recommendationCanBeUpdated() {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
- mNotificationController.clearPendingNotification(false);
-
+ mNotificationController.handleScreenStateChanged(false);
mNotificationController.handleScanResults(mOpenNetworks);
- // Recommendation made twice but no new notification posted.
+ // Recommendation made twice
verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
mOpenNetworks, mBlacklistedSsids);
- verify(mNotificationManager).notify(anyInt(), any());
- verify(mNotificationManager).cancel(anyInt());
+ verify(mNotificationBuilder, times(2)).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager, times(2)).notify(anyInt(), any());
}
/**
- * When a notification is posted and cleared without reseting delay, the next scan with open
- * networks should post a notification.
+ * When a notification is posted and cleared without resetting delay, the next scan with open
+ * networks should not post another notification.
*/
@Test
- public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() {
+ public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
- mNotificationController.clearPendingNotification(true);
+ mNotificationController.clearPendingNotification(false);
+
+ verify(mNotificationManager).cancel(anyInt());
mNotificationController.handleScanResults(mOpenNetworks);
- verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
- mOpenNetworks, mBlacklistedSsids);
- verify(mNotificationManager, times(2)).notify(anyInt(), any());
+ // no new notification posted
+ verify(mNotificationManager).notify(anyInt(), any());
}
/**
- * When a notification is tapped, open Wi-Fi settings.
+ * When a notification is posted and cleared without resetting delay, the next scan with open
+ * networks should post a notification.
*/
@Test
- public void notificationTap_opensWifiSettings() {
+ public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
- mBroadcastReceiver.onReceive(
- mContext, new Intent(OpenNetworkNotifier.ACTION_USER_TAPPED_CONTENT));
+ mNotificationController.clearPendingNotification(true);
+
+ mNotificationController.handleScanResults(mOpenNetworks);
- verify(mContext).startActivity(any());
+ verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
+ mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder, times(2)).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager, times(2)).notify(anyInt(), any());
}
/**
@@ -284,14 +304,18 @@ public class OpenNetworkNotifierTest {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
mBroadcastReceiver.onReceive(
- mContext, new Intent(OpenNetworkNotifier.ACTION_USER_DISMISSED_NOTIFICATION));
+ mContext,
+ new Intent(ConnectToNetworkNotificationBuilder.ACTION_USER_DISMISSED_NOTIFICATION));
verify(mWifiConfigManager).saveToStore(false /* forceWrite */);
- mNotificationController.handleScanResults(mOpenNetworks);
+ mNotificationController.clearPendingNotification(true);
+ List<ScanDetail> scanResults = mOpenNetworks;
+ mNotificationController.handleScanResults(scanResults);
Set<String> expectedBlacklist = new ArraySet<>();
expectedBlacklist.add(mDummyNetwork.SSID);
@@ -299,7 +323,7 @@ public class OpenNetworkNotifierTest {
}
/**
- * When a notification is posted and cleared without reseting delay, after the delay has passed
+ * When a notification is posted and cleared without resetting delay, after the delay has passed
* the next scan with open networks should post a notification.
*/
@Test
@@ -307,6 +331,7 @@ public class OpenNetworkNotifierTest {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
mNotificationController.clearPendingNotification(false);
@@ -318,6 +343,7 @@ public class OpenNetworkNotifierTest {
verify(mOpenNetworkRecommender, times(2)).recommendNetwork(
mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder, times(2)).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager, times(2)).notify(anyInt(), any());
}
@@ -339,6 +365,7 @@ public class OpenNetworkNotifierTest {
mNotificationController.handleScanResults(mOpenNetworks);
verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
verify(mNotificationManager).notify(anyInt(), any());
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
@@ -348,4 +375,174 @@ public class OpenNetworkNotifierTest {
verify(mNotificationManager).cancel(anyInt());
}
+
+ /**
+ * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} does not connect to
+ * any network if the initial notification is not showing.
+ */
+ @Test
+ public void actionConnectToNetwork_notificationNotShowing_doesNothing() {
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
+
+ verify(mWifiStateMachine, never()).sendMessage(any(Message.class));
+ }
+
+ /**
+ * {@link ConnectToNetworkNotificationBuilder#ACTION_CONNECT_TO_NETWORK} connects to the
+ * currently recommended network if it exists.
+ */
+ @Test
+ public void actionConnectToNetwork_currentRecommendationExists_connectsAndPostsNotification() {
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ // Initial Notification
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager).notify(anyInt(), any());
+
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
+
+ verify(mWifiStateMachine).sendMessage(any(Message.class));
+ // Connecting Notification
+ verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
+ verify(mNotificationManager, times(2)).notify(anyInt(), any());
+ }
+
+ /**
+ * {@link OpenNetworkNotifier#handleWifiConnected()} does not post connected notification if
+ * the connecting notification is not showing
+ */
+ @Test
+ public void networkConnectionSuccess_wasNotInConnectingFlow_doesNothing() {
+ mNotificationController.handleWifiConnected();
+
+ verify(mNotificationManager, never()).notify(anyInt(), any());
+ }
+
+ /**
+ * {@link OpenNetworkNotifier#handleWifiConnected()} clears notification that is not connecting.
+ */
+ @Test
+ public void networkConnectionSuccess_wasShowingNotification_clearsNotification() {
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ // Initial Notification
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager).notify(anyInt(), any());
+
+ mNotificationController.handleWifiConnected();
+
+ verify(mNotificationManager).cancel(anyInt());
+ }
+
+ /**
+ * {@link OpenNetworkNotifier#handleWifiConnected()} posts the connected notification if
+ * the connecting notification is showing.
+ */
+ @Test
+ public void networkConnectionSuccess_wasInConnectingFlow_postsConnectedNotification() {
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ // Initial Notification
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager).notify(anyInt(), any());
+
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
+
+ // Connecting Notification
+ verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
+ verify(mNotificationManager, times(2)).notify(anyInt(), any());
+
+ mNotificationController.handleWifiConnected();
+
+ // Connected Notification
+ verify(mNotificationBuilder).createNetworkConnectedNotification(mDummyNetwork);
+ verify(mNotificationManager, times(3)).notify(anyInt(), any());
+ }
+
+ /**
+ * {@link OpenNetworkNotifier#handleConnectionFailure()} posts the Failed to Connect
+ * notification if the connecting notification is showing.
+ */
+ @Test
+ public void networkConnectionFailure_wasNotInConnectingFlow_doesNothing() {
+ mNotificationController.handleConnectionFailure();
+
+ verify(mNotificationManager, never()).notify(anyInt(), any());
+ }
+
+ /**
+ * {@link OpenNetworkNotifier#handleConnectionFailure()} posts the Failed to Connect
+ * notification if the connecting notification is showing.
+ */
+ @Test
+ public void networkConnectionFailure_wasInConnectingFlow_postsFailedToConnectNotification() {
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ // Initial Notification
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager).notify(anyInt(), any());
+
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
+
+ // Connecting Notification
+ verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
+ verify(mNotificationManager, times(2)).notify(anyInt(), any());
+
+ mNotificationController.handleConnectionFailure();
+
+ // Failed to Connect Notification
+ verify(mNotificationBuilder).createNetworkFailedNotification();
+ verify(mNotificationManager, times(3)).notify(anyInt(), any());
+ }
+
+ /**
+ * When a {@link WifiManager#CONNECT_NETWORK_FAILED} is received from the connection callback
+ * of {@link WifiStateMachine#sendMessage(Message)}, a Failed to Connect notification should
+ * be posted. On tapping this notification, Wi-Fi Settings should be launched.
+ */
+ @Test
+ public void connectionFailedCallback_postsFailedToConnectNotification() throws RemoteException {
+ mNotificationController.handleScanResults(mOpenNetworks);
+
+ verify(mOpenNetworkRecommender).recommendNetwork(mOpenNetworks, mBlacklistedSsids);
+ // Initial Notification
+ verify(mNotificationBuilder).createConnectToNetworkNotification(mDummyNetwork);
+ verify(mNotificationManager).notify(anyInt(), any());
+
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(ConnectToNetworkNotificationBuilder.ACTION_CONNECT_TO_NETWORK));
+
+ ArgumentCaptor<Message> connectMessageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mWifiStateMachine).sendMessage(connectMessageCaptor.capture());
+ Message connectMessage = connectMessageCaptor.getValue();
+
+ // Connecting Notification
+ verify(mNotificationBuilder).createNetworkConnectingNotification(mDummyNetwork);
+ verify(mNotificationManager, times(2)).notify(anyInt(), any());
+
+ Message connectFailedMsg = Message.obtain();
+ connectFailedMsg.what = WifiManager.CONNECT_NETWORK_FAILED;
+ connectMessage.replyTo.send(connectFailedMsg);
+ mLooper.dispatchAll();
+
+ // Failed to Connect Notification
+ verify(mNotificationBuilder).createNetworkFailedNotification();
+ verify(mNotificationManager, times(3)).notify(anyInt(), any());
+
+ mBroadcastReceiver.onReceive(mContext,
+ new Intent(ConnectToNetworkNotificationBuilder
+ .ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE));
+
+ ArgumentCaptor<Intent> pickerIntentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivity(pickerIntentCaptor.capture());
+ assertEquals(pickerIntentCaptor.getValue().getAction(), Settings.ACTION_WIFI_SETTINGS);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 70f660e8e..d14c8fc9f 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -43,7 +43,6 @@ import android.text.TextUtils;
import android.util.Pair;
import com.android.internal.R;
-import com.android.server.wifi.WifiConfigStoreLegacy.WifiConfigStoreDataLegacy;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;
@@ -101,7 +100,6 @@ public class WifiConfigManagerTest {
@Mock private TelephonyManager mTelephonyManager;
@Mock private WifiKeyStore mWifiKeyStore;
@Mock private WifiConfigStore mWifiConfigStore;
- @Mock private WifiConfigStoreLegacy mWifiConfigStoreLegacy;
@Mock private PackageManager mPackageManager;
@Mock private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
@Mock private WifiPermissionsUtil mWifiPermissionsUtil;
@@ -2539,74 +2537,6 @@ public class WifiConfigManagerTest {
}
/**
- * Verifies the loading of networks using {@link WifiConfigManager#migrateFromLegacyStore()} ()}
- * attempts to migrate data from legacy stores when the legacy store files are present.
- */
- @Test
- public void testMigrationFromLegacyStore() throws Exception {
- // Create the store data to be returned from legacy stores.
- List<WifiConfiguration> networks = new ArrayList<>();
- networks.add(WifiConfigurationTestUtil.createPskNetwork());
- networks.add(WifiConfigurationTestUtil.createEapNetwork());
- networks.add(WifiConfigurationTestUtil.createWepNetwork());
- String deletedEphemeralSSID = "EphemeralSSID";
- Set<String> deletedEphermalSSIDs = new HashSet<>(Arrays.asList(deletedEphemeralSSID));
- WifiConfigStoreDataLegacy storeData =
- new WifiConfigStoreDataLegacy(networks, deletedEphermalSSIDs);
-
- when(mWifiConfigStoreLegacy.areStoresPresent()).thenReturn(true);
- when(mWifiConfigStore.areStoresPresent()).thenReturn(false);
- when(mWifiConfigStoreLegacy.read()).thenReturn(storeData);
-
- // Now trigger the migration from legacy store. This should populate the in memory list with
- // all the networks above from the legacy store.
- assertTrue(mWifiConfigManager.migrateFromLegacyStore());
-
- verify(mWifiConfigStoreLegacy).read();
- verify(mWifiConfigStoreLegacy).removeStores();
-
- List<WifiConfiguration> retrievedNetworks =
- mWifiConfigManager.getConfiguredNetworksWithPasswords();
- WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- networks, retrievedNetworks);
- assertTrue(mWifiConfigManager.wasEphemeralNetworkDeleted(deletedEphemeralSSID));
- }
-
- /**
- * Verifies the loading of networks using {@link WifiConfigManager#migrateFromLegacyStore()} ()}
- * does not attempt to migrate data from legacy stores when the legacy store files are absent
- * (i.e migration was already done once).
- */
- @Test
- public void testNoDuplicateMigrationFromLegacyStore() throws Exception {
- when(mWifiConfigStoreLegacy.areStoresPresent()).thenReturn(false);
-
- // Now trigger a migration from legacy store.
- assertTrue(mWifiConfigManager.migrateFromLegacyStore());
-
- verify(mWifiConfigStoreLegacy, never()).read();
- verify(mWifiConfigStoreLegacy, never()).removeStores();
- }
-
- /**
- * Verifies the loading of networks using {@link WifiConfigManager#migrateFromLegacyStore()} ()}
- * does not attempt to migrate data from legacy stores when the new store files are present
- * (i.e migration was already done once).
- */
- @Test
- public void testNewStoreFilesPresentNoMigrationFromLegacyStore() throws Exception {
- when(mWifiConfigStore.areStoresPresent()).thenReturn(true);
- when(mWifiConfigStoreLegacy.areStoresPresent()).thenReturn(true);
-
- // Now trigger a migration from legacy store.
- assertTrue(mWifiConfigManager.migrateFromLegacyStore());
-
- verify(mWifiConfigStoreLegacy, never()).read();
- // Verify that we went ahead and deleted the old store files.
- verify(mWifiConfigStoreLegacy).removeStores();
- }
-
- /**
* Verifies the loading of networks using {@link WifiConfigManager#loadFromStore()} does
* not attempt to read from any of the stores (new or legacy) when the store files are
* not present.
@@ -2614,12 +2544,10 @@ public class WifiConfigManagerTest {
@Test
public void testFreshInstallDoesNotLoadFromStore() throws Exception {
when(mWifiConfigStore.areStoresPresent()).thenReturn(false);
- when(mWifiConfigStoreLegacy.areStoresPresent()).thenReturn(false);
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore, never()).read();
- verify(mWifiConfigStoreLegacy, never()).read();
assertTrue(mWifiConfigManager.getConfiguredNetworksWithPasswords().isEmpty());
}
@@ -2632,11 +2560,9 @@ public class WifiConfigManagerTest {
public void testHandleUserSwitchAfterFreshInstall() throws Exception {
int user2 = TEST_DEFAULT_USER + 1;
when(mWifiConfigStore.areStoresPresent()).thenReturn(false);
- when(mWifiConfigStoreLegacy.areStoresPresent()).thenReturn(false);
assertTrue(mWifiConfigManager.loadFromStore());
verify(mWifiConfigStore, never()).read();
- verify(mWifiConfigStoreLegacy, never()).read();
setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// Now switch the user to user 2.
@@ -3395,7 +3321,7 @@ public class WifiConfigManagerTest {
mWifiConfigManager =
new WifiConfigManager(
mContext, mClock, mUserManager, mTelephonyManager,
- mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy,
+ mWifiKeyStore, mWifiConfigStore,
mWifiPermissionsUtil, mWifiPermissionsWrapper, mNetworkListStoreData,
mDeletedEphemeralSsidsStoreData);
mWifiConfigManager.enableVerboseLogging(1);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreLegacyTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreLegacyTest.java
deleted file mode 100644
index 4b4e875a1..000000000
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreLegacyTest.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wifi;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-import android.app.test.MockAnswerUtil.AnswerWithArguments;
-import android.net.IpConfiguration;
-import android.net.wifi.WifiConfiguration;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.text.TextUtils;
-import android.util.SparseArray;
-
-import com.android.server.net.IpConfigStore;
-import com.android.server.wifi.hotspot2.LegacyPasspointConfig;
-import com.android.server.wifi.hotspot2.LegacyPasspointConfigParser;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Unit tests for {@link com.android.server.wifi.WifiConfigStoreLegacy}.
- */
-@SmallTest
-public class WifiConfigStoreLegacyTest {
- private static final String MASKED_FIELD_VALUE = "*";
-
- // Test mocks
- @Mock private WifiNative mWifiNative;
- @Mock private WifiNetworkHistory mWifiNetworkHistory;
- @Mock private IpConfigStore mIpconfigStore;
- @Mock private LegacyPasspointConfigParser mPasspointConfigParser;
-
- /**
- * Test instance of WifiConfigStore.
- */
- private WifiConfigStoreLegacy mWifiConfigStore;
-
-
- /**
- * Setup the test environment.
- */
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- mWifiConfigStore = new WifiConfigStoreLegacy(mWifiNetworkHistory, mWifiNative,
- mIpconfigStore, mPasspointConfigParser);
- }
-
- /**
- * Called after each test
- */
- @After
- public void cleanup() {
- validateMockitoUsage();
- }
-
- /**
- * Verify loading of network configurations from legacy stores. This is verifying the population
- * of the masked wpa_supplicant fields using wpa_supplicant.conf file.
- */
- @Test
- public void testLoadFromStores() throws Exception {
- WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork();
- WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
- WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
- WifiConfiguration passpointNetwork = WifiConfigurationTestUtil.createPasspointNetwork();
- eapNetwork.enterpriseConfig.setPassword("EapPassword");
-
- // Initialize Passpoint configuration data.
- int passpointNetworkId = 1234;
- String fqdn = passpointNetwork.FQDN;
- String providerFriendlyName = passpointNetwork.providerFriendlyName;
- long[] roamingConsortiumIds = new long[] {0x1234, 0x5678};
- String realm = "test.com";
- String imsi = "214321";
-
- // Update Passpoint network.
- // Network ID is used for lookup network extras, so use an unique ID for passpoint network.
- passpointNetwork.networkId = passpointNetworkId;
- passpointNetwork.enterpriseConfig.setPassword("PaspointPassword");
- // Reset FQDN and provider friendly name so that the derived network from #read will
- // obtained these information from networkExtras and {@link LegacyPasspointConfigParser}.
- passpointNetwork.FQDN = null;
- passpointNetwork.providerFriendlyName = null;
-
- final List<WifiConfiguration> networks = new ArrayList<>();
- networks.add(pskNetwork);
- networks.add(wepNetwork);
- networks.add(eapNetwork);
- networks.add(passpointNetwork);
-
- // Setup legacy Passpoint configuration data.
- Map<String, LegacyPasspointConfig> passpointConfigs = new HashMap<>();
- LegacyPasspointConfig passpointConfig = new LegacyPasspointConfig();
- passpointConfig.mFqdn = fqdn;
- passpointConfig.mFriendlyName = providerFriendlyName;
- passpointConfig.mRoamingConsortiumOis = roamingConsortiumIds;
- passpointConfig.mRealm = realm;
- passpointConfig.mImsi = imsi;
- passpointConfigs.put(fqdn, passpointConfig);
-
- // Return the config data with passwords masked from wpa_supplicant control interface.
- doAnswer(new AnswerWithArguments() {
- public boolean answer(Map<String, WifiConfiguration> configs,
- SparseArray<Map<String, String>> networkExtras) {
- for (Map.Entry<String, WifiConfiguration> entry:
- createWpaSupplicantLoadData(networks).entrySet()) {
- configs.put(entry.getKey(), entry.getValue());
- }
- // Setup networkExtras for Passpoint configuration.
- networkExtras.put(passpointNetworkId, createNetworkExtrasForPasspointConfig(fqdn));
- return true;
- }
- }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class));
-
- when(mPasspointConfigParser.parseConfig(anyString())).thenReturn(passpointConfigs);
- WifiConfigStoreLegacy.WifiConfigStoreDataLegacy storeData = mWifiConfigStore.read();
-
- // Update the expected configuration for Passpoint network.
- passpointNetwork.isLegacyPasspointConfig = true;
- passpointNetwork.FQDN = fqdn;
- passpointNetwork.providerFriendlyName = providerFriendlyName;
- passpointNetwork.roamingConsortiumIds = roamingConsortiumIds;
- passpointNetwork.enterpriseConfig.setRealm(realm);
- passpointNetwork.enterpriseConfig.setPlmn(imsi);
-
- WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
- networks, storeData.getConfigurations());
- }
-
- private SparseArray<IpConfiguration> createIpConfigStoreLoadData(
- List<WifiConfiguration> configurations) {
- SparseArray<IpConfiguration> newIpConfigurations = new SparseArray<>();
- for (WifiConfiguration config : configurations) {
- newIpConfigurations.put(
- config.configKey().hashCode(),
- new IpConfiguration(config.getIpConfiguration()));
- }
- return newIpConfigurations;
- }
-
- private Map<String, String> createPskMap(List<WifiConfiguration> configurations) {
- Map<String, String> pskMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- if (!TextUtils.isEmpty(config.preSharedKey)) {
- pskMap.put(config.configKey(), config.preSharedKey);
- }
- }
- return pskMap;
- }
-
- private Map<String, String> createWepKey0Map(List<WifiConfiguration> configurations) {
- Map<String, String> wepKeyMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- if (!TextUtils.isEmpty(config.wepKeys[0])) {
- wepKeyMap.put(config.configKey(), config.wepKeys[0]);
- }
- }
- return wepKeyMap;
- }
-
- private Map<String, String> createWepKey1Map(List<WifiConfiguration> configurations) {
- Map<String, String> wepKeyMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- if (!TextUtils.isEmpty(config.wepKeys[1])) {
- wepKeyMap.put(config.configKey(), config.wepKeys[1]);
- }
- }
- return wepKeyMap;
- }
-
- private Map<String, String> createWepKey2Map(List<WifiConfiguration> configurations) {
- Map<String, String> wepKeyMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- if (!TextUtils.isEmpty(config.wepKeys[2])) {
- wepKeyMap.put(config.configKey(), config.wepKeys[2]);
- }
- }
- return wepKeyMap;
- }
-
- private Map<String, String> createWepKey3Map(List<WifiConfiguration> configurations) {
- Map<String, String> wepKeyMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- if (!TextUtils.isEmpty(config.wepKeys[3])) {
- wepKeyMap.put(config.configKey(), config.wepKeys[3]);
- }
- }
- return wepKeyMap;
- }
-
- private Map<String, String> createEapPasswordMap(List<WifiConfiguration> configurations) {
- Map<String, String> eapPasswordMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- if (!TextUtils.isEmpty(config.enterpriseConfig.getPassword())) {
- eapPasswordMap.put(config.configKey(), config.enterpriseConfig.getPassword());
- }
- }
- return eapPasswordMap;
- }
-
- private Map<String, WifiConfiguration> createWpaSupplicantLoadData(
- List<WifiConfiguration> configurations) {
- Map<String, WifiConfiguration> configurationMap = new HashMap<>();
- for (WifiConfiguration config : configurations) {
- configurationMap.put(config.configKey(true), config);
- }
- return configurationMap;
- }
-
- private List<WifiConfiguration> createMaskedWifiConfigurations(
- List<WifiConfiguration> configurations) {
- List<WifiConfiguration> newConfigurations = new ArrayList<>();
- for (WifiConfiguration config : configurations) {
- newConfigurations.add(createMaskedWifiConfiguration(config));
- }
- return newConfigurations;
- }
-
- private WifiConfiguration createMaskedWifiConfiguration(WifiConfiguration configuration) {
- WifiConfiguration newConfig = new WifiConfiguration(configuration);
- if (!TextUtils.isEmpty(configuration.preSharedKey)) {
- newConfig.preSharedKey = MASKED_FIELD_VALUE;
- }
- if (!TextUtils.isEmpty(configuration.wepKeys[0])) {
- newConfig.wepKeys[0] = MASKED_FIELD_VALUE;
- }
- if (!TextUtils.isEmpty(configuration.wepKeys[1])) {
- newConfig.wepKeys[1] = MASKED_FIELD_VALUE;
- }
- if (!TextUtils.isEmpty(configuration.wepKeys[2])) {
- newConfig.wepKeys[2] = MASKED_FIELD_VALUE;
- }
- if (!TextUtils.isEmpty(configuration.wepKeys[3])) {
- newConfig.wepKeys[3] = MASKED_FIELD_VALUE;
- }
- if (!TextUtils.isEmpty(configuration.enterpriseConfig.getPassword())) {
- newConfig.enterpriseConfig.setPassword(MASKED_FIELD_VALUE);
- }
- return newConfig;
- }
-
- private Map<String, String> createNetworkExtrasForPasspointConfig(String fqdn) {
- Map<String, String> extras = new HashMap<>();
- extras.put(SupplicantStaNetworkHal.ID_STRING_KEY_FQDN, fqdn);
- return extras;
- }
-}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index a8278d365..6420fac88 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -614,7 +614,7 @@ public class WifiConnectivityManagerTest {
* Expected behavior: ONA handles scan results
*/
@Test
- public void wifiDisconnected_noConnectionCandidate_openNetworkNotificationScanResultsHandled() {
+ public void wifiDisconnected_noConnectionCandidate_openNetworkNotifierScanResultsHandled() {
// no connection candidate selected
when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
anyBoolean(), anyBoolean())).thenReturn(null);
@@ -637,18 +637,17 @@ public class WifiConnectivityManagerTest {
}
/**
- * When wifi is connected, {@link OpenNetworkNotifier} tries to clear the pending
- * notification and does not reset notification repeat delay.
+ * When wifi is connected, {@link OpenNetworkNotifier} handles the Wi-Fi connected behavior.
*
- * Expected behavior: ONA clears pending notification and does not reset repeat delay.
+ * Expected behavior: ONA handles connected behavior
*/
@Test
- public void wifiConnected_openNetworkNotificationClearsPendingNotification() {
+ public void wifiConnected_openNetworkNotifierHandlesConnection() {
// Set WiFi to connected state
mWifiConnectivityManager.handleConnectionStateChanged(
WifiConnectivityManager.WIFI_STATE_CONNECTED);
- verify(mOpenNetworkNotifier).clearPendingNotification(false /* isRepeatDelayReset*/);
+ verify(mOpenNetworkNotifier).handleWifiConnected();
}
/**
@@ -658,7 +657,7 @@ public class WifiConnectivityManagerTest {
* Expected behavior: ONA does not clear pending notification.
*/
@Test
- public void wifiDisconnected_openNetworkNotificationDoesNotClearPendingNotification() {
+ public void wifiDisconnected_openNetworkNotifierDoesNotClearPendingNotification() {
// Set WiFi to disconnected state
mWifiConnectivityManager.handleConnectionStateChanged(
WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
@@ -667,22 +666,52 @@ public class WifiConnectivityManagerTest {
}
/**
+ * When a Wi-Fi connection attempt ends, {@link OpenNetworkNotifier} handles the connection
+ * failure. A failure code that is not {@link WifiMetrics.ConnectionEvent#FAILURE_NONE}
+ * represents a connection failure.
+ *
+ * Expected behavior: ONA handles connection failure.
+ */
+ @Test
+ public void wifiConnectionEndsWithFailure_openNetworkNotifierHandlesConnectionFailure() {
+ mWifiConnectivityManager.handleConnectionAttemptEnded(
+ WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED);
+
+ verify(mOpenNetworkNotifier).handleConnectionFailure();
+ }
+
+ /**
+ * When a Wi-Fi connection attempt ends, {@link OpenNetworkNotifier} does not handle connection
+ * failure after a successful connection. {@link WifiMetrics.ConnectionEvent#FAILURE_NONE}
+ * represents a successful connection.
+ *
+ * Expected behavior: ONA does nothing.
+ */
+ @Test
+ public void wifiConnectionEndsWithSuccess_openNetworkNotifierDoesNotHandleConnectionFailure() {
+ mWifiConnectivityManager.handleConnectionAttemptEnded(
+ WifiMetrics.ConnectionEvent.FAILURE_NONE);
+
+ verify(mOpenNetworkNotifier, never()).handleConnectionFailure();
+ }
+
+ /**
* When Wi-Fi is disabled, clear the pending notification and reset notification repeat delay.
*
* Expected behavior: clear pending notification and reset notification repeat delay
* */
@Test
- public void openNetworkNotificationControllerToggledOnWifiStateChanges() {
+ public void openNetworkNotifierClearsPendingNotificationOnWifiDisabled() {
mWifiConnectivityManager.setWifiEnabled(false);
- verify(mOpenNetworkNotifier).clearPendingNotification(true /* isRepeatDelayReset */);
+ verify(mOpenNetworkNotifier).clearPendingNotification(true /* resetRepeatDelay */);
}
/**
* Verify that the ONA controller tracks screen state changes.
*/
@Test
- public void openNetworkNotificationControllerTracksScreenStateChanges() {
+ public void openNetworkNotifierTracksScreenStateChanges() {
mWifiConnectivityManager.handleScreenStateChanged(false);
verify(mOpenNetworkNotifier).handleScreenStateChanged(false);
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/LegacyPasspointConfigParserTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/LegacyPasspointConfigParserTest.java
deleted file mode 100644
index 10ebceb22..000000000
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/LegacyPasspointConfigParserTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.hotspot2;
-
-import static org.junit.Assert.*;
-
-import android.os.FileUtils;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import org.junit.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Unit tests for {@link com.android.server.wifi.hotspot2.LegacyPasspointConfigParser}.
- */
-@SmallTest
-public class LegacyPasspointConfigParserTest {
- private static final String TEST_CONFIG =
- "tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)\n"
- + "8:MgmtTree+\n"
- + "17:PerProviderSubscription+\n"
- + "4:r1i1+\n"
- + "6:HomeSP+\n"
- + "c:FriendlyName=12:Test Provider 1™\n"
- + "4:FQDN=9:test1.net\n"
- + "13:RoamingConsortiumOI=9:1234,5678\n"
- + ".\n"
- + "a:Credential+\n"
- + "10:UsernamePassword+\n"
- + "8:Username=5:user1\n"
- + "8:Password=5:pass1\n"
- + "\n"
- + "9:EAPMethod+\n"
- + "7:EAPType=2:21\n"
- + "b:InnerMethod=3:PAP\n"
- + ".\n"
- + ".\n"
- + "5:Realm=9:test1.com\n"
- + ".\n"
- + ".\n"
- + ".\n"
- + "17:PerProviderSubscription+\n"
- + "4:r1i2+\n"
- + "6:HomeSP+\n"
- + "c:FriendlyName=f:Test Provider 2\n"
- + "4:FQDN=9:test2.net\n"
- + ".\n"
- + "a:Credential+\n"
- + "3:SIM+\n"
- + "4:IMSI=4:1234\n"
- + "7:EAPType=2:18\n"
- + ".\n"
- + "5:Realm=9:test2.com\n"
- + ".\n"
- + ".\n"
- + ".\n"
- + ".\n";
-
- /**
- * Helper function for generating {@link LegacyPasspointConfig} objects based on the predefined
- * test configuration string {@link #TEST_CONFIG}
- *
- * @return Map of FQDN to {@link LegacyPasspointConfig}
- */
- private Map<String, LegacyPasspointConfig> generateTestConfig() {
- Map<String, LegacyPasspointConfig> configs = new HashMap<>();
-
- LegacyPasspointConfig config1 = new LegacyPasspointConfig();
- config1.mFqdn = "test1.net";
- config1.mFriendlyName = "Test Provider 1™";
- config1.mRoamingConsortiumOis = new long[] {0x1234, 0x5678};
- config1.mRealm = "test1.com";
- configs.put("test1.net", config1);
-
- LegacyPasspointConfig config2 = new LegacyPasspointConfig();
- config2.mFqdn = "test2.net";
- config2.mFriendlyName = "Test Provider 2";
- config2.mRealm = "test2.com";
- config2.mImsi = "1234";
- configs.put("test2.net", config2);
-
- return configs;
- }
-
- /**
- * Helper function for parsing configuration data.
- *
- * @param data The configuration data to parse
- * @return Map of FQDN to {@link LegacyPasspointConfig}
- * @throws Exception
- */
- private Map<String, LegacyPasspointConfig> parseConfig(String data) throws Exception {
- // Write configuration data to file.
- File configFile = File.createTempFile("LegacyPasspointConfig", "");
- FileUtils.stringToFile(configFile, data);
-
- // Parse the configuration file.
- LegacyPasspointConfigParser parser = new LegacyPasspointConfigParser();
- Map<String, LegacyPasspointConfig> configMap =
- parser.parseConfig(configFile.getAbsolutePath());
-
- configFile.delete();
- return configMap;
- }
-
- /**
- * Verify that the expected {@link LegacyPasspointConfig} objects are return when parsing
- * predefined test configuration data {@link #TEST_CONFIG}.
- *
- * @throws Exception
- */
- @Test
- public void parseTestConfig() throws Exception {
- Map<String, LegacyPasspointConfig> parsedConfig = parseConfig(TEST_CONFIG);
- assertEquals(generateTestConfig(), parsedConfig);
- }
-
- /**
- * Verify that an empty map is return when parsing a configuration containing an empty
- * configuration (MgmtTree).
- *
- * @throws Exception
- */
- @Test
- public void parseEmptyConfig() throws Exception {
- String emptyConfig = "tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)\n"
- + "8:MgmtTree+\n"
- + ".\n";
- Map<String, LegacyPasspointConfig> parsedConfig = parseConfig(emptyConfig);
- assertTrue(parsedConfig.isEmpty());
- }
-
- /**
- * Verify that an empty map is return when parsing an empty configuration data.
- *
- * @throws Exception
- */
- @Test
- public void parseEmptyData() throws Exception {
- Map<String, LegacyPasspointConfig> parsedConfig = parseConfig("");
- assertTrue(parsedConfig.isEmpty());
- }
-
- /**
- * Verify that an IOException is thrown when parsing a configuration containing an unknown
- * root name. The expected root name is "MgmtTree".
- *
- * @throws Exception
- */
- @Test(expected = IOException.class)
- public void parseConfigWithUnknownRootName() throws Exception {
- String config = "tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)\n"
- + "8:TestTest+\n"
- + ".\n";
- parseConfig(config);
- }
-
- /**
- * Verify that an IOException is thrown when parsing a configuration containing a line with
- * mismatched string length for the name.
- *
- * @throws Exception
- */
- @Test(expected = IOException.class)
- public void parseConfigWithMismatchedStringLengthInName() throws Exception {
- String config = "tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)\n"
- + "9:MgmtTree+\n"
- + ".\n";
- parseConfig(config);
- }
-
- /**
- * Verify that an IOException is thrown when parsing a configuration containing a line with
- * mismatched string length for the value.
- *
- * @throws Exception
- */
- @Test(expected = IOException.class)
- public void parseConfigWithMismatchedStringLengthInValue() throws Exception {
- String config = "tree 3:1.2(urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0)\n"
- + "8:MgmtTree+\n"
- + "4:test=5:test\n"
- + ".\n";
- parseConfig(config);
- }
-}