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