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.plugins.ActivityStarter.OnDismissAction; 22 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING; 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.view.KeyEvent; 33 import android.view.MotionEvent; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.view.ViewRootImpl; 37 import android.view.WindowManagerGlobal; 38 39 import androidx.annotation.NonNull; 40 import androidx.annotation.Nullable; 41 import androidx.annotation.VisibleForTesting; 42 43 import com.android.internal.util.LatencyTracker; 44 import com.android.internal.widget.LockPatternUtils; 45 import com.android.keyguard.KeyguardMessageArea; 46 import com.android.keyguard.KeyguardMessageAreaController; 47 import com.android.keyguard.KeyguardUpdateMonitor; 48 import com.android.keyguard.KeyguardUpdateMonitorCallback; 49 import com.android.keyguard.KeyguardViewController; 50 import com.android.keyguard.ViewMediatorCallback; 51 import com.android.systemui.DejankUtils; 52 import com.android.systemui.dagger.SysUISingleton; 53 import com.android.systemui.dock.DockManager; 54 import com.android.systemui.keyguard.FaceAuthScreenBrightnessController; 55 import com.android.systemui.keyguard.WakefulnessLifecycle; 56 import com.android.systemui.navigationbar.NavigationModeController; 57 import com.android.systemui.plugins.statusbar.StatusBarStateController; 58 import com.android.systemui.shared.system.QuickStepContract; 59 import com.android.systemui.shared.system.SysUiStatsLog; 60 import com.android.systemui.statusbar.NotificationMediaManager; 61 import com.android.systemui.statusbar.NotificationShadeWindowController; 62 import com.android.systemui.statusbar.RemoteInputController; 63 import com.android.systemui.statusbar.SysuiStatusBarStateController; 64 import com.android.systemui.statusbar.notification.ViewGroupFadeHelper; 65 import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback; 66 import com.android.systemui.statusbar.policy.ConfigurationController; 67 import com.android.systemui.statusbar.policy.KeyguardStateController; 68 69 import java.io.PrintWriter; 70 import java.util.ArrayList; 71 import java.util.Objects; 72 import java.util.Optional; 73 74 import javax.inject.Inject; 75 76 /** 77 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back 78 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done, 79 * which is in turn, reported to this class by the current 80 * {@link com.android.keyguard.KeyguardViewController}. 81 */ 82 @SysUISingleton 83 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback, 84 StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener, 85 PanelExpansionListener, NavigationModeController.ModeChangedListener, 86 KeyguardViewController, WakefulnessLifecycle.Observer { 87 88 // When hiding the Keyguard with timing supplied from WindowManager, better be early than late. 89 private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3; 90 91 // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync 92 // with the appear animations of the PIN/pattern/password views. 93 private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320; 94 95 private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200; 96 97 // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to 98 // make everything a bit slower to bridge a gap until the user is unlocked and home screen has 99 // dranw its first frame. 100 private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000; 101 102 private static String TAG = "StatusBarKeyguardViewManager"; 103 104 protected final Context mContext; 105 private final ConfigurationController mConfigurationController; 106 private final NavigationModeController mNavigationModeController; 107 private final NotificationShadeWindowController mNotificationShadeWindowController; 108 private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController; 109 private final KeyguardBouncer.Factory mKeyguardBouncerFactory; 110 private final WakefulnessLifecycle mWakefulnessLifecycle; 111 private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; 112 private final KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory; 113 private KeyguardMessageAreaController mKeyguardMessageAreaController; 114 private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { 115 @Override 116 public void onFullyShown() { 117 updateStates(); 118 mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE"); 119 } 120 121 @Override 122 public void onStartingToHide() { 123 updateStates(); 124 } 125 126 @Override 127 public void onStartingToShow() { 128 updateStates(); 129 } 130 131 @Override 132 public void onFullyHidden() { 133 } 134 135 @Override 136 public void onExpansionChanged(float expansion) { 137 if (mAlternateAuthInterceptor != null) { 138 mAlternateAuthInterceptor.setBouncerExpansionChanged(expansion); 139 } 140 updateStates(); 141 } 142 143 @Override 144 public void onVisibilityChanged(boolean isVisible) { 145 if (!isVisible) { 146 cancelPostAuthActions(); 147 } 148 if (mAlternateAuthInterceptor != null) { 149 mAlternateAuthInterceptor.onBouncerVisibilityChanged(); 150 } 151 } 152 }; 153 private final DockManager.DockEventListener mDockEventListener = 154 new DockManager.DockEventListener() { 155 @Override 156 public void onEvent(int event) { 157 boolean isDocked = mDockManager.isDocked(); 158 if (isDocked == mIsDocked) { 159 return; 160 } 161 mIsDocked = isDocked; 162 updateStates(); 163 } 164 }; 165 166 protected LockPatternUtils mLockPatternUtils; 167 protected ViewMediatorCallback mViewMediatorCallback; 168 protected StatusBar mStatusBar; 169 private NotificationPanelViewController mNotificationPanelViewController; 170 private BiometricUnlockController mBiometricUnlockController; 171 172 private ViewGroup mContainer; 173 private View mNotificationContainer; 174 175 protected KeyguardBouncer mBouncer; 176 protected boolean mShowing; 177 protected boolean mOccluded; 178 protected boolean mRemoteInputActive; 179 private boolean mGlobalActionsVisible = false; 180 private boolean mLastGlobalActionsVisible = false; 181 private boolean mDozing; 182 private boolean mPulsing; 183 private boolean mGesturalNav; 184 private boolean mIsDocked; 185 186 protected boolean mFirstUpdate = true; 187 protected boolean mLastShowing; 188 protected boolean mLastOccluded; 189 private boolean mLastBouncerShowing; 190 private boolean mLastBouncerIsOrWillBeShowing; 191 private boolean mLastBouncerDismissible; 192 protected boolean mLastRemoteInputActive; 193 private boolean mLastDozing; 194 private boolean mLastGesturalNav; 195 private boolean mLastIsDocked; 196 private boolean mLastPulsing; 197 private int mLastBiometricMode; 198 private boolean mQsExpanded; 199 private boolean mAnimatedToSleep; 200 201 private OnDismissAction mAfterKeyguardGoneAction; 202 private Runnable mKeyguardGoneCancelAction; 203 private boolean mDismissActionWillAnimateOnKeyguard; 204 private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>(); 205 206 // Dismiss action to be launched when we stop dozing or the keyguard is gone. 207 private DismissWithActionRequest mPendingWakeupAction; 208 private final KeyguardStateController mKeyguardStateController; 209 private final NotificationMediaManager mMediaManager; 210 private final SysuiStatusBarStateController mStatusBarStateController; 211 private final DockManager mDockManager; 212 private final KeyguardUpdateMonitor mKeyguardUpdateManager; 213 private KeyguardBypassController mBypassController; 214 @Nullable private AlternateAuthInterceptor mAlternateAuthInterceptor; 215 216 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = 217 new KeyguardUpdateMonitorCallback() { 218 @Override 219 public void onEmergencyCallAction() { 220 221 // Since we won't get a setOccluded call we have to reset the view manually such that 222 // the bouncer goes away. 223 if (mOccluded) { 224 reset(true /* hideBouncerWhenShowing */); 225 } 226 } 227 }; 228 229 @Inject StatusBarKeyguardViewManager( Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils, SysuiStatusBarStateController sysuiStatusBarStateController, ConfigurationController configurationController, KeyguardUpdateMonitor keyguardUpdateMonitor, NavigationModeController navigationModeController, DockManager dockManager, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController, NotificationMediaManager notificationMediaManager, KeyguardBouncer.Factory keyguardBouncerFactory, WakefulnessLifecycle wakefulnessLifecycle, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, KeyguardMessageAreaController.Factory keyguardMessageAreaFactory)230 public StatusBarKeyguardViewManager( 231 Context context, 232 ViewMediatorCallback callback, 233 LockPatternUtils lockPatternUtils, 234 SysuiStatusBarStateController sysuiStatusBarStateController, 235 ConfigurationController configurationController, 236 KeyguardUpdateMonitor keyguardUpdateMonitor, 237 NavigationModeController navigationModeController, 238 DockManager dockManager, 239 NotificationShadeWindowController notificationShadeWindowController, 240 KeyguardStateController keyguardStateController, 241 Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController, 242 NotificationMediaManager notificationMediaManager, 243 KeyguardBouncer.Factory keyguardBouncerFactory, 244 WakefulnessLifecycle wakefulnessLifecycle, 245 UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, 246 KeyguardMessageAreaController.Factory keyguardMessageAreaFactory) { 247 mContext = context; 248 mViewMediatorCallback = callback; 249 mLockPatternUtils = lockPatternUtils; 250 mConfigurationController = configurationController; 251 mNavigationModeController = navigationModeController; 252 mNotificationShadeWindowController = notificationShadeWindowController; 253 mKeyguardStateController = keyguardStateController; 254 mMediaManager = notificationMediaManager; 255 mKeyguardUpdateManager = keyguardUpdateMonitor; 256 mStatusBarStateController = sysuiStatusBarStateController; 257 mDockManager = dockManager; 258 mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController; 259 mKeyguardBouncerFactory = keyguardBouncerFactory; 260 mWakefulnessLifecycle = wakefulnessLifecycle; 261 mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; 262 mKeyguardMessageAreaFactory = keyguardMessageAreaFactory; 263 } 264 265 @Override registerStatusBar(StatusBar statusBar, ViewGroup container, NotificationPanelViewController notificationPanelViewController, BiometricUnlockController biometricUnlockController, View notificationContainer, KeyguardBypassController bypassController)266 public void registerStatusBar(StatusBar statusBar, 267 ViewGroup container, 268 NotificationPanelViewController notificationPanelViewController, 269 BiometricUnlockController biometricUnlockController, 270 View notificationContainer, 271 KeyguardBypassController bypassController) { 272 mStatusBar = statusBar; 273 mContainer = container; 274 mBiometricUnlockController = biometricUnlockController; 275 mBouncer = mKeyguardBouncerFactory.create(container, mExpansionCallback); 276 mNotificationPanelViewController = notificationPanelViewController; 277 notificationPanelViewController.addExpansionListener(this); 278 mBypassController = bypassController; 279 mNotificationContainer = notificationContainer; 280 mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create( 281 KeyguardMessageArea.findSecurityMessageDisplay(container)); 282 mFaceAuthScreenBrightnessController.ifPresent((it) -> { 283 View overlay = new View(mContext); 284 container.addView(overlay); 285 it.attach(overlay); 286 }); 287 288 registerListeners(); 289 } 290 291 /** 292 * Sets the given alt auth interceptor to null if it's the current auth interceptor. Else, 293 * does nothing. 294 */ removeAlternateAuthInterceptor(@onNull AlternateAuthInterceptor authInterceptor)295 public void removeAlternateAuthInterceptor(@NonNull AlternateAuthInterceptor authInterceptor) { 296 if (Objects.equals(mAlternateAuthInterceptor, authInterceptor)) { 297 mAlternateAuthInterceptor = null; 298 resetAlternateAuth(true); 299 } 300 } 301 302 /** 303 * Sets a new alt auth interceptor. 304 */ setAlternateAuthInterceptor(@onNull AlternateAuthInterceptor authInterceptor)305 public void setAlternateAuthInterceptor(@NonNull AlternateAuthInterceptor authInterceptor) { 306 mAlternateAuthInterceptor = authInterceptor; 307 resetAlternateAuth(false); 308 } 309 registerListeners()310 private void registerListeners() { 311 mKeyguardUpdateManager.registerCallback(mUpdateMonitorCallback); 312 mStatusBarStateController.addCallback(this); 313 mConfigurationController.addCallback(this); 314 mGesturalNav = QuickStepContract.isGesturalMode( 315 mNavigationModeController.addListener(this)); 316 if (mDockManager != null) { 317 mDockManager.addListener(mDockEventListener); 318 mIsDocked = mDockManager.isDocked(); 319 } 320 mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() { 321 @Override 322 public void onFinishedWakingUp() { 323 mAnimatedToSleep = false; 324 updateStates(); 325 } 326 327 @Override 328 public void onFinishedGoingToSleep() { 329 mAnimatedToSleep = 330 mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying(); 331 updateStates(); 332 } 333 }); 334 } 335 336 @Override onDensityOrFontScaleChanged()337 public void onDensityOrFontScaleChanged() { 338 hideBouncer(true /* destroyView */); 339 } 340 341 @Override onPanelExpansionChanged(float expansion, boolean tracking)342 public void onPanelExpansionChanged(float expansion, boolean tracking) { 343 // We don't want to translate the bounce when: 344 // • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to 345 // conserve the original animation. 346 // • The user quickly taps on the display and we show "swipe up to unlock." 347 // • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY 348 // • Full-screen user switcher is displayed. 349 if (mNotificationPanelViewController.isUnlockHintRunning()) { 350 mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); 351 } else if (bouncerNeedsScrimming()) { 352 mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); 353 } else if (mShowing) { 354 if (!isWakeAndUnlocking() && !mStatusBar.isInLaunchTransition()) { 355 mBouncer.setExpansion(expansion); 356 } 357 if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking 358 && !mKeyguardStateController.canDismissLockScreen() 359 && !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) { 360 mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */); 361 } 362 } else if (mPulsing && expansion == KeyguardBouncer.EXPANSION_VISIBLE) { 363 // Panel expanded while pulsing but didn't translate the bouncer (because we are 364 // unlocked.) Let's simply wake-up to dismiss the lock screen. 365 mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE"); 366 } 367 } 368 369 /** 370 * Update the global actions visibility state in order to show the navBar when active. 371 */ setGlobalActionsVisible(boolean isVisible)372 public void setGlobalActionsVisible(boolean isVisible) { 373 mGlobalActionsVisible = isVisible; 374 updateStates(); 375 } 376 377 /** 378 * Show the keyguard. Will handle creating and attaching to the view manager 379 * lazily. 380 */ 381 @Override show(Bundle options)382 public void show(Bundle options) { 383 mShowing = true; 384 mNotificationShadeWindowController.setKeyguardShowing(true); 385 mKeyguardStateController.notifyKeyguardState(mShowing, 386 mKeyguardStateController.isOccluded()); 387 reset(true /* hideBouncerWhenShowing */); 388 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 389 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); 390 } 391 392 /** 393 * Shows the notification keyguard or the bouncer depending on 394 * {@link KeyguardBouncer#needsFullscreenBouncer()}. 395 */ showBouncerOrKeyguard(boolean hideBouncerWhenShowing)396 protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) { 397 if (mBouncer.needsFullscreenBouncer() && !mDozing) { 398 // The keyguard might be showing (already). So we need to hide it. 399 mStatusBar.hideKeyguard(); 400 mBouncer.show(true /* resetSecuritySelection */); 401 } else { 402 mStatusBar.showKeyguard(); 403 if (hideBouncerWhenShowing) { 404 hideBouncer(shouldDestroyViewOnReset() /* destroyView */); 405 mBouncer.prepare(); 406 } 407 } 408 updateStates(); 409 } 410 shouldDestroyViewOnReset()411 protected boolean shouldDestroyViewOnReset() { 412 return false; 413 } 414 415 /** 416 * If applicable, shows the alternate authentication bouncer. Else, shows the input 417 * (pin/password/pattern) bouncer. 418 * @param scrimmed true when the input bouncer should show scrimmed, false when the user will be 419 * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)} 420 */ showGenericBouncer(boolean scrimmed)421 public void showGenericBouncer(boolean scrimmed) { 422 if (mAlternateAuthInterceptor != null) { 423 updateAlternateAuthShowing(mAlternateAuthInterceptor.showAlternateAuthBouncer()); 424 return; 425 } 426 427 showBouncer(scrimmed); 428 } 429 430 /** 431 * Hides the input bouncer (pin/password/pattern). 432 */ 433 @VisibleForTesting hideBouncer(boolean destroyView)434 void hideBouncer(boolean destroyView) { 435 if (mBouncer == null) { 436 return; 437 } 438 if (mShowing) { 439 // If we were showing the bouncer and then aborting, we need to also clear out any 440 // potential actions unless we actually unlocked. 441 cancelPostAuthActions(); 442 } 443 mBouncer.hide(destroyView); 444 cancelPendingWakeupAction(); 445 } 446 447 /** 448 * Shows the keyguard input bouncer - the password challenge on the lock screen 449 * 450 * @param scrimmed true when the bouncer should show scrimmed, false when the user will be 451 * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)} 452 */ showBouncer(boolean scrimmed)453 public void showBouncer(boolean scrimmed) { 454 if (mShowing && !mBouncer.isShowing()) { 455 mBouncer.show(false /* resetSecuritySelection */, scrimmed); 456 } 457 updateStates(); 458 } 459 dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone)460 public void dismissWithAction(OnDismissAction r, Runnable cancelAction, 461 boolean afterKeyguardGone) { 462 dismissWithAction(r, cancelAction, afterKeyguardGone, null /* message */); 463 } 464 dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message)465 public void dismissWithAction(OnDismissAction r, Runnable cancelAction, 466 boolean afterKeyguardGone, String message) { 467 if (mShowing) { 468 cancelPendingWakeupAction(); 469 // If we're dozing, this needs to be delayed until after we wake up - unless we're 470 // wake-and-unlocking, because there dozing will last until the end of the transition. 471 if (mDozing && !isWakeAndUnlocking()) { 472 mPendingWakeupAction = new DismissWithActionRequest( 473 r, cancelAction, afterKeyguardGone, message); 474 return; 475 } 476 477 mAfterKeyguardGoneAction = r; 478 mKeyguardGoneCancelAction = cancelAction; 479 mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard(); 480 481 // If there is an an alternate auth interceptor (like the UDFPS), show that one instead 482 // of the bouncer. 483 if (mAlternateAuthInterceptor != null) { 484 if (!afterKeyguardGone) { 485 mBouncer.setDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); 486 mAfterKeyguardGoneAction = null; 487 mKeyguardGoneCancelAction = null; 488 } 489 490 updateAlternateAuthShowing(mAlternateAuthInterceptor.showAlternateAuthBouncer()); 491 return; 492 } 493 494 if (afterKeyguardGone) { 495 // we'll handle the dismiss action after keyguard is gone, so just show the bouncer 496 mBouncer.show(false /* resetSecuritySelection */); 497 } else { 498 // after authentication success, run dismiss action with the option to defer 499 // hiding the keyguard based on the return value of the OnDismissAction 500 mBouncer.showWithDismissAction(mAfterKeyguardGoneAction, mKeyguardGoneCancelAction); 501 // bouncer will handle the dismiss action, so we no longer need to track it here 502 mAfterKeyguardGoneAction = null; 503 mKeyguardGoneCancelAction = null; 504 } 505 } 506 updateStates(); 507 } 508 isWakeAndUnlocking()509 private boolean isWakeAndUnlocking() { 510 int mode = mBiometricUnlockController.getMode(); 511 return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING; 512 } 513 514 /** 515 * Adds a {@param runnable} to be executed after Keyguard is gone. 516 */ addAfterKeyguardGoneRunnable(Runnable runnable)517 public void addAfterKeyguardGoneRunnable(Runnable runnable) { 518 mAfterKeyguardGoneRunnables.add(runnable); 519 } 520 521 @Override reset(boolean hideBouncerWhenShowing)522 public void reset(boolean hideBouncerWhenShowing) { 523 if (mShowing) { 524 // Hide quick settings. 525 mNotificationPanelViewController.resetViews(/* animate= */ true); 526 // Hide bouncer and quick-quick settings. 527 if (mOccluded && !mDozing) { 528 mStatusBar.hideKeyguard(); 529 if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) { 530 hideBouncer(false /* destroyView */); 531 } 532 } else { 533 showBouncerOrKeyguard(hideBouncerWhenShowing); 534 } 535 resetAlternateAuth(false); 536 mKeyguardUpdateManager.sendKeyguardReset(); 537 updateStates(); 538 } 539 } 540 541 /** 542 * Stop showing any alternate auth methods 543 */ resetAlternateAuth(boolean forceUpdateScrim)544 public void resetAlternateAuth(boolean forceUpdateScrim) { 545 final boolean updateScrim = (mAlternateAuthInterceptor != null 546 && mAlternateAuthInterceptor.hideAlternateAuthBouncer()) 547 || forceUpdateScrim; 548 updateAlternateAuthShowing(updateScrim); 549 } 550 updateAlternateAuthShowing(boolean updateScrim)551 private void updateAlternateAuthShowing(boolean updateScrim) { 552 if (mKeyguardMessageAreaController != null) { 553 mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAlternateAuth()); 554 } 555 mBypassController.setAltBouncerShowing(isShowingAlternateAuth()); 556 557 if (updateScrim) { 558 mStatusBar.updateScrimController(); 559 } 560 } 561 562 @Override onStartedWakingUp()563 public void onStartedWakingUp() { 564 mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() 565 .setAnimationsDisabled(false); 566 } 567 568 @Override onStartedGoingToSleep()569 public void onStartedGoingToSleep() { 570 mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() 571 .setAnimationsDisabled(true); 572 } 573 574 @Override onFinishedGoingToSleep()575 public void onFinishedGoingToSleep() { 576 mBouncer.onScreenTurnedOff(); 577 } 578 579 @Override onRemoteInputActive(boolean active)580 public void onRemoteInputActive(boolean active) { 581 mRemoteInputActive = active; 582 updateStates(); 583 } 584 setDozing(boolean dozing)585 private void setDozing(boolean dozing) { 586 if (mDozing != dozing) { 587 mDozing = dozing; 588 if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) { 589 reset(dozing /* hideBouncerWhenShowing */); 590 } 591 updateStates(); 592 593 if (!dozing) { 594 launchPendingWakeupAction(); 595 } 596 } 597 } 598 599 /** 600 * If {@link StatusBar} is pulsing. 601 */ setPulsing(boolean pulsing)602 public void setPulsing(boolean pulsing) { 603 if (mPulsing != pulsing) { 604 mPulsing = pulsing; 605 updateStates(); 606 } 607 } 608 609 @Override setNeedsInput(boolean needsInput)610 public void setNeedsInput(boolean needsInput) { 611 mNotificationShadeWindowController.setKeyguardNeedsInput(needsInput); 612 } 613 614 @Override isUnlockWithWallpaper()615 public boolean isUnlockWithWallpaper() { 616 return mNotificationShadeWindowController.isShowingWallpaper(); 617 } 618 619 @Override setOccluded(boolean occluded, boolean animate)620 public void setOccluded(boolean occluded, boolean animate) { 621 mStatusBar.setOccluded(occluded); 622 if (occluded && !mOccluded && mShowing) { 623 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 624 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED); 625 if (mStatusBar.isInLaunchTransition()) { 626 mOccluded = true; 627 mStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */, 628 new Runnable() { 629 @Override 630 public void run() { 631 mNotificationShadeWindowController.setKeyguardOccluded(mOccluded); 632 reset(true /* hideBouncerWhenShowing */); 633 } 634 }); 635 return; 636 } 637 } else if (!occluded && mOccluded && mShowing) { 638 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 639 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); 640 } 641 boolean isOccluding = !mOccluded && occluded; 642 mOccluded = occluded; 643 if (mShowing) { 644 mMediaManager.updateMediaMetaData(false, animate && !occluded); 645 } 646 mNotificationShadeWindowController.setKeyguardOccluded(occluded); 647 648 // setDozing(false) will call reset once we stop dozing. 649 if (!mDozing) { 650 // If Keyguard is reshown, don't hide the bouncer as it might just have been requested 651 // by a FLAG_DISMISS_KEYGUARD_ACTIVITY. 652 reset(isOccluding /* hideBouncerWhenShowing*/); 653 } 654 if (animate && !occluded && mShowing && !mBouncer.isShowing()) { 655 mStatusBar.animateKeyguardUnoccluding(); 656 } 657 } 658 isOccluded()659 public boolean isOccluded() { 660 return mOccluded; 661 } 662 663 @Override startPreHideAnimation(Runnable finishRunnable)664 public void startPreHideAnimation(Runnable finishRunnable) { 665 if (mBouncer.isShowing()) { 666 mBouncer.startPreHideAnimation(finishRunnable); 667 mStatusBar.onBouncerPreHideAnimation(); 668 669 // We update the state (which will show the keyguard) only if an animation will run on 670 // the keyguard. If there is no animation, we wait before updating the state so that we 671 // go directly from bouncer to launcher/app. 672 if (mDismissActionWillAnimateOnKeyguard) { 673 updateStates(); 674 } 675 } else if (finishRunnable != null) { 676 finishRunnable.run(); 677 } 678 mNotificationPanelViewController.blockExpansionForCurrentTouch(); 679 } 680 681 @Override blockPanelExpansionFromCurrentTouch()682 public void blockPanelExpansionFromCurrentTouch() { 683 mNotificationPanelViewController.blockExpansionForCurrentTouch(); 684 } 685 686 @Override hide(long startTime, long fadeoutDuration)687 public void hide(long startTime, long fadeoutDuration) { 688 mShowing = false; 689 mKeyguardStateController.notifyKeyguardState(mShowing, 690 mKeyguardStateController.isOccluded()); 691 launchPendingWakeupAction(); 692 693 if (mKeyguardUpdateManager.needsSlowUnlockTransition()) { 694 fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED; 695 } 696 long uptimeMillis = SystemClock.uptimeMillis(); 697 long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis); 698 699 if (mStatusBar.isInLaunchTransition() 700 || mKeyguardStateController.isFlingingToDismissKeyguard()) { 701 final boolean wasFlingingToDismissKeyguard = 702 mKeyguardStateController.isFlingingToDismissKeyguard(); 703 mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() { 704 @Override 705 public void run() { 706 mNotificationShadeWindowController.setKeyguardShowing(false); 707 mNotificationShadeWindowController.setKeyguardFadingAway(true); 708 hideBouncer(true /* destroyView */); 709 updateStates(); 710 } 711 }, new Runnable() { 712 @Override 713 public void run() { 714 mStatusBar.hideKeyguard(); 715 mNotificationShadeWindowController.setKeyguardFadingAway(false); 716 717 if (wasFlingingToDismissKeyguard) { 718 mStatusBar.finishKeyguardFadingAway(); 719 } 720 721 mViewMediatorCallback.keyguardGone(); 722 executeAfterKeyguardGoneAction(); 723 } 724 }); 725 } else { 726 executeAfterKeyguardGoneAction(); 727 boolean wakeUnlockPulsing = 728 mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; 729 boolean needsFading = needsBypassFading(); 730 if (needsFading) { 731 delay = 0; 732 fadeoutDuration = KeyguardBypassController.BYPASS_FADE_DURATION; 733 } else if (wakeUnlockPulsing) { 734 delay = 0; 735 fadeoutDuration = 240; 736 } 737 mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration, needsFading); 738 mBiometricUnlockController.startKeyguardFadingAway(); 739 hideBouncer(true /* destroyView */); 740 if (wakeUnlockPulsing) { 741 if (needsFading) { 742 ViewGroupFadeHelper.fadeOutAllChildrenExcept( 743 mNotificationPanelViewController.getView(), 744 mNotificationContainer, 745 fadeoutDuration, 746 () -> { 747 mStatusBar.hideKeyguard(); 748 onKeyguardFadedAway(); 749 }); 750 } else { 751 mStatusBar.fadeKeyguardWhilePulsing(); 752 } 753 wakeAndUnlockDejank(); 754 } else { 755 boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); 756 if (!staying) { 757 mNotificationShadeWindowController.setKeyguardFadingAway(true); 758 if (needsFading) { 759 ViewGroupFadeHelper.fadeOutAllChildrenExcept( 760 mNotificationPanelViewController.getView(), 761 mNotificationContainer, 762 fadeoutDuration, 763 () -> { 764 mStatusBar.hideKeyguard(); 765 }); 766 } else { 767 mStatusBar.hideKeyguard(); 768 } 769 // hide() will happen asynchronously and might arrive after the scrims 770 // were already hidden, this means that the transition callback won't 771 // be triggered anymore and StatusBarWindowController will be forever in 772 // the fadingAway state. 773 mStatusBar.updateScrimController(); 774 wakeAndUnlockDejank(); 775 } else { 776 mStatusBar.hideKeyguard(); 777 mStatusBar.finishKeyguardFadingAway(); 778 mBiometricUnlockController.finishKeyguardFadingAway(); 779 } 780 } 781 updateStates(); 782 mNotificationShadeWindowController.setKeyguardShowing(false); 783 mViewMediatorCallback.keyguardGone(); 784 } 785 SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, 786 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN); 787 } 788 needsBypassFading()789 private boolean needsBypassFading() { 790 return (mBiometricUnlockController.getMode() == MODE_UNLOCK_FADING 791 || mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING 792 || mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK) 793 && mBypassController.getBypassEnabled(); 794 } 795 796 @Override onNavigationModeChanged(int mode)797 public void onNavigationModeChanged(int mode) { 798 boolean gesturalNav = QuickStepContract.isGesturalMode(mode); 799 if (gesturalNav != mGesturalNav) { 800 mGesturalNav = gesturalNav; 801 updateStates(); 802 } 803 } 804 onThemeChanged()805 public void onThemeChanged() { 806 boolean wasShowing = mBouncer.isShowing(); 807 boolean wasScrimmed = mBouncer.isScrimmed(); 808 809 hideBouncer(true /* destroyView */); 810 mBouncer.prepare(); 811 812 if (wasShowing) showBouncer(wasScrimmed); 813 } 814 onKeyguardFadedAway()815 public void onKeyguardFadedAway() { 816 mContainer.postDelayed(() -> mNotificationShadeWindowController 817 .setKeyguardFadingAway(false), 100); 818 ViewGroupFadeHelper.reset(mNotificationPanelViewController.getView()); 819 mStatusBar.finishKeyguardFadingAway(); 820 mBiometricUnlockController.finishKeyguardFadingAway(); 821 WindowManagerGlobal.getInstance().trimMemory( 822 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); 823 824 } 825 wakeAndUnlockDejank()826 private void wakeAndUnlockDejank() { 827 if (mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK 828 && LatencyTracker.isEnabled(mContext)) { 829 BiometricSourceType type = mBiometricUnlockController.getBiometricType(); 830 DejankUtils.postAfterTraversal(() -> { 831 LatencyTracker.getInstance(mContext).onActionEnd( 832 type == BiometricSourceType.FACE 833 ? LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK 834 : LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK); 835 }); 836 } 837 } 838 executeAfterKeyguardGoneAction()839 private void executeAfterKeyguardGoneAction() { 840 if (mAfterKeyguardGoneAction != null) { 841 mAfterKeyguardGoneAction.onDismiss(); 842 mAfterKeyguardGoneAction = null; 843 } 844 mKeyguardGoneCancelAction = null; 845 mDismissActionWillAnimateOnKeyguard = false; 846 for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) { 847 mAfterKeyguardGoneRunnables.get(i).run(); 848 } 849 mAfterKeyguardGoneRunnables.clear(); 850 } 851 852 @Override dismissAndCollapse()853 public void dismissAndCollapse() { 854 mStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true); 855 } 856 857 /** 858 * WARNING: This method might cause Binder calls. 859 */ isSecure()860 public boolean isSecure() { 861 return mBouncer.isSecure(); 862 } 863 864 @Override isShowing()865 public boolean isShowing() { 866 return mShowing; 867 } 868 869 /** 870 * Notifies this manager that the back button has been pressed. 871 * 872 * @param hideImmediately Hide bouncer when {@code true}, keep it around otherwise. 873 * Non-scrimmed bouncers have a special animation tied to the expansion 874 * of the notification panel. 875 * @return whether the back press has been handled 876 */ onBackPressed(boolean hideImmediately)877 public boolean onBackPressed(boolean hideImmediately) { 878 if (mBouncer.isShowing()) { 879 mStatusBar.endAffordanceLaunch(); 880 // The second condition is for SIM card locked bouncer 881 if (mBouncer.isScrimmed() && !mBouncer.needsFullscreenBouncer()) { 882 hideBouncer(false); 883 updateStates(); 884 } else { 885 reset(hideImmediately); 886 } 887 return true; 888 } 889 return false; 890 } 891 892 @Override isBouncerShowing()893 public boolean isBouncerShowing() { 894 return mBouncer.isShowing() || isShowingAlternateAuth(); 895 } 896 897 @Override bouncerIsOrWillBeShowing()898 public boolean bouncerIsOrWillBeShowing() { 899 return mBouncer.isShowing() || mBouncer.getShowingSoon(); 900 } 901 isFullscreenBouncer()902 public boolean isFullscreenBouncer() { 903 return mBouncer.isFullscreenBouncer(); 904 } 905 906 /** 907 * Clear out any potential actions that were saved to run when the device is unlocked 908 */ cancelPostAuthActions()909 public void cancelPostAuthActions() { 910 if (bouncerIsOrWillBeShowing()) { 911 return; // allow bouncer to trigger saved actions 912 } 913 mAfterKeyguardGoneAction = null; 914 mDismissActionWillAnimateOnKeyguard = false; 915 if (mKeyguardGoneCancelAction != null) { 916 mKeyguardGoneCancelAction.run(); 917 mKeyguardGoneCancelAction = null; 918 } 919 } 920 getNavBarShowDelay()921 private long getNavBarShowDelay() { 922 if (mKeyguardStateController.isKeyguardFadingAway()) { 923 return mKeyguardStateController.getKeyguardFadingAwayDelay(); 924 } else if (mBouncer.isShowing()) { 925 return NAV_BAR_SHOW_DELAY_BOUNCER; 926 } else { 927 // No longer dozing, or remote input is active. No delay. 928 return 0; 929 } 930 } 931 932 private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() { 933 @Override 934 public void run() { 935 mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() 936 .show(navigationBars()); 937 } 938 }; 939 updateStates()940 protected void updateStates() { 941 if (mContainer == null ) { 942 return; 943 } 944 int vis = mContainer.getSystemUiVisibility(); 945 boolean showing = mShowing; 946 boolean occluded = mOccluded; 947 boolean bouncerShowing = mBouncer.isShowing(); 948 boolean bouncerIsOrWillBeShowing = bouncerIsOrWillBeShowing(); 949 boolean bouncerDismissible = !mBouncer.isFullscreenBouncer(); 950 boolean remoteInputActive = mRemoteInputActive; 951 952 if ((bouncerDismissible || !showing || remoteInputActive) != 953 (mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive) 954 || mFirstUpdate) { 955 if (bouncerDismissible || !showing || remoteInputActive) { 956 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK); 957 } else { 958 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK); 959 } 960 } 961 962 boolean navBarVisible = isNavBarVisible(); 963 boolean lastNavBarVisible = getLastNavBarVisible(); 964 if (navBarVisible != lastNavBarVisible || mFirstUpdate) { 965 updateNavigationBarVisibility(navBarVisible); 966 } 967 968 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) { 969 mNotificationShadeWindowController.setBouncerShowing(bouncerShowing); 970 mStatusBar.setBouncerShowing(bouncerShowing); 971 } 972 973 if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) { 974 mKeyguardUpdateManager.onKeyguardVisibilityChanged(showing && !occluded); 975 } 976 if (bouncerIsOrWillBeShowing != mLastBouncerIsOrWillBeShowing || mFirstUpdate) { 977 mKeyguardUpdateManager.sendKeyguardBouncerChanged(bouncerIsOrWillBeShowing); 978 } 979 980 mFirstUpdate = false; 981 mLastShowing = showing; 982 mLastGlobalActionsVisible = mGlobalActionsVisible; 983 mLastOccluded = occluded; 984 mLastBouncerShowing = bouncerShowing; 985 mLastBouncerIsOrWillBeShowing = bouncerIsOrWillBeShowing; 986 mLastBouncerDismissible = bouncerDismissible; 987 mLastRemoteInputActive = remoteInputActive; 988 mLastDozing = mDozing; 989 mLastPulsing = mPulsing; 990 mLastBiometricMode = mBiometricUnlockController.getMode(); 991 mLastGesturalNav = mGesturalNav; 992 mLastIsDocked = mIsDocked; 993 mStatusBar.onKeyguardViewManagerStatesUpdated(); 994 } 995 updateNavigationBarVisibility(boolean navBarVisible)996 protected void updateNavigationBarVisibility(boolean navBarVisible) { 997 if (mStatusBar.getNavigationBarView() != null) { 998 if (navBarVisible) { 999 long delay = getNavBarShowDelay(); 1000 if (delay == 0) { 1001 mMakeNavigationBarVisibleRunnable.run(); 1002 } else { 1003 mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable, 1004 delay); 1005 } 1006 } else { 1007 mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable); 1008 mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() 1009 .hide(navigationBars()); 1010 } 1011 } 1012 } 1013 1014 /** 1015 * @return Whether the navigation bar should be made visible based on the current state. 1016 */ isNavBarVisible()1017 protected boolean isNavBarVisible() { 1018 int biometricMode = mBiometricUnlockController.getMode(); 1019 boolean keyguardShowing = mShowing && !mOccluded; 1020 boolean hideWhileDozing = mDozing && biometricMode != MODE_WAKE_AND_UNLOCK_PULSING; 1021 boolean keyguardWithGestureNav = (keyguardShowing && !mDozing || mPulsing && !mIsDocked) 1022 && mGesturalNav; 1023 return (!mAnimatedToSleep && !keyguardShowing && !hideWhileDozing || mBouncer.isShowing() 1024 || mRemoteInputActive || keyguardWithGestureNav 1025 || mGlobalActionsVisible); 1026 } 1027 1028 /** 1029 * @return Whether the navigation bar was made visible based on the last known state. 1030 */ getLastNavBarVisible()1031 protected boolean getLastNavBarVisible() { 1032 boolean keyguardShowing = mLastShowing && !mLastOccluded; 1033 boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING; 1034 boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing 1035 || mLastPulsing && !mLastIsDocked) && mLastGesturalNav; 1036 return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing 1037 || mLastRemoteInputActive || keyguardWithGestureNav 1038 || mLastGlobalActionsVisible); 1039 } 1040 shouldDismissOnMenuPressed()1041 public boolean shouldDismissOnMenuPressed() { 1042 return mBouncer.shouldDismissOnMenuPressed(); 1043 } 1044 interceptMediaKey(KeyEvent event)1045 public boolean interceptMediaKey(KeyEvent event) { 1046 return mBouncer.interceptMediaKey(event); 1047 } 1048 1049 /** 1050 * @return true if the pre IME back event should be handled 1051 */ dispatchBackKeyEventPreIme()1052 public boolean dispatchBackKeyEventPreIme() { 1053 return mBouncer.dispatchBackKeyEventPreIme(); 1054 } 1055 readyForKeyguardDone()1056 public void readyForKeyguardDone() { 1057 mViewMediatorCallback.readyForKeyguardDone(); 1058 } 1059 1060 @Override shouldDisableWindowAnimationsForUnlock()1061 public boolean shouldDisableWindowAnimationsForUnlock() { 1062 return mStatusBar.isInLaunchTransition(); 1063 } 1064 1065 @Override shouldSubtleWindowAnimationsForUnlock()1066 public boolean shouldSubtleWindowAnimationsForUnlock() { 1067 return needsBypassFading(); 1068 } 1069 1070 @Override isGoingToNotificationShade()1071 public boolean isGoingToNotificationShade() { 1072 return mStatusBarStateController.leaveOpenOnKeyguardHide(); 1073 } 1074 isSecure(int userId)1075 public boolean isSecure(int userId) { 1076 return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId); 1077 } 1078 1079 @Override keyguardGoingAway()1080 public void keyguardGoingAway() { 1081 mStatusBar.keyguardGoingAway(); 1082 } 1083 1084 @Override setKeyguardGoingAwayState(boolean isKeyguardGoingAway)1085 public void setKeyguardGoingAwayState(boolean isKeyguardGoingAway) { 1086 mNotificationShadeWindowController.setKeyguardGoingAway(isKeyguardGoingAway); 1087 } 1088 1089 @Override onCancelClicked()1090 public void onCancelClicked() { 1091 // No-op 1092 } 1093 1094 /** 1095 * Notifies that the user has authenticated by other means than using the bouncer, for example, 1096 * fingerprint. 1097 */ notifyKeyguardAuthenticated(boolean strongAuth)1098 public void notifyKeyguardAuthenticated(boolean strongAuth) { 1099 mBouncer.notifyKeyguardAuthenticated(strongAuth); 1100 1101 if (mAlternateAuthInterceptor != null && isShowingAlternateAuthOrAnimating()) { 1102 resetAlternateAuth(false); 1103 executeAfterKeyguardGoneAction(); 1104 } 1105 } 1106 showBouncerMessage(String message, ColorStateList colorState)1107 public void showBouncerMessage(String message, ColorStateList colorState) { 1108 if (isShowingAlternateAuth()) { 1109 if (mKeyguardMessageAreaController != null) { 1110 mKeyguardMessageAreaController.setNextMessageColor(colorState); 1111 mKeyguardMessageAreaController.setMessage(message); 1112 } 1113 } else { 1114 mBouncer.showMessage(message, colorState); 1115 } 1116 } 1117 1118 @Override getViewRootImpl()1119 public ViewRootImpl getViewRootImpl() { 1120 return mStatusBar.getStatusBarView().getViewRootImpl(); 1121 } 1122 launchPendingWakeupAction()1123 public void launchPendingWakeupAction() { 1124 DismissWithActionRequest request = mPendingWakeupAction; 1125 mPendingWakeupAction = null; 1126 if (request != null) { 1127 if (mShowing) { 1128 dismissWithAction(request.dismissAction, request.cancelAction, 1129 request.afterKeyguardGone, request.message); 1130 } else if (request.dismissAction != null) { 1131 request.dismissAction.onDismiss(); 1132 } 1133 } 1134 } 1135 cancelPendingWakeupAction()1136 public void cancelPendingWakeupAction() { 1137 DismissWithActionRequest request = mPendingWakeupAction; 1138 mPendingWakeupAction = null; 1139 if (request != null && request.cancelAction != null) { 1140 request.cancelAction.run(); 1141 } 1142 } 1143 bouncerNeedsScrimming()1144 public boolean bouncerNeedsScrimming() { 1145 return mOccluded || mBouncer.willDismissWithAction() 1146 || mStatusBar.isFullScreenUserSwitcherState() 1147 || (mBouncer.isShowing() && mBouncer.isScrimmed()) 1148 || mBouncer.isFullscreenBouncer(); 1149 } 1150 1151 /** 1152 * Apply keyguard configuration from the currently active resources. This can be called when the 1153 * device configuration changes, to re-apply some resources that are qualified on the device 1154 * configuration. 1155 */ updateResources()1156 public void updateResources() { 1157 if (mBouncer != null) { 1158 mBouncer.updateResources(); 1159 } 1160 } 1161 dump(PrintWriter pw)1162 public void dump(PrintWriter pw) { 1163 pw.println("StatusBarKeyguardViewManager:"); 1164 pw.println(" mShowing: " + mShowing); 1165 pw.println(" mOccluded: " + mOccluded); 1166 pw.println(" mRemoteInputActive: " + mRemoteInputActive); 1167 pw.println(" mDozing: " + mDozing); 1168 pw.println(" mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction); 1169 pw.println(" mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables); 1170 pw.println(" mPendingWakeupAction: " + mPendingWakeupAction); 1171 1172 if (mBouncer != null) { 1173 mBouncer.dump(pw); 1174 } 1175 1176 if (mAlternateAuthInterceptor != null) { 1177 pw.println("AltAuthInterceptor: "); 1178 mAlternateAuthInterceptor.dump(pw); 1179 } 1180 } 1181 1182 @Override onDozingChanged(boolean isDozing)1183 public void onDozingChanged(boolean isDozing) { 1184 setDozing(isDozing); 1185 } 1186 1187 /** 1188 * Whether qs is currently expanded. 1189 */ isQsExpanded()1190 public boolean isQsExpanded() { 1191 return mQsExpanded; 1192 } 1193 /** 1194 * Set whether qs is currently expanded 1195 */ setQsExpanded(boolean expanded)1196 public void setQsExpanded(boolean expanded) { 1197 mQsExpanded = expanded; 1198 if (mAlternateAuthInterceptor != null) { 1199 mAlternateAuthInterceptor.setQsExpanded(expanded); 1200 } 1201 } 1202 getBouncer()1203 public KeyguardBouncer getBouncer() { 1204 return mBouncer; 1205 } 1206 isShowingAlternateAuth()1207 public boolean isShowingAlternateAuth() { 1208 return mAlternateAuthInterceptor != null 1209 && mAlternateAuthInterceptor.isShowingAlternateAuthBouncer(); 1210 } 1211 isShowingAlternateAuthOrAnimating()1212 public boolean isShowingAlternateAuthOrAnimating() { 1213 return mAlternateAuthInterceptor != null 1214 && (mAlternateAuthInterceptor.isShowingAlternateAuthBouncer() 1215 || mAlternateAuthInterceptor.isAnimating()); 1216 } 1217 1218 /** 1219 * Forward touches to any alternate authentication affordances. 1220 */ onTouch(MotionEvent event)1221 public boolean onTouch(MotionEvent event) { 1222 if (mAlternateAuthInterceptor == null) { 1223 return false; 1224 } 1225 1226 return mAlternateAuthInterceptor.onTouch(event); 1227 } 1228 1229 /** Update keyguard position based on a tapped X coordinate. */ updateKeyguardPosition(float x)1230 public void updateKeyguardPosition(float x) { 1231 if (mBouncer != null) { 1232 mBouncer.updateKeyguardPosition(x); 1233 } 1234 } 1235 1236 private static class DismissWithActionRequest { 1237 final OnDismissAction dismissAction; 1238 final Runnable cancelAction; 1239 final boolean afterKeyguardGone; 1240 final String message; 1241 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, boolean afterKeyguardGone, String message)1242 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, 1243 boolean afterKeyguardGone, String message) { 1244 this.dismissAction = dismissAction; 1245 this.cancelAction = cancelAction; 1246 this.afterKeyguardGone = afterKeyguardGone; 1247 this.message = message; 1248 } 1249 } 1250 1251 /** 1252 * Request to authenticate using face. 1253 */ requestFace(boolean request)1254 public void requestFace(boolean request) { 1255 mKeyguardUpdateManager.requestFaceAuthOnOccludingApp(request); 1256 } 1257 1258 /** 1259 * Request to authenticate using the fingerprint sensor. If the fingerprint sensor is udfps, 1260 * uses the color provided by udfpsColor for the fingerprint icon. 1261 */ requestFp(boolean request, int udfpsColor)1262 public void requestFp(boolean request, int udfpsColor) { 1263 mKeyguardUpdateManager.requestFingerprintAuthOnOccludingApp(request); 1264 if (mAlternateAuthInterceptor != null) { 1265 mAlternateAuthInterceptor.requestUdfps(request, udfpsColor); 1266 } 1267 } 1268 1269 /** 1270 * Delegate used to send show/reset events to an alternate authentication method instead of the 1271 * regular pin/pattern/password bouncer. 1272 */ 1273 public interface AlternateAuthInterceptor { 1274 /** 1275 * Show alternate authentication bouncer. 1276 * @return whether alternate auth method was newly shown 1277 */ showAlternateAuthBouncer()1278 boolean showAlternateAuthBouncer(); 1279 1280 /** 1281 * Hide alternate authentication bouncer 1282 * @return whether the alternate auth method was newly hidden 1283 */ hideAlternateAuthBouncer()1284 boolean hideAlternateAuthBouncer(); 1285 1286 /** 1287 * @return true if the alternate auth bouncer is showing 1288 */ isShowingAlternateAuthBouncer()1289 boolean isShowingAlternateAuthBouncer(); 1290 1291 /** 1292 * print information for the alternate auth interceptor registered 1293 */ dump(PrintWriter pw)1294 void dump(PrintWriter pw); 1295 1296 /** 1297 * @return true if the new auth method bouncer is currently animating in or out. 1298 */ isAnimating()1299 boolean isAnimating(); 1300 1301 /** 1302 * Set whether qs is currently expanded. 1303 */ setQsExpanded(boolean expanded)1304 void setQsExpanded(boolean expanded); 1305 1306 /** 1307 * Forward potential touches to authentication interceptor 1308 * @return true if event was handled 1309 */ onTouch(MotionEvent event)1310 boolean onTouch(MotionEvent event); 1311 1312 /** 1313 * Update pin/pattern/password bouncer expansion amount where 0 is visible and 1 is fully 1314 * hidden 1315 */ setBouncerExpansionChanged(float expansion)1316 void setBouncerExpansionChanged(float expansion); 1317 1318 /** 1319 * called when the bouncer view visibility has changed. 1320 */ onBouncerVisibilityChanged()1321 void onBouncerVisibilityChanged(); 1322 1323 /** 1324 * Use when an app occluding the keyguard would like to give the user ability to 1325 * unlock the device using udfps. 1326 * 1327 * @param color of the udfps icon. should have proper contrast with its background. only 1328 * used if requestUdfps = true 1329 */ requestUdfps(boolean requestUdfps, int color)1330 void requestUdfps(boolean requestUdfps, int color); 1331 1332 } 1333 }