1 /* 2 * Copyright (C) 2014 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.statusbar.phone; 18 19 import static android.view.WindowInsets.Type.navigationBars; 20 21 import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN; 22 import static com.android.systemui.plugins.ActivityStarter.OnDismissAction; 23 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK; 24 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; 25 26 import android.content.Context; 27 import android.content.res.ColorStateList; 28 import android.hardware.biometrics.BiometricSourceType; 29 import android.os.Bundle; 30 import android.os.SystemClock; 31 import android.os.Trace; 32 import android.util.Log; 33 import android.view.KeyEvent; 34 import android.view.MotionEvent; 35 import android.view.View; 36 import android.view.ViewGroup; 37 import android.view.ViewRootImpl; 38 import android.view.WindowInsetsController; 39 import android.window.BackEvent; 40 import android.window.OnBackAnimationCallback; 41 import android.window.OnBackInvokedDispatcher; 42 43 import androidx.annotation.NonNull; 44 import androidx.annotation.Nullable; 45 import androidx.annotation.VisibleForTesting; 46 47 import com.android.internal.util.LatencyTracker; 48 import com.android.internal.widget.LockPatternUtils; 49 import com.android.keyguard.KeyguardSecurityModel; 50 import com.android.keyguard.KeyguardUpdateMonitor; 51 import com.android.keyguard.KeyguardUpdateMonitorCallback; 52 import com.android.keyguard.KeyguardViewController; 53 import com.android.keyguard.TrustGrantFlags; 54 import com.android.keyguard.ViewMediatorCallback; 55 import com.android.systemui.DejankUtils; 56 import com.android.systemui.Flags; 57 import com.android.systemui.animation.back.FlingOnBackAnimationCallback; 58 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor; 59 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor; 60 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor; 61 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback; 62 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; 63 import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags; 64 import com.android.systemui.bouncer.ui.BouncerView; 65 import com.android.systemui.bouncer.util.BouncerTestUtilsKt; 66 import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor; 67 import com.android.systemui.dagger.SysUISingleton; 68 import com.android.systemui.dagger.qualifiers.Main; 69 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor; 70 import com.android.systemui.dock.DockManager; 71 import com.android.systemui.dreams.DreamOverlayStateController; 72 import com.android.systemui.keyguard.DismissCallbackRegistry; 73 import com.android.systemui.keyguard.KeyguardWmStateRefactor; 74 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor; 75 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissTransitionInteractor; 76 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; 77 import com.android.systemui.keyguard.shared.model.DismissAction; 78 import com.android.systemui.keyguard.shared.model.KeyguardDone; 79 import com.android.systemui.keyguard.shared.model.TransitionStep; 80 import com.android.systemui.navigationbar.NavigationModeController; 81 import com.android.systemui.navigationbar.TaskbarDelegate; 82 import com.android.systemui.navigationbar.views.NavigationBarView; 83 import com.android.systemui.plugins.ActivityStarter; 84 import com.android.systemui.plugins.statusbar.StatusBarStateController; 85 import com.android.systemui.scene.domain.interactor.SceneInteractor; 86 import com.android.systemui.scene.shared.flag.SceneContainerFlag; 87 import com.android.systemui.scene.shared.model.Overlays; 88 import com.android.systemui.shade.ShadeController; 89 import com.android.systemui.shade.ShadeExpansionChangeEvent; 90 import com.android.systemui.shade.ShadeExpansionListener; 91 import com.android.systemui.shade.ShadeExpansionStateManager; 92 import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor; 93 import com.android.systemui.shared.system.QuickStepContract; 94 import com.android.systemui.shared.system.SysUiStatsLog; 95 import com.android.systemui.statusbar.NotificationShadeWindowController; 96 import com.android.systemui.statusbar.RemoteInputController; 97 import com.android.systemui.statusbar.StatusBarState; 98 import com.android.systemui.statusbar.SysuiStatusBarStateController; 99 import com.android.systemui.statusbar.domain.interactor.StatusBarKeyguardViewManagerInteractor; 100 import com.android.systemui.statusbar.policy.ConfigurationController; 101 import com.android.systemui.statusbar.policy.KeyguardStateController; 102 import com.android.systemui.unfold.FoldAodAnimationController; 103 import com.android.systemui.unfold.SysUIUnfoldComponent; 104 import com.android.systemui.user.domain.interactor.SelectedUserInteractor; 105 import com.android.systemui.util.concurrency.DelayableExecutor; 106 import com.android.systemui.util.kotlin.JavaAdapter; 107 108 import dagger.Lazy; 109 110 import kotlin.Unit; 111 112 import kotlinx.coroutines.CoroutineDispatcher; 113 import kotlinx.coroutines.Job; 114 115 import java.io.PrintWriter; 116 import java.io.StringWriter; 117 import java.util.ArrayList; 118 import java.util.HashSet; 119 import java.util.Objects; 120 import java.util.Optional; 121 import java.util.Set; 122 123 import javax.inject.Inject; 124 125 /** 126 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back 127 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done, 128 * which is in turn, reported to this class by the current 129 * {@link com.android.keyguard.KeyguardViewController}. 130 */ 131 @SysUISingleton 132 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback, 133 StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener, 134 ShadeExpansionListener, NavigationModeController.ModeChangedListener, 135 KeyguardViewController, FoldAodAnimationController.FoldAodAnimationStatus { 136 137 // When hiding the Keyguard with timing supplied from WindowManager, better be early than late. 138 private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3; 139 140 // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync 141 // with the appear animations of the PIN/pattern/password views. 142 private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320; 143 144 // The duration to fade the nav bar content in/out when the device starts to sleep 145 private static final long NAV_BAR_CONTENT_FADE_DURATION = 125; 146 147 // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to 148 // make everything a bit slower to bridge a gap until the user is unlocked and home screen has 149 // dranw its first frame. 150 private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000; 151 152 private static final String TAG = "StatusBarKeyguardViewManager"; 153 private static final boolean DEBUG = false; 154 155 protected final Context mContext; 156 private final ConfigurationController mConfigurationController; 157 private final NavigationModeController mNavigationModeController; 158 private final NotificationShadeWindowController mNotificationShadeWindowController; 159 private final DreamOverlayStateController mDreamOverlayStateController; 160 @Nullable 161 private final FoldAodAnimationController mFoldAodAnimationController; 162 private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor; 163 private final PrimaryBouncerInteractor mPrimaryBouncerInteractor; 164 private final AlternateBouncerInteractor mAlternateBouncerInteractor; 165 private final Lazy<BouncerInteractor> mBouncerInteractor; 166 private final BouncerView mPrimaryBouncerView; 167 private final Lazy<ShadeController> mShadeController; 168 private final Lazy<SceneInteractor> mSceneInteractorLazy; 169 private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractorLazy; 170 private final DismissCallbackRegistry mDismissCallbackRegistry; 171 private final CommunalSceneInteractor mCommunalSceneInteractor; 172 173 private Job mListenForAlternateBouncerTransitionSteps = null; 174 private Job mListenForKeyguardAuthenticatedBiometricsHandled = null; 175 private Job mListenForCanShowAlternateBouncer = null; 176 177 // Local cache of expansion events, to avoid duplicates 178 private float mFraction = -1f; 179 private boolean mTracking = false; 180 private boolean mBouncerShowingOverDream; 181 private int mAttemptsToShowBouncer = 0; 182 private DelayableExecutor mExecutor; 183 private boolean mIsSleeping = false; 184 185 private final PrimaryBouncerExpansionCallback mExpansionCallback = 186 new PrimaryBouncerExpansionCallback() { 187 private boolean mPrimaryBouncerAnimating; 188 189 @Override 190 public void onFullyShown() { 191 mPrimaryBouncerAnimating = false; 192 updateStates(); 193 } 194 195 @Override 196 public void onStartingToHide() { 197 mPrimaryBouncerAnimating = true; 198 updateStates(); 199 } 200 201 @Override 202 public void onStartingToShow() { 203 mPrimaryBouncerAnimating = true; 204 updateStates(); 205 } 206 207 @Override 208 public void onFullyHidden() { 209 mPrimaryBouncerAnimating = false; 210 updateStates(); 211 } 212 213 @Override 214 public void onExpansionChanged(float expansion) { 215 if (mPrimaryBouncerAnimating) { 216 mCentralSurfaces.setPrimaryBouncerHiddenFraction(expansion); 217 } 218 } 219 220 @Override 221 public void onVisibilityChanged(boolean isVisible) { 222 mBouncerShowingOverDream = 223 isVisible && mDreamOverlayStateController.isOverlayActive(); 224 225 if (!isVisible) { 226 mCentralSurfaces.setPrimaryBouncerHiddenFraction(EXPANSION_HIDDEN); 227 } 228 229 /* Register predictive back callback when keyguard becomes visible, and unregister 230 when it's hidden. */ 231 if (isVisible) { 232 registerBackCallback(); 233 } else { 234 unregisterBackCallback(); 235 } 236 } 237 }; 238 239 private final OnBackAnimationCallback mOnBackInvokedCallback = 240 new FlingOnBackAnimationCallback() { 241 @Override 242 public void onBackInvokedCompat() { 243 if (DEBUG) { 244 Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()"); 245 } 246 onBackPressed(); 247 if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) { 248 mPrimaryBouncerView.getDelegate().getBackCallback().onBackInvoked(); 249 } 250 } 251 252 @Override 253 public void onBackProgressedCompat(@NonNull BackEvent event) { 254 if (ComposeBouncerFlags.INSTANCE.isOnlyComposeBouncerEnabled()) { 255 mBouncerInteractor.get().onBackEventProgressed(event.getProgress()); 256 } 257 if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) { 258 mPrimaryBouncerView.getDelegate().getBackCallback().onBackProgressed(event); 259 } 260 } 261 262 @Override 263 public void onBackCancelledCompat() { 264 if (ComposeBouncerFlags.INSTANCE.isOnlyComposeBouncerEnabled()) { 265 mBouncerInteractor.get().onBackEventCancelled(); 266 } 267 if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) { 268 mPrimaryBouncerView.getDelegate().getBackCallback().onBackCancelled(); 269 } 270 } 271 272 @Override 273 public void onBackStartedCompat(@NonNull BackEvent event) { 274 if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) { 275 mPrimaryBouncerView.getDelegate().getBackCallback().onBackStarted(event); 276 } 277 } 278 }; 279 private boolean mIsBackCallbackRegistered = false; 280 281 private final DockManager.DockEventListener mDockEventListener = 282 new DockManager.DockEventListener() { 283 @Override 284 public void onEvent(int event) { 285 boolean isDocked = mDockManager.isDocked(); 286 if (isDocked == mIsDocked) { 287 return; 288 } 289 mIsDocked = isDocked; 290 updateStates(); 291 } 292 }; 293 294 protected LockPatternUtils mLockPatternUtils; 295 protected ViewMediatorCallback mViewMediatorCallback; 296 @Nullable protected CentralSurfaces mCentralSurfaces; 297 private ShadeLockscreenInteractor mShadeLockscreenInteractor; 298 private BiometricUnlockController mBiometricUnlockController; 299 private boolean mCentralSurfacesRegistered; 300 301 private View mNotificationContainer; 302 303 protected boolean mRemoteInputActive; 304 private boolean mGlobalActionsVisible = false; 305 private boolean mLastGlobalActionsVisible = false; 306 private boolean mDozing; 307 private boolean mPulsing; 308 private boolean mGesturalNav; 309 private boolean mIsDocked; 310 private boolean mScreenOffAnimationPlaying; 311 312 protected boolean mFirstUpdate = true; 313 protected boolean mLastShowing; 314 protected boolean mLastOccluded; 315 private boolean mLastPrimaryBouncerShowing; 316 private boolean mLastPrimaryBouncerIsOrWillBeShowing; 317 private boolean mLastBouncerDismissible; 318 protected boolean mLastRemoteInputActive; 319 private boolean mLastDozing; 320 private boolean mLastGesturalNav; 321 private boolean mLastIsDocked; 322 private boolean mLastPulsing; 323 private int mLastBiometricMode; 324 private boolean mLastScreenOffAnimationPlaying; 325 private float mQsExpansion; 326 327 final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>(); 328 private final ActivityStarter mActivityStarter; 329 330 private OnDismissAction mAfterKeyguardGoneAction; 331 private Runnable mKeyguardGoneCancelAction; 332 private boolean mDismissActionWillAnimateOnKeyguard; 333 private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>(); 334 335 // Dismiss action to be launched when we stop dozing or the keyguard is gone. 336 private DismissWithActionRequest mPendingWakeupAction; 337 private final KeyguardStateController mKeyguardStateController; 338 private final SysuiStatusBarStateController mStatusBarStateController; 339 private final DockManager mDockManager; 340 private final KeyguardUpdateMonitor mKeyguardUpdateManager; 341 private final LatencyTracker mLatencyTracker; 342 private final KeyguardSecurityModel mKeyguardSecurityModel; 343 private final SelectedUserInteractor mSelectedUserInteractor; 344 @Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI; 345 346 @Nullable private TaskbarDelegate mTaskbarDelegate; 347 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 348 new KeyguardUpdateMonitorCallback() { 349 @Override 350 public void onTrustGrantedForCurrentUser( 351 boolean dismissKeyguard, 352 boolean newlyUnlocked, 353 @NonNull TrustGrantFlags flags, 354 @Nullable String message 355 ) { 356 updateAlternateBouncerShowing(mAlternateBouncerInteractor.maybeHide()); 357 } 358 359 @Override 360 public void onEmergencyCallAction() { 361 // Since we won't get a setOccluded call we have to reset the view manually such that 362 // the bouncer goes away. 363 if (mKeyguardStateController.isOccluded()) { 364 reset(true /* hideBouncerWhenShowing */); 365 } 366 } 367 }; 368 private Lazy<KeyguardDismissActionInteractor> mKeyguardDismissActionInteractor; 369 private final JavaAdapter mJavaAdapter; 370 private StatusBarKeyguardViewManagerInteractor mStatusBarKeyguardViewManagerInteractor; 371 372 @Inject StatusBarKeyguardViewManager( Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils, SysuiStatusBarStateController sysuiStatusBarStateController, ConfigurationController configurationController, KeyguardUpdateMonitor keyguardUpdateMonitor, DreamOverlayStateController dreamOverlayStateController, NavigationModeController navigationModeController, DockManager dockManager, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Optional<SysUIUnfoldComponent> sysUIUnfoldComponent, Lazy<ShadeController> shadeController, LatencyTracker latencyTracker, KeyguardSecurityModel keyguardSecurityModel, PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor, PrimaryBouncerInteractor primaryBouncerInteractor, BouncerView primaryBouncerView, AlternateBouncerInteractor alternateBouncerInteractor, ActivityStarter activityStarter, KeyguardTransitionInteractor keyguardTransitionInteractor, KeyguardDismissTransitionInteractor keyguardDismissTransitionInteractor, @Main CoroutineDispatcher mainDispatcher, Lazy<KeyguardDismissActionInteractor> keyguardDismissActionInteractorLazy, SelectedUserInteractor selectedUserInteractor, JavaAdapter javaAdapter, Lazy<SceneInteractor> sceneInteractorLazy, StatusBarKeyguardViewManagerInteractor statusBarKeyguardViewManagerInteractor, @Main DelayableExecutor executor, Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy, DismissCallbackRegistry dismissCallbackRegistry, Lazy<BouncerInteractor> bouncerInteractor, CommunalSceneInteractor communalSceneInteractor )373 public StatusBarKeyguardViewManager( 374 Context context, 375 ViewMediatorCallback callback, 376 LockPatternUtils lockPatternUtils, 377 SysuiStatusBarStateController sysuiStatusBarStateController, 378 ConfigurationController configurationController, 379 KeyguardUpdateMonitor keyguardUpdateMonitor, 380 DreamOverlayStateController dreamOverlayStateController, 381 NavigationModeController navigationModeController, 382 DockManager dockManager, 383 NotificationShadeWindowController notificationShadeWindowController, 384 KeyguardStateController keyguardStateController, 385 Optional<SysUIUnfoldComponent> sysUIUnfoldComponent, 386 Lazy<ShadeController> shadeController, 387 LatencyTracker latencyTracker, 388 KeyguardSecurityModel keyguardSecurityModel, 389 PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor, 390 PrimaryBouncerInteractor primaryBouncerInteractor, 391 BouncerView primaryBouncerView, 392 AlternateBouncerInteractor alternateBouncerInteractor, 393 ActivityStarter activityStarter, 394 KeyguardTransitionInteractor keyguardTransitionInteractor, 395 KeyguardDismissTransitionInteractor keyguardDismissTransitionInteractor, 396 @Main CoroutineDispatcher mainDispatcher, 397 Lazy<KeyguardDismissActionInteractor> keyguardDismissActionInteractorLazy, 398 SelectedUserInteractor selectedUserInteractor, 399 JavaAdapter javaAdapter, 400 Lazy<SceneInteractor> sceneInteractorLazy, 401 StatusBarKeyguardViewManagerInteractor statusBarKeyguardViewManagerInteractor, 402 @Main DelayableExecutor executor, 403 Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy, 404 DismissCallbackRegistry dismissCallbackRegistry, 405 Lazy<BouncerInteractor> bouncerInteractor, 406 CommunalSceneInteractor communalSceneInteractor 407 ) { 408 mContext = context; 409 mExecutor = executor; 410 mViewMediatorCallback = callback; 411 mLockPatternUtils = lockPatternUtils; 412 mConfigurationController = configurationController; 413 mNavigationModeController = navigationModeController; 414 mNotificationShadeWindowController = notificationShadeWindowController; 415 mDreamOverlayStateController = dreamOverlayStateController; 416 mKeyguardStateController = keyguardStateController; 417 mKeyguardUpdateManager = keyguardUpdateMonitor; 418 mStatusBarStateController = sysuiStatusBarStateController; 419 mDockManager = dockManager; 420 mShadeController = shadeController; 421 mLatencyTracker = latencyTracker; 422 mKeyguardSecurityModel = keyguardSecurityModel; 423 mPrimaryBouncerCallbackInteractor = primaryBouncerCallbackInteractor; 424 mPrimaryBouncerInteractor = primaryBouncerInteractor; 425 mPrimaryBouncerView = primaryBouncerView; 426 mFoldAodAnimationController = sysUIUnfoldComponent 427 .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null); 428 mAlternateBouncerInteractor = alternateBouncerInteractor; 429 mBouncerInteractor = bouncerInteractor; 430 mActivityStarter = activityStarter; 431 mKeyguardTransitionInteractor = keyguardTransitionInteractor; 432 mKeyguardDismissTransitionInteractor = keyguardDismissTransitionInteractor; 433 mMainDispatcher = mainDispatcher; 434 mKeyguardDismissActionInteractor = keyguardDismissActionInteractorLazy; 435 mSelectedUserInteractor = selectedUserInteractor; 436 mJavaAdapter = javaAdapter; 437 mSceneInteractorLazy = sceneInteractorLazy; 438 mStatusBarKeyguardViewManagerInteractor = statusBarKeyguardViewManagerInteractor; 439 mDeviceEntryInteractorLazy = deviceEntryInteractorLazy; 440 mDismissCallbackRegistry = dismissCallbackRegistry; 441 mCommunalSceneInteractor = communalSceneInteractor; 442 } 443 444 KeyguardTransitionInteractor mKeyguardTransitionInteractor; 445 KeyguardDismissTransitionInteractor mKeyguardDismissTransitionInteractor; 446 CoroutineDispatcher mMainDispatcher; 447 448 @Override registerCentralSurfaces(CentralSurfaces centralSurfaces, ShadeLockscreenInteractor shadeLockscreenInteractor, ShadeExpansionStateManager shadeExpansionStateManager, BiometricUnlockController biometricUnlockController, View notificationContainer)449 public void registerCentralSurfaces(CentralSurfaces centralSurfaces, 450 ShadeLockscreenInteractor shadeLockscreenInteractor, 451 ShadeExpansionStateManager shadeExpansionStateManager, 452 BiometricUnlockController biometricUnlockController, 453 View notificationContainer) { 454 mCentralSurfaces = centralSurfaces; 455 mBiometricUnlockController = biometricUnlockController; 456 457 mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(mExpansionCallback); 458 mShadeLockscreenInteractor = shadeLockscreenInteractor; 459 if (shadeExpansionStateManager != null) { 460 ShadeExpansionChangeEvent currentState = 461 shadeExpansionStateManager.addExpansionListener(this); 462 onPanelExpansionChanged(currentState); 463 } 464 mNotificationContainer = notificationContainer; 465 mCentralSurfacesRegistered = true; 466 467 registerListeners(); 468 } 469 470 471 /** 472 * Sets the given OccludingAppBiometricUI to null if it's the current auth interceptor. Else, 473 * does nothing. 474 */ removeOccludingAppBiometricUI(@onNull OccludingAppBiometricUI biometricUI)475 public void removeOccludingAppBiometricUI(@NonNull OccludingAppBiometricUI biometricUI) { 476 if (Objects.equals(mOccludingAppBiometricUI, biometricUI)) { 477 mOccludingAppBiometricUI = null; 478 } 479 } 480 481 /** 482 * Sets a new OccludingAppBiometricUI. 483 */ setOccludingAppBiometricUI(@onNull OccludingAppBiometricUI biometricUI)484 public void setOccludingAppBiometricUI(@NonNull OccludingAppBiometricUI biometricUI) { 485 if (!Objects.equals(mOccludingAppBiometricUI, biometricUI)) { 486 mOccludingAppBiometricUI = biometricUI; 487 } 488 } 489 registerListeners()490 private void registerListeners() { 491 mKeyguardUpdateManager.registerCallback(mUpdateMonitorCallback); 492 mStatusBarStateController.addCallback(this); 493 mConfigurationController.addCallback(this); 494 mGesturalNav = QuickStepContract.isGesturalMode( 495 mNavigationModeController.addListener(this)); 496 if (mFoldAodAnimationController != null) { 497 mFoldAodAnimationController.addCallback(this); 498 } 499 if (mDockManager != null) { 500 mDockManager.addListener(mDockEventListener); 501 mIsDocked = mDockManager.isDocked(); 502 } 503 if (mListenForAlternateBouncerTransitionSteps != null) { 504 mListenForAlternateBouncerTransitionSteps.cancel(null); 505 } 506 mListenForAlternateBouncerTransitionSteps = null; 507 if (mListenForKeyguardAuthenticatedBiometricsHandled != null) { 508 mListenForKeyguardAuthenticatedBiometricsHandled.cancel(null); 509 } 510 mListenForKeyguardAuthenticatedBiometricsHandled = null; 511 if (mListenForCanShowAlternateBouncer != null) { 512 mListenForCanShowAlternateBouncer.cancel(null); 513 } 514 mListenForCanShowAlternateBouncer = null; 515 516 // Collector that keeps the AlternateBouncerInteractor#canShowAlternateBouncer flow hot. 517 mListenForCanShowAlternateBouncer = mJavaAdapter.alwaysCollectFlow( 518 mAlternateBouncerInteractor.getCanShowAlternateBouncer(), 519 this::consumeCanShowAlternateBouncer 520 ); 521 522 if (KeyguardWmStateRefactor.isEnabled()) { 523 // Show the keyguard views whenever we've told WM that the lockscreen is visible. 524 mJavaAdapter.alwaysCollectFlow( 525 mStatusBarKeyguardViewManagerInteractor.getKeyguardViewVisibility(), 526 this::consumeShowStatusBarKeyguardView); 527 528 mJavaAdapter.alwaysCollectFlow( 529 mStatusBarKeyguardViewManagerInteractor.getKeyguardViewOcclusionState(), 530 (occlusionState) -> setOccluded( 531 occlusionState.getOccluded(), occlusionState.getAnimate())); 532 } 533 } 534 535 @VisibleForTesting consumeFromAlternateBouncerTransitionSteps(TransitionStep step)536 void consumeFromAlternateBouncerTransitionSteps(TransitionStep step) { 537 SceneContainerFlag.assertInLegacyMode(); 538 hideAlternateBouncer(false); 539 } 540 541 /** 542 * Required without fix for b/328643370: missing AlternateBouncer (when occluded) => Gone 543 * transition. 544 */ 545 @VisibleForTesting consumeKeyguardAuthenticatedBiometricsHandled(Unit handled)546 void consumeKeyguardAuthenticatedBiometricsHandled(Unit handled) { 547 SceneContainerFlag.assertInLegacyMode(); 548 if (mAlternateBouncerInteractor.isVisibleState()) { 549 hideAlternateBouncer(false); 550 } 551 } 552 consumeShowStatusBarKeyguardView(boolean show)553 private void consumeShowStatusBarKeyguardView(boolean show) { 554 if (show != mLastShowing) { 555 if (show) { 556 show(null); 557 } else { 558 hide(0, 0); 559 } 560 } 561 } 562 consumeCanShowAlternateBouncer(boolean canShow)563 private void consumeCanShowAlternateBouncer(boolean canShow) { 564 if (SceneContainerFlag.isEnabled()) { 565 // When the scene framework is enabled, the alternative bouncer is hidden from the scene 566 // framework logic so there's no need for this logic here. 567 return; 568 } 569 570 // Hack: this is required to fix issues where 571 // KeyguardBouncerRepository#alternateBouncerVisible state is incorrectly set and then never 572 // reset. This is caused by usages of show()/forceShow() that only read this flow to set the 573 // alternate bouncer visible state, if there is a race condition between when that flow 574 // changes to false and when the read happens, the flow will be set to an incorrect value 575 // and not reset on time. 576 if (!canShow) { 577 Log.d(TAG, "canShowAlternateBouncer turned false, maybe try hiding the alternate " 578 + "bouncer if it is already visible"); 579 mAlternateBouncerInteractor.maybeHide(); 580 } 581 } 582 583 /** Register a callback, to be invoked by the Predictive Back system. */ registerBackCallback()584 private void registerBackCallback() { 585 if (!mIsBackCallbackRegistered) { 586 ViewRootImpl viewRoot = getViewRootImpl(); 587 if (viewRoot != null) { 588 viewRoot.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( 589 OnBackInvokedDispatcher.PRIORITY_DEFAULT, mOnBackInvokedCallback); 590 mIsBackCallbackRegistered = true; 591 } else { 592 if (DEBUG) { 593 Log.d(TAG, "view root was null, could not register back callback"); 594 } 595 } 596 } else { 597 if (DEBUG) { 598 Log.d(TAG, "prevented registering back callback twice"); 599 } 600 } 601 } 602 603 /** Unregister the callback formerly registered with the Predictive Back system. */ unregisterBackCallback()604 private void unregisterBackCallback() { 605 if (mIsBackCallbackRegistered) { 606 ViewRootImpl viewRoot = getViewRootImpl(); 607 if (viewRoot != null) { 608 viewRoot.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback( 609 mOnBackInvokedCallback); 610 mIsBackCallbackRegistered = false; 611 } else { 612 if (DEBUG) { 613 Log.d(TAG, "view root was null, could not unregister back callback"); 614 } 615 } 616 } else { 617 if (DEBUG) { 618 Log.d(TAG, "prevented unregistering back callback twice"); 619 } 620 } 621 } 622 shouldPlayBackAnimation()623 private boolean shouldPlayBackAnimation() { 624 // Suppress back animation when bouncer shouldn't be dismissed on back invocation. 625 return !needsFullscreenBouncer(); 626 } 627 628 @Override onDensityOrFontScaleChanged()629 public void onDensityOrFontScaleChanged() { 630 hideBouncer(true /* destroyView */); 631 } 632 beginShowingBouncer(ShadeExpansionChangeEvent event)633 private boolean beginShowingBouncer(ShadeExpansionChangeEvent event) { 634 // Avoid having the shade and the bouncer open at the same time over a dream. 635 final boolean hideBouncerOverDream = 636 mDreamOverlayStateController.isOverlayActive() 637 && (mShadeLockscreenInteractor.isExpanded() 638 || mShadeController.get().isExpandingOrCollapsing()); 639 640 final boolean isUserTrackingStarted = 641 event.getFraction() != EXPANSION_HIDDEN && event.getTracking(); 642 643 return mKeyguardStateController.isShowing() 644 && !primaryBouncerIsOrWillBeShowing() 645 && !mKeyguardStateController.isKeyguardGoingAway() 646 && isUserTrackingStarted 647 && !hideBouncerOverDream 648 && !mKeyguardStateController.isOccluded() 649 && !mKeyguardStateController.canDismissLockScreen() 650 && !bouncerIsAnimatingAway() 651 && !(mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED); 652 } 653 654 @Override onPanelExpansionChanged(ShadeExpansionChangeEvent event)655 public void onPanelExpansionChanged(ShadeExpansionChangeEvent event) { 656 float fraction = event.getFraction(); 657 boolean tracking = event.getTracking(); 658 659 if (mFraction == fraction && mTracking == tracking) { 660 // Ignore duplicate events, as they will cause confusion with bouncer expansion 661 return; 662 } 663 mFraction = fraction; 664 mTracking = tracking; 665 666 /* 667 * The bouncer may have received a call to show(), or the following will infer it from 668 * device state and touch handling. The bouncer MUST have been notified that it is about to 669 * show if any subsequent events are to be handled. 670 */ 671 if (!SceneContainerFlag.isEnabled() && beginShowingBouncer(event)) { 672 mPrimaryBouncerInteractor.show(/* isScrimmed= */false, 673 TAG + "#onPanelExpansionChanged"); 674 } 675 676 if (!primaryBouncerIsOrWillBeShowing()) { 677 return; 678 } 679 680 if (mKeyguardStateController.isShowing()) { 681 mPrimaryBouncerInteractor.setPanelExpansion(fraction); 682 } else { 683 mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_HIDDEN); 684 } 685 } 686 687 /** 688 * Update the global actions visibility state in order to show the navBar when active. 689 */ setGlobalActionsVisible(boolean isVisible)690 public void setGlobalActionsVisible(boolean isVisible) { 691 mGlobalActionsVisible = isVisible; 692 updateStates(); 693 } 694 setTaskbarDelegate(TaskbarDelegate taskbarDelegate)695 public void setTaskbarDelegate(TaskbarDelegate taskbarDelegate) { 696 mTaskbarDelegate = taskbarDelegate; 697 } 698 699 /** 700 * Show the keyguard. Will handle creating and attaching to the view manager 701 * lazily. 702 */ 703 @Override show(Bundle options)704 public void show(Bundle options) { 705 Trace.beginSection("StatusBarKeyguardViewManager#show"); 706 mNotificationShadeWindowController.setKeyguardShowing(true); 707 mKeyguardStateController.notifyKeyguardState(true, mKeyguardStateController.isOccluded()); 708 reset(true /* hideBouncerWhenShowing */); 709 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 710 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); 711 Trace.endSection(); 712 } 713 714 /** 715 * Shows the notification keyguard or the bouncer depending on 716 * {@link #needsFullscreenBouncer()}. 717 */ showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset, String reason)718 protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset, 719 String reason) { 720 boolean showBouncer = needsFullscreenBouncer() && !mDozing; 721 if (Flags.simPinRaceConditionOnRestart()) { 722 showBouncer = showBouncer && !mIsSleeping; 723 } 724 if (showBouncer) { 725 // The keyguard might be showing (already). So we need to hide it. 726 if (!primaryBouncerIsShowing()) { 727 if (SceneContainerFlag.isEnabled()) { 728 mCentralSurfaces.hideKeyguard(); 729 mSceneInteractorLazy.get().showOverlay( 730 Overlays.Bouncer, 731 TAG + "#showBouncerOrKeyguard" 732 ); 733 } else { 734 if (Flags.simPinRaceConditionOnRestart()) { 735 if (mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, reason)) { 736 mAttemptsToShowBouncer = 0; 737 mCentralSurfaces.hideKeyguard(); 738 } else { 739 if (mAttemptsToShowBouncer > 6) { 740 mAttemptsToShowBouncer = 0; 741 Log.e(TAG, "Too many failed attempts to show bouncer, showing " 742 + "keyguard instead"); 743 mCentralSurfaces.showKeyguard(); 744 } else { 745 Log.v(TAG, "Failed to show bouncer, attempt #: " 746 + mAttemptsToShowBouncer++); 747 mExecutor.executeDelayed(() -> 748 showBouncerOrKeyguard(hideBouncerWhenShowing, 749 isFalsingReset, reason), 750 500); 751 } 752 } 753 } else { 754 mCentralSurfaces.hideKeyguard(); 755 mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, reason); 756 } 757 } 758 } else if (!isFalsingReset) { 759 // Falsing resets can cause this to flicker, so don't reset in this case 760 Log.i(TAG, "Sim bouncer is already showing, issuing a refresh"); 761 mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, reason); 762 763 } 764 } else { 765 mCentralSurfaces.showKeyguard(); 766 if (hideBouncerWhenShowing) { 767 hideBouncer(false /* destroyView */); 768 } 769 } 770 updateStates(); 771 } 772 773 /** 774 * 775 * If possible, shows the alternate bouncer. Else, shows the primary (pin/pattern/password) 776 * bouncer. 777 * @param scrimmed true when the primary bouncer should show scrimmed, 778 * false when the user will be dragging it and translation should be deferred 779 * {@see KeyguardBouncer#show(boolean, boolean)} 780 */ showBouncer(boolean scrimmed, String reason)781 public void showBouncer(boolean scrimmed, String reason) { 782 if (SceneContainerFlag.isEnabled()) { 783 mDeviceEntryInteractorLazy.get().attemptDeviceEntry(); 784 return; 785 } 786 787 if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) { 788 Log.d(TAG, "showBouncer:alternateBouncer.forceShow()"); 789 mAlternateBouncerInteractor.forceShow(); 790 updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState()); 791 } else { 792 showPrimaryBouncer(scrimmed, reason); 793 } 794 } 795 796 /** 797 * Hides the input bouncer (pin/password/pattern). 798 */ 799 @VisibleForTesting hideBouncer(boolean destroyView)800 void hideBouncer(boolean destroyView) { 801 mPrimaryBouncerInteractor.hide(); 802 if (mKeyguardStateController.isShowing()) { 803 // If we were showing the bouncer and then aborting, we need to also clear out any 804 // potential actions unless we actually unlocked. 805 cancelPostAuthActions(); 806 } 807 cancelPendingWakeupAction(); 808 } 809 810 /** 811 * Shows the primary bouncer - the pin/pattern/password challenge on the lock screen. 812 * 813 * @param scrimmed true when the bouncer should show scrimmed, false when the user will be 814 * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)} 815 * @param reason string description for what is causing the bouncer to be requested 816 */ 817 @Override showPrimaryBouncer(boolean scrimmed, String reason)818 public void showPrimaryBouncer(boolean scrimmed, String reason) { 819 hideAlternateBouncer( 820 /* updateScrim= */ false, 821 // When the scene framework is on, don't ever clear the pending dismiss action from 822 /* clearDismissAction= */ !SceneContainerFlag.isEnabled()); 823 if (mKeyguardStateController.isShowing() && !isBouncerShowing()) { 824 if (SceneContainerFlag.isEnabled()) { 825 mSceneInteractorLazy.get().showOverlay( 826 Overlays.Bouncer, 827 "primary bouncer requested" 828 ); 829 } else { 830 mPrimaryBouncerInteractor.show(scrimmed, reason); 831 } 832 } 833 updateStates(); 834 } 835 dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone)836 public void dismissWithAction(OnDismissAction r, Runnable cancelAction, 837 boolean afterKeyguardGone) { 838 dismissWithAction(r, cancelAction, afterKeyguardGone, null /* message */); 839 } 840 dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message)841 public void dismissWithAction(OnDismissAction r, Runnable cancelAction, 842 boolean afterKeyguardGone, String message) { 843 if (ComposeBouncerFlags.INSTANCE.isEnabled()) { 844 if (r == null) { 845 return; 846 } 847 Trace.beginSection("StatusBarKeyguardViewManager#interactorDismissWithAction"); 848 if (afterKeyguardGone) { 849 mKeyguardDismissActionInteractor.get().setDismissAction( 850 new DismissAction.RunAfterKeyguardGone( 851 () -> { 852 r.onDismiss(); 853 return null; 854 }, 855 (cancelAction != null) ? cancelAction : () -> {}, 856 message == null ? "" : message, 857 r.willRunAnimationOnKeyguard() 858 ) 859 ); 860 } else { 861 mKeyguardDismissActionInteractor.get().setDismissAction( 862 new DismissAction.RunImmediately( 863 () -> { 864 if (r.onDismiss()) { 865 return KeyguardDone.LATER; 866 } else { 867 return KeyguardDone.IMMEDIATE; 868 } 869 }, 870 (cancelAction != null) ? cancelAction : () -> {}, 871 message == null ? "" : message, 872 r.willRunAnimationOnKeyguard() 873 ) 874 ); 875 } 876 877 showBouncer(true, TAG + "#dismissWithAction"); 878 Trace.endSection(); 879 return; 880 } 881 882 if (mKeyguardStateController.isShowing()) { 883 try { 884 Trace.beginSection("StatusBarKeyguardViewManager#dismissWithAction"); 885 cancelPendingWakeupAction(); 886 // If we're dozing, this needs to be delayed until after we wake up - unless we're 887 // wake-and-unlocking, because there dozing will last until the end of the 888 // transition. 889 if (mDozing && !isWakeAndUnlocking()) { 890 mPendingWakeupAction = new DismissWithActionRequest( 891 r, cancelAction, afterKeyguardGone, message); 892 return; 893 } 894 895 if (!ComposeBouncerFlags.INSTANCE.isEnabled()) { 896 mAfterKeyguardGoneAction = r; 897 mKeyguardGoneCancelAction = cancelAction; 898 mDismissActionWillAnimateOnKeyguard = r != null 899 && r.willRunAnimationOnKeyguard(); 900 } 901 902 // If there is an alternate auth interceptor (like the UDFPS), show that one 903 // instead of the bouncer. 904 if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) { 905 if (!afterKeyguardGone) { 906 mPrimaryBouncerInteractor.setDismissAction(mAfterKeyguardGoneAction, 907 mKeyguardGoneCancelAction); 908 mAfterKeyguardGoneAction = null; 909 mKeyguardGoneCancelAction = null; 910 } 911 912 Log.d(TAG, "dismissWithAction:alternateBouncer.forceShow()"); 913 mAlternateBouncerInteractor.forceShow(); 914 updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState()); 915 setKeyguardMessage(message, null, null); 916 return; 917 } 918 919 mViewMediatorCallback.setCustomMessage(message); 920 if (afterKeyguardGone) { 921 // we'll handle the dismiss action after keyguard is gone, so just show the 922 // bouncer 923 if (SceneContainerFlag.isEnabled()) { 924 mSceneInteractorLazy.get().showOverlay( 925 Overlays.Bouncer, 926 TAG + "#dismissWithAction" 927 ); 928 } else { 929 mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, 930 TAG + "#dismissWithAction, afterKeyguardGone"); 931 } 932 } else { 933 // after authentication success, run dismiss action with the option to defer 934 // hiding the keyguard based on the return value of the OnDismissAction 935 mPrimaryBouncerInteractor.setDismissAction( 936 mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); 937 if (SceneContainerFlag.isEnabled()) { 938 mSceneInteractorLazy.get().showOverlay( 939 Overlays.Bouncer, 940 TAG + "#dismissWithAction" 941 ); 942 } else { 943 mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, 944 TAG + "#dismissWithAction"); 945 } 946 // bouncer will handle the dismiss action, so we no longer need to track it here 947 mAfterKeyguardGoneAction = null; 948 mKeyguardGoneCancelAction = null; 949 } 950 } finally { 951 Trace.endSection(); 952 } 953 } else { 954 Log.w(TAG, "Ignoring request to dismiss, dumping state: "); 955 StringWriter sw = new StringWriter(); 956 mKeyguardStateController.dump(new PrintWriter(sw), null); 957 Log.w(TAG, sw.toString()); 958 } 959 updateStates(); 960 } 961 isWakeAndUnlocking()962 private boolean isWakeAndUnlocking() { 963 int mode = mBiometricUnlockController.getMode(); 964 return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING; 965 } 966 967 /** 968 * Adds a {@param runnable} to be executed after Keyguard is gone. 969 */ addAfterKeyguardGoneRunnable(Runnable runnable)970 public void addAfterKeyguardGoneRunnable(Runnable runnable) { 971 if (ComposeBouncerFlags.INSTANCE.isEnabled()) { 972 if (runnable != null) { 973 mKeyguardDismissActionInteractor.get().runAfterKeyguardGone(runnable); 974 } 975 return; 976 } 977 mAfterKeyguardGoneRunnables.add(runnable); 978 } 979 980 @Override reset(boolean hideBouncerWhenShowing)981 public void reset(boolean hideBouncerWhenShowing) { 982 reset(hideBouncerWhenShowing, /* isFalsingReset= */false); 983 } 984 reset(boolean hideBouncerWhenShowing, boolean isFalsingReset)985 public void reset(boolean hideBouncerWhenShowing, boolean isFalsingReset) { 986 if (mKeyguardStateController.isShowing() && !bouncerIsAnimatingAway()) { 987 final boolean isOccluded = mKeyguardStateController.isOccluded(); 988 // Hide quick settings. 989 mShadeLockscreenInteractor.resetViews(/* animate= */ !isOccluded); 990 // Hide bouncer and quick-quick settings. 991 if (isOccluded && !mDozing) { 992 mCentralSurfaces.hideKeyguard(); 993 if (hideBouncerWhenShowing || needsFullscreenBouncer()) { 994 // We're removing "reset" in the refactor - bouncer will be hidden by the root 995 // cause of the "reset" calls. 996 if (!KeyguardWmStateRefactor.isEnabled()) { 997 hideBouncer(false /* destroyView */); 998 } 999 } 1000 } else { 1001 showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset, "reset"); 1002 } 1003 if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing && isBouncerShowing()) { 1004 hideAlternateBouncer(true); 1005 mDismissCallbackRegistry.notifyDismissCancelled(); 1006 mPrimaryBouncerInteractor.setDismissAction(null, null); 1007 } 1008 mKeyguardUpdateManager.sendKeyguardReset(); 1009 updateStates(); 1010 } 1011 } 1012 1013 @Override hideAlternateBouncer(boolean updateScrim)1014 public void hideAlternateBouncer(boolean updateScrim) { 1015 hideAlternateBouncer(updateScrim, /* clearDismissAction= */ true); 1016 } 1017 1018 @Override hideAlternateBouncer(boolean updateScrim, boolean clearDismissAction)1019 public void hideAlternateBouncer(boolean updateScrim, boolean clearDismissAction) { 1020 if (clearDismissAction) { 1021 mKeyguardDismissActionInteractor.get().clearDismissAction(); 1022 } 1023 1024 updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() && updateScrim); 1025 } 1026 updateAlternateBouncerShowing(boolean updateScrim)1027 private void updateAlternateBouncerShowing(boolean updateScrim) { 1028 if (!mCentralSurfacesRegistered) { 1029 // if CentralSurfaces hasn't been registered yet, then the controllers below haven't 1030 // been initialized yet so there's no need to attempt to forward them events. 1031 return; 1032 } 1033 1034 final boolean isShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); 1035 if (!SceneContainerFlag.isEnabled()) { 1036 mKeyguardUpdateManager.setAlternateBouncerShowing(isShowingAlternateBouncer); 1037 } 1038 1039 if (updateScrim) { 1040 mCentralSurfaces.updateScrimController(); 1041 } 1042 } 1043 setRootViewAnimationDisabled(boolean disabled)1044 private void setRootViewAnimationDisabled(boolean disabled) { 1045 ViewGroup windowRootView = mNotificationShadeWindowController.getWindowRootView(); 1046 if (windowRootView != null) { 1047 WindowInsetsController insetsController = windowRootView.getWindowInsetsController(); 1048 if (insetsController != null) { 1049 insetsController.setAnimationsDisabled(disabled); 1050 } 1051 } 1052 } 1053 1054 @Override onStartedWakingUp()1055 public void onStartedWakingUp() { 1056 mIsSleeping = false; 1057 setRootViewAnimationDisabled(false); 1058 NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView(); 1059 if (navBarView != null) { 1060 navBarView.forEachView(view -> 1061 view.animate() 1062 .alpha(1f) 1063 .setDuration(NAV_BAR_CONTENT_FADE_DURATION) 1064 .start()); 1065 } 1066 } 1067 1068 @Override onStartedGoingToSleep()1069 public void onStartedGoingToSleep() { 1070 mIsSleeping = true; 1071 setRootViewAnimationDisabled(true); 1072 NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView(); 1073 if (navBarView != null) { 1074 navBarView.forEachView(view -> 1075 view.animate() 1076 .alpha(0f) 1077 .setDuration(NAV_BAR_CONTENT_FADE_DURATION) 1078 .start()); 1079 } 1080 } 1081 1082 @Override onFinishedGoingToSleep()1083 public void onFinishedGoingToSleep() { 1084 mPrimaryBouncerInteractor.hide(); 1085 } 1086 1087 @Override onRemoteInputActive(boolean active)1088 public void onRemoteInputActive(boolean active) { 1089 mRemoteInputActive = active; 1090 updateStates(); 1091 } 1092 setDozing(boolean dozing)1093 private void setDozing(boolean dozing) { 1094 if (mDozing != dozing) { 1095 mDozing = dozing; 1096 if (dozing || needsFullscreenBouncer() 1097 || mKeyguardStateController.isOccluded()) { 1098 reset(dozing /* hideBouncerWhenShowing */); 1099 } 1100 updateStates(); 1101 1102 if (!dozing) { 1103 launchPendingWakeupAction(); 1104 } 1105 } 1106 } 1107 1108 /** 1109 * If {@link CentralSurfaces} is pulsing. 1110 */ setPulsing(boolean pulsing)1111 public void setPulsing(boolean pulsing) { 1112 if (mPulsing != pulsing) { 1113 mPulsing = pulsing; 1114 updateStates(); 1115 } 1116 } 1117 1118 @Override setNeedsInput(boolean needsInput)1119 public void setNeedsInput(boolean needsInput) { 1120 mNotificationShadeWindowController.setKeyguardNeedsInput(needsInput); 1121 } 1122 1123 @Override isUnlockWithWallpaper()1124 public boolean isUnlockWithWallpaper() { 1125 return mNotificationShadeWindowController.isShowingWallpaper(); 1126 } 1127 1128 @Override isBouncerShowingOverDream()1129 public boolean isBouncerShowingOverDream() { 1130 return mBouncerShowingOverDream; 1131 } 1132 1133 @Override setOccluded(boolean occluded, boolean animate)1134 public void setOccluded(boolean occluded, boolean animate) { 1135 final boolean wasOccluded = mKeyguardStateController.isOccluded(); 1136 final boolean isOccluding = !wasOccluded && occluded; 1137 final boolean isUnOccluding = wasOccluded && !occluded; 1138 mKeyguardStateController.notifyKeyguardState( 1139 mKeyguardStateController.isShowing(), occluded); 1140 updateStates(); 1141 final boolean isShowing = mKeyguardStateController.isShowing(); 1142 final boolean isOccluded = mKeyguardStateController.isOccluded(); 1143 1144 if (isShowing && isOccluding) { 1145 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 1146 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED); 1147 if (mCentralSurfaces.isLaunchingActivityOverLockscreen()) { 1148 final Runnable postCollapseAction = () -> { 1149 if (!Flags.useTransitionsForKeyguardOccluded()) { 1150 mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); 1151 } 1152 reset(true /* hideBouncerWhenShowing */); 1153 }; 1154 if (mCentralSurfaces.isDismissingShadeForActivityLaunch()) { 1155 // When isDismissingShadeForActivityLaunch() is true, we know for sure that the 1156 // post collapse runnables will be run. 1157 mShadeController.get().addPostCollapseAction(postCollapseAction); 1158 } else { 1159 postCollapseAction.run(); 1160 } 1161 return; 1162 } 1163 } else if (isShowing && isUnOccluding) { 1164 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 1165 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); 1166 } 1167 if (!Flags.useTransitionsForKeyguardOccluded()) { 1168 mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); 1169 } 1170 1171 // setDozing(false) will call reset once we stop dozing. Also, if we're going away, there's 1172 // no need to reset the keyguard views as we'll be gone shortly. Resetting now could cause 1173 // unexpected visible behavior if the keyguard is still visible as we're animating unlocked. 1174 if (!mDozing && !mKeyguardStateController.isKeyguardGoingAway()) { 1175 // If Keyguard is reshown, don't hide the bouncer as it might just have been requested 1176 // by a FLAG_DISMISS_KEYGUARD_ACTIVITY. 1177 reset(isOccluding /* hideBouncerWhenShowing*/); 1178 } 1179 } 1180 1181 @Override startPreHideAnimation(Runnable finishRunnable)1182 public void startPreHideAnimation(Runnable finishRunnable) { 1183 if (primaryBouncerIsShowing()) { 1184 mPrimaryBouncerInteractor.startDisappearAnimation(finishRunnable); 1185 1186 // We update the state (which will show the keyguard) only if an animation will run on 1187 // the keyguard. If there is no animation, we wait before updating the state so that we 1188 // go directly from bouncer to launcher/app. 1189 if (ComposeBouncerFlags.INSTANCE.isEnabled()) { 1190 if (mKeyguardDismissActionInteractor.get().runDismissAnimationOnKeyguard()) { 1191 updateStates(); 1192 } 1193 } else if (mDismissActionWillAnimateOnKeyguard) { 1194 updateStates(); 1195 } 1196 } else if (finishRunnable != null) { 1197 finishRunnable.run(); 1198 } 1199 mShadeLockscreenInteractor.blockExpansionForCurrentTouch(); 1200 } 1201 1202 @Override blockPanelExpansionFromCurrentTouch()1203 public void blockPanelExpansionFromCurrentTouch() { 1204 mShadeLockscreenInteractor.blockExpansionForCurrentTouch(); 1205 } 1206 1207 @Override hide(long startTime, long fadeoutDuration)1208 public void hide(long startTime, long fadeoutDuration) { 1209 Trace.beginSection("StatusBarKeyguardViewManager#hide"); 1210 if (Flags.checkLockscreenGoneTransition()) { 1211 DejankUtils.notifyRendererOfExpensiveFrame( 1212 mNotificationShadeWindowController.getWindowRootView(), 1213 "StatusBarKeyguardViewManager#hide"); 1214 } 1215 mKeyguardStateController.notifyKeyguardState(false, 1216 mKeyguardStateController.isOccluded()); 1217 launchPendingWakeupAction(); 1218 1219 if (mKeyguardUpdateManager.needsSlowUnlockTransition()) { 1220 fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED; 1221 } 1222 long uptimeMillis = SystemClock.uptimeMillis(); 1223 long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis); 1224 1225 if (mKeyguardStateController.isFlingingToDismissKeyguard()) { 1226 final boolean wasFlingingToDismissKeyguard = 1227 mKeyguardStateController.isFlingingToDismissKeyguard(); 1228 mCentralSurfaces.fadeKeyguardAfterLaunchTransition(new Runnable() { 1229 @Override 1230 public void run() { 1231 mNotificationShadeWindowController.setKeyguardShowing(false); 1232 mNotificationShadeWindowController.setKeyguardFadingAway(true); 1233 hideBouncer(true /* destroyView */); 1234 updateStates(); 1235 } 1236 }, /* endRunnable */ new Runnable() { 1237 @Override 1238 public void run() { 1239 mCentralSurfaces.hideKeyguard(); 1240 mNotificationShadeWindowController.setKeyguardFadingAway(false); 1241 1242 if (wasFlingingToDismissKeyguard) { 1243 mCentralSurfaces.finishKeyguardFadingAway(); 1244 } 1245 1246 mViewMediatorCallback.keyguardGone(); 1247 executeAfterKeyguardGoneAction(); 1248 } 1249 }, /* cancelRunnable */ new Runnable() { 1250 @Override 1251 public void run() { 1252 mNotificationShadeWindowController.setKeyguardFadingAway(false); 1253 if (wasFlingingToDismissKeyguard) { 1254 mCentralSurfaces.finishKeyguardFadingAway(); 1255 } 1256 cancelPostAuthActions(); 1257 } 1258 }); 1259 } else { 1260 executeAfterKeyguardGoneAction(); 1261 mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration); 1262 mBiometricUnlockController.startKeyguardFadingAway(); 1263 hideBouncer(true /* destroyView */); 1264 1265 boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); 1266 if (!staying) { 1267 mNotificationShadeWindowController.setKeyguardFadingAway(true); 1268 wakeAndUnlockDejank(); 1269 mCentralSurfaces.hideKeyguard(); 1270 // hide() will happen asynchronously and might arrive after the scrims 1271 // were already hidden, this means that the transition callback won't 1272 // be triggered anymore and StatusBarWindowController will be forever in 1273 // the fadingAway state. 1274 mCentralSurfaces.updateScrimController(); 1275 } else { 1276 mCentralSurfaces.hideKeyguard(); 1277 mCentralSurfaces.finishKeyguardFadingAway(); 1278 mBiometricUnlockController.finishKeyguardFadingAway(); 1279 } 1280 1281 updateStates(); 1282 mNotificationShadeWindowController.setKeyguardShowing(false); 1283 mViewMediatorCallback.keyguardGone(); 1284 } 1285 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 1286 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN); 1287 Trace.endSection(); 1288 } 1289 1290 @Override onNavigationModeChanged(int mode)1291 public void onNavigationModeChanged(int mode) { 1292 boolean gesturalNav = QuickStepContract.isGesturalMode(mode); 1293 if (gesturalNav != mGesturalNav) { 1294 mGesturalNav = gesturalNav; 1295 updateStates(); 1296 } 1297 } 1298 onThemeChanged()1299 public void onThemeChanged() { 1300 updateResources(); 1301 } 1302 onKeyguardFadedAway()1303 public void onKeyguardFadedAway() { 1304 mNotificationContainer.postDelayed(() -> mNotificationShadeWindowController 1305 .setKeyguardFadingAway(false), 100); 1306 mShadeLockscreenInteractor.resetViewGroupFade(); 1307 mCentralSurfaces.finishKeyguardFadingAway(); 1308 mBiometricUnlockController.finishKeyguardFadingAway(); 1309 } 1310 wakeAndUnlockDejank()1311 private void wakeAndUnlockDejank() { 1312 if (mBiometricUnlockController.isWakeAndUnlock() && mLatencyTracker.isEnabled()) { 1313 BiometricSourceType type = mBiometricUnlockController.getBiometricType(); 1314 mLatencyTracker.onActionEnd(type == BiometricSourceType.FACE 1315 ? LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK 1316 : LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK); 1317 } 1318 } 1319 executeAfterKeyguardGoneAction()1320 private void executeAfterKeyguardGoneAction() { 1321 if (ComposeBouncerFlags.INSTANCE.isEnabled()) { 1322 return; 1323 } 1324 if (mAfterKeyguardGoneAction != null) { 1325 mAfterKeyguardGoneAction.onDismiss(); 1326 mAfterKeyguardGoneAction = null; 1327 } 1328 mKeyguardGoneCancelAction = null; 1329 mDismissActionWillAnimateOnKeyguard = false; 1330 for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) { 1331 mAfterKeyguardGoneRunnables.get(i).run(); 1332 } 1333 mAfterKeyguardGoneRunnables.clear(); 1334 } 1335 1336 @Override dismissAndCollapse()1337 public void dismissAndCollapse() { 1338 mActivityStarter.executeRunnableDismissingKeyguard( 1339 /* runnable= */ null, 1340 /* cancelAction= */ null, 1341 /* dismissShade= */ true, 1342 /* afterKeyguardGone= */ false, 1343 /* deferred= */ true 1344 ); 1345 } 1346 1347 /** 1348 * WARNING: This method might cause Binder calls. 1349 */ isSecure()1350 public boolean isSecure() { 1351 return mKeyguardSecurityModel.getSecurityMode( 1352 mSelectedUserInteractor.getSelectedUserId()) 1353 != KeyguardSecurityModel.SecurityMode.None; 1354 } 1355 1356 /** 1357 * Returns whether a back invocation can be handled, which depends on whether the keyguard 1358 * is currently showing (which itself is derived from multiple states). 1359 * 1360 * @return whether a back press can be handled right now. 1361 */ canHandleBackPressed()1362 public boolean canHandleBackPressed() { 1363 return primaryBouncerIsShowing(); 1364 } 1365 1366 /** 1367 * Notifies this manager that the back button has been pressed. 1368 */ onBackPressed()1369 public void onBackPressed() { 1370 if (!canHandleBackPressed()) { 1371 return; 1372 } 1373 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); 1374 1375 boolean hideBouncerOverDreamOrHub = isBouncerShowing() 1376 && (mDreamOverlayStateController.isOverlayActive() 1377 || mCommunalSceneInteractor.isIdleOnCommunal().getValue()); 1378 mCentralSurfaces.endAffordanceLaunch(); 1379 // The second condition is for SIM card locked bouncer 1380 if (hideBouncerOverDreamOrHub 1381 || (primaryBouncerIsScrimmed() && !needsFullscreenBouncer())) { 1382 hideBouncer(false); 1383 updateStates(); 1384 } else { 1385 /* Non-scrimmed bouncers have a special animation tied to the expansion 1386 * of the notification panel. We decide whether to kick this animation off 1387 * by computing the hideImmediately boolean. 1388 */ 1389 boolean hideImmediately = mCentralSurfaces.shouldKeyguardHideImmediately(); 1390 reset(hideImmediately); 1391 if (hideImmediately) { 1392 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false); 1393 } else { 1394 mShadeLockscreenInteractor.expandToNotifications(); 1395 } 1396 } 1397 return; 1398 } 1399 1400 @Override isBouncerShowing()1401 public boolean isBouncerShowing() { 1402 return primaryBouncerIsShowing() || mAlternateBouncerInteractor.isVisibleState(); 1403 } 1404 1405 @Override primaryBouncerIsOrWillBeShowing()1406 public boolean primaryBouncerIsOrWillBeShowing() { 1407 return isBouncerShowing() || isPrimaryBouncerInTransit(); 1408 } 1409 isFullscreenBouncer()1410 public boolean isFullscreenBouncer() { 1411 return mPrimaryBouncerView.getDelegate() != null 1412 && mPrimaryBouncerView.getDelegate().isFullScreenBouncer(); 1413 } 1414 1415 /** 1416 * Clear out any potential actions that were saved to run when the device is unlocked 1417 */ cancelPostAuthActions()1418 public void cancelPostAuthActions() { 1419 if (primaryBouncerIsOrWillBeShowing()) { 1420 return; // allow the primary bouncer to trigger saved actions 1421 } 1422 mAfterKeyguardGoneAction = null; 1423 mDismissActionWillAnimateOnKeyguard = false; 1424 if (mKeyguardGoneCancelAction != null) { 1425 mKeyguardGoneCancelAction.run(); 1426 mKeyguardGoneCancelAction = null; 1427 } 1428 } 1429 getNavBarShowDelay()1430 private long getNavBarShowDelay() { 1431 if (mKeyguardStateController.isKeyguardFadingAway()) { 1432 return mKeyguardStateController.getKeyguardFadingAwayDelay(); 1433 } else if (isBouncerShowing()) { 1434 return NAV_BAR_SHOW_DELAY_BOUNCER; 1435 } else { 1436 // No longer dozing, or remote input is active. No delay. 1437 return 0; 1438 } 1439 } 1440 1441 private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() { 1442 @Override 1443 public void run() { 1444 NavigationBarView view = mCentralSurfaces.getNavigationBarView(); 1445 if (view != null) { 1446 view.setVisibility(View.VISIBLE); 1447 } 1448 mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController() 1449 .show(navigationBars()); 1450 } 1451 }; 1452 updateStates()1453 protected void updateStates() { 1454 if (!mCentralSurfacesRegistered) { 1455 return; 1456 } 1457 boolean showing = mKeyguardStateController.isShowing(); 1458 boolean occluded = mKeyguardStateController.isOccluded(); 1459 boolean primaryBouncerShowing = primaryBouncerIsShowing(); 1460 boolean primaryBouncerIsOrWillBeShowing = primaryBouncerIsOrWillBeShowing(); 1461 boolean primaryBouncerDismissible = !isFullscreenBouncer(); 1462 boolean remoteInputActive = mRemoteInputActive; 1463 1464 if ((primaryBouncerDismissible || !showing || remoteInputActive) 1465 != (mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive) 1466 || mFirstUpdate) { 1467 if (primaryBouncerDismissible || !showing || remoteInputActive) { 1468 mPrimaryBouncerInteractor.setBackButtonEnabled(true); 1469 } else { 1470 mPrimaryBouncerInteractor.setBackButtonEnabled(false); 1471 } 1472 } 1473 1474 boolean navBarVisible = isNavBarVisible(); 1475 boolean lastNavBarVisible = getLastNavBarVisible(); 1476 if (navBarVisible != lastNavBarVisible || mFirstUpdate) { 1477 updateNavigationBarVisibility(navBarVisible); 1478 } 1479 1480 boolean isPrimaryBouncerShowingChanged = 1481 primaryBouncerShowing != mLastPrimaryBouncerShowing; 1482 mLastPrimaryBouncerShowing = primaryBouncerShowing; 1483 1484 if (isPrimaryBouncerShowingChanged || mFirstUpdate) { 1485 mNotificationShadeWindowController.setBouncerShowing(primaryBouncerShowing); 1486 mCentralSurfaces.setBouncerShowing(primaryBouncerShowing); 1487 } 1488 if (!SceneContainerFlag.isEnabled()) { 1489 if (primaryBouncerIsOrWillBeShowing != mLastPrimaryBouncerIsOrWillBeShowing 1490 || mFirstUpdate 1491 || isPrimaryBouncerShowingChanged) { 1492 mKeyguardUpdateManager.sendPrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing, 1493 primaryBouncerShowing); 1494 } 1495 } 1496 1497 mFirstUpdate = false; 1498 mLastShowing = showing; 1499 mLastGlobalActionsVisible = mGlobalActionsVisible; 1500 mLastOccluded = occluded; 1501 mLastPrimaryBouncerIsOrWillBeShowing = primaryBouncerIsOrWillBeShowing; 1502 mLastBouncerDismissible = primaryBouncerDismissible; 1503 mLastRemoteInputActive = remoteInputActive; 1504 mLastDozing = mDozing; 1505 mLastPulsing = mPulsing; 1506 mLastScreenOffAnimationPlaying = mScreenOffAnimationPlaying; 1507 mLastBiometricMode = mBiometricUnlockController.getMode(); 1508 mLastGesturalNav = mGesturalNav; 1509 mLastIsDocked = mIsDocked; 1510 mCentralSurfaces.onKeyguardViewManagerStatesUpdated(); 1511 } 1512 1513 /** 1514 * Updates the visibility of the nav bar window (which will cause insets changes). 1515 */ updateNavigationBarVisibility(boolean navBarVisible)1516 protected void updateNavigationBarVisibility(boolean navBarVisible) { 1517 if (mCentralSurfaces.getNavigationBarView() != null 1518 || (mTaskbarDelegate != null && mTaskbarDelegate.isInitialized())) { 1519 if (navBarVisible) { 1520 long delay = getNavBarShowDelay(); 1521 if (delay == 0) { 1522 mMakeNavigationBarVisibleRunnable.run(); 1523 } else { 1524 mNotificationContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable, 1525 delay); 1526 } 1527 } else { 1528 mNotificationContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable); 1529 mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController() 1530 .hide(navigationBars()); 1531 } 1532 } 1533 } 1534 1535 /** 1536 * @return Whether the navigation bar should be made visible based on the current state. 1537 */ isNavBarVisible()1538 public boolean isNavBarVisible() { 1539 boolean isWakeAndUnlockPulsing = mBiometricUnlockController != null 1540 && mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; 1541 boolean keyguardVisible = mKeyguardStateController.isVisible(); 1542 boolean hideWhileDozing = mDozing && !isWakeAndUnlockPulsing; 1543 boolean keyguardWithGestureNav = (keyguardVisible && !mDozing && !mScreenOffAnimationPlaying 1544 || mPulsing && !mIsDocked) 1545 && mGesturalNav; 1546 return (!keyguardVisible && !hideWhileDozing && !mScreenOffAnimationPlaying 1547 || primaryBouncerIsShowing() 1548 || mRemoteInputActive 1549 || keyguardWithGestureNav 1550 || mGlobalActionsVisible); 1551 } 1552 1553 /** 1554 * @return Whether the navigation bar was made visible based on the last known state. 1555 */ getLastNavBarVisible()1556 protected boolean getLastNavBarVisible() { 1557 boolean keyguardShowing = mLastShowing && !mLastOccluded; 1558 boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING; 1559 boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing 1560 && !mLastScreenOffAnimationPlaying || mLastPulsing && !mLastIsDocked) 1561 && mLastGesturalNav; 1562 return (!keyguardShowing && !hideWhileDozing && !mLastScreenOffAnimationPlaying 1563 || mLastPrimaryBouncerShowing || mLastRemoteInputActive || keyguardWithGestureNav 1564 || mLastGlobalActionsVisible); 1565 } 1566 shouldDismissOnMenuPressed()1567 public boolean shouldDismissOnMenuPressed() { 1568 return (mPrimaryBouncerView.getDelegate() != null 1569 && mPrimaryBouncerView.getDelegate().shouldDismissOnMenuPressed()) || ( 1570 ComposeBouncerFlags.INSTANCE.isEnabled() && BouncerTestUtilsKt.shouldEnableMenuKey( 1571 mContext.getResources())); 1572 } 1573 interceptMediaKey(KeyEvent event)1574 public boolean interceptMediaKey(KeyEvent event) { 1575 ComposeBouncerFlags.assertInLegacyMode(); 1576 return mPrimaryBouncerView.getDelegate() != null 1577 && mPrimaryBouncerView.getDelegate().interceptMediaKey(event); 1578 } 1579 1580 /** 1581 * @return true if the pre IME back event should be handled 1582 */ dispatchBackKeyEventPreIme()1583 public boolean dispatchBackKeyEventPreIme() { 1584 return mPrimaryBouncerView.getDelegate() != null 1585 && mPrimaryBouncerView.getDelegate().dispatchBackKeyEventPreIme(); 1586 } 1587 1588 @Override readyForKeyguardDone()1589 public void readyForKeyguardDone() { 1590 mViewMediatorCallback.readyForKeyguardDone(); 1591 } 1592 1593 @Override shouldDisableWindowAnimationsForUnlock()1594 public boolean shouldDisableWindowAnimationsForUnlock() { 1595 return false; 1596 } 1597 1598 @Override shouldSubtleWindowAnimationsForUnlock()1599 public boolean shouldSubtleWindowAnimationsForUnlock() { 1600 return false; 1601 } 1602 1603 @Override isGoingToNotificationShade()1604 public boolean isGoingToNotificationShade() { 1605 return mStatusBarStateController.leaveOpenOnKeyguardHide(); 1606 } 1607 isSecure(int userId)1608 public boolean isSecure(int userId) { 1609 return isSecure() || mLockPatternUtils.isSecure(userId); 1610 } 1611 1612 @Override keyguardGoingAway()1613 public void keyguardGoingAway() { 1614 mCentralSurfaces.keyguardGoingAway(); 1615 } 1616 1617 @Override setKeyguardGoingAwayState(boolean isKeyguardGoingAway)1618 public void setKeyguardGoingAwayState(boolean isKeyguardGoingAway) { 1619 mNotificationShadeWindowController.setKeyguardGoingAway(isKeyguardGoingAway); 1620 } 1621 1622 @Override onCancelClicked()1623 public void onCancelClicked() { 1624 // No-op 1625 } 1626 1627 /** 1628 * Notifies that the user has authenticated by other means than using the bouncer, for example, 1629 * fingerprint and the keyguard should immediately dismiss. 1630 */ notifyKeyguardAuthenticated(boolean strongAuth)1631 public void notifyKeyguardAuthenticated(boolean strongAuth) { 1632 mPrimaryBouncerInteractor.notifyKeyguardAuthenticatedBiometrics(strongAuth); 1633 1634 if (mAlternateBouncerInteractor.isVisibleState()) { 1635 executeAfterKeyguardGoneAction(); 1636 } 1637 1638 if (KeyguardWmStateRefactor.isEnabled()) { 1639 mKeyguardDismissTransitionInteractor.startDismissKeyguardTransition( 1640 "SBKVM#keyguardAuthenticated"); 1641 } 1642 } 1643 1644 /** Display security message to relevant KeyguardMessageArea. */ setKeyguardMessage(String message, ColorStateList colorState, BiometricSourceType biometricSourceType)1645 public void setKeyguardMessage(String message, ColorStateList colorState, 1646 BiometricSourceType biometricSourceType) { 1647 if (!mAlternateBouncerInteractor.isVisibleState()) { 1648 mPrimaryBouncerInteractor.showMessage(message, colorState); 1649 } 1650 } 1651 1652 @Override getViewRootImpl()1653 public ViewRootImpl getViewRootImpl() { 1654 ViewGroup viewGroup = mNotificationShadeWindowController.getWindowRootView(); 1655 if (viewGroup != null) { 1656 return viewGroup.getViewRootImpl(); 1657 } else { 1658 if (DEBUG) { 1659 Log.d(TAG, "ViewGroup was null, cannot get ViewRootImpl"); 1660 } 1661 return null; 1662 } 1663 } 1664 launchPendingWakeupAction()1665 public void launchPendingWakeupAction() { 1666 DismissWithActionRequest request = mPendingWakeupAction; 1667 mPendingWakeupAction = null; 1668 if (request != null) { 1669 if (mKeyguardStateController.isShowing()) { 1670 dismissWithAction(request.dismissAction, request.cancelAction, 1671 request.afterKeyguardGone, request.message); 1672 } else if (request.dismissAction != null) { 1673 request.dismissAction.onDismiss(); 1674 } 1675 } 1676 } 1677 cancelPendingWakeupAction()1678 public void cancelPendingWakeupAction() { 1679 DismissWithActionRequest request = mPendingWakeupAction; 1680 mPendingWakeupAction = null; 1681 if (request != null && request.cancelAction != null) { 1682 request.cancelAction.run(); 1683 } 1684 } 1685 1686 /** 1687 * Whether the primary bouncer requires scrimming. 1688 */ primaryBouncerNeedsScrimming()1689 public boolean primaryBouncerNeedsScrimming() { 1690 // When a dream overlay is active, scrimming will cause any expansion to immediately expand. 1691 return (mKeyguardStateController.isOccluded() 1692 && !mDreamOverlayStateController.isOverlayActive()) 1693 || primaryBouncerWillDismissWithAction() 1694 || (primaryBouncerIsShowing() && primaryBouncerIsScrimmed()) 1695 || isFullscreenBouncer(); 1696 } 1697 1698 /** 1699 * Apply keyguard configuration from the currently active resources. This can be called when the 1700 * device configuration changes, to re-apply some resources that are qualified on the device 1701 * configuration. 1702 */ updateResources()1703 public void updateResources() { 1704 mPrimaryBouncerInteractor.updateResources(); 1705 } 1706 dump(PrintWriter pw)1707 public void dump(PrintWriter pw) { 1708 pw.println("StatusBarKeyguardViewManager:"); 1709 pw.println(" mRemoteInputActive: " + mRemoteInputActive); 1710 pw.println(" mDozing: " + mDozing); 1711 pw.println(" mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction); 1712 pw.println(" mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables); 1713 pw.println(" mPendingWakeupAction: " + mPendingWakeupAction); 1714 pw.println(" isBouncerShowing(): " + isBouncerShowing()); 1715 pw.println(" bouncerIsOrWillBeShowing(): " + primaryBouncerIsOrWillBeShowing()); 1716 pw.println(" Registered KeyguardViewManagerCallbacks:"); 1717 pw.println(" SceneContainerFlag enabled:" 1718 + SceneContainerFlag.isEnabled()); 1719 pw.println(" ComposeBouncerFlags enabled:" 1720 + ComposeBouncerFlags.INSTANCE.isEnabled()); 1721 for (KeyguardViewManagerCallback callback : mCallbacks) { 1722 pw.println(" " + callback); 1723 } 1724 1725 if (mOccludingAppBiometricUI != null) { 1726 pw.println("mOccludingAppBiometricUI:"); 1727 mOccludingAppBiometricUI.dump(pw); 1728 } 1729 } 1730 1731 @Override onDozingChanged(boolean isDozing)1732 public void onDozingChanged(boolean isDozing) { 1733 setDozing(isDozing); 1734 } 1735 1736 @Override onFoldToAodAnimationChanged()1737 public void onFoldToAodAnimationChanged() { 1738 if (mFoldAodAnimationController != null) { 1739 mScreenOffAnimationPlaying = mFoldAodAnimationController.shouldPlayAnimation(); 1740 } 1741 } 1742 1743 /** 1744 * Add a callback to listen for changes 1745 */ addCallback(KeyguardViewManagerCallback callback)1746 public void addCallback(KeyguardViewManagerCallback callback) { 1747 mCallbacks.add(callback); 1748 } 1749 1750 /** 1751 * Removes callback to stop receiving updates 1752 */ removeCallback(KeyguardViewManagerCallback callback)1753 public void removeCallback(KeyguardViewManagerCallback callback) { 1754 mCallbacks.remove(callback); 1755 } 1756 1757 /** 1758 * Whether qs is currently expanded. 1759 */ getQsExpansion()1760 public float getQsExpansion() { 1761 return mQsExpansion; 1762 } 1763 1764 /** 1765 * Update qs expansion. 1766 */ setQsExpansion(float qsExpansion)1767 public void setQsExpansion(float qsExpansion) { 1768 mQsExpansion = qsExpansion; 1769 for (KeyguardViewManagerCallback callback : mCallbacks) { 1770 callback.onQSExpansionChanged(mQsExpansion); 1771 } 1772 } 1773 1774 /** Update keyguard position based on a tapped X coordinate. */ updateKeyguardPosition(float x)1775 public void updateKeyguardPosition(float x) { 1776 mPrimaryBouncerInteractor.setKeyguardPosition(x); 1777 } 1778 1779 private static class DismissWithActionRequest { 1780 final OnDismissAction dismissAction; 1781 final Runnable cancelAction; 1782 final boolean afterKeyguardGone; 1783 final String message; 1784 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, boolean afterKeyguardGone, String message)1785 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, 1786 boolean afterKeyguardGone, String message) { 1787 this.dismissAction = dismissAction; 1788 this.cancelAction = cancelAction; 1789 this.afterKeyguardGone = afterKeyguardGone; 1790 this.message = message; 1791 } 1792 } 1793 1794 /** 1795 * Request to authenticate using the fingerprint sensor. If the fingerprint sensor is udfps, 1796 * uses the color provided by udfpsColor for the fingerprint icon. 1797 */ requestFp(boolean request, int udfpsColor)1798 public void requestFp(boolean request, int udfpsColor) { 1799 mKeyguardUpdateManager.requestFingerprintAuthOnOccludingApp(request); 1800 if (mOccludingAppBiometricUI != null) { 1801 mOccludingAppBiometricUI.requestUdfps(request, udfpsColor); 1802 } 1803 } 1804 1805 /** 1806 * Returns if bouncer expansion is between 0 and 1 non-inclusive. 1807 */ isPrimaryBouncerInTransit()1808 public boolean isPrimaryBouncerInTransit() { 1809 return mPrimaryBouncerInteractor.isInTransit(); 1810 } 1811 1812 /** 1813 * Returns if bouncer is showing 1814 */ primaryBouncerIsShowing()1815 public boolean primaryBouncerIsShowing() { 1816 return mPrimaryBouncerInteractor.isFullyShowing(); 1817 } 1818 1819 /** 1820 * Returns if bouncer is scrimmed 1821 */ primaryBouncerIsScrimmed()1822 public boolean primaryBouncerIsScrimmed() { 1823 return mPrimaryBouncerInteractor.isScrimmed(); 1824 } 1825 1826 /** 1827 * Returns if bouncer is animating away 1828 */ bouncerIsAnimatingAway()1829 public boolean bouncerIsAnimatingAway() { 1830 return mPrimaryBouncerInteractor.isAnimatingAway(); 1831 } 1832 1833 /** 1834 * Returns if bouncer will dismiss with action 1835 */ primaryBouncerWillDismissWithAction()1836 public boolean primaryBouncerWillDismissWithAction() { 1837 return mPrimaryBouncerInteractor.willDismissWithAction(); 1838 } 1839 1840 /** 1841 * Returns if bouncer needs fullscreen bouncer. i.e. sim pin security method 1842 */ needsFullscreenBouncer()1843 public boolean needsFullscreenBouncer() { 1844 KeyguardSecurityModel.SecurityMode mode = mKeyguardSecurityModel.getSecurityMode( 1845 mSelectedUserInteractor.getSelectedUserId()); 1846 return mode == KeyguardSecurityModel.SecurityMode.SimPin 1847 || mode == KeyguardSecurityModel.SecurityMode.SimPuk; 1848 } 1849 1850 @VisibleForTesting setAttemptsToShowBouncer(int attempts)1851 void setAttemptsToShowBouncer(int attempts) { 1852 mAttemptsToShowBouncer = attempts; 1853 } 1854 1855 /** 1856 * Delegate used to send show and hide events to an alternate authentication method instead of 1857 * the regular pin/pattern/password bouncer. 1858 */ 1859 public interface OccludingAppBiometricUI { 1860 /** 1861 * Use when an app occluding the keyguard would like to give the user ability to 1862 * unlock the device using udfps. 1863 * 1864 * @param color of the udfps icon. should have proper contrast with its background. only 1865 * used if requestUdfps = true 1866 */ requestUdfps(boolean requestUdfps, int color)1867 void requestUdfps(boolean requestUdfps, int color); 1868 1869 /** 1870 * print information for the alternate bouncer registered 1871 */ dump(PrintWriter pw)1872 void dump(PrintWriter pw); 1873 } 1874 1875 /** 1876 * Callback for KeyguardViewManager state changes. 1877 */ 1878 public interface KeyguardViewManagerCallback { 1879 /** 1880 * Set the amount qs is expanded. For example, swipe down from the top of the 1881 * lock screen to start the full QS expansion. 1882 */ onQSExpansionChanged(float qsExpansion)1883 default void onQSExpansionChanged(float qsExpansion) { } 1884 1885 /** 1886 * Forward touch events to callbacks 1887 */ onTouch(MotionEvent event)1888 default void onTouch(MotionEvent event) { } 1889 } 1890 } 1891