Merge changes Ifa1eef1f,If59ecbd3,Ie3e640f6 into oc-mr1-dev

* changes:
  ONA: Refactor notification builder and register broadcast receiver.
  ONA: Rename WifiNotificationController to OpenNetworkNotifier
  ONA: Recommend a network using rssi strength.
diff --git a/service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java b/service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java
new file mode 100644
index 0000000..5963b57
--- /dev/null
+++ b/service/java/com/android/server/wifi/OpenNetworkNotificationBuilder.java
@@ -0,0 +1,91 @@
+/*
+ * 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
new file mode 100644
index 0000000..fc144c1
--- /dev/null
+++ b/service/java/com/android/server/wifi/OpenNetworkNotifier.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2013 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.annotation.NonNull;
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.wifi.ScanResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Takes care of handling the "open wi-fi network available" notification
+ * @hide
+ */
+public class 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";
+
+    /**
+     * The {@link Clock#getWallClockMillis()} must be at least this value for us
+     * to show the notification again.
+     */
+    private long mNotificationRepeatTime;
+    /**
+     * When a notification is shown, we wait this amount before possibly showing it again.
+     */
+    private final long mNotificationRepeatDelay;
+    /** Default repeat delay in seconds. */
+    @VisibleForTesting
+    static final int DEFAULT_REPEAT_DELAY_SEC = 900;
+
+    /** 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;
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final FrameworkFacade mFrameworkFacade;
+    private final Clock mClock;
+    private final OpenNetworkRecommender mOpenNetworkRecommender;
+    private final OpenNetworkNotificationBuilder mOpenNetworkNotificationBuilder;
+
+    private ScanResult mRecommendedNetwork;
+
+    OpenNetworkNotifier(
+            Context context,
+            Looper looper,
+            FrameworkFacade framework,
+            Clock clock,
+            OpenNetworkRecommender openNetworkRecommender) {
+        mContext = context;
+        mHandler = new Handler(looper);
+        mFrameworkFacade = framework;
+        mClock = clock;
+        mOpenNetworkRecommender = openNetworkRecommender;
+        mOpenNetworkNotificationBuilder = new OpenNetworkNotificationBuilder(context, framework);
+        mScreenOn = false;
+
+        // Setting is in seconds
+        mNotificationRepeatDelay = mFrameworkFacade.getIntegerSetting(context,
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+                DEFAULT_REPEAT_DELAY_SEC) * 1000L;
+        NotificationEnabledSettingObserver settingObserver = new NotificationEnabledSettingObserver(
+                mHandler);
+        settingObserver.register();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_USER_DISMISSED_NOTIFICATION);
+        filter.addAction(ACTION_USER_TAPPED_CONTENT);
+        mContext.registerReceiver(
+                mBroadcastReceiver, filter, null /* broadcastPermission */, mHandler);
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver =
+            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();
+                    }
+                }
+            };
+
+    /**
+     * Clears the pending notification. This is called by {@link WifiConnectivityManager} on stop.
+     *
+     * @param resetRepeatDelay resets the time delay for repeated notification if true.
+     */
+    public void clearPendingNotification(boolean resetRepeatDelay) {
+        if (resetRepeatDelay) {
+            mNotificationRepeatTime = 0;
+        }
+
+        if (mNotificationShown) {
+            getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_AVAILABLE);
+            mRecommendedNetwork = null;
+            mNotificationShown = false;
+        }
+    }
+
+    private boolean isControllerEnabled() {
+        return mSettingEnabled && !UserManager.get(mContext)
+                .hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT);
+    }
+
+    /**
+     * If there are open networks, attempt to post an open network notification.
+     *
+     * @param availableNetworks Available networks from
+     * {@link WifiNetworkSelector.NetworkEvaluator#getFilteredScanDetailsForOpenUnsavedNetworks()}.
+     */
+    public void handleScanResults(@NonNull List<ScanDetail> availableNetworks) {
+        if (!isControllerEnabled()) {
+            clearPendingNotification(true /* resetRepeatDelay */);
+            return;
+        }
+        if (availableNetworks.isEmpty()) {
+            clearPendingNotification(false /* resetRepeatDelay */);
+            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) {
+            return;
+        }
+
+        mRecommendedNetwork = mOpenNetworkRecommender.recommendNetwork(
+                availableNetworks, mRecommendedNetwork);
+
+        postNotification(availableNetworks.size());
+    }
+
+    /** Handles screen state changes. */
+    public void handleScreenStateChanged(boolean screenOn) {
+        mScreenOn = screenOn;
+    }
+
+    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) {
+            return;
+        }
+
+        getNotificationManager().notify(
+                SystemMessage.NOTE_NETWORK_AVAILABLE,
+                mOpenNetworkNotificationBuilder.createOpenNetworkAvailableNotification(
+                        numNetworks));
+        mNotificationShown = true;
+        mNotificationRepeatTime = mClock.getWallClockMillis() + mNotificationRepeatDelay;
+    }
+
+    /** Opens Wi-Fi picker. */
+    private void handleUserClickedContentAction() {
+        mNotificationShown = false;
+        mContext.startActivity(
+                new Intent(Settings.ACTION_WIFI_SETTINGS)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+    }
+
+    /** A delay is set before the next shown notification after user dismissal. */
+    private void handleUserDismissedAction() {
+        mNotificationShown = false;
+    }
+
+    /** Dump ONA controller state. */
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("OpenNetworkNotifier: ");
+        pw.println("mSettingEnabled " + mSettingEnabled);
+        pw.println("currentTime: " + mClock.getWallClockMillis());
+        pw.println("mNotificationRepeatTime: " + mNotificationRepeatTime);
+        pw.println("mNotificationShown: " + mNotificationShown);
+    }
+
+    private class NotificationEnabledSettingObserver extends ContentObserver {
+        NotificationEnabledSettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void register() {
+            mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor(
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this);
+            mSettingEnabled = getValue();
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            mSettingEnabled = getValue();
+            clearPendingNotification(true /* resetRepeatDelay */);
+        }
+
+        private boolean getValue() {
+            return mFrameworkFacade.getIntegerSetting(mContext,
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1) == 1;
+        }
+    }
+}
diff --git a/service/java/com/android/server/wifi/OpenNetworkRecommender.java b/service/java/com/android/server/wifi/OpenNetworkRecommender.java
new file mode 100644
index 0000000..cd460e5
--- /dev/null
+++ b/service/java/com/android/server/wifi/OpenNetworkRecommender.java
@@ -0,0 +1,62 @@
+/*
+ * 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.annotation.NonNull;
+import android.net.wifi.ScanResult;
+
+import java.util.List;
+
+/**
+ * Helps recommend the best available network for {@link OpenNetworkNotifier}.
+ * @hide
+ */
+public class OpenNetworkRecommender {
+
+    /**
+     * Recommends the network with the best signal strength.
+     *
+     * @param networks List of scan details to pick a recommendation. This list should not be null
+     *                 or empty.
+     * @param currentRecommendation The currently recommended network.
+     */
+    public ScanResult recommendNetwork(
+            @NonNull List<ScanDetail> networks, ScanResult currentRecommendation) {
+        ScanResult currentUpdatedRecommendation = null;
+        ScanResult result = null;
+        int highestRssi = Integer.MIN_VALUE;
+        for (ScanDetail scanDetail : networks) {
+            ScanResult scanResult = scanDetail.getScanResult();
+
+            if (currentRecommendation != null
+                    && currentRecommendation.SSID.equals(scanResult.SSID)) {
+                currentUpdatedRecommendation = scanResult;
+            }
+
+            if (scanResult.level > highestRssi) {
+                result = scanResult;
+                highestRssi = scanResult.level;
+            }
+        }
+        if (currentUpdatedRecommendation != null
+                && currentUpdatedRecommendation.level >= result.level) {
+            return currentUpdatedRecommendation;
+        } else {
+            return result;
+        }
+    }
+}
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 1cdc549..9603357 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -133,7 +133,7 @@
     private final WifiConnectivityHelper mConnectivityHelper;
     private final WifiNetworkSelector mNetworkSelector;
     private final WifiLastResortWatchdog mWifiLastResortWatchdog;
