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