• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.systemui.shade;
18 
19 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
20 
21 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
22 
23 import static com.google.common.truth.Truth.assertThat;
24 
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyBoolean;
27 import static org.mockito.ArgumentMatchers.anyFloat;
28 import static org.mockito.ArgumentMatchers.anyInt;
29 import static org.mockito.ArgumentMatchers.anyLong;
30 import static org.mockito.ArgumentMatchers.eq;
31 import static org.mockito.Mockito.atLeast;
32 import static org.mockito.Mockito.doAnswer;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.reset;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
37 
38 import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
39 
40 import android.annotation.IdRes;
41 import android.content.ContentResolver;
42 import android.content.res.Configuration;
43 import android.content.res.Resources;
44 import android.database.ContentObserver;
45 import android.os.Handler;
46 import android.os.Looper;
47 import android.os.PowerManager;
48 import android.os.UserManager;
49 import android.util.DisplayMetrics;
50 import android.view.LayoutInflater;
51 import android.view.MotionEvent;
52 import android.view.View;
53 import android.view.ViewGroup;
54 import android.view.ViewParent;
55 import android.view.ViewPropertyAnimator;
56 import android.view.ViewStub;
57 import android.view.ViewTreeObserver;
58 import android.view.accessibility.AccessibilityManager;
59 
60 import androidx.constraintlayout.widget.ConstraintSet;
61 
62 import com.android.internal.jank.InteractionJankMonitor;
63 import com.android.internal.logging.MetricsLogger;
64 import com.android.internal.logging.UiEventLogger;
65 import com.android.internal.logging.testing.UiEventLoggerFake;
66 import com.android.internal.util.LatencyTracker;
67 import com.android.keyguard.KeyguardClockSwitch;
68 import com.android.keyguard.KeyguardClockSwitchController;
69 import com.android.keyguard.KeyguardStatusView;
70 import com.android.keyguard.KeyguardStatusViewController;
71 import com.android.keyguard.KeyguardUpdateMonitor;
72 import com.android.keyguard.LockIconViewController;
73 import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
74 import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
75 import com.android.keyguard.dagger.KeyguardStatusViewComponent;
76 import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
77 import com.android.systemui.R;
78 import com.android.systemui.SysuiTestCase;
79 import com.android.systemui.biometrics.AuthController;
80 import com.android.systemui.classifier.FalsingCollectorFake;
81 import com.android.systemui.classifier.FalsingManagerFake;
82 import com.android.systemui.common.ui.view.LongPressHandlingView;
83 import com.android.systemui.doze.DozeLog;
84 import com.android.systemui.dump.DumpManager;
85 import com.android.systemui.flags.FeatureFlags;
86 import com.android.systemui.fragments.FragmentHostManager;
87 import com.android.systemui.fragments.FragmentService;
88 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
89 import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
90 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
91 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
92 import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
93 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
94 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
95 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
96 import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
97 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
98 import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
99 import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
100 import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
101 import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
102 import com.android.systemui.media.controls.pipeline.MediaDataManager;
103 import com.android.systemui.media.controls.ui.KeyguardMediaController;
104 import com.android.systemui.media.controls.ui.MediaHierarchyManager;
105 import com.android.systemui.model.SysUiState;
106 import com.android.systemui.navigationbar.NavigationBarController;
107 import com.android.systemui.navigationbar.NavigationModeController;
108 import com.android.systemui.plugins.FalsingManager;
109 import com.android.systemui.plugins.qs.QS;
110 import com.android.systemui.qs.QSFragment;
111 import com.android.systemui.screenrecord.RecordingController;
112 import com.android.systemui.shade.transition.ShadeTransitionController;
113 import com.android.systemui.statusbar.CommandQueue;
114 import com.android.systemui.statusbar.KeyguardIndicationController;
115 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
116 import com.android.systemui.statusbar.NotificationRemoteInputManager;
117 import com.android.systemui.statusbar.NotificationShadeDepthController;
118 import com.android.systemui.statusbar.NotificationShadeWindowController;
119 import com.android.systemui.statusbar.NotificationShelfController;
120 import com.android.systemui.statusbar.PulseExpansionHandler;
121 import com.android.systemui.statusbar.QsFrameTranslateController;
122 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
123 import com.android.systemui.statusbar.SysuiStatusBarStateController;
124 import com.android.systemui.statusbar.VibratorHelper;
125 import com.android.systemui.statusbar.notification.ConversationNotificationManager;
126 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
127 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
128 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
129 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
130 import com.android.systemui.statusbar.notification.stack.AmbientState;
131 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
132 import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
133 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
134 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
135 import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
136 import com.android.systemui.statusbar.phone.CentralSurfaces;
137 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
138 import com.android.systemui.statusbar.phone.DozeParameters;
139 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
140 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
141 import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
142 import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
143 import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
144 import com.android.systemui.statusbar.phone.KeyguardBypassController;
145 import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
146 import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
147 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
148 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
149 import com.android.systemui.statusbar.phone.ScrimController;
150 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
151 import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
152 import com.android.systemui.statusbar.phone.TapAgainViewController;
153 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
154 import com.android.systemui.statusbar.policy.ConfigurationController;
155 import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
156 import com.android.systemui.statusbar.policy.KeyguardStateController;
157 import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
158 import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
159 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
160 import com.android.systemui.unfold.SysUIUnfoldComponent;
161 import com.android.systemui.util.time.FakeSystemClock;
162 import com.android.systemui.util.time.SystemClock;
163 import com.android.wm.shell.animation.FlingAnimationUtils;
164 
165 import org.junit.After;
166 import org.junit.Before;
167 import org.mockito.ArgumentCaptor;
168 import org.mockito.Captor;
169 import org.mockito.Mock;
170 import org.mockito.MockitoAnnotations;
171 import org.mockito.stubbing.Answer;
172 
173 import java.util.List;
174 import java.util.Optional;
175 
176 import dagger.Lazy;
177 import kotlinx.coroutines.CoroutineDispatcher;
178 
179 public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
180 
181     protected static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
182     protected static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
183     protected static final int PANEL_WIDTH = 500; // Random value just for the test.
184 
185     @Mock protected CentralSurfaces mCentralSurfaces;
186     @Mock protected NotificationStackScrollLayout mNotificationStackScrollLayout;
187     @Mock protected KeyguardBottomAreaView mKeyguardBottomArea;
188     @Mock protected KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
189     @Mock protected ViewPropertyAnimator mViewPropertyAnimator;
190     @Mock protected KeyguardBottomAreaView mQsFrame;
191     @Mock protected HeadsUpManagerPhone mHeadsUpManager;
192     @Mock protected NotificationShelfController mNotificationShelfController;
193     @Mock protected NotificationGutsManager mGutsManager;
194     @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
195     @Mock protected KeyguardUserSwitcherView mUserSwitcherView;
196     @Mock protected ViewStub mUserSwitcherStubView;
197     @Mock protected HeadsUpTouchHelper.Callback mHeadsUpCallback;
198     @Mock protected KeyguardUpdateMonitor mUpdateMonitor;
199     @Mock protected KeyguardBypassController mKeyguardBypassController;
200     @Mock protected DozeParameters mDozeParameters;
201     @Mock protected ScreenOffAnimationController mScreenOffAnimationController;
202     @Mock protected NotificationPanelView mView;
203     @Mock protected LayoutInflater mLayoutInflater;
204     @Mock protected FeatureFlags mFeatureFlags;
205     @Mock protected DynamicPrivacyController mDynamicPrivacyController;
206     @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
207     @Mock protected KeyguardStateController mKeyguardStateController;
208     @Mock protected DozeLog mDozeLog;
209     @Mock protected ShadeLogger mShadeLog;
210     @Mock protected ShadeHeightLogger mShadeHeightLogger;
211     @Mock protected CommandQueue mCommandQueue;
212     @Mock protected VibratorHelper mVibratorHelper;
213     @Mock protected LatencyTracker mLatencyTracker;
214     @Mock protected PowerManager mPowerManager;
215     @Mock protected AccessibilityManager mAccessibilityManager;
216     @Mock protected MetricsLogger mMetricsLogger;
217     @Mock protected Resources mResources;
218     @Mock protected Configuration mConfiguration;
219     @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
220     @Mock protected MediaHierarchyManager mMediaHierarchyManager;
221     @Mock protected ConversationNotificationManager mConversationNotificationManager;
222     @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
223     @Mock protected KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
224     @Mock protected KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
225     @Mock protected KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
226     @Mock protected KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
227     @Mock protected KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
228     @Mock protected KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
229     @Mock protected KeyguardUserSwitcherController mKeyguardUserSwitcherController;
230     @Mock protected KeyguardStatusViewComponent mKeyguardStatusViewComponent;
231     @Mock protected KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
232     @Mock protected KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
233     @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
234     @Mock protected KeyguardStatusViewController mKeyguardStatusViewController;
235     @Mock protected KeyguardStatusBarViewController mKeyguardStatusBarViewController;
236     @Mock protected NotificationStackScrollLayoutController
237             mNotificationStackScrollLayoutController;
238     @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
239     @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
240     @Mock protected AuthController mAuthController;
241     @Mock protected ScrimController mScrimController;
242     @Mock protected MediaDataManager mMediaDataManager;
243     @Mock protected AmbientState mAmbientState;
244     @Mock protected UserManager mUserManager;
245     @Mock protected UiEventLogger mUiEventLogger;
246     @Mock protected LockIconViewController mLockIconViewController;
247     @Mock protected KeyguardMediaController mKeyguardMediaController;
248     @Mock protected NavigationModeController mNavigationModeController;
249     @Mock protected NavigationBarController mNavigationBarController;
250     @Mock protected QuickSettingsController mQsController;
251     @Mock protected ShadeHeaderController mShadeHeaderController;
252     @Mock protected ContentResolver mContentResolver;
253     @Mock protected TapAgainViewController mTapAgainViewController;
254     @Mock protected KeyguardIndicationController mKeyguardIndicationController;
255     @Mock protected FragmentService mFragmentService;
256     @Mock protected FragmentHostManager mFragmentHostManager;
257     @Mock protected NotificationRemoteInputManager mNotificationRemoteInputManager;
258     @Mock protected RecordingController mRecordingController;
259     @Mock protected LockscreenGestureLogger mLockscreenGestureLogger;
260     @Mock protected DumpManager mDumpManager;
261     @Mock protected InteractionJankMonitor mInteractionJankMonitor;
262     @Mock protected NotificationsQSContainerController mNotificationsQSContainerController;
263     @Mock protected QsFrameTranslateController mQsFrameTranslateController;
264     @Mock protected StatusBarWindowStateController mStatusBarWindowStateController;
265     @Mock protected KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
266     @Mock protected NotificationShadeWindowController mNotificationShadeWindowController;
267     @Mock protected SysUiState mSysUiState;
268     @Mock protected NotificationListContainer mNotificationListContainer;
269     @Mock protected NotificationStackSizeCalculator mNotificationStackSizeCalculator;
270     @Mock protected UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
271     @Mock protected ShadeTransitionController mShadeTransitionController;
272     @Mock protected QS mQs;
273     @Mock protected QSFragment mQSFragment;
274     @Mock protected ViewGroup mQsHeader;
275     @Mock protected ViewParent mViewParent;
276     @Mock protected ViewTreeObserver mViewTreeObserver;
277     @Mock protected KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
278     @Mock protected DreamingToLockscreenTransitionViewModel
279             mDreamingToLockscreenTransitionViewModel;
280     @Mock protected OccludedToLockscreenTransitionViewModel
281             mOccludedToLockscreenTransitionViewModel;
282     @Mock protected LockscreenToDreamingTransitionViewModel
283             mLockscreenToDreamingTransitionViewModel;
284     @Mock protected LockscreenToOccludedTransitionViewModel
285             mLockscreenToOccludedTransitionViewModel;
286     @Mock protected GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
287 
288     @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
289     @Mock protected KeyguardLongPressViewModel mKeyuardLongPressViewModel;
290     @Mock protected AlternateBouncerInteractor mAlternateBouncerInteractor;
291     @Mock protected MotionEvent mDownMotionEvent;
292     @Mock protected CoroutineDispatcher mMainDispatcher;
293     @Captor
294     protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
295             mEmptySpaceClickListenerCaptor;
296 
297     protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
298     protected KeyguardInteractor mKeyguardInteractor;
299     protected NotificationPanelViewController.TouchHandler mTouchHandler;
300     protected ConfigurationController mConfigurationController;
301     protected SysuiStatusBarStateController mStatusBarStateController;
302     protected NotificationPanelViewController mNotificationPanelViewController;
303     protected View.AccessibilityDelegate mAccessibilityDelegate;
304     protected NotificationsQuickSettingsContainer mNotificationContainerParent;
305     protected List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
306     protected Handler mMainHandler;
307     protected View.OnLayoutChangeListener mLayoutChangeListener;
308 
309     protected final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
310     protected final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
311     protected final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
312     protected final ShadeExpansionStateManager mShadeExpansionStateManager =
313             new ShadeExpansionStateManager();
314 
315     protected QuickSettingsController mQuickSettingsController;
316     @Mock protected Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
317 
318     protected FragmentHostManager.FragmentListener mFragmentListener;
319 
320     @Before
setup()321     public void setup() {
322         MockitoAnnotations.initMocks(this);
323         mMainDispatcher = getMainDispatcher();
324         mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
325                 new FakeKeyguardRepository());
326         mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
327                 mFeatureFlags, new FakeKeyguardBouncerRepository());
328         SystemClock systemClock = new FakeSystemClock();
329         mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
330                 mInteractionJankMonitor, mShadeExpansionStateManager);
331 
332         KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
333         keyguardStatusView.setId(R.id.keyguard_status_view);
334 
335         when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
336         when(mHeadsUpCallback.getContext()).thenReturn(mContext);
337         when(mView.getResources()).thenReturn(mResources);
338         when(mView.getWidth()).thenReturn(PANEL_WIDTH);
339         when(mResources.getConfiguration()).thenReturn(mConfiguration);
340         mConfiguration.orientation = ORIENTATION_PORTRAIT;
341         when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
342         mDisplayMetrics.density = 100;
343         when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
344         when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
345                 .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
346         when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
347                 .thenReturn(10);
348         when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
349                 .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
350         when(mView.getContext()).thenReturn(getContext());
351         when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
352         when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
353         when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
354                 mUserSwitcherStubView);
355         when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
356         when(mView.findViewById(R.id.notification_stack_scroller))
357                 .thenReturn(mNotificationStackScrollLayout);
358         when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
359         when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
360                 .thenReturn(mHeadsUpCallback);
361         when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
362         when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
363         when(mKeyguardBottomArea.animate()).thenReturn(mViewPropertyAnimator);
364         when(mView.animate()).thenReturn(mViewPropertyAnimator);
365         when(mViewPropertyAnimator.translationX(anyFloat())).thenReturn(mViewPropertyAnimator);
366         when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator);
367         when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator);
368         when(mViewPropertyAnimator.setInterpolator(any())).thenReturn(mViewPropertyAnimator);
369         when(mViewPropertyAnimator.setListener(any())).thenReturn(mViewPropertyAnimator);
370         when(mViewPropertyAnimator.setUpdateListener(any())).thenReturn(mViewPropertyAnimator);
371         when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
372         when(mView.findViewById(R.id.keyguard_status_view))
373                 .thenReturn(mock(KeyguardStatusView.class));
374         mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
375         mNotificationContainerParent.addView(keyguardStatusView);
376         mNotificationContainerParent.onFinishInflate();
377         when(mView.findViewById(R.id.notification_container_parent))
378                 .thenReturn(mNotificationContainerParent);
379         when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
380         FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
381                 mDisplayMetrics);
382         when(mKeyguardQsUserSwitchComponentFactory.build(any()))
383                 .thenReturn(mKeyguardQsUserSwitchComponent);
384         when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
385                 .thenReturn(mKeyguardQsUserSwitchController);
386         when(mKeyguardUserSwitcherComponentFactory.build(any()))
387                 .thenReturn(mKeyguardUserSwitcherComponent);
388         when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
389                 .thenReturn(mKeyguardUserSwitcherController);
390         when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
391         when(mQs.getView()).thenReturn(mView);
392         when(mQSFragment.getView()).thenReturn(mView);
393         doAnswer(invocation -> {
394             mFragmentListener = invocation.getArgument(1);
395             return null;
396         }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
397         doAnswer((Answer<Void>) invocation -> {
398             mTouchHandler = invocation.getArgument(0);
399             return null;
400         }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
401 
402         // Dreaming->Lockscreen
403         when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition())
404                 .thenReturn(emptyFlow());
405         when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha())
406                 .thenReturn(emptyFlow());
407         when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
408                 .thenReturn(emptyFlow());
409 
410         // Occluded->Lockscreen
411         when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition())
412                 .thenReturn(emptyFlow());
413         when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
414                 .thenReturn(emptyFlow());
415         when(mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
416                 .thenReturn(emptyFlow());
417 
418         // Lockscreen->Dreaming
419         when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
420                 .thenReturn(emptyFlow());
421         when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
422                 .thenReturn(emptyFlow());
423         when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
424                 .thenReturn(emptyFlow());
425 
426         // Gone->Dreaming
427         when(mKeyguardTransitionInteractor.getGoneToDreamingTransition())
428                 .thenReturn(emptyFlow());
429         when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
430                 .thenReturn(emptyFlow());
431         when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
432                 .thenReturn(emptyFlow());
433 
434         // Lockscreen->Occluded
435         when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition())
436                 .thenReturn(emptyFlow());
437         when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
438                 .thenReturn(emptyFlow());
439         when(mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(anyInt()))
440                 .thenReturn(emptyFlow());
441 
442         NotificationWakeUpCoordinator coordinator =
443                 new NotificationWakeUpCoordinator(
444                         mDumpManager,
445                         mock(HeadsUpManagerPhone.class),
446                         new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
447                                 mInteractionJankMonitor, mShadeExpansionStateManager),
448                         mKeyguardBypassController,
449                         mDozeParameters,
450                         mScreenOffAnimationController,
451                         mock(NotificationWakeUpCoordinatorLogger.class));
452         mConfigurationController = new ConfigurationControllerImpl(mContext);
453         PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
454                 mContext,
455                 coordinator,
456                 mKeyguardBypassController, mHeadsUpManager,
457                 mock(NotificationRoundnessManager.class),
458                 mConfigurationController,
459                 mStatusBarStateController,
460                 mFalsingManager,
461                 mShadeExpansionStateManager,
462                 mLockscreenShadeTransitionController,
463                 new FalsingCollectorFake(),
464                 mDumpManager);
465         when(mKeyguardStatusViewComponentFactory.build(any()))
466                 .thenReturn(mKeyguardStatusViewComponent);
467         when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
468                 .thenReturn(mKeyguardClockSwitchController);
469         when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
470                 .thenReturn(mKeyguardStatusViewController);
471         when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
472                 .thenReturn(mKeyguardStatusBarViewComponent);
473         when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
474                 .thenReturn(mKeyguardStatusBarViewController);
475         when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
476                 .thenReturn(keyguardStatusView);
477         when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
478                 .thenReturn(mUserSwitcherView);
479         when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
480                 .thenReturn(mKeyguardBottomArea);
481         when(mNotificationRemoteInputManager.isRemoteInputActive())
482                 .thenReturn(false);
483         when(mInteractionJankMonitor.begin(any(), anyInt()))
484                 .thenReturn(true);
485         when(mInteractionJankMonitor.end(anyInt()))
486                 .thenReturn(true);
487         doAnswer(invocation -> {
488             ((Runnable) invocation.getArgument(0)).run();
489             return null;
490         }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
491         doAnswer(invocation -> {
492             mLayoutChangeListener = invocation.getArgument(0);
493             return null;
494         }).when(mView).addOnLayoutChangeListener(any());
495 
496         when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
497         when(mView.getParent()).thenReturn(mViewParent);
498         when(mQs.getHeader()).thenReturn(mQsHeader);
499         when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
500         when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
501 
502         mMainHandler = new Handler(Looper.getMainLooper());
503 
504         when(mView.requireViewById(R.id.keyguard_long_press))
505                 .thenReturn(mock(LongPressHandlingView.class));
506 
507         mNotificationPanelViewController = new NotificationPanelViewController(
508                 mView,
509                 mMainHandler,
510                 mLayoutInflater,
511                 mFeatureFlags,
512                 coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
513                 mFalsingManager, new FalsingCollectorFake(),
514                 mKeyguardStateController,
515                 mStatusBarStateController,
516                 mStatusBarWindowStateController,
517                 mNotificationShadeWindowController,
518                 mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
519                 mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
520                 mMetricsLogger,
521                 mShadeLog,
522                 mShadeHeightLogger,
523                 mConfigurationController,
524                 () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
525                 mConversationNotificationManager, mMediaHierarchyManager,
526                 mStatusBarKeyguardViewManager,
527                 mGutsManager,
528                 mNotificationsQSContainerController,
529                 mNotificationStackScrollLayoutController,
530                 mKeyguardStatusViewComponentFactory,
531                 mKeyguardQsUserSwitchComponentFactory,
532                 mKeyguardUserSwitcherComponentFactory,
533                 mKeyguardStatusBarViewComponentFactory,
534                 mLockscreenShadeTransitionController,
535                 mAuthController,
536                 mScrimController,
537                 mUserManager,
538                 mMediaDataManager,
539                 mNotificationShadeDepthController,
540                 mAmbientState,
541                 mLockIconViewController,
542                 mKeyguardMediaController,
543                 mTapAgainViewController,
544                 mNavigationModeController,
545                 mNavigationBarController,
546                 mQsController,
547                 mFragmentService,
548                 mContentResolver,
549                 mShadeHeaderController,
550                 mScreenOffAnimationController,
551                 mLockscreenGestureLogger,
552                 mShadeExpansionStateManager,
553                 mSysUIUnfoldComponent,
554                 mSysUiState,
555                 () -> mKeyguardBottomAreaViewController,
556                 mKeyguardUnlockAnimationController,
557                 mKeyguardIndicationController,
558                 mNotificationListContainer,
559                 mNotificationStackSizeCalculator,
560                 mUnlockedScreenOffAnimationController,
561                 mShadeTransitionController,
562                 mInteractionJankMonitor,
563                 systemClock,
564                 mKeyguardBottomAreaViewModel,
565                 mKeyguardBottomAreaInteractor,
566                 mAlternateBouncerInteractor,
567                 mDreamingToLockscreenTransitionViewModel,
568                 mOccludedToLockscreenTransitionViewModel,
569                 mLockscreenToDreamingTransitionViewModel,
570                 mGoneToDreamingTransitionViewModel,
571                 mLockscreenToOccludedTransitionViewModel,
572                 mMainDispatcher,
573                 mKeyguardTransitionInteractor,
574                 mDumpManager,
575                 mKeyuardLongPressViewModel,
576                 mKeyguardInteractor);
577         mNotificationPanelViewController.initDependencies(
578                 mCentralSurfaces,
579                 null,
580                 () -> {},
581                 mNotificationShelfController);
582         mNotificationPanelViewController.setTrackingStartedListener(() -> {});
583         mNotificationPanelViewController.setOpenCloseListener(
584                 new NotificationPanelViewController.OpenCloseListener() {
585                     @Override
586                     public void onClosingFinished() {}
587 
588                     @Override
589                     public void onOpenStarted() {}
590                 });
591         mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
592         ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
593                 ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
594         verify(mView, atLeast(1)).addOnAttachStateChangeListener(
595                 onAttachStateChangeListenerArgumentCaptor.capture());
596         mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
597 
598         ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
599                 ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
600         verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
601         mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
602         mNotificationPanelViewController.getStatusBarStateController()
603                 .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
604         mNotificationPanelViewController
605                 .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
606         verify(mNotificationStackScrollLayoutController)
607                 .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
608         verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
609         reset(mKeyguardStatusViewController);
610 
611         when(mNotificationPanelViewControllerLazy.get())
612                 .thenReturn(mNotificationPanelViewController);
613         mQuickSettingsController = new QuickSettingsController(
614                 mNotificationPanelViewControllerLazy,
615                 mView,
616                 mQsFrameTranslateController,
617                 mShadeTransitionController,
618                 expansionHandler,
619                 mNotificationRemoteInputManager,
620                 mShadeExpansionStateManager,
621                 mStatusBarKeyguardViewManager,
622                 mNotificationStackScrollLayoutController,
623                 mLockscreenShadeTransitionController,
624                 mNotificationShadeDepthController,
625                 mShadeHeaderController,
626                 mStatusBarTouchableRegionManager,
627                 mKeyguardStateController,
628                 mKeyguardBypassController,
629                 mUpdateMonitor,
630                 mScrimController,
631                 mMediaDataManager,
632                 mMediaHierarchyManager,
633                 mAmbientState,
634                 mRecordingController,
635                 mFalsingManager,
636                 new FalsingCollectorFake(),
637                 mAccessibilityManager,
638                 mLockscreenGestureLogger,
639                 mMetricsLogger,
640                 mFeatureFlags,
641                 mInteractionJankMonitor,
642                 mShadeLog
643         );
644     }
645 
646     @After
tearDown()647     public void tearDown() {
648         mNotificationPanelViewController.mBottomAreaShadeAlphaAnimator.cancel();
649         mNotificationPanelViewController.cancelHeightAnimator();
650         mMainHandler.removeCallbacksAndMessages(null);
651     }
652 
setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding, int ambientPadding)653     protected void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
654             int ambientPadding) {
655 
656         when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
657         when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
658         when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
659         when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
660 
661         when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
662                 .thenReturn(indicationPadding);
663         mNotificationPanelViewController.loadDimens();
664 
665         mNotificationPanelViewController.setAmbientIndicationTop(
666                 /* ambientIndicationTop= */ stackBottom - ambientPadding,
667                 /* ambientTextVisible= */ true);
668     }
669 
triggerPositionClockAndNotifications()670     protected void triggerPositionClockAndNotifications() {
671         mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
672     }
673 
getFalsingTapListener()674     protected FalsingManager.FalsingTapListener getFalsingTapListener() {
675         for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
676             listener.onViewAttachedToWindow(mView);
677         }
678         assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
679         return mFalsingManager.getTapListeners().get(0);
680     }
681 
givenViewAttached()682     protected void givenViewAttached() {
683         for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
684             listener.onViewAttachedToWindow(mView);
685         }
686     }
687 
getConstraintSetLayout(@dRes int id)688     protected ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
689         ConstraintSet constraintSet = new ConstraintSet();
690         constraintSet.clone(mNotificationContainerParent);
691         return constraintSet.getConstraint(id).layout;
692     }
693 
enableSplitShade(boolean enabled)694     protected void enableSplitShade(boolean enabled) {
695         when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
696         mNotificationPanelViewController.updateResources();
697     }
698 
updateMultiUserSetting(boolean enabled)699     protected void updateMultiUserSetting(boolean enabled) {
700         when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
701         when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
702         final ArgumentCaptor<ContentObserver> observerCaptor =
703                 ArgumentCaptor.forClass(ContentObserver.class);
704         verify(mContentResolver)
705                 .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
706         observerCaptor.getValue().onChange(/* selfChange */ false);
707     }
708 
updateSmallestScreenWidth(int smallestScreenWidthDp)709     protected void updateSmallestScreenWidth(int smallestScreenWidthDp) {
710         Configuration configuration = new Configuration();
711         configuration.smallestScreenWidthDp = smallestScreenWidthDp;
712         mConfigurationController.onConfigurationChanged(configuration);
713     }
714 
onTouchEvent(MotionEvent ev)715     protected void onTouchEvent(MotionEvent ev) {
716         mTouchHandler.onTouch(mView, ev);
717     }
718 
setDozing(boolean dozing, boolean dozingAlwaysOn)719     protected void setDozing(boolean dozing, boolean dozingAlwaysOn) {
720         when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
721         mNotificationPanelViewController.setDozing(
722                 /* dozing= */ dozing,
723                 /* animate= */ false
724         );
725     }
726 
assertKeyguardStatusViewCentered()727     protected void assertKeyguardStatusViewCentered() {
728         mNotificationPanelViewController.updateResources();
729         assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
730                 ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
731     }
732 
assertKeyguardStatusViewNotCentered()733     protected void assertKeyguardStatusViewNotCentered() {
734         mNotificationPanelViewController.updateResources();
735         assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
736                 R.id.qs_edge_guideline);
737     }
738 
setIsFullWidth(boolean fullWidth)739     protected void setIsFullWidth(boolean fullWidth) {
740         float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
741         when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
742         triggerLayoutChange();
743     }
744 
triggerLayoutChange()745     protected void triggerLayoutChange() {
746         mLayoutChangeListener.onLayoutChange(
747                 mView,
748                 /* left= */ 0,
749                 /* top= */ 0,
750                 /* right= */ 0,
751                 /* bottom= */ 0,
752                 /* oldLeft= */ 0,
753                 /* oldTop= */ 0,
754                 /* oldRight= */ 0,
755                 /* oldBottom= */ 0
756         );
757     }
758 
getMainDispatcher()759     protected CoroutineDispatcher getMainDispatcher() {
760         return mMainDispatcher;
761     }
762 }
763