-    private final WifiNotificationController mWifiNotificationController;
+    private final OpenNetworkNotifier mOpenNetworkNotifier;
     private final WifiMetrics mWifiMetrics;
     private final AlarmManager mAlarmManager;
     private final Handler mEventHandler;
@@ -270,7 +270,7 @@
             return true;
         } else {
             if (mWifiState == WIFI_STATE_DISCONNECTED) {
-                mWifiNotificationController.handleScanResults(
+                mOpenNetworkNotifier.handleScanResults(
                         mNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks());
             }
             return false;
@@ -540,7 +540,7 @@
             WifiScanner scanner, WifiConfigManager configManager, WifiInfo wifiInfo,
             WifiNetworkSelector networkSelector, WifiConnectivityHelper connectivityHelper,
             WifiLastResortWatchdog wifiLastResortWatchdog,
-            WifiNotificationController wifiNotificationController, WifiMetrics wifiMetrics,
+            OpenNetworkNotifier openNetworkNotifier, WifiMetrics wifiMetrics,
             Looper looper, Clock clock, LocalLog localLog, boolean enable,
             FrameworkFacade frameworkFacade,
             SavedNetworkEvaluator savedNetworkEvaluator,
@@ -554,7 +554,7 @@
         mConnectivityHelper = connectivityHelper;
         mLocalLog = localLog;
         mWifiLastResortWatchdog = wifiLastResortWatchdog;
-        mWifiNotificationController = wifiNotificationController;
+        mOpenNetworkNotifier = openNetworkNotifier;
         mWifiMetrics = wifiMetrics;
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mEventHandler = new Handler(looper);
@@ -1041,7 +1041,7 @@
 
         mScreenOn = screenOn;
 
-        mWifiNotificationController.handleScreenStateChanged(screenOn);
+        mOpenNetworkNotifier.handleScreenStateChanged(screenOn);
 
         startConnectivityScan(SCAN_ON_SCHEDULE);
     }
@@ -1071,7 +1071,7 @@
         mWifiState = state;
 
         if (mWifiState == WIFI_STATE_CONNECTED) {
-            mWifiNotificationController.clearPendingNotification(false /* resetRepeatDelay */);
+            mOpenNetworkNotifier.clearPendingNotification(false /* resetRepeatDelay */);
         }
 
         // Reset BSSID of last connection attempt and kick off
@@ -1307,7 +1307,7 @@
         stopConnectivityScan();
         clearBssidBlacklist();
         resetLastPeriodicSingleScanTimeStamp();
-        mWifiNotificationController.clearPendingNotification(true /* resetRepeatDelay */);
+        mOpenNetworkNotifier.clearPendingNotification(true /* resetRepeatDelay */);
         mLastConnectionAttemptBssid = null;
         mWaitForFullBandScanResults = false;
     }
