1 /* 2 * Copyright (C) 2020 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 17 package com.android.keyguard; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNull; 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyBoolean; 23 import static org.mockito.ArgumentMatchers.eq; 24 import static org.mockito.Mockito.never; 25 import static org.mockito.Mockito.reset; 26 import static org.mockito.Mockito.times; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 import android.database.ContentObserver; 31 import android.os.UserHandle; 32 import android.provider.Settings; 33 import android.testing.AndroidTestingRunner; 34 import android.view.View; 35 36 import androidx.test.filters.SmallTest; 37 38 import com.android.systemui.Flags; 39 import com.android.systemui.plugins.clocks.ClockFaceConfig; 40 import com.android.systemui.plugins.clocks.ClockTickRate; 41 import com.android.systemui.shared.clocks.ClockRegistry; 42 import com.android.systemui.statusbar.StatusBarState; 43 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.mockito.ArgumentCaptor; 47 import org.mockito.verification.VerificationMode; 48 49 @SmallTest 50 @RunWith(AndroidTestingRunner.class) 51 public class KeyguardClockSwitchControllerTest extends KeyguardClockSwitchControllerBaseTest { 52 @Test testInit_viewAlreadyAttached()53 public void testInit_viewAlreadyAttached() { 54 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 55 56 mController.init(); 57 58 verifyAttachment(times(1)); 59 } 60 61 @Test testInit_viewNotYetAttached()62 public void testInit_viewNotYetAttached() { 63 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 64 65 ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor = 66 ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class); 67 68 when(mView.isAttachedToWindow()).thenReturn(false); 69 mController.init(); 70 verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture()); 71 72 verifyAttachment(never()); 73 74 listenerArgumentCaptor.getValue().onViewAttachedToWindow(mView); 75 76 verifyAttachment(times(1)); 77 } 78 79 @Test testInitSubControllers()80 public void testInitSubControllers() { 81 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 82 83 mController.init(); 84 verify(mKeyguardSliceViewController).init(); 85 } 86 87 @Test testInit_viewDetached()88 public void testInit_viewDetached() { 89 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 90 91 ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor = 92 ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class); 93 mController.init(); 94 verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture()); 95 96 verifyAttachment(times(1)); 97 98 listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView); 99 verify(mClockEventController).unregisterListeners(); 100 } 101 102 @Test testPluginPassesStatusBarState()103 public void testPluginPassesStatusBarState() { 104 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 105 106 ArgumentCaptor<ClockRegistry.ClockChangeListener> listenerArgumentCaptor = 107 ArgumentCaptor.forClass(ClockRegistry.ClockChangeListener.class); 108 109 mController.init(); 110 verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture()); 111 112 listenerArgumentCaptor.getValue().onCurrentClockChanged(); 113 verify(mView, times(2)).setClock(mClockController, StatusBarState.SHADE); 114 verify(mClockEventController, times(2)).setClock(mClockController); 115 } 116 117 @Test testSmartspaceEnabledRemovesKeyguardStatusArea()118 public void testSmartspaceEnabledRemovesKeyguardStatusArea() { 119 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 120 121 when(mSmartspaceController.isEnabled()).thenReturn(true); 122 mController.init(); 123 124 assertEquals(View.GONE, mSliceView.getVisibility()); 125 } 126 127 @Test onLocaleListChangedRebuildsSmartspaceView()128 public void onLocaleListChangedRebuildsSmartspaceView() { 129 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 130 131 when(mSmartspaceController.isEnabled()).thenReturn(true); 132 mController.init(); 133 134 mController.onLocaleListChanged(); 135 // Should be called once on initial setup, then once again for locale change 136 verify(mSmartspaceController, times(2)).buildAndConnectView(mView); 137 } 138 139 @Test onLocaleListChanged_rebuildsSmartspaceViews_whenDecouplingEnabled()140 public void onLocaleListChanged_rebuildsSmartspaceViews_whenDecouplingEnabled() { 141 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 142 143 when(mSmartspaceController.isEnabled()).thenReturn(true); 144 when(mSmartspaceController.isDateWeatherDecoupled()).thenReturn(true); 145 mController.init(); 146 147 mController.onLocaleListChanged(); 148 // Should be called once on initial setup, then once again for locale change 149 verify(mSmartspaceController, times(2)).buildAndConnectDateView(mView); 150 verify(mSmartspaceController, times(2)).buildAndConnectWeatherView(mView); 151 verify(mSmartspaceController, times(2)).buildAndConnectView(mView); 152 } 153 154 @Test testSmartspaceDisabledShowsKeyguardStatusArea()155 public void testSmartspaceDisabledShowsKeyguardStatusArea() { 156 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 157 158 when(mSmartspaceController.isEnabled()).thenReturn(false); 159 mController.init(); 160 161 assertEquals(View.VISIBLE, mSliceView.getVisibility()); 162 } 163 164 @Test testRefresh()165 public void testRefresh() { 166 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 167 168 mController.refresh(); 169 170 verify(mSmartspaceController).requestSmartspaceUpdate(); 171 } 172 173 @Test testChangeToDoubleLineClockSetsSmallClock()174 public void testChangeToDoubleLineClockSetsSmallClock() { 175 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 176 177 when(mSecureSettings.getIntForUser(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1, 178 UserHandle.USER_CURRENT)) 179 .thenReturn(0); 180 ArgumentCaptor<ContentObserver> observerCaptor = 181 ArgumentCaptor.forClass(ContentObserver.class); 182 mController.init(); 183 mExecutor.runAllReady(); 184 verify(mSecureSettings).registerContentObserverForUserSync( 185 eq(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK), 186 anyBoolean(), observerCaptor.capture(), eq(UserHandle.USER_ALL)); 187 ContentObserver observer = observerCaptor.getValue(); 188 mExecutor.runAllReady(); 189 190 // When a settings change has occurred to the small clock, make sure the view is adjusted 191 reset(mView); 192 when(mView.getResources()).thenReturn(mResources); 193 observer.onChange(true); 194 mExecutor.runAllReady(); 195 verify(mView).switchToClock(KeyguardClockSwitch.SMALL, /* animate */ true); 196 } 197 198 @Test testGetClock_ForwardsToClock()199 public void testGetClock_ForwardsToClock() { 200 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 201 202 assertEquals(mClockController, mController.getClock()); 203 } 204 205 @Test testGetLargeClockBottom_returnsExpectedValue()206 public void testGetLargeClockBottom_returnsExpectedValue() { 207 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 208 209 when(mLargeClockFrame.getVisibility()).thenReturn(View.VISIBLE); 210 when(mLargeClockFrame.getHeight()).thenReturn(100); 211 when(mSmallClockFrame.getHeight()).thenReturn(50); 212 when(mLargeClockView.getHeight()).thenReturn(40); 213 when(mSmallClockView.getHeight()).thenReturn(20); 214 mController.init(); 215 216 assertEquals(170, mController.getClockBottom(1000)); 217 } 218 219 @Test testGetSmallLargeClockBottom_returnsExpectedValue()220 public void testGetSmallLargeClockBottom_returnsExpectedValue() { 221 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 222 223 when(mLargeClockFrame.getVisibility()).thenReturn(View.GONE); 224 when(mLargeClockFrame.getHeight()).thenReturn(100); 225 when(mSmallClockFrame.getHeight()).thenReturn(50); 226 when(mLargeClockView.getHeight()).thenReturn(40); 227 when(mSmallClockView.getHeight()).thenReturn(20); 228 mController.init(); 229 230 assertEquals(1120, mController.getClockBottom(1000)); 231 } 232 233 @Test testGetClockBottom_nullClock_returnsZero()234 public void testGetClockBottom_nullClock_returnsZero() { 235 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 236 237 when(mClockEventController.getClock()).thenReturn(null); 238 assertEquals(0, mController.getClockBottom(10)); 239 } 240 241 @Test testChangeLockscreenWeatherEnabledSetsWeatherViewVisible()242 public void testChangeLockscreenWeatherEnabledSetsWeatherViewVisible() { 243 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 244 245 when(mSmartspaceController.isWeatherEnabled()).thenReturn(true); 246 ArgumentCaptor<ContentObserver> observerCaptor = 247 ArgumentCaptor.forClass(ContentObserver.class); 248 mController.init(); 249 mExecutor.runAllReady(); 250 verify(mSecureSettings).registerContentObserverForUserSync( 251 eq(Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED), anyBoolean(), 252 observerCaptor.capture(), eq(UserHandle.USER_ALL)); 253 ContentObserver observer = observerCaptor.getValue(); 254 mExecutor.runAllReady(); 255 // When a settings change has occurred, check that view is visible. 256 observer.onChange(true); 257 mExecutor.runAllReady(); 258 assertEquals(View.VISIBLE, mFakeWeatherView.getVisibility()); 259 } 260 261 @Test testChangeClockDateWeatherEnabled_SetsDateWeatherViewVisibility()262 public void testChangeClockDateWeatherEnabled_SetsDateWeatherViewVisibility() { 263 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 264 265 ArgumentCaptor<ClockRegistry.ClockChangeListener> listenerArgumentCaptor = 266 ArgumentCaptor.forClass(ClockRegistry.ClockChangeListener.class); 267 when(mSmartspaceController.isEnabled()).thenReturn(true); 268 when(mSmartspaceController.isDateWeatherDecoupled()).thenReturn(true); 269 when(mSmartspaceController.isWeatherEnabled()).thenReturn(true); 270 mController.init(); 271 mExecutor.runAllReady(); 272 assertEquals(View.VISIBLE, mFakeDateView.getVisibility()); 273 274 when(mSmallClockController.getConfig()) 275 .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false, true)); 276 when(mLargeClockController.getConfig()) 277 .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, true, false, true)); 278 verify(mClockRegistry).registerClockChangeListener(listenerArgumentCaptor.capture()); 279 listenerArgumentCaptor.getValue().onCurrentClockChanged(); 280 281 mExecutor.runAllReady(); 282 assertEquals(View.INVISIBLE, mFakeDateView.getVisibility()); 283 } 284 285 @Test testGetClock_nullClock_returnsNull()286 public void testGetClock_nullClock_returnsNull() { 287 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 288 289 when(mClockEventController.getClock()).thenReturn(null); 290 assertNull(mController.getClock()); 291 } 292 verifyAttachment(VerificationMode times)293 private void verifyAttachment(VerificationMode times) { 294 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 295 296 verify(mClockRegistry, times).registerClockChangeListener( 297 any(ClockRegistry.ClockChangeListener.class)); 298 verify(mClockEventController, times).registerListeners(mView); 299 } 300 301 @Test testSplitShadeEnabledSetToSmartspaceController()302 public void testSplitShadeEnabledSetToSmartspaceController() { 303 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 304 305 mController.setSplitShadeEnabled(true); 306 verify(mSmartspaceController, times(1)).setSplitShadeEnabled(true); 307 verify(mSmartspaceController, times(0)).setSplitShadeEnabled(false); 308 } 309 310 @Test testSplitShadeDisabledSetToSmartspaceController()311 public void testSplitShadeDisabledSetToSmartspaceController() { 312 mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT); 313 314 mController.setSplitShadeEnabled(false); 315 verify(mSmartspaceController, times(1)).setSplitShadeEnabled(false); 316 verify(mSmartspaceController, times(0)).setSplitShadeEnabled(true); 317 } 318 } 319