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