@@ -1367,6 +1367,6 @@
         pw.println("WifiConnectivityManager - Log Begin ----");
         mLocalLog.dump(fd, pw, args);
         pw.println("WifiConnectivityManager - Log End ----");
-        mWifiNotificationController.dump(fd, pw, args);
+        mOpenNetworkNotifier.dump(fd, pw, args);
     }
 }
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 2418738..60c5d2f 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -87,7 +87,7 @@
     private final WifiStateMachine mWifiStateMachine;
     private final WifiSettingsStore mSettingsStore;
     private final WifiCertManager mCertManager;
-    private final WifiNotificationController mNotificationController;
+    private final OpenNetworkNotifier mOpenNetworkNotifier;
     private final WifiLockManager mLockManager;
     private final WifiController mWifiController;
     private final WificondControl mWificondControl;
@@ -231,8 +231,9 @@
                 this, mBackupManagerProxy, mCountryCode, mWifiNative,
                 new WrongPasswordNotifier(mContext, mFrameworkFacade));
         mCertManager = new WifiCertManager(mContext);
-        mNotificationController = new WifiNotificationController(mContext,
-                mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade, null);
+        mOpenNetworkNotifier = new OpenNetworkNotifier(mContext,
+                mWifiStateMachineHandlerThread.getLooper(), mFrameworkFacade, mClock,
+                new OpenNetworkRecommender());
         mLockManager = new WifiLockManager(mContext, BatteryStatsService.getService());
         mWifiController = new WifiController(mContext, mWifiStateMachine, mSettingsStore,
                 mLockManager, mWifiServiceHandlerThread.getLooper(), mFrameworkFacade);
