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