diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-08-16 20:31:41 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-08-16 20:31:41 +0000 |
commit | 69fa2e7fa12b8f4c24a27b3291a0744cd808a324 (patch) | |
tree | ba39a6d972ed25f35ed653e3b1308a6a74811b19 | |
parent | 0af8182c7a421108aff122440724ecc5d1e4c6d7 (diff) | |
parent | 579066a6f282b9d6729a93b7cce3b18980a0a61d (diff) |
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.
10 files changed, 840 insertions, 485 deletions
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 000000000..5963b57a3 --- /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 000000000..fc144c139 --- /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 000000000..cd460e58b --- /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 1cdc549ca..9603357a1 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -133,7 +133,7 @@ public class WifiConnectivityManager { 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 @@ public class WifiConnectivityManager { return true; } else { if (mWifiState == WIFI_STATE_DISCONNECTED) { - mWifiNotificationController.handleScanResults( + mOpenNetworkNotifier.handleScanResults( mNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks()); } return false; @@ -540,7 +540,7 @@ public class WifiConnectivityManager { 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 @@ public class WifiConnectivityManager { 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 @@ public class WifiConnectivityManager { mScreenOn = screenOn; - mWifiNotificationController.handleScreenStateChanged(screenOn); + mOpenNetworkNotifier.handleScreenStateChanged(screenOn); startConnectivityScan(SCAN_ON_SCHEDULE); } @@ -1071,7 +1071,7 @@ public class WifiConnectivityManager { 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 @@ public class WifiConnectivityManager { stopConnectivityScan(); clearBssidBlacklist(); resetLastPeriodicSingleScanTimeStamp(); - mWifiNotificationController.clearPendingNotification(true /* resetRepeatDelay */); + mOpenNetworkNotifier.clearPendingNotification(true /* resetRepeatDelay */); mLastConnectionAttemptBssid = null; mWaitForFullBandScanResults = false; } @@ -1367,6 +1367,6 @@ public class WifiConnectivityManager { 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 241873824..60c5d2fb9 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -87,7 +87,7 @@ public class WifiInjector { 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 @@ public class WifiInjector { 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 @@ public class WifiInjector { 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 797fd438b..000000000 --- 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 000000000..29c068ddc --- /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 000000000..becc1d2e8 --- /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 bdb6b14ed..a8278d365 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 @@ public class WifiConnectivityManagerTest { @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 @@ public class WifiConnectivityManagerTest { 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 @@ public class WifiConnectivityManagerTest { } /** - * {@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 @@ public class WifiConnectivityManagerTest { 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 @@ public class WifiConnectivityManagerTest { 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 @@ public class WifiConnectivityManagerTest { mWifiConnectivityManager.handleConnectionStateChanged( WifiConnectivityManager.WIFI_STATE_DISCONNECTED); - verify(mWifiNotificationController, never()).clearPendingNotification(anyBoolean()); + verify(mOpenNetworkNotifier, never()).clearPendingNotification(anyBoolean()); } /** @@ -675,7 +675,7 @@ public class WifiConnectivityManagerTest { public void openNetworkNotificationControllerToggledOnWifiStateChanges() { mWifiConnectivityManager.setWifiEnabled(false); - verify(mWifiNotificationController).clearPendingNotification(true /* isRepeatDelayReset */); + verify(mOpenNetworkNotifier).clearPendingNotification(true /* isRepeatDelayReset */); } /** @@ -685,11 +685,11 @@ public class WifiConnectivityManagerTest { 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 @@ public class WifiConnectivityManagerTest { /** * 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 @@ public class WifiConnectivityManagerTest { 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 27055a885..000000000 --- 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()); - } -} |