@@ -431,7 +432,7 @@
                                                                boolean hasConnectionRequests) {
         return new WifiConnectivityManager(mContext, mWifiStateMachine, getWifiScanner(),
                 mWifiConfigManager, wifiInfo, mWifiNetworkSelector, mWifiConnectivityHelper,
-                mWifiLastResortWatchdog, mNotificationController, mWifiMetrics,
+                mWifiLastResortWatchdog, mOpenNetworkNotifier, mWifiMetrics,
                 mWifiStateMachineHandlerThread.getLooper(), mClock, mConnectivityLocalLog,
                 hasConnectionRequests, mFrameworkFacade, mSavedNetworkEvaluator,
                 mScoredNetworkEvaluator, mPasspointNetworkEvaluator);
diff --git a/service/java/com/android/server/wifi/WifiNotificationController.java b/service/java/com/android/server/wifi/WifiNotificationController.java
deleted file mode 100644
index 797fd43..0000000
--- a/service/java/com/android/server/wifi/WifiNotificationController.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2013 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.annotation.NonNull;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.TaskStackBuilder;
-import android.content.Context;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import com.android.internal.notification.SystemNotificationChannels;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.List;
-
-/**
- * Takes care of handling the "open wi-fi network available" notification
- * @hide
- */
-public class WifiNotificationController {
-    /**
-     * The icon to show in the 'available networks' notification. This will also
-     * be the ID of the Notification given to the NotificationManager.
-     */
-    private static final int ICON_NETWORKS_AVAILABLE =
-            com.android.internal.R.drawable.stat_notify_wifi_in_range;
-    /**
-     * When a notification is shown, we wait this amount before possibly showing it again.
-     */
-    private final long NOTIFICATION_REPEAT_DELAY_MS;
-
-    /** Whether the user has set the setting to show the 'available networks' notification. */
-    private boolean mSettingEnabled;
-
-    /**
-     * Observes the user setting to keep {@link #mSettingEnabled} in sync.
-     */
-    private NotificationEnabledSettingObserver mNotificationEnabledSettingObserver;
-
-    /**
-     * The {@link System#currentTimeMillis()} must be at least this value for us
-     * to show the notification again.
-     */
-    private long mNotificationRepeatTime;
-    /**
-     * The Notification object given to the NotificationManager.
-     */
-    private Notification.Builder mNotificationBuilder;
-    /**
-     * Whether the notification is being shown, as set by us. That is, if the
-     * user cancels the notification, we will not receive the callback so this
-     * will still be true. We only guarantee if this is false, then the
-     * notification is not showing.
-     */
-    private boolean mNotificationShown;
-    /** Whether the screen is on or not. */
-    private boolean mScreenOn;
-
-    private final Context mContext;
-    private FrameworkFacade mFrameworkFacade;
-
-    WifiNotificationController(Context context,
-                               Looper looper,
-                               FrameworkFacade framework,
-                               Notification.Builder builder) {
-        mContext = context;
-        mFrameworkFacade = framework;
-        mNotificationBuilder = builder;
-
-        mScreenOn = false;
-
-        // Setting is in seconds
-        NOTIFICATION_REPEAT_DELAY_MS = mFrameworkFacade.getIntegerSetting(context,
-                Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000L;
-        mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(
-                new Handler(looper));
-        mNotificationEnabledSettingObserver.register();
-    }
-
-    /**
-     * Clears the pending notification. This is called by {@link WifiConnectivityManager} on stop.
-     *
-     * @param resetRepeatDelay resets the time delay for repeated notification if true.
-     */
-    public void clearPendingNotification(boolean resetRepeatDelay) {
-        if (resetRepeatDelay) {
-            mNotificationRepeatTime = 0;
-        }
-        setNotificationVisible(false, 0, false, 0);
-    }
-
-    private boolean isControllerEnabled() {
-        return mSettingEnabled && !UserManager.get(mContext)
-                .hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT);
-    }
-
-    /**
-     * If there are open networks, attempt to post an open network notification.
-     *
-     * @param availableNetworks Available networks from
-     * {@link WifiNetworkSelector.NetworkEvaluator#getFilteredScanDetailsForOpenUnsavedNetworks()}.
-     */
-    public void handleScanResults(@NonNull List<ScanDetail> availableNetworks) {
-        if (!isControllerEnabled()) {
-            clearPendingNotification(true /* resetRepeatDelay */);
-            return;
-        }
-        if (availableNetworks.isEmpty()) {
-            clearPendingNotification(false /* resetRepeatDelay */);
-            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) {
-            return;
-        }
-
-        setNotificationVisible(true, availableNetworks.size(), false, 0);
-    }
-
-    /** Handles screen state changes. */
-    public void handleScreenStateChanged(boolean screenOn) {
-        mScreenOn = screenOn;
-    }
-
-    /**
-     * Display or don't display a notification that there are open Wi-Fi networks.
-     * @param visible {@code true} if notification should be visible, {@code false} otherwise
-     * @param numNetworks the number networks seen
-     * @param force {@code true} to force notification to be shown/not-shown,
-     * even if it is already shown/not-shown.
-     * @param delay time in milliseconds after which the notification should be made
-     * visible or invisible.
-     */
-    private void setNotificationVisible(boolean visible, int numNetworks, boolean force,
-            int delay) {
-
-        // Since we use auto cancel on the notification, when the
-        // mNetworksAvailableNotificationShown is true, the notification may
-        // have actually been canceled.  However, when it is false we know
-        // for sure that it is not being shown (it will not be shown any other
-        // place than here)
-
-        // If it should be hidden and it is already hidden, then noop
-        if (!visible && !mNotificationShown && !force) {
-            return;
-        }
-
-        NotificationManager notificationManager = (NotificationManager) mContext
-                .getSystemService(Context.NOTIFICATION_SERVICE);
-
-        Message message;
-        if (visible) {
-
-            // Not enough time has passed to show the notification again
-            if (System.currentTimeMillis() < mNotificationRepeatTime) {
-                return;
-            }
-
-            if (mNotificationBuilder == null) {
-                // Cache the Notification builder object.
-                mNotificationBuilder = new Notification.Builder(mContext,
-                        SystemNotificationChannels.NETWORK_AVAILABLE)
-                        .setWhen(0)
-                        .setSmallIcon(ICON_NETWORKS_AVAILABLE)
-                        .setAutoCancel(true)
-                        .setContentIntent(TaskStackBuilder.create(mContext)
-                                .addNextIntentWithParentStack(
-                                        new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK))
-                                .getPendingIntent(0, 0, null, UserHandle.CURRENT))
-                        .setColor(mContext.getResources().getColor(
-                                com.android.internal.R.color.system_notification_accent_color));
-            }
-
-            CharSequence title = mContext.getResources().getQuantityText(
-                    com.android.internal.R.plurals.wifi_available, numNetworks);
-            CharSequence details = mContext.getResources().getQuantityText(
-                    com.android.internal.R.plurals.wifi_available_detailed, numNetworks);
-            mNotificationBuilder.setTicker(title);
-            mNotificationBuilder.setContentTitle(title);
-            mNotificationBuilder.setContentText(details);
-
-            mNotificationRepeatTime = System.currentTimeMillis() + NOTIFICATION_REPEAT_DELAY_MS;
-
-            notificationManager.notifyAsUser(null, ICON_NETWORKS_AVAILABLE,
-                    mNotificationBuilder.build(), UserHandle.ALL);
-        } else {
-            notificationManager.cancelAsUser(null, ICON_NETWORKS_AVAILABLE, UserHandle.ALL);
-        }
-
-        mNotificationShown = visible;
-    }
-
-    /** Dump ONA controller state. */
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("WifiNotificationController: ");
-        pw.println("mSettingEnabled " + mSettingEnabled);
-        pw.println("mNotificationRepeatTime " + mNotificationRepeatTime);
-        pw.println("mNotificationShown " + mNotificationShown);
-    }
-
-    private class NotificationEnabledSettingObserver extends ContentObserver {
-        NotificationEnabledSettingObserver(Handler handler) {
-            super(handler);
-        }
-
-        public void register() {
-            mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor(
-                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON), true, this);
-            mSettingEnabled = getValue();
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            super.onChange(selfChange);
-            mSettingEnabled = getValue();
-            clearPendingNotification(true /* resetRepeatDelay */);
-        }
-
-        private boolean getValue() {
-            return mFrameworkFacade.getIntegerSetting(mContext,
-                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1) == 1;
-        }
-    }
-}
diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
new file mode 100644
index 0000000..29c068d
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/OpenNetworkNotifierTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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 com.android.server.wifi.OpenNetworkNotifier.DEFAULT_REPEAT_DELAY_SEC;
+
+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.os.UserHandle;
+import android.os.UserManager;
+import android.os.test.TestLooper;
+import android.provider.Settings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link OpenNetworkNotifier}.
+ */
+public class OpenNetworkNotifierTest {
+
+    private static final String TEST_SSID_1 = "Test SSID 1";
+    private static final int MIN_RSSI_LEVEL = -127;
+
+    @Mock private Context mContext;
+    @Mock private Resources mResources;
+    @Mock private FrameworkFacade mFrameworkFacade;
+    @Mock private Clock mClock;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder;
+    @Mock private NotificationManager mNotificationManager;
+    @Mock private OpenNetworkRecommender mOpenNetworkRecommender;
+    @Mock private UserManager mUserManager;
+    private OpenNetworkNotifier mNotificationController;
+    private BroadcastReceiver mBroadcastReceiver;
+    private ScanResult mDummyNetwork;
+
+
+    /** Initialize objects before each test run. */
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getSystemService(Context.NOTIFICATION_SERVICE))
+                .thenReturn(mNotificationManager);
+        when(mFrameworkFacade.getIntegerSetting(mContext,
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(1);
+        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);
+        mDummyNetwork = new ScanResult();
+        mDummyNetwork.SSID = TEST_SSID_1;
+        mDummyNetwork.capabilities = "[ESS]";
+        mDummyNetwork.level = MIN_RSSI_LEVEL;
+        when(mOpenNetworkRecommender.recommendNetwork(any(), any())).thenReturn(mDummyNetwork);
+
+        TestLooper mock_looper = new TestLooper();
+        mNotificationController = new OpenNetworkNotifier(
+                mContext, mock_looper.getLooper(), mFrameworkFacade,
+                mClock, mOpenNetworkRecommender);
+        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
+        mNotificationController.handleScreenStateChanged(true);
+    }
+
+    private List<ScanDetail> createOpenScanResults() {
+        List<ScanDetail> scanResults = new ArrayList<>();
+        scanResults.add(new ScanDetail(mDummyNetwork, null /* networkDetail */));
+        return scanResults;
+    }
+
+    /**
+     * When scan results with open networks are handled, a notification is posted.
+     */
+    @Test
+    public void handleScanResults_hasOpenNetworks_notificationDisplayed() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+    }
+
+    /**
+     * When scan results with no open networks are handled, a notification is not posted.
+     */
+    @Test
+    public void handleScanResults_emptyList_notificationNotDisplayed() {
+        mNotificationController.handleScanResults(new ArrayList<>());
+
+        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
+        verify(mNotificationManager, never()).notify(anyInt(), any());
+    }
+
+    /**
+     * When a notification is showing and scan results with no open networks are handled, the
+     * notification is cleared.
+     */
+    @Test
+    public void handleScanResults_notificationShown_emptyList_notificationCleared() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        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.
+     */
+    @Test
+    public void handleScanResults_notificationShown_screenOff_emptyList_notificationCleared() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        mNotificationController.handleScreenStateChanged(false);
+        mNotificationController.handleScanResults(new ArrayList<>());
+
+        verify(mNotificationManager).cancel(anyInt());
+    }
+
+    /**
+     * If notification is showing, do not post another notification.
+     */
+    @Test
+    public void handleScanResults_notificationShowing_doesNotRepostNotification() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+    }
+
+    /**
+     * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a
+     * notification is shown, clear the notification.
+     */
+    @Test
+    public void clearPendingNotification_clearsNotificationIfOneIsShowing() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        mNotificationController.clearPendingNotification(true);
+
+        verify(mNotificationManager).cancel(anyInt());
+    }
+
+    /**
+     * When {@link OpenNetworkNotifier#clearPendingNotification(boolean)} is called and a
+     * notification was not previously shown, do not clear the notification.
+     */
+    @Test
+    public void clearPendingNotification_doesNotClearNotificationIfNoneShowing() {
+        mNotificationController.clearPendingNotification(true);
+
+        verify(mNotificationManager, never()).cancel(anyInt());
+    }
+
+    /**
+     * When screen is off and notification is not displayed, notification is not posted on handling
+     * new scan results with open networks.
+     */
+    @Test
+    public void screenOff_handleScanResults_notificationNotDisplayed() {
+        mNotificationController.handleScreenStateChanged(false);
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
+        verify(mNotificationManager, never()).notify(anyInt(), any());
+    }
+
+    /**
+     * When a notification is posted and cleared without reseting delay, the next scan with open
+     * networks should not post another notification.
+     */
+    @Test
+    public void postNotification_clearNotificationWithoutDelayReset_shouldNotPostNotification() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        mNotificationController.clearPendingNotification(false);
+
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        // Recommendation made twice but no new notification posted.
+        verify(mOpenNetworkRecommender, times(2)).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+        verify(mNotificationManager).cancel(anyInt());
+    }
+
+    /**
+     * When a notification is posted and cleared without reseting delay, the next scan with open
+     * networks should post a notification.
+     */
+    @Test
+    public void postNotification_clearNotificationWithDelayReset_shouldPostNotification() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        mNotificationController.clearPendingNotification(true);
+
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender, times(2)).recommendNetwork(any(), any());
+        verify(mNotificationManager, times(2)).notify(anyInt(), any());
+    }
+
+    /**
+     * When a notification is tapped, open Wi-Fi settings.
+     */
+    @Test
+    public void notificationTap_opensWifiSettings() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        mBroadcastReceiver.onReceive(
+                mContext, new Intent(OpenNetworkNotifier.ACTION_USER_TAPPED_CONTENT));
+
+        verify(mContext).startActivity(any());
+    }
+
+    /**
+     * When a notification is posted and cleared without reseting delay, after the delay has passed
+     * the next scan with open networks should post a notification.
+     */
+    @Test
+    public void delaySet_delayPassed_shouldPostNotification() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        mNotificationController.clearPendingNotification(false);
+
+        // twice the delay time passed
+        when(mClock.getWallClockMillis()).thenReturn(DEFAULT_REPEAT_DELAY_SEC * 1000L * 2);
+
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender, times(2)).recommendNetwork(any(), any());
+        verify(mNotificationManager, times(2)).notify(anyInt(), any());
+    }
+
+    /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} disables the feature. */
+    @Test
+    public void userHasDisallowConfigWifiRestriction_notificationNotDisplayed() {
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
+                .thenReturn(true);
+
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender, never()).recommendNetwork(any(), any());
+        verify(mNotificationManager, never()).notify(anyInt(), any());
+    }
+
+    /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} clears the showing notification. */
+    @Test
+    public void userHasDisallowConfigWifiRestriction_showingNotificationIsCleared() {
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mOpenNetworkRecommender).recommendNetwork(any(), any());
+        verify(mNotificationManager).notify(anyInt(), any());
+
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
+                .thenReturn(true);
+
+        mNotificationController.handleScanResults(createOpenScanResults());
+
+        verify(mNotificationManager).cancel(anyInt());
+    }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java b/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java
new file mode 100644
index 0000000..becc1d2
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/OpenNetworkRecommenderTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wifi;
+
+import static org.junit.Assert.assertEquals;
+
+import android.net.wifi.ScanResult;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link OpenNetworkRecommender}.
+ */
+public class OpenNetworkRecommenderTest {
+
+    private static final String TEST_SSID_1 = "Test SSID 1";
+    private static final String TEST_SSID_2 = "Test SSID 2";
+    private static final int MIN_RSSI_LEVEL = -127;
+
+    private OpenNetworkRecommender mOpenNetworkRecommender;
+
+    @Before
+    public void setUp() throws Exception {
+        mOpenNetworkRecommender = new OpenNetworkRecommender();
+    }
+
+    private List<ScanDetail> createOpenScanResults(String... ssids) {
+        List<ScanDetail> scanResults = new ArrayList<>();
+        for (String ssid : ssids) {
+            ScanResult scanResult = new ScanResult();
+            scanResult.SSID = ssid;
+            scanResult.capabilities = "[ESS]";
+            scanResults.add(new ScanDetail(scanResult, null /* networkDetail */));
+        }
+        return scanResults;
+    }
+
+    /** If list of open networks contain only one network, that network should be returned. */
+    @Test
+    public void onlyNetworkIsRecommended() {
+        List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1);
+        scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL;
+
+        ScanResult actual = mOpenNetworkRecommender.recommendNetwork(scanResults, null);
+        ScanResult expected = scanResults.get(0).getScanResult();
+        assertEquals(expected, actual);
+    }
+
+    /** Verifies that the network with the highest rssi is recommended. */
+    @Test
+    public void networkWithHighestRssiIsRecommended() {
+        List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1, TEST_SSID_2);
+        scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL;
+        scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL + 1;
+
+        ScanResult actual = mOpenNetworkRecommender.recommendNetwork(scanResults, null);
+        ScanResult expected = scanResults.get(1).getScanResult();
+        assertEquals(expected, actual);
+    }
+
+    /**
+     * If the current recommended network is present in the list for the next recommendation and has
+     * an equal RSSI, the recommendation should not change.
+     */
+    @Test
+    public void currentRecommendationHasEquallyHighRssi_shouldNotChangeRecommendation() {
+        List<ScanDetail> scanResults = createOpenScanResults(TEST_SSID_1, TEST_SSID_2);
+        scanResults.get(0).getScanResult().level = MIN_RSSI_LEVEL + 1;
+        scanResults.get(1).getScanResult().level = MIN_RSSI_LEVEL + 1;
+
+        ScanResult currentRecommendation = new ScanResult(scanResults.get(1).getScanResult());
+        // next recommendation does not depend on the rssi of the input recommendation.
+        currentRecommendation.level = MIN_RSSI_LEVEL;
+
+        ScanResult expected = scanResults.get(1).getScanResult();
+        ScanResult actual = mOpenNetworkRecommender.recommendNetwork(
+                scanResults, currentRecommendation);
+        assertEquals(expected, actual);
+    }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index bdb6b14..a8278d3 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -123,7 +123,7 @@
     @Mock private NetworkScoreManager mNetworkScoreManager;
     @Mock private Clock mClock;
     @Mock private WifiLastResortWatchdog mWifiLastResortWatchdog;
