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 
StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils)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 
registerStatusBar(StatusBar statusBar, ViewGroup container, ScrimController scrimController, FingerprintUnlockController fingerprintUnlockController, DismissCallbackRegistry dismissCallbackRegistry)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      */
show(Bundle options)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      */
showBouncerOrKeyguard(boolean hideBouncerWhenShowing)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 
showBouncer()167     private void showBouncer() {
168         if (mShowing) {
169             mBouncer.show(false /* resetSecuritySelection */);
170         }
171         updateStates();
172     }
173 
dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone)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      */
addAfterKeyguardGoneRunnable(Runnable runnable)190     public void addAfterKeyguardGoneRunnable(Runnable runnable) {
191         mAfterKeyguardGoneRunnables.add(runnable);
192     }
193 
194     /**
195      * Reset the state of the view.
196      */
reset(boolean hideBouncerWhenShowing)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 
onStartedGoingToSleep()211     public void onStartedGoingToSleep() {
212         mStatusBar.onStartedGoingToSleep();
213     }
214 
onFinishedGoingToSleep()215     public void onFinishedGoingToSleep() {
216         mDeviceInteractive = false;
217         mStatusBar.onFinishedGoingToSleep();
218         mBouncer.onScreenTurnedOff();
219     }
220 
onStartedWakingUp()221     public void onStartedWakingUp() {
222         Trace.beginSection("StatusBarKeyguardViewManager#onStartedWakingUp");
223         mDeviceInteractive = true;
224         mDeviceWillWakeUp = false;
225         mStatusBar.onStartedWakingUp();
226         Trace.endSection();
227     }
228 
onScreenTurningOn()229     public void onScreenTurningOn() {
230         Trace.beginSection("StatusBarKeyguardViewManager#onScreenTurningOn");
231         mStatusBar.onScreenTurningOn();
232         Trace.endSection();
233     }
234 
isScreenTurnedOn()235     public boolean isScreenTurnedOn() {
236         return mScreenTurnedOn;
237     }
238 
onScreenTurnedOn()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
onRemoteInputActive(boolean active)253     public void onRemoteInputActive(boolean active) {
254         mRemoteInputActive = active;
255         updateStates();
256     }
257 
onScreenTurnedOff()258     public void onScreenTurnedOff() {
259         mScreenTurnedOn = false;
260         mStatusBar.onScreenTurnedOff();
261     }
262 
notifyDeviceWakeUpRequested()263     public void notifyDeviceWakeUpRequested() {
264         mDeviceWillWakeUp = !mDeviceInteractive;
265     }
266 
setNeedsInput(boolean needsInput)267     public void setNeedsInput(boolean needsInput) {
268         mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
269     }
270 
isUnlockWithWallpaper()271     public boolean isUnlockWithWallpaper() {
272         return mStatusBarWindowManager.isShowingWallpaper();
273     }
274 
setOccluded(boolean occluded, boolean animate)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 
isOccluded()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      */
startPreHideAnimation(Runnable finishRunnable)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      */
hide(long startTime, long fadeoutDuration)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 
onDensityOrFontScaleChanged()408     public void onDensityOrFontScaleChanged() {
409         mBouncer.hide(true /* destroyView */);
410     }
411 
animateScrimControllerKeyguardFadingOut(long delay, long duration, boolean skipFirstFrame)412     private void animateScrimControllerKeyguardFadingOut(long delay, long duration,
413             boolean skipFirstFrame) {
414         animateScrimControllerKeyguardFadingOut(delay, duration, null /* endRunnable */,
415                 skipFirstFrame);
416     }
417 
animateScrimControllerKeyguardFadingOut(long delay, long duration, final Runnable endRunnable, boolean skipFirstFrame)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 
executeAfterKeyguardGoneAction()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      */
dismissAndCollapse()458     public void dismissAndCollapse() {
459         mStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true);
460     }
461 
dismiss()462     public void dismiss() {
463         showBouncer();
464     }
465 
466     /**
467      * WARNING: This method might cause Binder calls.
468      */
isSecure()469     public boolean isSecure() {
470         return mBouncer.isSecure();
471     }
472 
473     /**
474      * @return Whether the keyguard is showing
475      */
isShowing()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      */
onBackPressed()485     public boolean onBackPressed() {
486         if (mBouncer.isShowing()) {
487             mStatusBar.endAffordanceLaunch();
488             reset(true /* hideBouncerWhenShowing */);
489             return true;
490         }
491         return false;
492     }
493 
isBouncerShowing()494     public boolean isBouncerShowing() {
495         return mBouncer.isShowing();
496     }
497 
getNavBarShowDelay()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 
updateStates()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      */
isNavBarVisible()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      */
getLastNavBarVisible()588     protected boolean getLastNavBarVisible() {
589         return (!(mLastShowing && !mLastOccluded) || mLastBouncerShowing || mLastRemoteInputActive)
590                 && !mLastDeferScrimFadeOut;
591     }
592 
shouldDismissOnMenuPressed()593     public boolean shouldDismissOnMenuPressed() {
594         return mBouncer.shouldDismissOnMenuPressed();
595     }
596 
interceptMediaKey(KeyEvent event)597     public boolean interceptMediaKey(KeyEvent event) {
598         return mBouncer.interceptMediaKey(event);
599     }
600 
readyForKeyguardDone()601     public void readyForKeyguardDone() {
602         mViewMediatorCallback.readyForKeyguardDone();
603     }
604 
shouldDisableWindowAnimationsForUnlock()605     public boolean shouldDisableWindowAnimationsForUnlock() {
606         return mStatusBar.isInLaunchTransition();
607     }
608 
isGoingToNotificationShade()609     public boolean isGoingToNotificationShade() {
610         return mStatusBar.isGoingToNotificationShade();
611     }
612 
isSecure(int userId)613     public boolean isSecure(int userId) {
614         return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
615     }
616 
keyguardGoingAway()617     public void keyguardGoingAway() {
618         mStatusBar.keyguardGoingAway();
619     }
620 
animateCollapsePanels(float speedUpFactor)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      */
notifyKeyguardAuthenticated(boolean strongAuth)630     public void notifyKeyguardAuthenticated(boolean strongAuth) {
631         mBouncer.notifyKeyguardAuthenticated(strongAuth);
632     }
633 
showBouncerMessage(String message, int color)634     public void showBouncerMessage(String message, int color) {
635         mBouncer.showMessage(message, color);
636     }
637 
getViewRootImpl()638     public ViewRootImpl getViewRootImpl() {
639         return mStatusBar.getStatusBarView().getViewRootImpl();
640     }
641 }
642