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