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