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