1/* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import static com.android.server.wifi.WakeupNotificationFactory.ACTION_DISMISS_NOTIFICATION; 20import static com.android.server.wifi.WakeupNotificationFactory.ACTION_OPEN_WIFI_PREFERENCES; 21import static com.android.server.wifi.WakeupNotificationFactory.ACTION_TURN_OFF_WIFI_WAKE; 22 23import static org.junit.Assert.assertFalse; 24import static org.junit.Assert.assertTrue; 25import static org.mockito.ArgumentMatchers.any; 26import static org.mockito.ArgumentMatchers.eq; 27import static org.mockito.Mockito.never; 28import static org.mockito.Mockito.times; 29import static org.mockito.Mockito.verify; 30import static org.mockito.Mockito.when; 31 32import android.app.NotificationManager; 33import android.content.BroadcastReceiver; 34import android.content.Context; 35import android.content.Intent; 36import android.content.IntentFilter; 37import android.os.Handler; 38import android.os.test.TestLooper; 39import android.provider.Settings; 40 41import org.junit.Before; 42import org.junit.Test; 43import org.mockito.ArgumentCaptor; 44import org.mockito.InOrder; 45import org.mockito.Mock; 46import org.mockito.Mockito; 47import org.mockito.MockitoAnnotations; 48 49/** Unit tests for {@link com.android.server.wifi.WakeupOnboarding} */ 50public class WakeupOnboardingTest { 51 52 @Mock private Context mContext; 53 @Mock private WifiConfigManager mWifiConfigManager; 54 @Mock private FrameworkFacade mFrameworkFacade; 55 @Mock private WakeupNotificationFactory mWakeupNotificationFactory; 56 @Mock private NotificationManager mNotificationManager; 57 58 private TestLooper mLooper; 59 private WakeupOnboarding mWakeupOnboarding; 60 61 // convenience method for resetting onboarded status 62 private void setOnboardedStatus(boolean isOnboarded) { 63 mWakeupOnboarding.getIsOnboadedDataSource().setData(isOnboarded); 64 } 65 66 private void setNotificationsShown(int numNotifications) { 67 mWakeupOnboarding.getNotificationsDataSource().setData(numNotifications); 68 } 69 70 @Before 71 public void setUp() { 72 MockitoAnnotations.initMocks(this); 73 74 when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) 75 .thenReturn(mNotificationManager); 76 77 mLooper = new TestLooper(); 78 mWakeupOnboarding = new WakeupOnboarding(mContext, mWifiConfigManager, mLooper.getLooper(), 79 mFrameworkFacade, mWakeupNotificationFactory); 80 } 81 82 /** 83 * Verify that the notification shows if the user isn't onboarded. 84 */ 85 @Test 86 public void showsNotificationIfNotOnboarded() { 87 setOnboardedStatus(false); 88 mWakeupOnboarding.maybeShowNotification(); 89 90 verify(mNotificationManager).notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); 91 } 92 93 /** 94 * Verify that the notification does not show if the user is onboarded. 95 */ 96 @Test 97 public void doesNotShowNotificationIfAlreadyOnboarded() { 98 setOnboardedStatus(true); 99 mWakeupOnboarding.maybeShowNotification(); 100 101 verify(mNotificationManager, never()) 102 .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); 103 } 104 105 /** 106 * Verify that the notification does not relaunch if it's already showing. 107 */ 108 @Test 109 public void doesNotShowNotificationIfAlreadyShowing() { 110 setOnboardedStatus(false); 111 mWakeupOnboarding.maybeShowNotification(); 112 mWakeupOnboarding.maybeShowNotification(); 113 114 InOrder inOrder = Mockito.inOrder(mNotificationManager); 115 inOrder.verify(mNotificationManager) 116 .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); 117 inOrder.verifyNoMoreInteractions(); 118 } 119 120 /** 121 * Verify that the user is onboarded when the notification is dismissed. 122 */ 123 @Test 124 public void dismissNotificationAction_setsOnboarded() { 125 setOnboardedStatus(false); 126 assertFalse(mWakeupOnboarding.isOnboarded()); 127 128 mWakeupOnboarding.maybeShowNotification(); 129 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 130 verify(mContext).registerReceiver(captor.capture(), any(IntentFilter.class), any(), 131 any(Handler.class)); 132 BroadcastReceiver broadcastReceiver = captor.getValue(); 133 134 broadcastReceiver.onReceive(mContext, new Intent(ACTION_DISMISS_NOTIFICATION)); 135 136 verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); 137 assertTrue(mWakeupOnboarding.isOnboarded()); 138 } 139 140 /** 141 * Verify that the user is onboarded and Wifi Wake is turned off when the user selects the 142 * ACTION_TURN_OFF_WIFI_WAKE action. 143 */ 144 @Test 145 public void turnOffWifiWakeAction_setsOnboardedAndTurnsOffWifiWake() { 146 setOnboardedStatus(false); 147 assertFalse(mWakeupOnboarding.isOnboarded()); 148 149 mWakeupOnboarding.maybeShowNotification(); 150 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 151 verify(mContext).registerReceiver(captor.capture(), any(IntentFilter.class), any(), 152 any(Handler.class)); 153 BroadcastReceiver broadcastReceiver = captor.getValue(); 154 155 broadcastReceiver.onReceive(mContext, new Intent(ACTION_TURN_OFF_WIFI_WAKE)); 156 157 verify(mFrameworkFacade).setIntegerSetting(mContext, 158 Settings.Global.WIFI_WAKEUP_ENABLED, 0); 159 160 verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); 161 assertTrue(mWakeupOnboarding.isOnboarded()); 162 } 163 164 /** 165 * Verify that the user is onboarded and sent to WifiSettings when the user selects the 166 * ACTION_OPEN_WIFI_SETTINGS action. 167 */ 168 @Test 169 public void openWifiSettingsAction_setsOnboardedAndOpensWifiSettings() { 170 setOnboardedStatus(false); 171 assertFalse(mWakeupOnboarding.isOnboarded()); 172 173 mWakeupOnboarding.maybeShowNotification(); 174 ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); 175 verify(mContext).registerReceiver(captor.capture(), any(IntentFilter.class), any(), 176 any(Handler.class)); 177 BroadcastReceiver broadcastReceiver = captor.getValue(); 178 179 broadcastReceiver.onReceive(mContext, new Intent(ACTION_OPEN_WIFI_PREFERENCES)); 180 181 verify(mContext).startActivity(any()); 182 183 verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); 184 assertTrue(mWakeupOnboarding.isOnboarded()); 185 } 186 187 /** 188 * Verify that onStop() doesn't onboard the user. 189 */ 190 @Test 191 public void onStopDismissesNotificationWithoutOnboarding() { 192 setOnboardedStatus(false); 193 assertFalse(mWakeupOnboarding.isOnboarded()); 194 195 mWakeupOnboarding.maybeShowNotification(); 196 mWakeupOnboarding.onStop(); 197 198 verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); 199 assertFalse(mWakeupOnboarding.isOnboarded()); 200 } 201 202 /** 203 * Verify that incrementing the notification count saves to store. 204 */ 205 @Test 206 public void setOnboardedSavesToStore() { 207 setOnboardedStatus(false); 208 mWakeupOnboarding.setOnboarded(); 209 verify(mWifiConfigManager).saveToStore(false /* forceWrite */); 210 assertTrue(mWakeupOnboarding.isOnboarded()); 211 } 212 213 /** 214 * Verify that incrementing the notification count saves to store. 215 */ 216 @Test 217 public void incrementingNotificationCountSavesToStore() { 218 setOnboardedStatus(false); 219 setNotificationsShown(0); 220 mWakeupOnboarding.maybeShowNotification(); 221 verify(mWifiConfigManager).saveToStore(false /* forceWrite */); 222 } 223 224 /** 225 * Verify that the notification does not show multiple times within 24 hours. 226 */ 227 @Test 228 public void doesNotShowMultipleNotificationsWithin24Hours() { 229 setOnboardedStatus(false); 230 setNotificationsShown(0); 231 232 mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); 233 mWakeupOnboarding.onStop(); 234 mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); 235 236 InOrder inOrder = Mockito.inOrder(mNotificationManager); 237 inOrder.verify(mNotificationManager) 238 .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); 239 inOrder.verify(mNotificationManager).cancel(WakeupNotificationFactory.ONBOARD_ID); 240 inOrder.verifyNoMoreInteractions(); 241 } 242 243 /** 244 * Verify that notification reappears after 24 hours if not onboarded. 245 */ 246 @Test 247 public void showsNotificationsOutsideOf24Hours() { 248 setOnboardedStatus(false); 249 setNotificationsShown(0); 250 251 mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); 252 assertFalse(mWakeupOnboarding.isOnboarded()); 253 254 mWakeupOnboarding.onStop(); 255 mWakeupOnboarding.maybeShowNotification(WakeupOnboarding.REQUIRED_NOTIFICATION_DELAY + 1); 256 257 verify(mNotificationManager, times(2)) 258 .notify(eq(WakeupNotificationFactory.ONBOARD_ID), any()); 259 } 260 261 /** 262 * Verify that the user is onboarded after 263 * {@link WakeupOnboarding#NOTIFICATIONS_UNTIL_ONBOARDED} notifications are shown. 264 */ 265 @Test 266 public void onboardsUserAfterThreeNotifications() { 267 setOnboardedStatus(false); 268 setNotificationsShown(WakeupOnboarding.NOTIFICATIONS_UNTIL_ONBOARDED - 1); 269 270 mWakeupOnboarding.maybeShowNotification(0 /* timestamp */); 271 assertTrue(mWakeupOnboarding.isOnboarded()); 272 } 273} 274