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