-    @Mock private WifiNotificationController mWifiNotificationController;
+    @Mock private OpenNetworkNotifier mOpenNetworkNotifier;
     @Mock private WifiMetrics mWifiMetrics;
     @Mock private WifiNetworkScoreCache mScoreCache;
     @Captor ArgumentCaptor<ScanResult> mCandidateScanResultCaptor;
@@ -294,7 +294,7 @@
     WifiConnectivityManager createConnectivityManager() {
         return new WifiConnectivityManager(mContext, mWifiStateMachine, mWifiScanner,
                 mWifiConfigManager, mWifiInfo, mWifiNS, mWifiConnectivityHelper,
-                mWifiLastResortWatchdog, mWifiNotificationController, mWifiMetrics,
+                mWifiLastResortWatchdog, mOpenNetworkNotifier, mWifiMetrics,
                 mLooper.getLooper(), mClock, mLocalLog, true, mFrameworkFacade, null, null, null);
     }
 
@@ -609,7 +609,7 @@
     }
 
     /**
-     * {@link WifiNotificationController} handles scan results on network selection.
+     * {@link OpenNetworkNotifier} handles scan results on network selection.
      *
      * Expected behavior: ONA handles scan results
      */
@@ -633,11 +633,11 @@
         mWifiConnectivityManager.handleConnectionStateChanged(
                 WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
 
-        verify(mWifiNotificationController).handleScanResults(expectedOpenNetworks);
+        verify(mOpenNetworkNotifier).handleScanResults(expectedOpenNetworks);
     }
 
     /**
-     * When wifi is connected, {@link WifiNotificationController} tries to clear the pending
+     * When wifi is connected, {@link OpenNetworkNotifier} tries to clear the pending
      * notification and does not reset notification repeat delay.
      *
      * Expected behavior: ONA clears pending notification and does not reset repeat delay.
@@ -648,11 +648,11 @@
         mWifiConnectivityManager.handleConnectionStateChanged(
                 WifiConnectivityManager.WIFI_STATE_CONNECTED);
 
-        verify(mWifiNotificationController).clearPendingNotification(false /* isRepeatDelayReset*/);
+        verify(mOpenNetworkNotifier).clearPendingNotification(false /* isRepeatDelayReset*/);
     }
 
     /**
-     * When wifi is connected, {@link WifiNotificationController} handles connection state
+     * When wifi is connected, {@link OpenNetworkNotifier} handles connection state
      * change.
      *
      * Expected behavior: ONA does not clear pending notification.
@@ -663,7 +663,7 @@
         mWifiConnectivityManager.handleConnectionStateChanged(
                 WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
 
-        verify(mWifiNotificationController, never()).clearPendingNotification(anyBoolean());
+        verify(mOpenNetworkNotifier, never()).clearPendingNotification(anyBoolean());
     }
 
     /**
@@ -675,7 +675,7 @@
     public void openNetworkNotificationControllerToggledOnWifiStateChanges() {
         mWifiConnectivityManager.setWifiEnabled(false);
 
-        verify(mWifiNotificationController).clearPendingNotification(true /* isRepeatDelayReset */);
+        verify(mOpenNetworkNotifier).clearPendingNotification(true /* isRepeatDelayReset */);
     }
 
     /**
@@ -685,11 +685,11 @@
     public void openNetworkNotificationControllerTracksScreenStateChanges() {
         mWifiConnectivityManager.handleScreenStateChanged(false);
 
-        verify(mWifiNotificationController).handleScreenStateChanged(false);
+        verify(mOpenNetworkNotifier).handleScreenStateChanged(false);
 
         mWifiConnectivityManager.handleScreenStateChanged(true);
 
-        verify(mWifiNotificationController).handleScreenStateChanged(true);
+        verify(mOpenNetworkNotifier).handleScreenStateChanged(true);
     }
 
     /**
@@ -1652,7 +1652,7 @@
     /**
      *  Dump ONA controller.
      *
-     * Expected behavior: {@link WifiNotificationController#dump(FileDescriptor, PrintWriter,
+     * Expected behavior: {@link OpenNetworkNotifier#dump(FileDescriptor, PrintWriter,
      * String[])} is invoked.
      */
     @Test
