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