2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.systemui.statusbar.phone;
19 import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
20 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_FADING;
21 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
22 import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
24 import android.content.ComponentCallbacks2;
25 import android.content.Context;
26 import android.content.res.ColorStateList;
27 import android.os.Bundle;
28 import android.os.SystemClock;
29 import android.util.StatsLog;
30 import android.view.KeyEvent;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.view.ViewRootImpl;
34 import android.view.WindowManagerGlobal;
36 import com.android.internal.util.LatencyTracker;
37 import com.android.internal.widget.LockPatternUtils;
38 import com.android.keyguard.KeyguardUpdateMonitor;
39 import com.android.keyguard.KeyguardUpdateMonitorCallback;
40 import com.android.keyguard.ViewMediatorCallback;
41 import com.android.settingslib.animation.AppearAnimationUtils;
42 import com.android.systemui.DejankUtils;
43 import com.android.systemui.Dependency;
44 import com.android.systemui.SystemUIFactory;
45 import com.android.systemui.dock.DockManager;
46 import com.android.systemui.keyguard.DismissCallbackRegistry;
47 import com.android.systemui.plugins.statusbar.StatusBarStateController;
48 import com.android.systemui.shared.system.QuickStepContract;
49 import com.android.systemui.statusbar.CommandQueue;
50 import com.android.systemui.statusbar.CrossFadeHelper;
51 import com.android.systemui.statusbar.NotificationMediaManager;
52 import com.android.systemui.statusbar.RemoteInputController;
53 import com.android.systemui.statusbar.StatusBarState;
54 import com.android.systemui.statusbar.SysuiStatusBarStateController;
55 import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
56 import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
57 import com.android.systemui.statusbar.policy.ConfigurationController;
58 import com.android.systemui.statusbar.policy.KeyguardMonitor;
59 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
61 import java.io.PrintWriter;
62 import java.util.ArrayList;
65 * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
66 * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
67 * which is in turn, reported to this class by the current
68 * {@link com.android.keyguard.KeyguardViewBase}.
70 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
71 StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
72 PanelExpansionListener, NavigationModeController.ModeChangedListener {
74 // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
75 private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
77 // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync
78 // with the appear animations of the PIN/pattern/password views.
79 private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320;
81 private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200;
83 // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to
84 // make everything a bit slower to bridge a gap until the user is unlocked and home screen has
85 // dranw its first frame.
86 private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
88 private static String TAG = "StatusBarKeyguardViewManager";
90 protected final Context mContext;
91 private final StatusBarWindowController mStatusBarWindowController;
92 private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
94 public void onFullyShown() {
96 mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE");
101 public void onStartingToHide() {
106 public void onStartingToShow() {
111 public void onFullyHidden() {
116 private final DockManager.DockEventListener mDockEventListener =
117 new DockManager.DockEventListener() {
119 public void onEvent(int event) {
120 boolean isDocked = mDockManager.isDocked();
121 if (isDocked == mIsDocked) {
124 mIsDocked = isDocked;
129 protected LockPatternUtils mLockPatternUtils;
130 protected ViewMediatorCallback mViewMediatorCallback;
131 protected StatusBar mStatusBar;
132 private NotificationPanelView mNotificationPanelView;
133 private BiometricUnlockController mBiometricUnlockController;
135 private ViewGroup mContainer;
136 private ViewGroup mLockIconContainer;
137 private View mNotificationContainer;
139 protected KeyguardBouncer mBouncer;
140 protected boolean mShowing;
141 protected boolean mOccluded;
142 protected boolean mRemoteInputActive;
143 private boolean mDozing;
144 private boolean mPulsing;
145 private boolean mGesturalNav;
146 private boolean mIsDocked;
148 protected boolean mFirstUpdate = true;
149 protected boolean mLastShowing;
150 protected boolean mLastOccluded;
151 private boolean mLastBouncerShowing;
152 private boolean mLastBouncerDismissible;
153 protected boolean mLastRemoteInputActive;
154 private boolean mLastDozing;
155 private boolean mLastGesturalNav;
156 private boolean mLastIsDocked;
157 private boolean mLastPulsing;
158 private int mLastBiometricMode;
159 private boolean mGoingToSleepVisibleNotOccluded;
160 private boolean mLastLockVisible;
162 private OnDismissAction mAfterKeyguardGoneAction;
163 private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
165 // Dismiss action to be launched when we stop dozing or the keyguard is gone.
166 private DismissWithActionRequest mPendingWakeupAction;
167 private final KeyguardMonitorImpl mKeyguardMonitor =
168 (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
169 private final NotificationMediaManager mMediaManager =
170 Dependency.get(NotificationMediaManager.class);
171 private final SysuiStatusBarStateController mStatusBarStateController =
172 (SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
173 private final DockManager mDockManager;
174 private KeyguardBypassController mBypassController;
176 private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
177 new KeyguardUpdateMonitorCallback() {
179 public void onEmergencyCallAction() {
181 // Since we won't get a setOccluded call we have to reset the view manually such that
182 // the bouncer goes away.
184 reset(true /* hideBouncerWhenShowing */);
189 public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
190 LockPatternUtils lockPatternUtils) {
192 mViewMediatorCallback = callback;
193 mLockPatternUtils = lockPatternUtils;
194 mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
195 KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
196 mStatusBarStateController.addCallback(this);
197 Dependency.get(ConfigurationController.class).addCallback(this);
198 mGesturalNav = QuickStepContract.isGesturalMode(
199 Dependency.get(NavigationModeController.class).addListener(this));
200 mDockManager = Dependency.get(DockManager.class);
201 if (mDockManager != null) {
202 mDockManager.addListener(mDockEventListener);
203 mIsDocked = mDockManager.isDocked();
207 public void registerStatusBar(StatusBar statusBar,
209 NotificationPanelView notificationPanelView,
210 BiometricUnlockController biometricUnlockController,
211 DismissCallbackRegistry dismissCallbackRegistry,
212 ViewGroup lockIconContainer, View notificationContainer,
213 KeyguardBypassController bypassController) {
214 mStatusBar = statusBar;
215 mContainer = container;
216 mLockIconContainer = lockIconContainer;
217 if (mLockIconContainer != null) {
218 mLastLockVisible = mLockIconContainer.getVisibility() == View.VISIBLE;
220 mBiometricUnlockController = biometricUnlockController;
221 mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
222 mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
223 mExpansionCallback, bypassController);
224 mNotificationPanelView = notificationPanelView;
225 notificationPanelView.addExpansionListener(this);
226 mBypassController = bypassController;
227 mNotificationContainer = notificationContainer;
231 public void onPanelExpansionChanged(float expansion, boolean tracking) {
232 // We don't want to translate the bounce when:
233 // • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to
234 // conserve the original animation.
235 // • The user quickly taps on the display and we show "swipe up to unlock."
236 // • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY
237 // • Full-screen user switcher is displayed.
238 if (mNotificationPanelView.isUnlockHintRunning()) {
239 mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
240 } else if (bouncerNeedsScrimming()) {
241 mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
242 } else if (mShowing) {
243 if (!isWakeAndUnlocking() && !mStatusBar.isInLaunchTransition()) {
244 mBouncer.setExpansion(expansion);
246 if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking
247 && mStatusBar.isKeyguardCurrentlySecure()
248 && !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
249 mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
251 } else if (mPulsing && expansion == KeyguardBouncer.EXPANSION_VISIBLE) {
252 // Panel expanded while pulsing but didn't translate the bouncer (because we are
253 // unlocked.) Let's simply wake-up to dismiss the lock screen.
254 mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE");
259 public void onQsExpansionChanged(float expansion) {
263 private void updateLockIcon() {
264 // Not all form factors have a lock icon
265 if (mLockIconContainer == null) {
268 boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD
269 && !mNotificationPanelView.isQsExpanded();
270 boolean lockVisible = (mBouncer.isShowing() || keyguardWithoutQs)
271 && !mBouncer.isAnimatingAway() && !mKeyguardMonitor.isKeyguardFadingAway();
273 if (mLastLockVisible != lockVisible) {
274 mLastLockVisible = lockVisible;
276 CrossFadeHelper.fadeIn(mLockIconContainer,
277 AppearAnimationUtils.DEFAULT_APPEAR_DURATION /* duration */,
281 if (needsBypassFading()) {
282 duration = KeyguardBypassController.BYPASS_PANEL_FADE_DURATION;
284 duration = AppearAnimationUtils.DEFAULT_APPEAR_DURATION / 2;
286 CrossFadeHelper.fadeOut(mLockIconContainer,
287 duration /* duration */,
288 0 /* delay */, null /* runnable */);
294 * Show the keyguard. Will handle creating and attaching to the view manager
297 public void show(Bundle options) {
299 mStatusBarWindowController.setKeyguardShowing(true);
300 mKeyguardMonitor.notifyKeyguardState(
301 mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());
302 reset(true /* hideBouncerWhenShowing */);
303 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
304 StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
308 * Shows the notification keyguard or the bouncer depending on
309 * {@link KeyguardBouncer#needsFullscreenBouncer()}.
311 protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
312 if (mBouncer.needsFullscreenBouncer() && !mDozing) {
313 // The keyguard might be showing (already). So we need to hide it.
314 mStatusBar.hideKeyguard();
315 mBouncer.show(true /* resetSecuritySelection */);
317 mStatusBar.showKeyguard();
318 if (hideBouncerWhenShowing) {
319 hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
326 protected boolean shouldDestroyViewOnReset() {
330 private void hideBouncer(boolean destroyView) {
331 if (mBouncer == null) {
334 mBouncer.hide(destroyView);
335 cancelPendingWakeupAction();
338 public void showBouncer(boolean scrimmed) {
339 if (mShowing && !mBouncer.isShowing()) {
340 mBouncer.show(false /* resetSecuritySelection */, scrimmed);
345 public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
346 boolean afterKeyguardGone) {
347 dismissWithAction(r, cancelAction, afterKeyguardGone, null /* message */);
350 public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
351 boolean afterKeyguardGone, String message) {
353 cancelPendingWakeupAction();
354 // If we're dozing, this needs to be delayed until after we wake up - unless we're
355 // wake-and-unlocking, because there dozing will last until the end of the transition.
356 if (mDozing && !isWakeAndUnlocking()) {
357 mPendingWakeupAction = new DismissWithActionRequest(
358 r, cancelAction, afterKeyguardGone, message);
362 if (!afterKeyguardGone) {
363 mBouncer.showWithDismissAction(r, cancelAction);
365 mAfterKeyguardGoneAction = r;
366 mBouncer.show(false /* resetSecuritySelection */);
372 private boolean isWakeAndUnlocking() {
373 int mode = mBiometricUnlockController.getMode();
374 return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING;
378 * Adds a {@param runnable} to be executed after Keyguard is gone.
380 public void addAfterKeyguardGoneRunnable(Runnable runnable) {
381 mAfterKeyguardGoneRunnables.add(runnable);
385 * Reset the state of the view.
387 public void reset(boolean hideBouncerWhenShowing) {
389 if (mOccluded && !mDozing) {
390 mStatusBar.hideKeyguard();
391 if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
392 hideBouncer(false /* destroyView */);
395 showBouncerOrKeyguard(hideBouncerWhenShowing);
397 KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
402 public boolean isGoingToSleepVisibleNotOccluded() {
403 return mGoingToSleepVisibleNotOccluded;
406 public void onStartedGoingToSleep() {
407 mGoingToSleepVisibleNotOccluded = isShowing() && !isOccluded();
410 public void onFinishedGoingToSleep() {
411 mGoingToSleepVisibleNotOccluded = false;
412 mBouncer.onScreenTurnedOff();
415 public void onStartedWakingUp() {
419 public void onScreenTurningOn() {
423 public void onScreenTurnedOn() {
428 public void onRemoteInputActive(boolean active) {
429 mRemoteInputActive = active;
433 private void setDozing(boolean dozing) {
434 if (mDozing != dozing) {
436 if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) {
437 reset(dozing /* hideBouncerWhenShowing */);
442 launchPendingWakeupAction();
448 * If {@link StatusBar} is pulsing.
450 public void setPulsing(boolean pulsing) {
451 if (mPulsing != pulsing) {
457 public void setNeedsInput(boolean needsInput) {
458 mStatusBarWindowController.setKeyguardNeedsInput(needsInput);
461 public boolean isUnlockWithWallpaper() {
462 return mStatusBarWindowController.isShowingWallpaper();
465 public void setOccluded(boolean occluded, boolean animate) {
466 mStatusBar.setOccluded(occluded);
467 if (occluded && !mOccluded && mShowing) {
468 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
469 StatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED);
470 if (mStatusBar.isInLaunchTransition()) {
472 mStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
476 mStatusBarWindowController.setKeyguardOccluded(mOccluded);
477 reset(true /* hideBouncerWhenShowing */);
482 } else if (!occluded && mOccluded && mShowing) {
483 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
484 StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
486 boolean isOccluding = !mOccluded && occluded;
487 mOccluded = occluded;
489 mMediaManager.updateMediaMetaData(false, animate && !occluded);
491 mStatusBarWindowController.setKeyguardOccluded(occluded);
493 // setDozing(false) will call reset once we stop dozing.
495 // If Keyguard is reshown, don't hide the bouncer as it might just have been requested
496 // by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
497 reset(isOccluding /* hideBouncerWhenShowing*/);
499 if (animate && !occluded && mShowing && !mBouncer.isShowing()) {
500 mStatusBar.animateKeyguardUnoccluding();
504 public boolean isOccluded() {
509 * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
510 * security view of the bouncer.
512 * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
513 * no action should be run
515 public void startPreHideAnimation(Runnable finishRunnable) {
516 if (mBouncer.isShowing()) {
517 mBouncer.startPreHideAnimation(finishRunnable);
518 mNotificationPanelView.onBouncerPreHideAnimation();
519 } else if (finishRunnable != null) {
520 finishRunnable.run();
522 mNotificationPanelView.blockExpansionForCurrentTouch();
527 * Hides the keyguard view
529 public void hide(long startTime, long fadeoutDuration) {
531 mKeyguardMonitor.notifyKeyguardState(
532 mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());
533 launchPendingWakeupAction();
535 if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) {
536 fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
538 long uptimeMillis = SystemClock.uptimeMillis();
539 long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
541 if (mStatusBar.isInLaunchTransition() ) {
542 mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
545 mStatusBarWindowController.setKeyguardShowing(false);
546 mStatusBarWindowController.setKeyguardFadingAway(true);
547 hideBouncer(true /* destroyView */);
553 mStatusBar.hideKeyguard();
554 mStatusBarWindowController.setKeyguardFadingAway(false);
555 mViewMediatorCallback.keyguardGone();
556 executeAfterKeyguardGoneAction();
560 executeAfterKeyguardGoneAction();
561 boolean wakeUnlockPulsing =
562 mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
563 boolean needsFading = needsBypassFading();
566 fadeoutDuration = KeyguardBypassController.BYPASS_PANEL_FADE_DURATION;
567 } else if (wakeUnlockPulsing) {
569 fadeoutDuration = 240;
571 mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration, needsFading);
572 mBiometricUnlockController.startKeyguardFadingAway();
573 hideBouncer(true /* destroyView */);
574 if (wakeUnlockPulsing) {
576 ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
577 mNotificationContainer,
580 mStatusBar.hideKeyguard();
581 onKeyguardFadedAway();
584 mStatusBar.fadeKeyguardWhilePulsing();
586 wakeAndUnlockDejank();
588 boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
590 mStatusBarWindowController.setKeyguardFadingAway(true);
592 ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
593 mNotificationContainer,
596 mStatusBar.hideKeyguard();
599 mStatusBar.hideKeyguard();
601 // hide() will happen asynchronously and might arrive after the scrims
602 // were already hidden, this means that the transition callback won't
603 // be triggered anymore and StatusBarWindowController will be forever in
604 // the fadingAway state.
605 mStatusBar.updateScrimController();
606 wakeAndUnlockDejank();
608 mStatusBar.hideKeyguard();
609 mStatusBar.finishKeyguardFadingAway();
610 mBiometricUnlockController.finishKeyguardFadingAway();
615 mStatusBarWindowController.setKeyguardShowing(false);
616 mViewMediatorCallback.keyguardGone();
618 StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
619 StatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
622 private boolean needsBypassFading() {
623 return (mBiometricUnlockController.getMode() == MODE_UNLOCK_FADING
624 || mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING
625 || mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK)
626 && mBypassController.getBypassEnabled();
630 public void onDensityOrFontScaleChanged() {
631 hideBouncer(true /* destroyView */);
635 public void onNavigationModeChanged(int mode) {
636 boolean gesturalNav = QuickStepContract.isGesturalMode(mode);
637 if (gesturalNav != mGesturalNav) {
638 mGesturalNav = gesturalNav;
643 public void onThemeChanged() {
644 hideBouncer(true /* destroyView */);
648 public void onKeyguardFadedAway() {
649 mContainer.postDelayed(() -> mStatusBarWindowController.setKeyguardFadingAway(false),
651 ViewGroupFadeHelper.reset(mNotificationPanelView);
652 mStatusBar.finishKeyguardFadingAway();
653 mBiometricUnlockController.finishKeyguardFadingAway();
654 WindowManagerGlobal.getInstance().trimMemory(
655 ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
659 private void wakeAndUnlockDejank() {
660 if (mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK
661 && LatencyTracker.isEnabled(mContext)) {
662 DejankUtils.postAfterTraversal(() ->
663 LatencyTracker.getInstance(mContext).onActionEnd(
664 LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK));
668 private void executeAfterKeyguardGoneAction() {
669 if (mAfterKeyguardGoneAction != null) {
670 mAfterKeyguardGoneAction.onDismiss();
671 mAfterKeyguardGoneAction = null;
673 for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
674 mAfterKeyguardGoneRunnables.get(i).run();
676 mAfterKeyguardGoneRunnables.clear();
680 * Dismisses the keyguard by going to the next screen or making it gone.
682 public void dismissAndCollapse() {
683 mStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true);
687 * WARNING: This method might cause Binder calls.
689 public boolean isSecure() {
690 return mBouncer.isSecure();
694 * @return Whether the keyguard is showing
696 public boolean isShowing() {
701 * Notifies this manager that the back button has been pressed.
703 * @param hideImmediately Hide bouncer when {@code true}, keep it around otherwise.
704 * Non-scrimmed bouncers have a special animation tied to the expansion
705 * of the notification panel.
706 * @return whether the back press has been handled
708 public boolean onBackPressed(boolean hideImmediately) {
709 if (mBouncer.isShowing()) {
710 mStatusBar.endAffordanceLaunch();
711 // The second condition is for SIM card locked bouncer
712 if (mBouncer.isScrimmed() && !mBouncer.needsFullscreenBouncer()) {
716 reset(hideImmediately);
723 public boolean isBouncerShowing() {
724 return mBouncer.isShowing();
728 * When bouncer is fully visible or {@link KeyguardBouncer#show(boolean)} was called but
729 * animation didn't finish yet.
731 public boolean bouncerIsOrWillBeShowing() {
732 return mBouncer.isShowing() || mBouncer.inTransit();
735 public boolean isFullscreenBouncer() {
736 return mBouncer.isFullscreenBouncer();
739 private long getNavBarShowDelay() {
740 if (mKeyguardMonitor.isKeyguardFadingAway()) {
741 return mKeyguardMonitor.getKeyguardFadingAwayDelay();
742 } else if (mBouncer.isShowing()) {
743 return NAV_BAR_SHOW_DELAY_BOUNCER;
745 // No longer dozing, or remote input is active. No delay.
750 private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
753 mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
757 protected void updateStates() {
758 int vis = mContainer.getSystemUiVisibility();
759 boolean showing = mShowing;
760 boolean occluded = mOccluded;
761 boolean bouncerShowing = mBouncer.isShowing();
762 boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
763 boolean remoteInputActive = mRemoteInputActive;
765 if ((bouncerDismissible || !showing || remoteInputActive) !=
766 (mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive)
768 if (bouncerDismissible || !showing || remoteInputActive) {
769 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
771 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
775 boolean navBarVisible = isNavBarVisible();
776 boolean lastNavBarVisible = getLastNavBarVisible();
777 if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
778 updateNavigationBarVisibility(navBarVisible);
781 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
782 mStatusBarWindowController.setBouncerShowing(bouncerShowing);
783 mStatusBar.setBouncerShowing(bouncerShowing);
786 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
787 if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
788 updateMonitor.onKeyguardVisibilityChanged(showing && !occluded);
790 if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
791 updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
794 mFirstUpdate = false;
795 mLastShowing = showing;
796 mLastOccluded = occluded;
797 mLastBouncerShowing = bouncerShowing;
798 mLastBouncerDismissible = bouncerDismissible;
799 mLastRemoteInputActive = remoteInputActive;
800 mLastDozing = mDozing;
801 mLastPulsing = mPulsing;
802 mLastBiometricMode = mBiometricUnlockController.getMode();
803 mLastGesturalNav = mGesturalNav;
804 mLastIsDocked = mIsDocked;
805 mStatusBar.onKeyguardViewManagerStatesUpdated();
808 protected void updateNavigationBarVisibility(boolean navBarVisible) {
809 if (mStatusBar.getNavigationBarView() != null) {
811 long delay = getNavBarShowDelay();
813 mMakeNavigationBarVisibleRunnable.run();
815 mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
819 mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
820 mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE);
826 * @return Whether the navigation bar should be made visible based on the current state.
828 protected boolean isNavBarVisible() {
829 int biometricMode = mBiometricUnlockController.getMode();
830 boolean keyguardShowing = mShowing && !mOccluded;
831 boolean hideWhileDozing = mDozing && biometricMode != MODE_WAKE_AND_UNLOCK_PULSING;
832 boolean keyguardWithGestureNav = (keyguardShowing && !mDozing || mPulsing && !mIsDocked)
834 return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing()
835 || mRemoteInputActive || keyguardWithGestureNav);
839 * @return Whether the navigation bar was made visible based on the last known state.
841 protected boolean getLastNavBarVisible() {
842 boolean keyguardShowing = mLastShowing && !mLastOccluded;
843 boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING;
844 boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing
845 || mLastPulsing && !mLastIsDocked) && mLastGesturalNav;
846 return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing
847 || mLastRemoteInputActive || keyguardWithGestureNav);
850 public boolean shouldDismissOnMenuPressed() {
851 return mBouncer.shouldDismissOnMenuPressed();
854 public boolean interceptMediaKey(KeyEvent event) {
855 return mBouncer.interceptMediaKey(event);
858 public void readyForKeyguardDone() {
859 mViewMediatorCallback.readyForKeyguardDone();
862 public boolean shouldDisableWindowAnimationsForUnlock() {
863 return mStatusBar.isInLaunchTransition();
868 * @return Whether subtle animation should be used for unlocking the device.
870 public boolean shouldSubtleWindowAnimationsForUnlock() {
871 return needsBypassFading();
874 public boolean isGoingToNotificationShade() {
875 return ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
876 .leaveOpenOnKeyguardHide();
879 public boolean isSecure(int userId) {
880 return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
883 public void keyguardGoingAway() {
884 mStatusBar.keyguardGoingAway();
887 public void animateCollapsePanels(float speedUpFactor) {
888 mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
889 false /* delayed */, speedUpFactor);
894 * Called when cancel button in bouncer is pressed.
896 public void onCancelClicked() {
901 * Notifies that the user has authenticated by other means than using the bouncer, for example,
904 public void notifyKeyguardAuthenticated(boolean strongAuth) {
905 mBouncer.notifyKeyguardAuthenticated(strongAuth);
908 public void showBouncerMessage(String message, ColorStateList colorState) {
909 mBouncer.showMessage(message, colorState);
912 public ViewRootImpl getViewRootImpl() {
913 return mStatusBar.getStatusBarView().getViewRootImpl();
916 public void launchPendingWakeupAction() {
917 DismissWithActionRequest request = mPendingWakeupAction;
918 mPendingWakeupAction = null;
919 if (request != null) {
921 dismissWithAction(request.dismissAction, request.cancelAction,
922 request.afterKeyguardGone, request.message);
923 } else if (request.dismissAction != null) {
924 request.dismissAction.onDismiss();
929 public void cancelPendingWakeupAction() {
930 DismissWithActionRequest request = mPendingWakeupAction;
931 mPendingWakeupAction = null;
932 if (request != null && request.cancelAction != null) {
933 request.cancelAction.run();
937 public boolean bouncerNeedsScrimming() {
938 return mOccluded || mBouncer.willDismissWithAction()
939 || mStatusBar.isFullScreenUserSwitcherState()
940 || (mBouncer.isShowing() && mBouncer.isScrimmed())
941 || mBouncer.isFullscreenBouncer();
944 public void dump(PrintWriter pw) {
945 pw.println("StatusBarKeyguardViewManager:");
946 pw.println(" mShowing: " + mShowing);
947 pw.println(" mOccluded: " + mOccluded);
948 pw.println(" mRemoteInputActive: " + mRemoteInputActive);
949 pw.println(" mDozing: " + mDozing);
950 pw.println(" mGoingToSleepVisibleNotOccluded: " + mGoingToSleepVisibleNotOccluded);
951 pw.println(" mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction);
952 pw.println(" mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables);
953 pw.println(" mPendingWakeupAction: " + mPendingWakeupAction);
955 if (mBouncer != null) {
961 public void onStateChanged(int newState) {
966 public void onDozingChanged(boolean isDozing) {
970 public KeyguardBouncer getBouncer() {
974 private static class DismissWithActionRequest {
975 final OnDismissAction dismissAction;
976 final Runnable cancelAction;
977 final boolean afterKeyguardGone;
978 final String message;
980 DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
981 boolean afterKeyguardGone, String message) {
982 this.dismissAction = dismissAction;
983 this.cancelAction = cancelAction;
984 this.afterKeyguardGone = afterKeyguardGone;
985 this.message = message;