@@ -1661,6 +1661,6 @@
         PrintWriter pw = new PrintWriter(sw);
         mWifiConnectivityManager.dump(new FileDescriptor(), pw, new String[]{});
 
-        verify(mWifiNotificationController).dump(any(), any(), any());
+        verify(mOpenNetworkNotifier).dump(any(), any(), any());
     }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNotificationControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNotificationControllerTest.java
deleted file mode 100644
index 27055a8..0000000
--- a/tests/wifitests/src/com/android/server/wifi/WifiNotificationControllerTest.java
+++ /dev/null
@@ -1,208 +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.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.res.Resources;
-import android.net.wifi.ScanResult;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.os.test.TestLooper;
-import android.provider.Settings;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit tests for {@link WifiNotificationController}.
- */
-public class WifiNotificationControllerTest {
-
-    @Mock private Context mContext;
-    @Mock private Resources mResources;
-    @Mock private FrameworkFacade mFrameworkFacade;
-    @Mock private NotificationManager mNotificationManager;
-    @Mock private UserManager mUserManager;
-    private WifiNotificationController mNotificationController;
-
-
-    /** Initialize objects before each test run. */
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        when(mContext.getSystemService(Context.NOTIFICATION_SERVICE))
-                .thenReturn(mNotificationManager);
-        when(mFrameworkFacade.getIntegerSetting(mContext,
-                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1)).thenReturn(1);
-        when(mContext.getSystemService(Context.USER_SERVICE))
-                .thenReturn(mUserManager);
-        when(mContext.getResources()).thenReturn(mResources);
-
-        TestLooper mock_looper = new TestLooper();
-        mNotificationController = new WifiNotificationController(
-                mContext, mock_looper.getLooper(), mFrameworkFacade,
-                mock(Notification.Builder.class));
-        mNotificationController.handleScreenStateChanged(true);
-    }
-
-    private List<ScanDetail> createOpenScanResults() {
-        List<ScanDetail> scanResults = new ArrayList<>();
-        ScanResult scanResult = new ScanResult();
-        scanResult.capabilities = "[ESS]";
-        scanResults.add(new ScanDetail(scanResult, null /* networkDetail */));
-        return scanResults;
-    }
-
-    /**
-     * When scan results with open networks are handled, a notification is posted.
-     */
-    @Test
-    public void handleScanResults_hasOpenNetworks_notificationDisplayed() {
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).notifyAsUser(any(), anyInt(), any(), any());
-    }
-
-    /**
-     * When scan results with no open networks are handled, a notification is not posted.
-     */
-    @Test
-    public void handleScanResults_emptyList_notificationNotDisplayed() {
-        mNotificationController.handleScanResults(new ArrayList<>());
-
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
-    }
-
-    /**
-     * When a notification is showing and scan results with no open networks are handled, the
-     * notification is cleared.
-     */
-    @Test
-    public void handleScanResults_notificationShown_emptyList_notificationCleared() {
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).notifyAsUser(any(), anyInt(), any(), any());
-
-        mNotificationController.handleScanResults(new ArrayList<>());
-
-        verify(mNotificationManager).cancelAsUser(any(), anyInt(), any());
-    }
-    /**
-     * 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_notificationShown_screenOff_emptyList_notificationCleared() {
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).notifyAsUser(any(), anyInt(), any(), any());
-
-        mNotificationController.handleScreenStateChanged(false);
-        mNotificationController.handleScanResults(new ArrayList<>());
-
-        verify(mNotificationManager).cancelAsUser(any(), anyInt(), any());
-    }
-
-    /**
-     * If notification is showing, do not post another notification.
-     */
-    @Test
-    public void handleScanResults_notificationShowing_doesNotRepostNotification() {
-        mNotificationController.handleScanResults(createOpenScanResults());
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).notifyAsUser(any(), anyInt(), any(), any());
-    }
-
-    /**
-     * When {@link WifiNotificationController#clearPendingNotification(boolean)} is called and a
-     * notification is shown, clear the notification.
-     */
-    @Test
-    public void clearPendingNotification_clearsNotificationIfOneIsShowing() {
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).notifyAsUser(any(), anyInt(), any(), any());
-
-        mNotificationController.clearPendingNotification(true);
-
-        verify(mNotificationManager).cancelAsUser(any(), anyInt(), any());
-    }
-
-    /**
-     * When {@link WifiNotificationController#clearPendingNotification(boolean)} is called and a
-     * notification was not previously shown, do not clear the notification.
-     */
-    @Test
-    public void clearPendingNotification_doesNotClearNotificationIfNoneShowing() {
-        mNotificationController.clearPendingNotification(true);
-
-        verify(mNotificationManager, never()).cancelAsUser(any(), anyInt(), any());
-    }
-
-    /**
-     * When screen is off and notification is not displayed, notification is not posted on handling
-     * new scan results with open networks.
-     */
-    @Test
-    public void screenOff_handleScanResults_notificationNotDisplayed() {
-        mNotificationController.handleScreenStateChanged(false);
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
-    }
-
-    /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} disables the feature. */
-    @Test
-    public void userHasDisallowConfigWifiRestriction_notificationNotDisplayed() {
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
-                .thenReturn(true);
-
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
-    }
-
-    /** Verifies that {@link UserManager#DISALLOW_CONFIG_WIFI} clears the showing notification. */
-    @Test
-    public void userHasDisallowConfigWifiRestriction_showingNotificationIsCleared() {
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).notifyAsUser(any(), anyInt(), any(), any());
-
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT))
-                .thenReturn(true);
-
-        mNotificationController.handleScanResults(createOpenScanResults());
-
-        verify(mNotificationManager).cancelAsUser(any(), anyInt(), any());
-    }
-}