1 /* 2 * Copyright (C) 2023 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 android.view.View.INVISIBLE; 20 21 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.Mockito.atLeast; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.content.res.Resources; 30 import android.view.View; 31 import android.view.ViewGroup; 32 import android.widget.FrameLayout; 33 import android.widget.LinearLayout; 34 import android.widget.RelativeLayout; 35 36 import com.android.systemui.SysuiTestCase; 37 import com.android.systemui.dump.DumpManager; 38 import com.android.systemui.flags.FakeFeatureFlags; 39 import com.android.systemui.keyguard.KeyguardUnlockAnimationController; 40 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor; 41 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory; 42 import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager; 43 import com.android.systemui.log.LogBuffer; 44 import com.android.systemui.plugins.clocks.ClockAnimations; 45 import com.android.systemui.plugins.clocks.ClockController; 46 import com.android.systemui.plugins.clocks.ClockEvents; 47 import com.android.systemui.plugins.clocks.ClockFaceConfig; 48 import com.android.systemui.plugins.clocks.ClockFaceController; 49 import com.android.systemui.plugins.clocks.ClockFaceEvents; 50 import com.android.systemui.plugins.clocks.ClockTickRate; 51 import com.android.systemui.plugins.statusbar.StatusBarStateController; 52 import com.android.systemui.res.R; 53 import com.android.systemui.shared.clocks.AnimatableClockView; 54 import com.android.systemui.shared.clocks.ClockRegistry; 55 import com.android.systemui.statusbar.StatusBarState; 56 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController; 57 import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerAlwaysOnDisplayViewBinder; 58 import com.android.systemui.statusbar.phone.NotificationIconAreaController; 59 import com.android.systemui.statusbar.phone.NotificationIconContainer; 60 import com.android.systemui.util.concurrency.FakeExecutor; 61 import com.android.systemui.util.settings.SecureSettings; 62 import com.android.systemui.util.time.FakeSystemClock; 63 64 import org.junit.Before; 65 import org.mockito.ArgumentCaptor; 66 import org.mockito.Captor; 67 import org.mockito.Mock; 68 import org.mockito.MockitoAnnotations; 69 70 public class KeyguardClockSwitchControllerBaseTest extends SysuiTestCase { 71 72 @Mock 73 protected KeyguardClockSwitch mView; 74 @Mock 75 protected StatusBarStateController mStatusBarStateController; 76 @Mock 77 protected ClockRegistry mClockRegistry; 78 @Mock 79 KeyguardSliceViewController mKeyguardSliceViewController; 80 @Mock 81 NotificationIconAreaController mNotificationIconAreaController; 82 @Mock 83 LockscreenSmartspaceController mSmartspaceController; 84 85 @Mock 86 Resources mResources; 87 @Mock 88 KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; 89 @Mock 90 protected ClockController mClockController; 91 @Mock 92 protected ClockFaceController mLargeClockController; 93 @Mock 94 protected ClockFaceController mSmallClockController; 95 @Mock 96 protected ClockAnimations mClockAnimations; 97 @Mock 98 protected ClockEvents mClockEvents; 99 @Mock 100 protected ClockFaceEvents mClockFaceEvents; 101 @Mock 102 DumpManager mDumpManager; 103 @Mock 104 ClockEventController mClockEventController; 105 106 @Mock 107 protected NotificationIconContainer mNotificationIcons; 108 @Mock 109 protected AnimatableClockView mSmallClockView; 110 @Mock 111 protected AnimatableClockView mLargeClockView; 112 @Mock 113 protected FrameLayout mSmallClockFrame; 114 @Mock 115 protected FrameLayout mLargeClockFrame; 116 @Mock 117 protected SecureSettings mSecureSettings; 118 @Mock 119 protected LogBuffer mLogBuffer; 120 121 @Mock 122 protected KeyguardClockInteractor mKeyguardClockInteractor; 123 124 protected final View mFakeDateView = (View) (new ViewGroup(mContext) { 125 @Override 126 protected void onLayout(boolean changed, int l, int t, int r, int b) {} 127 }); 128 protected final View mFakeWeatherView = new View(mContext); 129 protected final View mFakeSmartspaceView = new View(mContext); 130 131 protected KeyguardClockSwitchController mController; 132 protected View mSliceView; 133 protected LinearLayout mStatusArea; 134 protected FakeExecutor mExecutor; 135 protected FakeFeatureFlags mFakeFeatureFlags; 136 @Captor protected ArgumentCaptor<View.OnAttachStateChangeListener> mAttachCaptor = 137 ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class); 138 139 @Before setup()140 public void setup() { 141 MockitoAnnotations.initMocks(this); 142 143 mFakeDateView.setTag(R.id.tag_smartspace_view, new Object()); 144 mFakeWeatherView.setTag(R.id.tag_smartspace_view, new Object()); 145 mFakeSmartspaceView.setTag(R.id.tag_smartspace_view, new Object()); 146 147 when(mView.findViewById(R.id.left_aligned_notification_icon_container)) 148 .thenReturn(mNotificationIcons); 149 when(mNotificationIcons.getLayoutParams()).thenReturn( 150 mock(RelativeLayout.LayoutParams.class)); 151 when(mView.getContext()).thenReturn(getContext()); 152 when(mView.getResources()).thenReturn(mResources); 153 when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin)) 154 .thenReturn(100); 155 when(mResources.getDimensionPixelSize(com.android.systemui.customization.R.dimen.keyguard_large_clock_top_margin)) 156 .thenReturn(-200); 157 when(mResources.getInteger(com.android.internal.R.integer.config_doublelineClockDefault)) 158 .thenReturn(1); 159 when(mResources.getInteger(R.integer.keyguard_date_weather_view_invisibility)) 160 .thenReturn(INVISIBLE); 161 162 when(mView.findViewById(R.id.lockscreen_clock_view_large)).thenReturn(mLargeClockFrame); 163 when(mView.findViewById(R.id.lockscreen_clock_view)).thenReturn(mSmallClockFrame); 164 when(mSmallClockView.getContext()).thenReturn(getContext()); 165 when(mLargeClockView.getContext()).thenReturn(getContext()); 166 167 when(mView.isAttachedToWindow()).thenReturn(true); 168 when(mSmartspaceController.buildAndConnectDateView(any())).thenReturn(mFakeDateView); 169 when(mSmartspaceController.buildAndConnectWeatherView(any())).thenReturn(mFakeWeatherView); 170 when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView); 171 mExecutor = new FakeExecutor(new FakeSystemClock()); 172 mFakeFeatureFlags = new FakeFeatureFlags(); 173 mFakeFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false); 174 mController = new KeyguardClockSwitchController( 175 mView, 176 mStatusBarStateController, 177 mClockRegistry, 178 mKeyguardSliceViewController, 179 mNotificationIconAreaController, 180 mSmartspaceController, 181 mock(NotificationIconContainerAlwaysOnDisplayViewBinder.class), 182 mKeyguardUnlockAnimationController, 183 mSecureSettings, 184 mExecutor, 185 mExecutor, 186 mDumpManager, 187 mClockEventController, 188 mLogBuffer, 189 KeyguardInteractorFactory.create(mFakeFeatureFlags).getKeyguardInteractor(), 190 mKeyguardClockInteractor, 191 mFakeFeatureFlags, 192 mock(InWindowLauncherUnlockAnimationManager.class) 193 ); 194 195 when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE); 196 when(mLargeClockController.getView()).thenReturn(mLargeClockView); 197 when(mSmallClockController.getView()).thenReturn(mSmallClockView); 198 when(mClockController.getLargeClock()).thenReturn(mLargeClockController); 199 when(mClockController.getSmallClock()).thenReturn(mSmallClockController); 200 when(mClockController.getEvents()).thenReturn(mClockEvents); 201 when(mSmallClockController.getEvents()).thenReturn(mClockFaceEvents); 202 when(mLargeClockController.getEvents()).thenReturn(mClockFaceEvents); 203 when(mLargeClockController.getAnimations()).thenReturn(mClockAnimations); 204 when(mSmallClockController.getAnimations()).thenReturn(mClockAnimations); 205 when(mClockRegistry.createCurrentClock()).thenReturn(mClockController); 206 when(mClockEventController.getClock()).thenReturn(mClockController); 207 when(mSmallClockController.getConfig()) 208 .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false, false)); 209 when(mLargeClockController.getConfig()) 210 .thenReturn(new ClockFaceConfig(ClockTickRate.PER_MINUTE, false, false, false)); 211 212 mSliceView = new View(getContext()); 213 when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); 214 mStatusArea = new LinearLayout(getContext()); 215 when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(mStatusArea); 216 } 217 removeView(View v)218 private void removeView(View v) { 219 ViewGroup group = ((ViewGroup) v.getParent()); 220 if (group != null) { 221 group.removeView(v); 222 } 223 } 224 init()225 protected void init() { 226 mController.init(); 227 228 verify(mView, atLeast(1)).addOnAttachStateChangeListener(mAttachCaptor.capture()); 229 mAttachCaptor.getValue().onViewAttachedToWindow(mView); 230 } 231 } 232