Home | History | Annotate | Download | only in phone
      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 android.content.ComponentCallbacks2;
     20 import android.content.Context;
     21 import android.os.Bundle;
     22 import android.os.SystemClock;
     23 import android.os.Trace;
     24 import android.view.KeyEvent;
     25 import android.view.View;
     26 import android.view.ViewGroup;
     27 import android.view.ViewRootImpl;
     28 import android.view.WindowManagerGlobal;
     29 
     30 import com.android.internal.widget.LockPatternUtils;
     31 import com.android.keyguard.KeyguardUpdateMonitor;
     32 import com.android.keyguard.KeyguardUpdateMonitorCallback;
     33 import com.android.keyguard.ViewMediatorCallback;
     34 import com.android.systemui.DejankUtils;
     35 import com.android.keyguard.LatencyTracker;
     36 import com.android.systemui.Dependency;
     37 import com.android.systemui.SystemUIFactory;
     38 import com.android.systemui.keyguard.DismissCallbackRegistry;
     39 import com.android.systemui.statusbar.CommandQueue;
     40 import com.android.systemui.statusbar.RemoteInputController;
     41 
     42 import static com.android.keyguard.KeyguardHostView.OnDismissAction;
     43 import static com.android.systemui.statusbar.phone.FingerprintUnlockController.*;
     44 
     45 import java.util.ArrayList;
     46 
     47 /**
     48  * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
     49  * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
     50  * which is in turn, reported to this class by the current
     51  * {@link com.android.keyguard.KeyguardViewBase}.
     52  */
     53 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback {
     54 
     55     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
     56     private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
     57 
     58     // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync
     59     // with the appear animations of the PIN/pattern/password views.
     60     private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320;
     61 
     62     private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200;
     63 
     64     // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to
     65     // make everything a bit slower to bridge a gap until the user is unlocked and home screen has
     66     // dranw its first frame.
     67     private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
     68 
     69     private static String TAG = "StatusBarKeyguardViewManager";
     70 
     71     protected final Context mContext;
     72     private final StatusBarWindowManager mStatusBarWindowManager;
     73 
     74     protected LockPatternUtils mLockPatternUtils;
     75     protected ViewMediatorCallback mViewMediatorCallback;
     76     protected StatusBar mStatusBar;
     77     private ScrimController mScrimController;
     78     private FingerprintUnlockController mFingerprintUnlockController;
     79 
     80     private ViewGroup mContainer;
     81 
     82     private boolean mDeviceInteractive = false;
     83     private boolean mScreenTurnedOn;
     84     protected KeyguardBouncer mBouncer;
     85     protected boolean mShowing;
     86     protected boolean mOccluded;
     87     protected boolean mRemoteInputActive;
     88 
     89     protected boolean mFirstUpdate = true;
     90     protected boolean mLastShowing;
     91     protected boolean mLastOccluded;
     92     private boolean mLastBouncerShowing;
     93     private boolean mLastBouncerDismissible;
     94     protected boolean mLastRemoteInputActive;
     95     private boolean mLastDeferScrimFadeOut;
     96 
     97     private OnDismissAction mAfterKeyguardGoneAction;
     98     private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
     99     private boolean mDeviceWillWakeUp;
    100     private boolean mDeferScrimFadeOut;
    101 
    102     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
    103             new KeyguardUpdateMonitorCallback() {
    104         @Override
    105         public void onEmergencyCallAction() {
    106 
    107             // Since we won't get a setOccluded call we have to reset the view manually such that
    108             // the bouncer goes away.
    109             if (mOccluded) {
    110                 reset(false /* hideBouncerWhenShowing */);
    111             }
    112         }
    113     };
    114 
    115     public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
    116             LockPatternUtils lockPatternUtils) {
    117         mContext = context;
    118         mViewMediatorCallback = callback;
    119         mLockPatternUtils = lockPatternUtils;
    120         mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
    121         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
    122     }
    123 
    124     public void registerStatusBar(StatusBar statusBar,
    125             ViewGroup container,
    126             ScrimController scrimController,
    127             FingerprintUnlockController fingerprintUnlockController,
    128             DismissCallbackRegistry dismissCallbackRegistry) {
    129         mStatusBar = statusBar;
    130         mContainer = container;
    131         mScrimController = scrimController;
    132         mFingerprintUnlockController = fingerprintUnlockController;
    133         mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
    134                 mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry);
    135     }
    136 
    137     /**
    138      * Show the keyguard.  Will handle creating and attaching to the view manager
    139      * lazily.
    140      */
    141     public void show(Bundle options) {
    142         mShowing = true;
    143         mStatusBarWindowManager.setKeyguardShowing(true);
    144         mScrimController.abortKeyguardFadingOut();
    145         reset(true /* hideBouncerWhenShowing */);
    146     }
    147 
    148     /**
    149      * Shows the notification keyguard or the bouncer depending on
    150      * {@link KeyguardBouncer#needsFullscreenBouncer()}.
    151      */
    152     protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
    153         if (mBouncer.needsFullscreenBouncer()) {
    154 
    155             // The keyguard might be showing (already). So we need to hide it.
    156             mStatusBar.hideKeyguard();
    157             mBouncer.show(true /* resetSecuritySelection */);
    158         } else {
    159             mStatusBar.showKeyguard();
    160             if (hideBouncerWhenShowing) {
    161                 mBouncer.hide(false /* destroyView */);
    162                 mBouncer.prepare();
    163             }
    164         }
    165     }
    166 
    167     private void showBouncer() {
    168         if (mShowing) {
    169             mBouncer.show(false /* resetSecuritySelection */);
    170         }
    171         updateStates();
    172     }
    173 
    174     public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
    175             boolean afterKeyguardGone) {
    176         if (mShowing) {
    177             if (!afterKeyguardGone) {
    178                 mBouncer.showWithDismissAction(r, cancelAction);
    179             } else {
    180                 mAfterKeyguardGoneAction = r;
    181                 mBouncer.show(false /* resetSecuritySelection */);
    182             }
    183         }
    184         updateStates();
    185     }
    186 
    187     /**
    188      * Adds a {@param runnable} to be executed after Keyguard is gone.
    189      */
    190     public void addAfterKeyguardGoneRunnable(Runnable runnable) {
    191         mAfterKeyguardGoneRunnables.add(runnable);
    192     }
    193 
    194     /**
    195      * Reset the state of the view.
    196      */
    197     public void reset(boolean hideBouncerWhenShowing) {
    198         if (mShowing) {
    199             if (mOccluded) {
    200                 mStatusBar.hideKeyguard();
    201                 mStatusBar.stopWaitingForKeyguardExit();
    202                 mBouncer.hide(false /* destroyView */);
    203             } else {
    204                 showBouncerOrKeyguard(hideBouncerWhenShowing);
    205             }
    206             KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
    207             updateStates();
    208         }
    209     }
    210 
    211     public void onStartedGoingToSleep() {
    212         mStatusBar.onStartedGoingToSleep();
    213     }
    214 
    215     public void onFinishedGoingToSleep() {
    216         mDeviceInteractive = false;
    217         mStatusBar.onFinishedGoingToSleep();
    218         mBouncer.onScreenTurnedOff();
    219     }
    220 
    221     public void onStartedWakingUp() {
    222         Trace.beginSection("StatusBarKeyguardViewManager#onStartedWakingUp");
    223         mDeviceInteractive = true;
    224         mDeviceWillWakeUp = false;
    225         mStatusBar.onStartedWakingUp();
    226         Trace.endSection();
    227     }
    228 
    229     public void onScreenTurningOn() {
    230         Trace.beginSection("StatusBarKeyguardViewManager#onScreenTurningOn");
    231         mStatusBar.onScreenTurningOn();
    232         Trace.endSection();
    233     }
    234 
    235     public boolean isScreenTurnedOn() {
    236         return mScreenTurnedOn;
    237     }
    238 
    239     public void onScreenTurnedOn() {
    240         Trace.beginSection("StatusBarKeyguardViewManager#onScreenTurnedOn");
    241         mScreenTurnedOn = true;
    242         if (mDeferScrimFadeOut) {
    243             mDeferScrimFadeOut = false;
    244             animateScrimControllerKeyguardFadingOut(0, WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
    245                     true /* skipFirstFrame */);
    246             updateStates();
    247         }
    248         mStatusBar.onScreenTurnedOn();
    249         Trace.endSection();
    250     }
    251 
    252     @Override
    253     public void onRemoteInputActive(boolean active) {
    254         mRemoteInputActive = active;
    255         updateStates();
    256     }
    257 
    258     public void onScreenTurnedOff() {
    259         mScreenTurnedOn = false;
    260         mStatusBar.onScreenTurnedOff();
    261     }
    262 
    263     public void notifyDeviceWakeUpRequested() {
    264         mDeviceWillWakeUp = !mDeviceInteractive;
    265     }
    266 
    267     public void setNeedsInput(boolean needsInput) {
    268         mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
    269     }
    270 
    271     public boolean isUnlockWithWallpaper() {
    272         return mStatusBarWindowManager.isShowingWallpaper();
    273     }
    274 
    275     public void setOccluded(boolean occluded, boolean animate) {
    276         if (occluded != mOccluded) {
    277             mStatusBar.onKeyguardOccludedChanged(occluded);
    278         }
    279         if (occluded && !mOccluded && mShowing) {
    280             if (mStatusBar.isInLaunchTransition()) {
    281                 mOccluded = true;
    282                 mStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
    283                         new Runnable() {
    284                             @Override
    285                             public void run() {
    286                                 mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
    287                                 reset(true /* hideBouncerWhenShowing */);
    288                             }
    289                         });
    290                 return;
    291             }
    292         }
    293         mOccluded = occluded;
    294         if (mShowing) {
    295             mStatusBar.updateMediaMetaData(false, animate && !occluded);
    296         }
    297         mStatusBarWindowManager.setKeyguardOccluded(occluded);
    298 
    299         // If Keyguard is reshown, don't hide the bouncer as it might just have been requested by
    300         // a FLAG_DISMISS_KEYGUARD_ACTIVITY.
    301         reset(false /* hideBouncerWhenShowing*/);
    302         if (animate && !occluded && mShowing) {
    303             mStatusBar.animateKeyguardUnoccluding();
    304         }
    305     }
    306 
    307     public boolean isOccluded() {
    308         return mOccluded;
    309     }
    310 
    311     /**
    312      * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
    313      * security view of the bouncer.
    314      *
    315      * @param finishRunnable the runnable to be run after the animation finished, or {@code null} if
    316      *                       no action should be run
    317      */
    318     public void startPreHideAnimation(Runnable finishRunnable) {
    319         if (mBouncer.isShowing()) {
    320             mBouncer.startPreHideAnimation(finishRunnable);
    321         } else if (finishRunnable != null) {
    322             finishRunnable.run();
    323         }
    324     }
    325 
    326     /**
    327      * Hides the keyguard view
    328      */
    329     public void hide(long startTime, long fadeoutDuration) {
    330         mShowing = false;
    331 
    332         if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) {
    333             fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
    334         }
    335         long uptimeMillis = SystemClock.uptimeMillis();
    336         long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
    337 
    338         if (mStatusBar.isInLaunchTransition() ) {
    339             mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
    340                 @Override
    341                 public void run() {
    342                     mStatusBarWindowManager.setKeyguardShowing(false);
    343                     mStatusBarWindowManager.setKeyguardFadingAway(true);
    344                     mBouncer.hide(true /* destroyView */);
    345                     updateStates();
    346                     mScrimController.animateKeyguardFadingOut(
    347                             StatusBar.FADE_KEYGUARD_START_DELAY,
    348                             StatusBar.FADE_KEYGUARD_DURATION, null,
    349                             false /* skipFirstFrame */);
    350                 }
    351             }, new Runnable() {
    352                 @Override
    353                 public void run() {
    354                     mStatusBar.hideKeyguard();
    355                     mStatusBarWindowManager.setKeyguardFadingAway(false);
    356                     mViewMediatorCallback.keyguardGone();
    357                     executeAfterKeyguardGoneAction();
    358                 }
    359             });
    360         } else {
    361             executeAfterKeyguardGoneAction();
    362             boolean wakeUnlockPulsing =
    363                     mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
    364             if (wakeUnlockPulsing) {
    365                 delay = 0;
    366                 fadeoutDuration = 240;
    367             }
    368             mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
    369             mFingerprintUnlockController.startKeyguardFadingAway();
    370             mBouncer.hide(true /* destroyView */);
    371             if (wakeUnlockPulsing) {
    372                 mStatusBarWindowManager.setKeyguardFadingAway(true);
    373                 mStatusBar.fadeKeyguardWhilePulsing();
    374                 animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
    375                         mStatusBar::hideKeyguard, false /* skipFirstFrame */);
    376             } else {
    377                 mFingerprintUnlockController.startKeyguardFadingAway();
    378                 mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
    379                 boolean staying = mStatusBar.hideKeyguard();
    380                 if (!staying) {
    381                     mStatusBarWindowManager.setKeyguardFadingAway(true);
    382                     if (mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK) {
    383                         if (!mScreenTurnedOn) {
    384                             mDeferScrimFadeOut = true;
    385                         } else {
    386 
    387                             // Screen is already on, don't defer with fading out.
    388                             animateScrimControllerKeyguardFadingOut(0,
    389                                     WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS,
    390                                     true /* skipFirstFrame */);
    391                         }
    392                     } else {
    393                         animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
    394                                 false /* skipFirstFrame */);
    395                     }
    396                 } else {
    397                     mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
    398                     mStatusBar.finishKeyguardFadingAway();
    399                     mFingerprintUnlockController.finishKeyguardFadingAway();
    400                 }
    401             }
    402             updateStates();
    403             mStatusBarWindowManager.setKeyguardShowing(false);
    404             mViewMediatorCallback.keyguardGone();
    405         }
    406     }
    407 
    408     public void onDensityOrFontScaleChanged() {
    409         mBouncer.hide(true /* destroyView */);
    410     }
    411 
    412     private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
    413             boolean skipFirstFrame) {
    414         animateScrimControllerKeyguardFadingOut(delay, duration, null /* endRunnable */,
    415                 skipFirstFrame);
    416     }
    417 
    418     private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
    419             final Runnable endRunnable, boolean skipFirstFrame) {
    420         Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "Fading out", 0);
    421         mScrimController.animateKeyguardFadingOut(delay, duration, new Runnable() {
    422             @Override
    423             public void run() {
    424                 if (endRunnable != null) {
    425                     endRunnable.run();
    426                 }
    427                 mContainer.postDelayed(() -> mStatusBarWindowManager.setKeyguardFadingAway(false),
    428                         100);
    429                 mStatusBar.finishKeyguardFadingAway();
    430                 mFingerprintUnlockController.finishKeyguardFadingAway();
    431                 WindowManagerGlobal.getInstance().trimMemory(
    432                         ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
    433                 Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "Fading out", 0);
    434             }
    435         }, skipFirstFrame);
    436         if (mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK
    437                 && LatencyTracker.isEnabled(mContext)) {
    438             DejankUtils.postAfterTraversal(() ->
    439                     LatencyTracker.getInstance(mContext).onActionEnd(
    440                             LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK));
    441         }
    442     }
    443 
    444     private void executeAfterKeyguardGoneAction() {
    445         if (mAfterKeyguardGoneAction != null) {
    446             mAfterKeyguardGoneAction.onDismiss();
    447             mAfterKeyguardGoneAction = null;
    448         }
    449         for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
    450             mAfterKeyguardGoneRunnables.get(i).run();
    451         }
    452         mAfterKeyguardGoneRunnables.clear();
    453     }
    454 
    455     /**
    456      * Dismisses the keyguard by going to the next screen or making it gone.
    457      */
    458     public void dismissAndCollapse() {
    459         mStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true);
    460     }
    461 
    462     public void dismiss() {
    463         showBouncer();
    464     }
    465 
    466     /**
    467      * WARNING: This method might cause Binder calls.
    468      */
    469     public boolean isSecure() {
    470         return mBouncer.isSecure();
    471     }
    472 
    473     /**
    474      * @return Whether the keyguard is showing
    475      */
    476     public boolean isShowing() {
    477         return mShowing;
    478     }
    479 
    480     /**
    481      * Notifies this manager that the back button has been pressed.
    482      *
    483      * @return whether the back press has been handled
    484      */
    485     public boolean onBackPressed() {
    486         if (mBouncer.isShowing()) {
    487             mStatusBar.endAffordanceLaunch();
    488             reset(true /* hideBouncerWhenShowing */);
    489             return true;
    490         }
    491         return false;
    492     }
    493 
    494     public boolean isBouncerShowing() {
    495         return mBouncer.isShowing();
    496     }
    497 
    498     private long getNavBarShowDelay() {
    499         if (mStatusBar.isKeyguardFadingAway()) {
    500             return mStatusBar.getKeyguardFadingAwayDelay();
    501         } else {
    502 
    503             // Keyguard is not going away, thus we are showing the navigation bar because the
    504             // bouncer is appearing.
    505             return NAV_BAR_SHOW_DELAY_BOUNCER;
    506         }
    507     }
    508 
    509     private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
    510         @Override
    511         public void run() {
    512             mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
    513         }
    514     };
    515 
    516     protected void updateStates() {
    517         int vis = mContainer.getSystemUiVisibility();
    518         boolean showing = mShowing;
    519         boolean occluded = mOccluded;
    520         boolean bouncerShowing = mBouncer.isShowing();
    521         boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
    522         boolean remoteInputActive = mRemoteInputActive;
    523 
    524         if ((bouncerDismissible || !showing || remoteInputActive) !=
    525                 (mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive)
    526                 || mFirstUpdate) {
    527             if (bouncerDismissible || !showing || remoteInputActive) {
    528                 mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
    529             } else {
    530                 mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
    531             }
    532         }
    533 
    534         boolean navBarVisible = isNavBarVisible();
    535         boolean lastNavBarVisible = getLastNavBarVisible();
    536         if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
    537             if (mStatusBar.getNavigationBarView() != null) {
    538                 if (navBarVisible) {
    539                     long delay = getNavBarShowDelay();
    540                     if (delay == 0) {
    541                         mMakeNavigationBarVisibleRunnable.run();
    542                     } else {
    543                         mContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
    544                                 delay);
    545                     }
    546                 } else {
    547                     mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
    548                     mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE);
    549                 }
    550             }
    551         }
    552 
    553         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
    554             mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
    555             mStatusBar.setBouncerShowing(bouncerShowing);
    556             mScrimController.setBouncerShowing(bouncerShowing);
    557         }
    558 
    559         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
    560         if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
    561             updateMonitor.onKeyguardVisibilityChanged(showing && !occluded);
    562         }
    563         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
    564             updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
    565         }
    566 
    567         mFirstUpdate = false;
    568         mLastShowing = showing;
    569         mLastOccluded = occluded;
    570         mLastBouncerShowing = bouncerShowing;
    571         mLastBouncerDismissible = bouncerDismissible;
    572         mLastRemoteInputActive = remoteInputActive;
    573         mLastDeferScrimFadeOut = mDeferScrimFadeOut;
    574         mStatusBar.onKeyguardViewManagerStatesUpdated();
    575     }
    576 
    577     /**
    578      * @return Whether the navigation bar should be made visible based on the current state.
    579      */
    580     protected boolean isNavBarVisible() {
    581         return (!(mShowing && !mOccluded) || mBouncer.isShowing() || mRemoteInputActive)
    582                 && !mDeferScrimFadeOut;
    583     }
    584 
    585     /**
    586      * @return Whether the navigation bar was made visible based on the last known state.
    587      */
    588     protected boolean getLastNavBarVisible() {
    589         return (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing || mLastRemoteInputActive)
    590                 && !mLastDeferScrimFadeOut;
    591     }
    592 
    593     public boolean shouldDismissOnMenuPressed() {
    594         return mBouncer.shouldDismissOnMenuPressed();
    595     }
    596 
    597     public boolean interceptMediaKey(KeyEvent event) {
    598         return mBouncer.interceptMediaKey(event);
    599     }
    600 
    601     public void readyForKeyguardDone() {
    602         mViewMediatorCallback.readyForKeyguardDone();
    603     }
    604 
    605     public boolean shouldDisableWindowAnimationsForUnlock() {
    606         return mStatusBar.isInLaunchTransition();
    607     }
    608 
    609     public boolean isGoingToNotificationShade() {
    610         return mStatusBar.isGoingToNotificationShade();
    611     }
    612 
    613     public boolean isSecure(int userId) {
    614         return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
    615     }
    616 
    617     public void keyguardGoingAway() {
    618         mStatusBar.keyguardGoingAway();
    619     }
    620 
    621     public void animateCollapsePanels(float speedUpFactor) {
    622         mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
    623                 false /* delayed */, speedUpFactor);
    624     }
    625 
    626     /**
    627      * Notifies that the user has authenticated by other means than using the bouncer, for example,
    628      * fingerprint.
    629      */
    630     public void notifyKeyguardAuthenticated(boolean strongAuth) {
    631         mBouncer.notifyKeyguardAuthenticated(strongAuth);
    632     }
    633 
    634     public void showBouncerMessage(String message, int color) {
    635         mBouncer.showMessage(message, color);
    636     }
    637 
    638     public ViewRootImpl getViewRootImpl() {
    639         return mStatusBar.getStatusBarView().getViewRootImpl();
    640     }
    641 }
    642