• 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.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
22 import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
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.Context;
27 import android.content.res.ColorStateList;
28 import android.hardware.biometrics.BiometricSourceType;
29 import android.os.Bundle;
30 import android.os.SystemClock;
31 import android.os.Trace;
32 import android.util.Log;
33 import android.view.KeyEvent;
34 import android.view.MotionEvent;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.view.ViewRootImpl;
38 import android.view.WindowInsetsController;
39 import android.window.BackEvent;
40 import android.window.OnBackAnimationCallback;
41 import android.window.OnBackInvokedDispatcher;
42 
43 import androidx.annotation.NonNull;
44 import androidx.annotation.Nullable;
45 import androidx.annotation.VisibleForTesting;
46 
47 import com.android.internal.util.LatencyTracker;
48 import com.android.internal.widget.LockPatternUtils;
49 import com.android.keyguard.KeyguardSecurityModel;
50 import com.android.keyguard.KeyguardUpdateMonitor;
51 import com.android.keyguard.KeyguardUpdateMonitorCallback;
52 import com.android.keyguard.KeyguardViewController;
53 import com.android.keyguard.TrustGrantFlags;
54 import com.android.keyguard.ViewMediatorCallback;
55 import com.android.systemui.DejankUtils;
56 import com.android.systemui.Flags;
57 import com.android.systemui.animation.back.FlingOnBackAnimationCallback;
58 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
59 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
60 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
61 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
62 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
63 import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags;
64 import com.android.systemui.bouncer.ui.BouncerView;
65 import com.android.systemui.bouncer.util.BouncerTestUtilsKt;
66 import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor;
67 import com.android.systemui.dagger.SysUISingleton;
68 import com.android.systemui.dagger.qualifiers.Main;
69 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
70 import com.android.systemui.dock.DockManager;
71 import com.android.systemui.dreams.DreamOverlayStateController;
72 import com.android.systemui.keyguard.DismissCallbackRegistry;
73 import com.android.systemui.keyguard.KeyguardWmStateRefactor;
74 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor;
75 import com.android.systemui.keyguard.domain.interactor.KeyguardDismissTransitionInteractor;
76 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
77 import com.android.systemui.keyguard.shared.model.DismissAction;
78 import com.android.systemui.keyguard.shared.model.KeyguardDone;
79 import com.android.systemui.keyguard.shared.model.TransitionStep;
80 import com.android.systemui.navigationbar.NavigationModeController;
81 import com.android.systemui.navigationbar.TaskbarDelegate;
82 import com.android.systemui.navigationbar.views.NavigationBarView;
83 import com.android.systemui.plugins.ActivityStarter;
84 import com.android.systemui.plugins.statusbar.StatusBarStateController;
85 import com.android.systemui.scene.domain.interactor.SceneInteractor;
86 import com.android.systemui.scene.shared.flag.SceneContainerFlag;
87 import com.android.systemui.scene.shared.model.Overlays;
88 import com.android.systemui.shade.ShadeController;
89 import com.android.systemui.shade.ShadeExpansionChangeEvent;
90 import com.android.systemui.shade.ShadeExpansionListener;
91 import com.android.systemui.shade.ShadeExpansionStateManager;
92 import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor;
93 import com.android.systemui.shared.system.QuickStepContract;
94 import com.android.systemui.shared.system.SysUiStatsLog;
95 import com.android.systemui.statusbar.NotificationShadeWindowController;
96 import com.android.systemui.statusbar.RemoteInputController;
97 import com.android.systemui.statusbar.StatusBarState;
98 import com.android.systemui.statusbar.SysuiStatusBarStateController;
99 import com.android.systemui.statusbar.domain.interactor.StatusBarKeyguardViewManagerInteractor;
100 import com.android.systemui.statusbar.policy.ConfigurationController;
101 import com.android.systemui.statusbar.policy.KeyguardStateController;
102 import com.android.systemui.unfold.FoldAodAnimationController;
103 import com.android.systemui.unfold.SysUIUnfoldComponent;
104 import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
105 import com.android.systemui.util.concurrency.DelayableExecutor;
106 import com.android.systemui.util.kotlin.JavaAdapter;
107 
108 import dagger.Lazy;
109 
110 import kotlin.Unit;
111 
112 import kotlinx.coroutines.CoroutineDispatcher;
113 import kotlinx.coroutines.Job;
114 
115 import java.io.PrintWriter;
116 import java.io.StringWriter;
117 import java.util.ArrayList;
118 import java.util.HashSet;
119 import java.util.Objects;
120 import java.util.Optional;
121 import java.util.Set;
122 
123 import javax.inject.Inject;
124 
125 /**
126  * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
127  * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
128  * which is in turn, reported to this class by the current
129  * {@link com.android.keyguard.KeyguardViewController}.
130  */
131 @SysUISingleton
132 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
133         StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
134         ShadeExpansionListener, NavigationModeController.ModeChangedListener,
135         KeyguardViewController, FoldAodAnimationController.FoldAodAnimationStatus {
136 
137     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
138     private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
139 
140     // Delay for showing the navigation bar when the bouncer appears. This should be kept in sync
141     // with the appear animations of the PIN/pattern/password views.
142     private static final long NAV_BAR_SHOW_DELAY_BOUNCER = 320;
143 
144     // The duration to fade the nav bar content in/out when the device starts to sleep
145     private static final long NAV_BAR_CONTENT_FADE_DURATION = 125;
146 
147     // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to
148     // make everything a bit slower to bridge a gap until the user is unlocked and home screen has
149     // dranw its first frame.
150     private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
151 
152     private static final String TAG = "StatusBarKeyguardViewManager";
153     private static final boolean DEBUG = false;
154 
155     protected final Context mContext;
156     private final ConfigurationController mConfigurationController;
157     private final NavigationModeController mNavigationModeController;
158     private final NotificationShadeWindowController mNotificationShadeWindowController;
159     private final DreamOverlayStateController mDreamOverlayStateController;
160     @Nullable
161     private final FoldAodAnimationController mFoldAodAnimationController;
162     private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
163     private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
164     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
165     private final Lazy<BouncerInteractor> mBouncerInteractor;
166     private final BouncerView mPrimaryBouncerView;
167     private final Lazy<ShadeController> mShadeController;
168     private final Lazy<SceneInteractor> mSceneInteractorLazy;
169     private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractorLazy;
170     private final DismissCallbackRegistry mDismissCallbackRegistry;
171     private final CommunalSceneInteractor mCommunalSceneInteractor;
172 
173     private Job mListenForAlternateBouncerTransitionSteps = null;
174     private Job mListenForKeyguardAuthenticatedBiometricsHandled = null;
175     private Job mListenForCanShowAlternateBouncer = null;
176 
177     // Local cache of expansion events, to avoid duplicates
178     private float mFraction = -1f;
179     private boolean mTracking = false;
180     private boolean mBouncerShowingOverDream;
181     private int mAttemptsToShowBouncer = 0;
182     private DelayableExecutor mExecutor;
183     private boolean mIsSleeping = false;
184 
185     private final PrimaryBouncerExpansionCallback mExpansionCallback =
186             new PrimaryBouncerExpansionCallback() {
187             private boolean mPrimaryBouncerAnimating;
188 
189             @Override
190             public void onFullyShown() {
191                 mPrimaryBouncerAnimating = false;
192                 updateStates();
193             }
194 
195             @Override
196             public void onStartingToHide() {
197                 mPrimaryBouncerAnimating = true;
198                 updateStates();
199             }
200 
201             @Override
202             public void onStartingToShow() {
203                 mPrimaryBouncerAnimating = true;
204                 updateStates();
205             }
206 
207             @Override
208             public void onFullyHidden() {
209                 mPrimaryBouncerAnimating = false;
210                 updateStates();
211             }
212 
213             @Override
214             public void onExpansionChanged(float expansion) {
215                 if (mPrimaryBouncerAnimating) {
216                     mCentralSurfaces.setPrimaryBouncerHiddenFraction(expansion);
217                 }
218             }
219 
220             @Override
221             public void onVisibilityChanged(boolean isVisible) {
222                 mBouncerShowingOverDream =
223                         isVisible && mDreamOverlayStateController.isOverlayActive();
224 
225                 if (!isVisible) {
226                     mCentralSurfaces.setPrimaryBouncerHiddenFraction(EXPANSION_HIDDEN);
227                 }
228 
229                 /* Register predictive back callback when keyguard becomes visible, and unregister
230                 when it's hidden. */
231                 if (isVisible) {
232                     registerBackCallback();
233                 } else {
234                     unregisterBackCallback();
235                 }
236             }
237     };
238 
239     private final OnBackAnimationCallback mOnBackInvokedCallback =
240             new FlingOnBackAnimationCallback() {
241         @Override
242         public void onBackInvokedCompat() {
243             if (DEBUG) {
244                 Log.d(TAG, "onBackInvokedCallback() called, invoking onBackPressed()");
245             }
246             onBackPressed();
247             if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
248                 mPrimaryBouncerView.getDelegate().getBackCallback().onBackInvoked();
249             }
250         }
251 
252         @Override
253         public void onBackProgressedCompat(@NonNull BackEvent event) {
254             if (ComposeBouncerFlags.INSTANCE.isOnlyComposeBouncerEnabled()) {
255                 mBouncerInteractor.get().onBackEventProgressed(event.getProgress());
256             }
257             if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
258                 mPrimaryBouncerView.getDelegate().getBackCallback().onBackProgressed(event);
259             }
260         }
261 
262         @Override
263         public void onBackCancelledCompat() {
264             if (ComposeBouncerFlags.INSTANCE.isOnlyComposeBouncerEnabled()) {
265                 mBouncerInteractor.get().onBackEventCancelled();
266             }
267             if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
268                 mPrimaryBouncerView.getDelegate().getBackCallback().onBackCancelled();
269             }
270         }
271 
272         @Override
273         public void onBackStartedCompat(@NonNull BackEvent event) {
274             if (shouldPlayBackAnimation() && mPrimaryBouncerView.getDelegate() != null) {
275                 mPrimaryBouncerView.getDelegate().getBackCallback().onBackStarted(event);
276             }
277         }
278     };
279     private boolean mIsBackCallbackRegistered = false;
280 
281     private final DockManager.DockEventListener mDockEventListener =
282             new DockManager.DockEventListener() {
283                 @Override
284                 public void onEvent(int event) {
285                     boolean isDocked = mDockManager.isDocked();
286             if (isDocked == mIsDocked) {
287                 return;
288             }
289             mIsDocked = isDocked;
290             updateStates();
291         }
292     };
293 
294     protected LockPatternUtils mLockPatternUtils;
295     protected ViewMediatorCallback mViewMediatorCallback;
296     @Nullable protected CentralSurfaces mCentralSurfaces;
297     private ShadeLockscreenInteractor mShadeLockscreenInteractor;
298     private BiometricUnlockController mBiometricUnlockController;
299     private boolean mCentralSurfacesRegistered;
300 
301     private View mNotificationContainer;
302 
303     protected boolean mRemoteInputActive;
304     private boolean mGlobalActionsVisible = false;
305     private boolean mLastGlobalActionsVisible = false;
306     private boolean mDozing;
307     private boolean mPulsing;
308     private boolean mGesturalNav;
309     private boolean mIsDocked;
310     private boolean mScreenOffAnimationPlaying;
311 
312     protected boolean mFirstUpdate = true;
313     protected boolean mLastShowing;
314     protected boolean mLastOccluded;
315     private boolean mLastPrimaryBouncerShowing;
316     private boolean mLastPrimaryBouncerIsOrWillBeShowing;
317     private boolean mLastBouncerDismissible;
318     protected boolean mLastRemoteInputActive;
319     private boolean mLastDozing;
320     private boolean mLastGesturalNav;
321     private boolean mLastIsDocked;
322     private boolean mLastPulsing;
323     private int mLastBiometricMode;
324     private boolean mLastScreenOffAnimationPlaying;
325     private float mQsExpansion;
326 
327     final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
328     private final ActivityStarter mActivityStarter;
329 
330     private OnDismissAction mAfterKeyguardGoneAction;
331     private Runnable mKeyguardGoneCancelAction;
332     private boolean mDismissActionWillAnimateOnKeyguard;
333     private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
334 
335     // Dismiss action to be launched when we stop dozing or the keyguard is gone.
336     private DismissWithActionRequest mPendingWakeupAction;
337     private final KeyguardStateController mKeyguardStateController;
338     private final SysuiStatusBarStateController mStatusBarStateController;
339     private final DockManager mDockManager;
340     private final KeyguardUpdateMonitor mKeyguardUpdateManager;
341     private final LatencyTracker mLatencyTracker;
342     private final KeyguardSecurityModel mKeyguardSecurityModel;
343     private final SelectedUserInteractor mSelectedUserInteractor;
344     @Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
345 
346     @Nullable private TaskbarDelegate mTaskbarDelegate;
347     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
348             new KeyguardUpdateMonitorCallback() {
349                 @Override
350                 public void onTrustGrantedForCurrentUser(
351                         boolean dismissKeyguard,
352                         boolean newlyUnlocked,
353                         @NonNull TrustGrantFlags flags,
354                         @Nullable String message
355                 ) {
356                     updateAlternateBouncerShowing(mAlternateBouncerInteractor.maybeHide());
357                 }
358 
359         @Override
360         public void onEmergencyCallAction() {
361             // Since we won't get a setOccluded call we have to reset the view manually such that
362             // the bouncer goes away.
363             if (mKeyguardStateController.isOccluded()) {
364                 reset(true /* hideBouncerWhenShowing */);
365             }
366         }
367     };
368     private Lazy<KeyguardDismissActionInteractor> mKeyguardDismissActionInteractor;
369     private final JavaAdapter mJavaAdapter;
370     private StatusBarKeyguardViewManagerInteractor mStatusBarKeyguardViewManagerInteractor;
371 
372     @Inject
StatusBarKeyguardViewManager( Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils, SysuiStatusBarStateController sysuiStatusBarStateController, ConfigurationController configurationController, KeyguardUpdateMonitor keyguardUpdateMonitor, DreamOverlayStateController dreamOverlayStateController, NavigationModeController navigationModeController, DockManager dockManager, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Optional<SysUIUnfoldComponent> sysUIUnfoldComponent, Lazy<ShadeController> shadeController, LatencyTracker latencyTracker, KeyguardSecurityModel keyguardSecurityModel, PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor, PrimaryBouncerInteractor primaryBouncerInteractor, BouncerView primaryBouncerView, AlternateBouncerInteractor alternateBouncerInteractor, ActivityStarter activityStarter, KeyguardTransitionInteractor keyguardTransitionInteractor, KeyguardDismissTransitionInteractor keyguardDismissTransitionInteractor, @Main CoroutineDispatcher mainDispatcher, Lazy<KeyguardDismissActionInteractor> keyguardDismissActionInteractorLazy, SelectedUserInteractor selectedUserInteractor, JavaAdapter javaAdapter, Lazy<SceneInteractor> sceneInteractorLazy, StatusBarKeyguardViewManagerInteractor statusBarKeyguardViewManagerInteractor, @Main DelayableExecutor executor, Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy, DismissCallbackRegistry dismissCallbackRegistry, Lazy<BouncerInteractor> bouncerInteractor, CommunalSceneInteractor communalSceneInteractor )373     public StatusBarKeyguardViewManager(
374             Context context,
375             ViewMediatorCallback callback,
376             LockPatternUtils lockPatternUtils,
377             SysuiStatusBarStateController sysuiStatusBarStateController,
378             ConfigurationController configurationController,
379             KeyguardUpdateMonitor keyguardUpdateMonitor,
380             DreamOverlayStateController dreamOverlayStateController,
381             NavigationModeController navigationModeController,
382             DockManager dockManager,
383             NotificationShadeWindowController notificationShadeWindowController,
384             KeyguardStateController keyguardStateController,
385             Optional<SysUIUnfoldComponent> sysUIUnfoldComponent,
386             Lazy<ShadeController> shadeController,
387             LatencyTracker latencyTracker,
388             KeyguardSecurityModel keyguardSecurityModel,
389             PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
390             PrimaryBouncerInteractor primaryBouncerInteractor,
391             BouncerView primaryBouncerView,
392             AlternateBouncerInteractor alternateBouncerInteractor,
393             ActivityStarter activityStarter,
394             KeyguardTransitionInteractor keyguardTransitionInteractor,
395             KeyguardDismissTransitionInteractor keyguardDismissTransitionInteractor,
396             @Main CoroutineDispatcher mainDispatcher,
397             Lazy<KeyguardDismissActionInteractor> keyguardDismissActionInteractorLazy,
398             SelectedUserInteractor selectedUserInteractor,
399             JavaAdapter javaAdapter,
400             Lazy<SceneInteractor> sceneInteractorLazy,
401             StatusBarKeyguardViewManagerInteractor statusBarKeyguardViewManagerInteractor,
402             @Main DelayableExecutor executor,
403             Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy,
404             DismissCallbackRegistry dismissCallbackRegistry,
405             Lazy<BouncerInteractor> bouncerInteractor,
406             CommunalSceneInteractor communalSceneInteractor
407     ) {
408         mContext = context;
409         mExecutor = executor;
410         mViewMediatorCallback = callback;
411         mLockPatternUtils = lockPatternUtils;
412         mConfigurationController = configurationController;
413         mNavigationModeController = navigationModeController;
414         mNotificationShadeWindowController = notificationShadeWindowController;
415         mDreamOverlayStateController = dreamOverlayStateController;
416         mKeyguardStateController = keyguardStateController;
417         mKeyguardUpdateManager = keyguardUpdateMonitor;
418         mStatusBarStateController = sysuiStatusBarStateController;
419         mDockManager = dockManager;
420         mShadeController = shadeController;
421         mLatencyTracker = latencyTracker;
422         mKeyguardSecurityModel = keyguardSecurityModel;
423         mPrimaryBouncerCallbackInteractor = primaryBouncerCallbackInteractor;
424         mPrimaryBouncerInteractor = primaryBouncerInteractor;
425         mPrimaryBouncerView = primaryBouncerView;
426         mFoldAodAnimationController = sysUIUnfoldComponent
427                 .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
428         mAlternateBouncerInteractor = alternateBouncerInteractor;
429         mBouncerInteractor = bouncerInteractor;
430         mActivityStarter = activityStarter;
431         mKeyguardTransitionInteractor = keyguardTransitionInteractor;
432         mKeyguardDismissTransitionInteractor = keyguardDismissTransitionInteractor;
433         mMainDispatcher = mainDispatcher;
434         mKeyguardDismissActionInteractor = keyguardDismissActionInteractorLazy;
435         mSelectedUserInteractor = selectedUserInteractor;
436         mJavaAdapter = javaAdapter;
437         mSceneInteractorLazy = sceneInteractorLazy;
438         mStatusBarKeyguardViewManagerInteractor = statusBarKeyguardViewManagerInteractor;
439         mDeviceEntryInteractorLazy = deviceEntryInteractorLazy;
440         mDismissCallbackRegistry = dismissCallbackRegistry;
441         mCommunalSceneInteractor = communalSceneInteractor;
442     }
443 
444     KeyguardTransitionInteractor mKeyguardTransitionInteractor;
445     KeyguardDismissTransitionInteractor mKeyguardDismissTransitionInteractor;
446     CoroutineDispatcher mMainDispatcher;
447 
448     @Override
registerCentralSurfaces(CentralSurfaces centralSurfaces, ShadeLockscreenInteractor shadeLockscreenInteractor, ShadeExpansionStateManager shadeExpansionStateManager, BiometricUnlockController biometricUnlockController, View notificationContainer)449     public void registerCentralSurfaces(CentralSurfaces centralSurfaces,
450             ShadeLockscreenInteractor shadeLockscreenInteractor,
451             ShadeExpansionStateManager shadeExpansionStateManager,
452             BiometricUnlockController biometricUnlockController,
453             View notificationContainer) {
454         mCentralSurfaces = centralSurfaces;
455         mBiometricUnlockController = biometricUnlockController;
456 
457         mPrimaryBouncerCallbackInteractor.addBouncerExpansionCallback(mExpansionCallback);
458         mShadeLockscreenInteractor = shadeLockscreenInteractor;
459         if (shadeExpansionStateManager != null) {
460             ShadeExpansionChangeEvent currentState =
461                     shadeExpansionStateManager.addExpansionListener(this);
462             onPanelExpansionChanged(currentState);
463         }
464         mNotificationContainer = notificationContainer;
465         mCentralSurfacesRegistered = true;
466 
467         registerListeners();
468     }
469 
470 
471     /**
472      * Sets the given OccludingAppBiometricUI to null if it's the current auth interceptor. Else,
473      * does nothing.
474      */
removeOccludingAppBiometricUI(@onNull OccludingAppBiometricUI biometricUI)475     public void removeOccludingAppBiometricUI(@NonNull OccludingAppBiometricUI biometricUI) {
476         if (Objects.equals(mOccludingAppBiometricUI, biometricUI)) {
477             mOccludingAppBiometricUI = null;
478         }
479     }
480 
481     /**
482      * Sets a new OccludingAppBiometricUI.
483      */
setOccludingAppBiometricUI(@onNull OccludingAppBiometricUI biometricUI)484     public void setOccludingAppBiometricUI(@NonNull OccludingAppBiometricUI biometricUI) {
485         if (!Objects.equals(mOccludingAppBiometricUI, biometricUI)) {
486             mOccludingAppBiometricUI = biometricUI;
487         }
488     }
489 
registerListeners()490     private void registerListeners() {
491         mKeyguardUpdateManager.registerCallback(mUpdateMonitorCallback);
492         mStatusBarStateController.addCallback(this);
493         mConfigurationController.addCallback(this);
494         mGesturalNav = QuickStepContract.isGesturalMode(
495                 mNavigationModeController.addListener(this));
496         if (mFoldAodAnimationController != null) {
497             mFoldAodAnimationController.addCallback(this);
498         }
499         if (mDockManager != null) {
500             mDockManager.addListener(mDockEventListener);
501             mIsDocked = mDockManager.isDocked();
502         }
503         if (mListenForAlternateBouncerTransitionSteps != null) {
504             mListenForAlternateBouncerTransitionSteps.cancel(null);
505         }
506         mListenForAlternateBouncerTransitionSteps = null;
507         if (mListenForKeyguardAuthenticatedBiometricsHandled != null) {
508             mListenForKeyguardAuthenticatedBiometricsHandled.cancel(null);
509         }
510         mListenForKeyguardAuthenticatedBiometricsHandled = null;
511         if (mListenForCanShowAlternateBouncer != null) {
512             mListenForCanShowAlternateBouncer.cancel(null);
513         }
514         mListenForCanShowAlternateBouncer = null;
515 
516         // Collector that keeps the AlternateBouncerInteractor#canShowAlternateBouncer flow hot.
517         mListenForCanShowAlternateBouncer = mJavaAdapter.alwaysCollectFlow(
518                 mAlternateBouncerInteractor.getCanShowAlternateBouncer(),
519                 this::consumeCanShowAlternateBouncer
520         );
521 
522         if (KeyguardWmStateRefactor.isEnabled()) {
523             // Show the keyguard views whenever we've told WM that the lockscreen is visible.
524             mJavaAdapter.alwaysCollectFlow(
525                     mStatusBarKeyguardViewManagerInteractor.getKeyguardViewVisibility(),
526                     this::consumeShowStatusBarKeyguardView);
527 
528             mJavaAdapter.alwaysCollectFlow(
529                     mStatusBarKeyguardViewManagerInteractor.getKeyguardViewOcclusionState(),
530                     (occlusionState) -> setOccluded(
531                             occlusionState.getOccluded(), occlusionState.getAnimate()));
532         }
533     }
534 
535     @VisibleForTesting
consumeFromAlternateBouncerTransitionSteps(TransitionStep step)536     void consumeFromAlternateBouncerTransitionSteps(TransitionStep step) {
537         SceneContainerFlag.assertInLegacyMode();
538         hideAlternateBouncer(false);
539     }
540 
541     /**
542      * Required without fix for b/328643370: missing AlternateBouncer (when occluded) => Gone
543      * transition.
544      */
545     @VisibleForTesting
consumeKeyguardAuthenticatedBiometricsHandled(Unit handled)546     void consumeKeyguardAuthenticatedBiometricsHandled(Unit handled) {
547         SceneContainerFlag.assertInLegacyMode();
548         if (mAlternateBouncerInteractor.isVisibleState()) {
549             hideAlternateBouncer(false);
550         }
551     }
552 
consumeShowStatusBarKeyguardView(boolean show)553     private void consumeShowStatusBarKeyguardView(boolean show) {
554         if (show != mLastShowing) {
555             if (show) {
556                 show(null);
557             } else {
558                 hide(0, 0);
559             }
560         }
561     }
562 
consumeCanShowAlternateBouncer(boolean canShow)563     private void consumeCanShowAlternateBouncer(boolean canShow) {
564         if (SceneContainerFlag.isEnabled()) {
565             // When the scene framework is enabled, the alternative bouncer is hidden from the scene
566             // framework logic so there's no need for this logic here.
567             return;
568         }
569 
570         // Hack: this is required to fix issues where
571         // KeyguardBouncerRepository#alternateBouncerVisible state is incorrectly set and then never
572         // reset. This is caused by usages of show()/forceShow() that only read this flow to set the
573         // alternate bouncer visible state, if there is a race condition between when that flow
574         // changes to false and when the read happens, the flow will be set to an incorrect value
575         // and not reset on time.
576         if (!canShow) {
577             Log.d(TAG, "canShowAlternateBouncer turned false, maybe try hiding the alternate "
578                     + "bouncer if it is already visible");
579             mAlternateBouncerInteractor.maybeHide();
580         }
581     }
582 
583     /** Register a callback, to be invoked by the Predictive Back system. */
registerBackCallback()584     private void registerBackCallback() {
585         if (!mIsBackCallbackRegistered) {
586             ViewRootImpl viewRoot = getViewRootImpl();
587             if (viewRoot != null) {
588                 viewRoot.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
589                         OnBackInvokedDispatcher.PRIORITY_DEFAULT, mOnBackInvokedCallback);
590                 mIsBackCallbackRegistered = true;
591             } else {
592                 if (DEBUG) {
593                     Log.d(TAG, "view root was null, could not register back callback");
594                 }
595             }
596         } else {
597             if (DEBUG) {
598                 Log.d(TAG, "prevented registering back callback twice");
599             }
600         }
601     }
602 
603     /** Unregister the callback formerly registered with the Predictive Back system. */
unregisterBackCallback()604     private void unregisterBackCallback() {
605         if (mIsBackCallbackRegistered) {
606             ViewRootImpl viewRoot = getViewRootImpl();
607             if (viewRoot != null) {
608                 viewRoot.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(
609                         mOnBackInvokedCallback);
610                 mIsBackCallbackRegistered = false;
611             } else {
612                 if (DEBUG) {
613                     Log.d(TAG, "view root was null, could not unregister back callback");
614                 }
615             }
616         } else {
617             if (DEBUG) {
618                 Log.d(TAG, "prevented unregistering back callback twice");
619             }
620         }
621     }
622 
shouldPlayBackAnimation()623     private boolean shouldPlayBackAnimation() {
624         // Suppress back animation when bouncer shouldn't be dismissed on back invocation.
625         return !needsFullscreenBouncer();
626     }
627 
628     @Override
onDensityOrFontScaleChanged()629     public void onDensityOrFontScaleChanged() {
630         hideBouncer(true /* destroyView */);
631     }
632 
beginShowingBouncer(ShadeExpansionChangeEvent event)633     private boolean beginShowingBouncer(ShadeExpansionChangeEvent event) {
634         // Avoid having the shade and the bouncer open at the same time over a dream.
635         final boolean hideBouncerOverDream =
636                 mDreamOverlayStateController.isOverlayActive()
637                         && (mShadeLockscreenInteractor.isExpanded()
638                         || mShadeController.get().isExpandingOrCollapsing());
639 
640         final boolean isUserTrackingStarted =
641                 event.getFraction() != EXPANSION_HIDDEN && event.getTracking();
642 
643         return mKeyguardStateController.isShowing()
644                 && !primaryBouncerIsOrWillBeShowing()
645                 && !mKeyguardStateController.isKeyguardGoingAway()
646                 && isUserTrackingStarted
647                 && !hideBouncerOverDream
648                 && !mKeyguardStateController.isOccluded()
649                 && !mKeyguardStateController.canDismissLockScreen()
650                 && !bouncerIsAnimatingAway()
651                 && !(mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED);
652     }
653 
654     @Override
onPanelExpansionChanged(ShadeExpansionChangeEvent event)655     public void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
656         float fraction = event.getFraction();
657         boolean tracking = event.getTracking();
658 
659         if (mFraction == fraction && mTracking == tracking) {
660             // Ignore duplicate events, as they will cause confusion with bouncer expansion
661             return;
662         }
663         mFraction = fraction;
664         mTracking = tracking;
665 
666         /*
667          * The bouncer may have received a call to show(), or the following will infer it from
668          * device state and touch handling. The bouncer MUST have been notified that it is about to
669          * show if any subsequent events are to be handled.
670          */
671         if (!SceneContainerFlag.isEnabled() && beginShowingBouncer(event)) {
672             mPrimaryBouncerInteractor.show(/* isScrimmed= */false,
673                     TAG + "#onPanelExpansionChanged");
674         }
675 
676         if (!primaryBouncerIsOrWillBeShowing()) {
677             return;
678         }
679 
680         if (mKeyguardStateController.isShowing()) {
681             mPrimaryBouncerInteractor.setPanelExpansion(fraction);
682         } else {
683             mPrimaryBouncerInteractor.setPanelExpansion(EXPANSION_HIDDEN);
684         }
685     }
686 
687     /**
688      * Update the global actions visibility state in order to show the navBar when active.
689      */
setGlobalActionsVisible(boolean isVisible)690     public void setGlobalActionsVisible(boolean isVisible) {
691         mGlobalActionsVisible = isVisible;
692         updateStates();
693     }
694 
setTaskbarDelegate(TaskbarDelegate taskbarDelegate)695     public void setTaskbarDelegate(TaskbarDelegate taskbarDelegate) {
696         mTaskbarDelegate = taskbarDelegate;
697     }
698 
699     /**
700      * Show the keyguard.  Will handle creating and attaching to the view manager
701      * lazily.
702      */
703     @Override
show(Bundle options)704     public void show(Bundle options) {
705         Trace.beginSection("StatusBarKeyguardViewManager#show");
706         mNotificationShadeWindowController.setKeyguardShowing(true);
707         mKeyguardStateController.notifyKeyguardState(true, mKeyguardStateController.isOccluded());
708         reset(true /* hideBouncerWhenShowing */);
709         SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
710                 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
711         Trace.endSection();
712     }
713 
714     /**
715      * Shows the notification keyguard or the bouncer depending on
716      * {@link #needsFullscreenBouncer()}.
717      */
showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset, String reason)718     protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset,
719             String reason) {
720         boolean showBouncer = needsFullscreenBouncer() && !mDozing;
721         if (Flags.simPinRaceConditionOnRestart()) {
722             showBouncer = showBouncer && !mIsSleeping;
723         }
724         if (showBouncer) {
725             // The keyguard might be showing (already). So we need to hide it.
726             if (!primaryBouncerIsShowing()) {
727                 if (SceneContainerFlag.isEnabled()) {
728                     mCentralSurfaces.hideKeyguard();
729                     mSceneInteractorLazy.get().showOverlay(
730                             Overlays.Bouncer,
731                             TAG + "#showBouncerOrKeyguard"
732                     );
733                 } else {
734                     if (Flags.simPinRaceConditionOnRestart()) {
735                         if (mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, reason)) {
736                             mAttemptsToShowBouncer = 0;
737                             mCentralSurfaces.hideKeyguard();
738                         } else {
739                             if (mAttemptsToShowBouncer > 6) {
740                                 mAttemptsToShowBouncer = 0;
741                                 Log.e(TAG, "Too many failed attempts to show bouncer, showing "
742                                         + "keyguard instead");
743                                 mCentralSurfaces.showKeyguard();
744                             } else {
745                                 Log.v(TAG, "Failed to show bouncer, attempt #: "
746                                         + mAttemptsToShowBouncer++);
747                                 mExecutor.executeDelayed(() ->
748                                         showBouncerOrKeyguard(hideBouncerWhenShowing,
749                                             isFalsingReset, reason),
750                                         500);
751                             }
752                         }
753                     } else {
754                         mCentralSurfaces.hideKeyguard();
755                         mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, reason);
756                     }
757                 }
758             } else if (!isFalsingReset) {
759                 // Falsing resets can cause this to flicker, so don't reset in this case
760                 Log.i(TAG, "Sim bouncer is already showing, issuing a refresh");
761                 mPrimaryBouncerInteractor.show(/* isScrimmed= */ true, reason);
762 
763             }
764         } else {
765             mCentralSurfaces.showKeyguard();
766             if (hideBouncerWhenShowing) {
767                 hideBouncer(false /* destroyView */);
768             }
769         }
770         updateStates();
771     }
772 
773     /**
774      *
775      * If possible, shows the alternate bouncer. Else, shows the primary (pin/pattern/password)
776      * bouncer.
777      * @param scrimmed true when the primary bouncer should show scrimmed,
778      *                 false when the user will be dragging it and translation should be deferred
779      *                 {@see KeyguardBouncer#show(boolean, boolean)}
780      */
showBouncer(boolean scrimmed, String reason)781     public void showBouncer(boolean scrimmed, String reason) {
782         if (SceneContainerFlag.isEnabled()) {
783             mDeviceEntryInteractorLazy.get().attemptDeviceEntry();
784             return;
785         }
786 
787         if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) {
788             Log.d(TAG, "showBouncer:alternateBouncer.forceShow()");
789             mAlternateBouncerInteractor.forceShow();
790             updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
791         } else {
792             showPrimaryBouncer(scrimmed, reason);
793         }
794     }
795 
796     /**
797      * Hides the input bouncer (pin/password/pattern).
798      */
799     @VisibleForTesting
hideBouncer(boolean destroyView)800     void hideBouncer(boolean destroyView) {
801         mPrimaryBouncerInteractor.hide();
802         if (mKeyguardStateController.isShowing()) {
803             // If we were showing the bouncer and then aborting, we need to also clear out any
804             // potential actions unless we actually unlocked.
805             cancelPostAuthActions();
806         }
807         cancelPendingWakeupAction();
808     }
809 
810     /**
811      * Shows the primary bouncer - the pin/pattern/password challenge on the lock screen.
812      *
813      * @param scrimmed true when the bouncer should show scrimmed, false when the user will be
814      * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
815      * @param reason string description for what is causing the bouncer to be requested
816      */
817     @Override
showPrimaryBouncer(boolean scrimmed, String reason)818     public void showPrimaryBouncer(boolean scrimmed, String reason) {
819         hideAlternateBouncer(
820                 /* updateScrim= */ false,
821                 // When the scene framework is on, don't ever clear the pending dismiss action from
822                 /* clearDismissAction= */ !SceneContainerFlag.isEnabled());
823         if (mKeyguardStateController.isShowing() && !isBouncerShowing()) {
824             if (SceneContainerFlag.isEnabled()) {
825                 mSceneInteractorLazy.get().showOverlay(
826                         Overlays.Bouncer,
827                         "primary bouncer requested"
828                 );
829             } else {
830                 mPrimaryBouncerInteractor.show(scrimmed, reason);
831             }
832         }
833         updateStates();
834     }
835 
dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone)836     public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
837             boolean afterKeyguardGone) {
838         dismissWithAction(r, cancelAction, afterKeyguardGone, null /* message */);
839     }
840 
dismissWithAction(OnDismissAction r, Runnable cancelAction, boolean afterKeyguardGone, String message)841     public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
842             boolean afterKeyguardGone, String message) {
843         if (ComposeBouncerFlags.INSTANCE.isEnabled()) {
844             if (r == null) {
845                 return;
846             }
847             Trace.beginSection("StatusBarKeyguardViewManager#interactorDismissWithAction");
848             if (afterKeyguardGone) {
849                 mKeyguardDismissActionInteractor.get().setDismissAction(
850                         new DismissAction.RunAfterKeyguardGone(
851                                 () -> {
852                                     r.onDismiss();
853                                     return null;
854                                 },
855                                 (cancelAction != null) ? cancelAction : () -> {},
856                                 message == null ? "" : message,
857                                 r.willRunAnimationOnKeyguard()
858                         )
859                 );
860             } else {
861                 mKeyguardDismissActionInteractor.get().setDismissAction(
862                         new DismissAction.RunImmediately(
863                                 () -> {
864                                     if (r.onDismiss()) {
865                                         return KeyguardDone.LATER;
866                                     } else {
867                                         return KeyguardDone.IMMEDIATE;
868                                     }
869                                 },
870                                 (cancelAction != null) ? cancelAction : () -> {},
871                                 message == null ? "" : message,
872                                 r.willRunAnimationOnKeyguard()
873                         )
874                 );
875             }
876 
877             showBouncer(true, TAG + "#dismissWithAction");
878             Trace.endSection();
879             return;
880         }
881 
882         if (mKeyguardStateController.isShowing()) {
883             try {
884                 Trace.beginSection("StatusBarKeyguardViewManager#dismissWithAction");
885                 cancelPendingWakeupAction();
886                 // If we're dozing, this needs to be delayed until after we wake up - unless we're
887                 // wake-and-unlocking, because there dozing will last until the end of the
888                 // transition.
889                 if (mDozing && !isWakeAndUnlocking()) {
890                     mPendingWakeupAction = new DismissWithActionRequest(
891                             r, cancelAction, afterKeyguardGone, message);
892                     return;
893                 }
894 
895                 if (!ComposeBouncerFlags.INSTANCE.isEnabled()) {
896                     mAfterKeyguardGoneAction = r;
897                     mKeyguardGoneCancelAction = cancelAction;
898                     mDismissActionWillAnimateOnKeyguard = r != null
899                             && r.willRunAnimationOnKeyguard();
900                 }
901 
902                 // If there is an alternate auth interceptor (like the UDFPS), show that one
903                 // instead of the bouncer.
904                 if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) {
905                     if (!afterKeyguardGone) {
906                         mPrimaryBouncerInteractor.setDismissAction(mAfterKeyguardGoneAction,
907                                 mKeyguardGoneCancelAction);
908                         mAfterKeyguardGoneAction = null;
909                         mKeyguardGoneCancelAction = null;
910                     }
911 
912                     Log.d(TAG, "dismissWithAction:alternateBouncer.forceShow()");
913                     mAlternateBouncerInteractor.forceShow();
914                     updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
915                     setKeyguardMessage(message, null, null);
916                     return;
917                 }
918 
919                 mViewMediatorCallback.setCustomMessage(message);
920                 if (afterKeyguardGone) {
921                     // we'll handle the dismiss action after keyguard is gone, so just show the
922                     // bouncer
923                     if (SceneContainerFlag.isEnabled()) {
924                         mSceneInteractorLazy.get().showOverlay(
925                                 Overlays.Bouncer,
926                                 TAG + "#dismissWithAction"
927                         );
928                     } else {
929                         mPrimaryBouncerInteractor.show(/* isScrimmed= */ true,
930                                 TAG + "#dismissWithAction, afterKeyguardGone");
931                     }
932                 } else {
933                     // after authentication success, run dismiss action with the option to defer
934                     // hiding the keyguard based on the return value of the OnDismissAction
935                     mPrimaryBouncerInteractor.setDismissAction(
936                             mAfterKeyguardGoneAction, mKeyguardGoneCancelAction);
937                     if (SceneContainerFlag.isEnabled()) {
938                         mSceneInteractorLazy.get().showOverlay(
939                                 Overlays.Bouncer,
940                                 TAG + "#dismissWithAction"
941                         );
942                     } else {
943                         mPrimaryBouncerInteractor.show(/* isScrimmed= */ true,
944                                 TAG + "#dismissWithAction");
945                     }
946                     // bouncer will handle the dismiss action, so we no longer need to track it here
947                     mAfterKeyguardGoneAction = null;
948                     mKeyguardGoneCancelAction = null;
949                 }
950             } finally {
951                 Trace.endSection();
952             }
953         } else {
954             Log.w(TAG, "Ignoring request to dismiss, dumping state: ");
955             StringWriter sw = new StringWriter();
956             mKeyguardStateController.dump(new PrintWriter(sw), null);
957             Log.w(TAG, sw.toString());
958         }
959         updateStates();
960     }
961 
isWakeAndUnlocking()962     private boolean isWakeAndUnlocking() {
963         int mode = mBiometricUnlockController.getMode();
964         return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING;
965     }
966 
967     /**
968      * Adds a {@param runnable} to be executed after Keyguard is gone.
969      */
addAfterKeyguardGoneRunnable(Runnable runnable)970     public void addAfterKeyguardGoneRunnable(Runnable runnable) {
971         if (ComposeBouncerFlags.INSTANCE.isEnabled()) {
972             if (runnable != null) {
973                 mKeyguardDismissActionInteractor.get().runAfterKeyguardGone(runnable);
974             }
975             return;
976         }
977         mAfterKeyguardGoneRunnables.add(runnable);
978     }
979 
980     @Override
reset(boolean hideBouncerWhenShowing)981     public void reset(boolean hideBouncerWhenShowing) {
982         reset(hideBouncerWhenShowing, /* isFalsingReset= */false);
983     }
984 
reset(boolean hideBouncerWhenShowing, boolean isFalsingReset)985     public void reset(boolean hideBouncerWhenShowing, boolean isFalsingReset) {
986         if (mKeyguardStateController.isShowing() && !bouncerIsAnimatingAway()) {
987             final boolean isOccluded = mKeyguardStateController.isOccluded();
988             // Hide quick settings.
989             mShadeLockscreenInteractor.resetViews(/* animate= */ !isOccluded);
990             // Hide bouncer and quick-quick settings.
991             if (isOccluded && !mDozing) {
992                 mCentralSurfaces.hideKeyguard();
993                 if (hideBouncerWhenShowing || needsFullscreenBouncer()) {
994                     // We're removing "reset" in the refactor - bouncer will be hidden by the root
995                     // cause of the "reset" calls.
996                     if (!KeyguardWmStateRefactor.isEnabled()) {
997                         hideBouncer(false /* destroyView */);
998                     }
999                 }
1000             } else {
1001                 showBouncerOrKeyguard(hideBouncerWhenShowing, isFalsingReset, "reset");
1002             }
1003             if (!SceneContainerFlag.isEnabled() && hideBouncerWhenShowing && isBouncerShowing()) {
1004                 hideAlternateBouncer(true);
1005                 mDismissCallbackRegistry.notifyDismissCancelled();
1006                 mPrimaryBouncerInteractor.setDismissAction(null, null);
1007             }
1008             mKeyguardUpdateManager.sendKeyguardReset();
1009             updateStates();
1010         }
1011     }
1012 
1013     @Override
hideAlternateBouncer(boolean updateScrim)1014     public void hideAlternateBouncer(boolean updateScrim) {
1015         hideAlternateBouncer(updateScrim, /* clearDismissAction= */ true);
1016     }
1017 
1018     @Override
hideAlternateBouncer(boolean updateScrim, boolean clearDismissAction)1019     public void hideAlternateBouncer(boolean updateScrim, boolean clearDismissAction) {
1020         if (clearDismissAction) {
1021             mKeyguardDismissActionInteractor.get().clearDismissAction();
1022         }
1023 
1024         updateAlternateBouncerShowing(mAlternateBouncerInteractor.hide() && updateScrim);
1025     }
1026 
updateAlternateBouncerShowing(boolean updateScrim)1027     private void updateAlternateBouncerShowing(boolean updateScrim) {
1028         if (!mCentralSurfacesRegistered) {
1029             // if CentralSurfaces hasn't been registered yet, then the controllers below haven't
1030             // been initialized yet so there's no need to attempt to forward them events.
1031             return;
1032         }
1033 
1034         final boolean isShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState();
1035         if (!SceneContainerFlag.isEnabled()) {
1036             mKeyguardUpdateManager.setAlternateBouncerShowing(isShowingAlternateBouncer);
1037         }
1038 
1039         if (updateScrim) {
1040             mCentralSurfaces.updateScrimController();
1041         }
1042     }
1043 
setRootViewAnimationDisabled(boolean disabled)1044     private void setRootViewAnimationDisabled(boolean disabled) {
1045         ViewGroup windowRootView = mNotificationShadeWindowController.getWindowRootView();
1046         if (windowRootView != null) {
1047             WindowInsetsController insetsController = windowRootView.getWindowInsetsController();
1048             if (insetsController != null) {
1049                 insetsController.setAnimationsDisabled(disabled);
1050             }
1051         }
1052     }
1053 
1054     @Override
onStartedWakingUp()1055     public void onStartedWakingUp() {
1056         mIsSleeping = false;
1057         setRootViewAnimationDisabled(false);
1058         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
1059         if (navBarView != null) {
1060             navBarView.forEachView(view ->
1061                     view.animate()
1062                             .alpha(1f)
1063                             .setDuration(NAV_BAR_CONTENT_FADE_DURATION)
1064                             .start());
1065         }
1066     }
1067 
1068     @Override
onStartedGoingToSleep()1069     public void onStartedGoingToSleep() {
1070         mIsSleeping = true;
1071         setRootViewAnimationDisabled(true);
1072         NavigationBarView navBarView = mCentralSurfaces.getNavigationBarView();
1073         if (navBarView != null) {
1074             navBarView.forEachView(view ->
1075                     view.animate()
1076                             .alpha(0f)
1077                             .setDuration(NAV_BAR_CONTENT_FADE_DURATION)
1078                             .start());
1079         }
1080     }
1081 
1082     @Override
onFinishedGoingToSleep()1083     public void onFinishedGoingToSleep() {
1084         mPrimaryBouncerInteractor.hide();
1085     }
1086 
1087     @Override
onRemoteInputActive(boolean active)1088     public void onRemoteInputActive(boolean active) {
1089         mRemoteInputActive = active;
1090         updateStates();
1091     }
1092 
setDozing(boolean dozing)1093     private void setDozing(boolean dozing) {
1094         if (mDozing != dozing) {
1095             mDozing = dozing;
1096             if (dozing || needsFullscreenBouncer()
1097                     || mKeyguardStateController.isOccluded()) {
1098                 reset(dozing /* hideBouncerWhenShowing */);
1099             }
1100             updateStates();
1101 
1102             if (!dozing) {
1103                 launchPendingWakeupAction();
1104             }
1105         }
1106     }
1107 
1108     /**
1109      * If {@link CentralSurfaces} is pulsing.
1110      */
setPulsing(boolean pulsing)1111     public void setPulsing(boolean pulsing) {
1112         if (mPulsing != pulsing) {
1113             mPulsing = pulsing;
1114             updateStates();
1115         }
1116     }
1117 
1118     @Override
setNeedsInput(boolean needsInput)1119     public void setNeedsInput(boolean needsInput) {
1120         mNotificationShadeWindowController.setKeyguardNeedsInput(needsInput);
1121     }
1122 
1123     @Override
isUnlockWithWallpaper()1124     public boolean isUnlockWithWallpaper() {
1125         return mNotificationShadeWindowController.isShowingWallpaper();
1126     }
1127 
1128     @Override
isBouncerShowingOverDream()1129     public boolean isBouncerShowingOverDream() {
1130         return mBouncerShowingOverDream;
1131     }
1132 
1133     @Override
setOccluded(boolean occluded, boolean animate)1134     public void setOccluded(boolean occluded, boolean animate) {
1135         final boolean wasOccluded = mKeyguardStateController.isOccluded();
1136         final boolean isOccluding = !wasOccluded && occluded;
1137         final boolean isUnOccluding = wasOccluded  && !occluded;
1138         mKeyguardStateController.notifyKeyguardState(
1139                 mKeyguardStateController.isShowing(), occluded);
1140         updateStates();
1141         final boolean isShowing = mKeyguardStateController.isShowing();
1142         final boolean isOccluded = mKeyguardStateController.isOccluded();
1143 
1144         if (isShowing && isOccluding) {
1145             SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
1146                     SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED);
1147             if (mCentralSurfaces.isLaunchingActivityOverLockscreen()) {
1148                 final Runnable postCollapseAction = () -> {
1149                     if (!Flags.useTransitionsForKeyguardOccluded()) {
1150                         mNotificationShadeWindowController.setKeyguardOccluded(isOccluded);
1151                     }
1152                     reset(true /* hideBouncerWhenShowing */);
1153                 };
1154                 if (mCentralSurfaces.isDismissingShadeForActivityLaunch()) {
1155                     // When isDismissingShadeForActivityLaunch() is true, we know for sure that the
1156                     // post collapse runnables will be run.
1157                     mShadeController.get().addPostCollapseAction(postCollapseAction);
1158                 } else {
1159                     postCollapseAction.run();
1160                 }
1161                 return;
1162             }
1163         } else if (isShowing && isUnOccluding) {
1164             SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
1165                     SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
1166         }
1167         if (!Flags.useTransitionsForKeyguardOccluded()) {
1168             mNotificationShadeWindowController.setKeyguardOccluded(isOccluded);
1169         }
1170 
1171         // setDozing(false) will call reset once we stop dozing. Also, if we're going away, there's
1172         // no need to reset the keyguard views as we'll be gone shortly. Resetting now could cause
1173         // unexpected visible behavior if the keyguard is still visible as we're animating unlocked.
1174         if (!mDozing && !mKeyguardStateController.isKeyguardGoingAway()) {
1175             // If Keyguard is reshown, don't hide the bouncer as it might just have been requested
1176             // by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
1177             reset(isOccluding /* hideBouncerWhenShowing*/);
1178         }
1179     }
1180 
1181     @Override
startPreHideAnimation(Runnable finishRunnable)1182     public void startPreHideAnimation(Runnable finishRunnable) {
1183         if (primaryBouncerIsShowing()) {
1184             mPrimaryBouncerInteractor.startDisappearAnimation(finishRunnable);
1185 
1186             // We update the state (which will show the keyguard) only if an animation will run on
1187             // the keyguard. If there is no animation, we wait before updating the state so that we
1188             // go directly from bouncer to launcher/app.
1189             if (ComposeBouncerFlags.INSTANCE.isEnabled()) {
1190                 if (mKeyguardDismissActionInteractor.get().runDismissAnimationOnKeyguard()) {
1191                     updateStates();
1192                 }
1193             } else if (mDismissActionWillAnimateOnKeyguard) {
1194                 updateStates();
1195             }
1196         } else if (finishRunnable != null) {
1197             finishRunnable.run();
1198         }
1199         mShadeLockscreenInteractor.blockExpansionForCurrentTouch();
1200     }
1201 
1202     @Override
blockPanelExpansionFromCurrentTouch()1203     public void blockPanelExpansionFromCurrentTouch() {
1204         mShadeLockscreenInteractor.blockExpansionForCurrentTouch();
1205     }
1206 
1207     @Override
hide(long startTime, long fadeoutDuration)1208     public void hide(long startTime, long fadeoutDuration) {
1209         Trace.beginSection("StatusBarKeyguardViewManager#hide");
1210         if (Flags.checkLockscreenGoneTransition()) {
1211             DejankUtils.notifyRendererOfExpensiveFrame(
1212                     mNotificationShadeWindowController.getWindowRootView(),
1213                     "StatusBarKeyguardViewManager#hide");
1214         }
1215         mKeyguardStateController.notifyKeyguardState(false,
1216                 mKeyguardStateController.isOccluded());
1217         launchPendingWakeupAction();
1218 
1219         if (mKeyguardUpdateManager.needsSlowUnlockTransition()) {
1220             fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
1221         }
1222         long uptimeMillis = SystemClock.uptimeMillis();
1223         long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
1224 
1225         if (mKeyguardStateController.isFlingingToDismissKeyguard()) {
1226             final boolean wasFlingingToDismissKeyguard =
1227                     mKeyguardStateController.isFlingingToDismissKeyguard();
1228             mCentralSurfaces.fadeKeyguardAfterLaunchTransition(new Runnable() {
1229                 @Override
1230                 public void run() {
1231                     mNotificationShadeWindowController.setKeyguardShowing(false);
1232                     mNotificationShadeWindowController.setKeyguardFadingAway(true);
1233                     hideBouncer(true /* destroyView */);
1234                     updateStates();
1235                 }
1236             }, /* endRunnable */ new Runnable() {
1237                 @Override
1238                 public void run() {
1239                     mCentralSurfaces.hideKeyguard();
1240                     mNotificationShadeWindowController.setKeyguardFadingAway(false);
1241 
1242                     if (wasFlingingToDismissKeyguard) {
1243                         mCentralSurfaces.finishKeyguardFadingAway();
1244                     }
1245 
1246                     mViewMediatorCallback.keyguardGone();
1247                     executeAfterKeyguardGoneAction();
1248                 }
1249             }, /* cancelRunnable */ new Runnable() {
1250                 @Override
1251                 public void run() {
1252                     mNotificationShadeWindowController.setKeyguardFadingAway(false);
1253                     if (wasFlingingToDismissKeyguard) {
1254                         mCentralSurfaces.finishKeyguardFadingAway();
1255                     }
1256                     cancelPostAuthActions();
1257                 }
1258             });
1259         } else {
1260             executeAfterKeyguardGoneAction();
1261             mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
1262             mBiometricUnlockController.startKeyguardFadingAway();
1263             hideBouncer(true /* destroyView */);
1264 
1265             boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
1266             if (!staying) {
1267                 mNotificationShadeWindowController.setKeyguardFadingAway(true);
1268                 wakeAndUnlockDejank();
1269                 mCentralSurfaces.hideKeyguard();
1270                 // hide() will happen asynchronously and might arrive after the scrims
1271                 // were already hidden, this means that the transition callback won't
1272                 // be triggered anymore and StatusBarWindowController will be forever in
1273                 // the fadingAway state.
1274                 mCentralSurfaces.updateScrimController();
1275             } else {
1276                 mCentralSurfaces.hideKeyguard();
1277                 mCentralSurfaces.finishKeyguardFadingAway();
1278                 mBiometricUnlockController.finishKeyguardFadingAway();
1279             }
1280 
1281             updateStates();
1282             mNotificationShadeWindowController.setKeyguardShowing(false);
1283             mViewMediatorCallback.keyguardGone();
1284         }
1285         SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
1286                 SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
1287         Trace.endSection();
1288     }
1289 
1290     @Override
onNavigationModeChanged(int mode)1291     public void onNavigationModeChanged(int mode) {
1292         boolean gesturalNav = QuickStepContract.isGesturalMode(mode);
1293         if (gesturalNav != mGesturalNav) {
1294             mGesturalNav = gesturalNav;
1295             updateStates();
1296         }
1297     }
1298 
onThemeChanged()1299     public void onThemeChanged() {
1300         updateResources();
1301     }
1302 
onKeyguardFadedAway()1303     public void onKeyguardFadedAway() {
1304         mNotificationContainer.postDelayed(() -> mNotificationShadeWindowController
1305                         .setKeyguardFadingAway(false), 100);
1306         mShadeLockscreenInteractor.resetViewGroupFade();
1307         mCentralSurfaces.finishKeyguardFadingAway();
1308         mBiometricUnlockController.finishKeyguardFadingAway();
1309     }
1310 
wakeAndUnlockDejank()1311     private void wakeAndUnlockDejank() {
1312         if (mBiometricUnlockController.isWakeAndUnlock() && mLatencyTracker.isEnabled()) {
1313             BiometricSourceType type = mBiometricUnlockController.getBiometricType();
1314             mLatencyTracker.onActionEnd(type == BiometricSourceType.FACE
1315                             ? LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK
1316                             : LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK);
1317         }
1318     }
1319 
executeAfterKeyguardGoneAction()1320     private void executeAfterKeyguardGoneAction() {
1321         if (ComposeBouncerFlags.INSTANCE.isEnabled()) {
1322             return;
1323         }
1324         if (mAfterKeyguardGoneAction != null) {
1325             mAfterKeyguardGoneAction.onDismiss();
1326             mAfterKeyguardGoneAction = null;
1327         }
1328         mKeyguardGoneCancelAction = null;
1329         mDismissActionWillAnimateOnKeyguard = false;
1330         for (int i = 0; i < mAfterKeyguardGoneRunnables.size(); i++) {
1331             mAfterKeyguardGoneRunnables.get(i).run();
1332         }
1333         mAfterKeyguardGoneRunnables.clear();
1334     }
1335 
1336     @Override
dismissAndCollapse()1337     public void dismissAndCollapse() {
1338         mActivityStarter.executeRunnableDismissingKeyguard(
1339                 /* runnable= */ null,
1340                 /* cancelAction= */ null,
1341                 /* dismissShade= */ true,
1342                 /* afterKeyguardGone= */ false,
1343                 /* deferred= */ true
1344         );
1345     }
1346 
1347     /**
1348      * WARNING: This method might cause Binder calls.
1349      */
isSecure()1350     public boolean isSecure() {
1351         return mKeyguardSecurityModel.getSecurityMode(
1352                 mSelectedUserInteractor.getSelectedUserId())
1353                 != KeyguardSecurityModel.SecurityMode.None;
1354     }
1355 
1356     /**
1357      * Returns whether a back invocation can be handled, which depends on whether the keyguard
1358      * is currently showing (which itself is derived from multiple states).
1359      *
1360      * @return whether a back press can be handled right now.
1361      */
canHandleBackPressed()1362     public boolean canHandleBackPressed() {
1363         return primaryBouncerIsShowing();
1364     }
1365 
1366     /**
1367      * Notifies this manager that the back button has been pressed.
1368      */
onBackPressed()1369     public void onBackPressed() {
1370         if (!canHandleBackPressed()) {
1371             return;
1372         }
1373         mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
1374 
1375         boolean hideBouncerOverDreamOrHub = isBouncerShowing()
1376                 && (mDreamOverlayStateController.isOverlayActive()
1377                 || mCommunalSceneInteractor.isIdleOnCommunal().getValue());
1378         mCentralSurfaces.endAffordanceLaunch();
1379         // The second condition is for SIM card locked bouncer
1380         if (hideBouncerOverDreamOrHub
1381                 || (primaryBouncerIsScrimmed() && !needsFullscreenBouncer())) {
1382             hideBouncer(false);
1383             updateStates();
1384         } else {
1385             /* Non-scrimmed bouncers have a special animation tied to the expansion
1386              * of the notification panel. We decide whether to kick this animation off
1387              * by computing the hideImmediately boolean.
1388              */
1389             boolean hideImmediately = mCentralSurfaces.shouldKeyguardHideImmediately();
1390             reset(hideImmediately);
1391             if (hideImmediately) {
1392                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
1393             } else {
1394                 mShadeLockscreenInteractor.expandToNotifications();
1395             }
1396         }
1397         return;
1398     }
1399 
1400     @Override
isBouncerShowing()1401     public boolean isBouncerShowing() {
1402         return primaryBouncerIsShowing() || mAlternateBouncerInteractor.isVisibleState();
1403     }
1404 
1405     @Override
primaryBouncerIsOrWillBeShowing()1406     public boolean primaryBouncerIsOrWillBeShowing() {
1407         return isBouncerShowing() || isPrimaryBouncerInTransit();
1408     }
1409 
isFullscreenBouncer()1410     public boolean isFullscreenBouncer() {
1411         return mPrimaryBouncerView.getDelegate() != null
1412                 && mPrimaryBouncerView.getDelegate().isFullScreenBouncer();
1413     }
1414 
1415     /**
1416      * Clear out any potential actions that were saved to run when the device is unlocked
1417      */
cancelPostAuthActions()1418     public void cancelPostAuthActions() {
1419         if (primaryBouncerIsOrWillBeShowing()) {
1420             return; // allow the primary bouncer to trigger saved actions
1421         }
1422         mAfterKeyguardGoneAction = null;
1423         mDismissActionWillAnimateOnKeyguard = false;
1424         if (mKeyguardGoneCancelAction != null) {
1425             mKeyguardGoneCancelAction.run();
1426             mKeyguardGoneCancelAction = null;
1427         }
1428     }
1429 
getNavBarShowDelay()1430     private long getNavBarShowDelay() {
1431         if (mKeyguardStateController.isKeyguardFadingAway()) {
1432             return mKeyguardStateController.getKeyguardFadingAwayDelay();
1433         } else if (isBouncerShowing()) {
1434             return NAV_BAR_SHOW_DELAY_BOUNCER;
1435         } else {
1436             // No longer dozing, or remote input is active. No delay.
1437             return 0;
1438         }
1439     }
1440 
1441     private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
1442         @Override
1443         public void run() {
1444             NavigationBarView view = mCentralSurfaces.getNavigationBarView();
1445             if (view != null) {
1446                 view.setVisibility(View.VISIBLE);
1447             }
1448             mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
1449                     .show(navigationBars());
1450         }
1451     };
1452 
updateStates()1453     protected void updateStates() {
1454         if (!mCentralSurfacesRegistered) {
1455             return;
1456         }
1457         boolean showing = mKeyguardStateController.isShowing();
1458         boolean occluded = mKeyguardStateController.isOccluded();
1459         boolean primaryBouncerShowing = primaryBouncerIsShowing();
1460         boolean primaryBouncerIsOrWillBeShowing = primaryBouncerIsOrWillBeShowing();
1461         boolean primaryBouncerDismissible = !isFullscreenBouncer();
1462         boolean remoteInputActive = mRemoteInputActive;
1463 
1464         if ((primaryBouncerDismissible || !showing || remoteInputActive)
1465                 != (mLastBouncerDismissible || !mLastShowing || mLastRemoteInputActive)
1466                 || mFirstUpdate) {
1467             if (primaryBouncerDismissible || !showing || remoteInputActive) {
1468                 mPrimaryBouncerInteractor.setBackButtonEnabled(true);
1469             } else {
1470                 mPrimaryBouncerInteractor.setBackButtonEnabled(false);
1471             }
1472         }
1473 
1474         boolean navBarVisible = isNavBarVisible();
1475         boolean lastNavBarVisible = getLastNavBarVisible();
1476         if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
1477             updateNavigationBarVisibility(navBarVisible);
1478         }
1479 
1480         boolean isPrimaryBouncerShowingChanged =
1481             primaryBouncerShowing != mLastPrimaryBouncerShowing;
1482         mLastPrimaryBouncerShowing = primaryBouncerShowing;
1483 
1484         if (isPrimaryBouncerShowingChanged || mFirstUpdate) {
1485             mNotificationShadeWindowController.setBouncerShowing(primaryBouncerShowing);
1486             mCentralSurfaces.setBouncerShowing(primaryBouncerShowing);
1487         }
1488         if (!SceneContainerFlag.isEnabled()) {
1489             if (primaryBouncerIsOrWillBeShowing != mLastPrimaryBouncerIsOrWillBeShowing
1490                     || mFirstUpdate
1491                     || isPrimaryBouncerShowingChanged) {
1492                 mKeyguardUpdateManager.sendPrimaryBouncerChanged(primaryBouncerIsOrWillBeShowing,
1493                         primaryBouncerShowing);
1494             }
1495         }
1496 
1497         mFirstUpdate = false;
1498         mLastShowing = showing;
1499         mLastGlobalActionsVisible = mGlobalActionsVisible;
1500         mLastOccluded = occluded;
1501         mLastPrimaryBouncerIsOrWillBeShowing = primaryBouncerIsOrWillBeShowing;
1502         mLastBouncerDismissible = primaryBouncerDismissible;
1503         mLastRemoteInputActive = remoteInputActive;
1504         mLastDozing = mDozing;
1505         mLastPulsing = mPulsing;
1506         mLastScreenOffAnimationPlaying = mScreenOffAnimationPlaying;
1507         mLastBiometricMode = mBiometricUnlockController.getMode();
1508         mLastGesturalNav = mGesturalNav;
1509         mLastIsDocked = mIsDocked;
1510         mCentralSurfaces.onKeyguardViewManagerStatesUpdated();
1511     }
1512 
1513     /**
1514      * Updates the visibility of the nav bar window (which will cause insets changes).
1515      */
updateNavigationBarVisibility(boolean navBarVisible)1516     protected void updateNavigationBarVisibility(boolean navBarVisible) {
1517         if (mCentralSurfaces.getNavigationBarView() != null
1518                 || (mTaskbarDelegate != null && mTaskbarDelegate.isInitialized())) {
1519             if (navBarVisible) {
1520                 long delay = getNavBarShowDelay();
1521                 if (delay == 0) {
1522                     mMakeNavigationBarVisibleRunnable.run();
1523                 } else {
1524                     mNotificationContainer.postOnAnimationDelayed(mMakeNavigationBarVisibleRunnable,
1525                             delay);
1526                 }
1527             } else {
1528                 mNotificationContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
1529                 mNotificationShadeWindowController.getWindowRootView().getWindowInsetsController()
1530                         .hide(navigationBars());
1531             }
1532         }
1533     }
1534 
1535     /**
1536      * @return Whether the navigation bar should be made visible based on the current state.
1537      */
isNavBarVisible()1538     public boolean isNavBarVisible() {
1539         boolean isWakeAndUnlockPulsing = mBiometricUnlockController != null
1540                 && mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
1541         boolean keyguardVisible = mKeyguardStateController.isVisible();
1542         boolean hideWhileDozing = mDozing && !isWakeAndUnlockPulsing;
1543         boolean keyguardWithGestureNav = (keyguardVisible && !mDozing && !mScreenOffAnimationPlaying
1544                 || mPulsing && !mIsDocked)
1545                 && mGesturalNav;
1546         return (!keyguardVisible && !hideWhileDozing && !mScreenOffAnimationPlaying
1547                 || primaryBouncerIsShowing()
1548                 || mRemoteInputActive
1549                 || keyguardWithGestureNav
1550                 || mGlobalActionsVisible);
1551     }
1552 
1553     /**
1554      * @return Whether the navigation bar was made visible based on the last known state.
1555      */
getLastNavBarVisible()1556     protected boolean getLastNavBarVisible() {
1557         boolean keyguardShowing = mLastShowing && !mLastOccluded;
1558         boolean hideWhileDozing = mLastDozing && mLastBiometricMode != MODE_WAKE_AND_UNLOCK_PULSING;
1559         boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing
1560                 && !mLastScreenOffAnimationPlaying || mLastPulsing && !mLastIsDocked)
1561                 && mLastGesturalNav;
1562         return (!keyguardShowing && !hideWhileDozing && !mLastScreenOffAnimationPlaying
1563                 || mLastPrimaryBouncerShowing || mLastRemoteInputActive || keyguardWithGestureNav
1564                 || mLastGlobalActionsVisible);
1565     }
1566 
shouldDismissOnMenuPressed()1567     public boolean shouldDismissOnMenuPressed() {
1568         return (mPrimaryBouncerView.getDelegate() != null
1569                 && mPrimaryBouncerView.getDelegate().shouldDismissOnMenuPressed()) || (
1570                 ComposeBouncerFlags.INSTANCE.isEnabled() && BouncerTestUtilsKt.shouldEnableMenuKey(
1571                         mContext.getResources()));
1572     }
1573 
interceptMediaKey(KeyEvent event)1574     public boolean interceptMediaKey(KeyEvent event) {
1575         ComposeBouncerFlags.assertInLegacyMode();
1576         return mPrimaryBouncerView.getDelegate() != null
1577                 && mPrimaryBouncerView.getDelegate().interceptMediaKey(event);
1578     }
1579 
1580     /**
1581      * @return true if the pre IME back event should be handled
1582      */
dispatchBackKeyEventPreIme()1583     public boolean dispatchBackKeyEventPreIme() {
1584         return mPrimaryBouncerView.getDelegate() != null
1585                 && mPrimaryBouncerView.getDelegate().dispatchBackKeyEventPreIme();
1586     }
1587 
1588     @Override
readyForKeyguardDone()1589     public void readyForKeyguardDone() {
1590         mViewMediatorCallback.readyForKeyguardDone();
1591     }
1592 
1593     @Override
shouldDisableWindowAnimationsForUnlock()1594     public boolean shouldDisableWindowAnimationsForUnlock() {
1595         return false;
1596     }
1597 
1598     @Override
shouldSubtleWindowAnimationsForUnlock()1599     public boolean shouldSubtleWindowAnimationsForUnlock() {
1600         return false;
1601     }
1602 
1603     @Override
isGoingToNotificationShade()1604     public boolean isGoingToNotificationShade() {
1605         return mStatusBarStateController.leaveOpenOnKeyguardHide();
1606     }
1607 
isSecure(int userId)1608     public boolean isSecure(int userId) {
1609         return isSecure() || mLockPatternUtils.isSecure(userId);
1610     }
1611 
1612     @Override
keyguardGoingAway()1613     public void keyguardGoingAway() {
1614         mCentralSurfaces.keyguardGoingAway();
1615     }
1616 
1617     @Override
setKeyguardGoingAwayState(boolean isKeyguardGoingAway)1618     public void setKeyguardGoingAwayState(boolean isKeyguardGoingAway) {
1619         mNotificationShadeWindowController.setKeyguardGoingAway(isKeyguardGoingAway);
1620     }
1621 
1622     @Override
onCancelClicked()1623     public void onCancelClicked() {
1624         // No-op
1625     }
1626 
1627     /**
1628      * Notifies that the user has authenticated by other means than using the bouncer, for example,
1629      * fingerprint and the keyguard should immediately dismiss.
1630      */
notifyKeyguardAuthenticated(boolean strongAuth)1631     public void notifyKeyguardAuthenticated(boolean strongAuth) {
1632         mPrimaryBouncerInteractor.notifyKeyguardAuthenticatedBiometrics(strongAuth);
1633 
1634         if (mAlternateBouncerInteractor.isVisibleState()) {
1635             executeAfterKeyguardGoneAction();
1636         }
1637 
1638         if (KeyguardWmStateRefactor.isEnabled()) {
1639             mKeyguardDismissTransitionInteractor.startDismissKeyguardTransition(
1640                     "SBKVM#keyguardAuthenticated");
1641         }
1642     }
1643 
1644     /** Display security message to relevant KeyguardMessageArea. */
setKeyguardMessage(String message, ColorStateList colorState, BiometricSourceType biometricSourceType)1645     public void setKeyguardMessage(String message, ColorStateList colorState,
1646             BiometricSourceType biometricSourceType) {
1647         if (!mAlternateBouncerInteractor.isVisibleState()) {
1648             mPrimaryBouncerInteractor.showMessage(message, colorState);
1649         }
1650     }
1651 
1652     @Override
getViewRootImpl()1653     public ViewRootImpl getViewRootImpl() {
1654         ViewGroup viewGroup = mNotificationShadeWindowController.getWindowRootView();
1655         if (viewGroup != null) {
1656             return viewGroup.getViewRootImpl();
1657         } else {
1658             if (DEBUG) {
1659                 Log.d(TAG, "ViewGroup was null, cannot get ViewRootImpl");
1660             }
1661             return null;
1662         }
1663     }
1664 
launchPendingWakeupAction()1665     public void launchPendingWakeupAction() {
1666         DismissWithActionRequest request = mPendingWakeupAction;
1667         mPendingWakeupAction = null;
1668         if (request != null) {
1669             if (mKeyguardStateController.isShowing()) {
1670                 dismissWithAction(request.dismissAction, request.cancelAction,
1671                         request.afterKeyguardGone, request.message);
1672             } else if (request.dismissAction != null) {
1673                 request.dismissAction.onDismiss();
1674             }
1675         }
1676     }
1677 
cancelPendingWakeupAction()1678     public void cancelPendingWakeupAction() {
1679         DismissWithActionRequest request = mPendingWakeupAction;
1680         mPendingWakeupAction = null;
1681         if (request != null && request.cancelAction != null) {
1682             request.cancelAction.run();
1683         }
1684     }
1685 
1686     /**
1687      * Whether the primary bouncer requires scrimming.
1688      */
primaryBouncerNeedsScrimming()1689     public boolean primaryBouncerNeedsScrimming() {
1690         // When a dream overlay is active, scrimming will cause any expansion to immediately expand.
1691         return (mKeyguardStateController.isOccluded()
1692                 && !mDreamOverlayStateController.isOverlayActive())
1693                 || primaryBouncerWillDismissWithAction()
1694                 || (primaryBouncerIsShowing() && primaryBouncerIsScrimmed())
1695                 || isFullscreenBouncer();
1696     }
1697 
1698     /**
1699      * Apply keyguard configuration from the currently active resources. This can be called when the
1700      * device configuration changes, to re-apply some resources that are qualified on the device
1701      * configuration.
1702      */
updateResources()1703     public void updateResources() {
1704         mPrimaryBouncerInteractor.updateResources();
1705     }
1706 
dump(PrintWriter pw)1707     public void dump(PrintWriter pw) {
1708         pw.println("StatusBarKeyguardViewManager:");
1709         pw.println("  mRemoteInputActive: " + mRemoteInputActive);
1710         pw.println("  mDozing: " + mDozing);
1711         pw.println("  mAfterKeyguardGoneAction: " + mAfterKeyguardGoneAction);
1712         pw.println("  mAfterKeyguardGoneRunnables: " + mAfterKeyguardGoneRunnables);
1713         pw.println("  mPendingWakeupAction: " + mPendingWakeupAction);
1714         pw.println("  isBouncerShowing(): " + isBouncerShowing());
1715         pw.println("  bouncerIsOrWillBeShowing(): " + primaryBouncerIsOrWillBeShowing());
1716         pw.println("  Registered KeyguardViewManagerCallbacks:");
1717         pw.println(" SceneContainerFlag enabled:"
1718                 + SceneContainerFlag.isEnabled());
1719         pw.println(" ComposeBouncerFlags enabled:"
1720                 + ComposeBouncerFlags.INSTANCE.isEnabled());
1721         for (KeyguardViewManagerCallback callback : mCallbacks) {
1722             pw.println("      " + callback);
1723         }
1724 
1725         if (mOccludingAppBiometricUI != null) {
1726             pw.println("mOccludingAppBiometricUI:");
1727             mOccludingAppBiometricUI.dump(pw);
1728         }
1729     }
1730 
1731     @Override
onDozingChanged(boolean isDozing)1732     public void onDozingChanged(boolean isDozing) {
1733         setDozing(isDozing);
1734     }
1735 
1736     @Override
onFoldToAodAnimationChanged()1737     public void onFoldToAodAnimationChanged() {
1738         if (mFoldAodAnimationController != null) {
1739             mScreenOffAnimationPlaying = mFoldAodAnimationController.shouldPlayAnimation();
1740         }
1741     }
1742 
1743     /**
1744      * Add a callback to listen for changes
1745      */
addCallback(KeyguardViewManagerCallback callback)1746     public void addCallback(KeyguardViewManagerCallback callback) {
1747         mCallbacks.add(callback);
1748     }
1749 
1750     /**
1751      * Removes callback to stop receiving updates
1752      */
removeCallback(KeyguardViewManagerCallback callback)1753     public void removeCallback(KeyguardViewManagerCallback callback) {
1754         mCallbacks.remove(callback);
1755     }
1756 
1757     /**
1758      * Whether qs is currently expanded.
1759      */
getQsExpansion()1760     public float getQsExpansion() {
1761         return mQsExpansion;
1762     }
1763 
1764     /**
1765      * Update qs expansion.
1766      */
setQsExpansion(float qsExpansion)1767     public void setQsExpansion(float qsExpansion) {
1768         mQsExpansion = qsExpansion;
1769         for (KeyguardViewManagerCallback callback : mCallbacks) {
1770             callback.onQSExpansionChanged(mQsExpansion);
1771         }
1772     }
1773 
1774     /** Update keyguard position based on a tapped X coordinate. */
updateKeyguardPosition(float x)1775     public void updateKeyguardPosition(float x) {
1776         mPrimaryBouncerInteractor.setKeyguardPosition(x);
1777     }
1778 
1779     private static class DismissWithActionRequest {
1780         final OnDismissAction dismissAction;
1781         final Runnable cancelAction;
1782         final boolean afterKeyguardGone;
1783         final String message;
1784 
DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction, boolean afterKeyguardGone, String message)1785         DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
1786                 boolean afterKeyguardGone, String message) {
1787             this.dismissAction = dismissAction;
1788             this.cancelAction = cancelAction;
1789             this.afterKeyguardGone = afterKeyguardGone;
1790             this.message = message;
1791         }
1792     }
1793 
1794     /**
1795      * Request to authenticate using the fingerprint sensor.  If the fingerprint sensor is udfps,
1796      * uses the color provided by udfpsColor for the fingerprint icon.
1797      */
requestFp(boolean request, int udfpsColor)1798     public void requestFp(boolean request, int udfpsColor) {
1799         mKeyguardUpdateManager.requestFingerprintAuthOnOccludingApp(request);
1800         if (mOccludingAppBiometricUI != null) {
1801             mOccludingAppBiometricUI.requestUdfps(request, udfpsColor);
1802         }
1803     }
1804 
1805     /**
1806      * Returns if bouncer expansion is between 0 and 1 non-inclusive.
1807      */
isPrimaryBouncerInTransit()1808     public boolean isPrimaryBouncerInTransit() {
1809         return mPrimaryBouncerInteractor.isInTransit();
1810     }
1811 
1812     /**
1813      * Returns if bouncer is showing
1814      */
primaryBouncerIsShowing()1815     public boolean primaryBouncerIsShowing() {
1816         return mPrimaryBouncerInteractor.isFullyShowing();
1817     }
1818 
1819     /**
1820      * Returns if bouncer is scrimmed
1821      */
primaryBouncerIsScrimmed()1822     public boolean primaryBouncerIsScrimmed() {
1823         return mPrimaryBouncerInteractor.isScrimmed();
1824     }
1825 
1826     /**
1827      * Returns if bouncer is animating away
1828      */
bouncerIsAnimatingAway()1829     public boolean bouncerIsAnimatingAway() {
1830         return mPrimaryBouncerInteractor.isAnimatingAway();
1831     }
1832 
1833     /**
1834      * Returns if bouncer will dismiss with action
1835      */
primaryBouncerWillDismissWithAction()1836     public boolean primaryBouncerWillDismissWithAction() {
1837         return mPrimaryBouncerInteractor.willDismissWithAction();
1838     }
1839 
1840     /**
1841      * Returns if bouncer needs fullscreen bouncer. i.e. sim pin security method
1842      */
needsFullscreenBouncer()1843     public boolean needsFullscreenBouncer() {
1844         KeyguardSecurityModel.SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
1845                 mSelectedUserInteractor.getSelectedUserId());
1846         return mode == KeyguardSecurityModel.SecurityMode.SimPin
1847                 || mode == KeyguardSecurityModel.SecurityMode.SimPuk;
1848     }
1849 
1850     @VisibleForTesting
setAttemptsToShowBouncer(int attempts)1851     void setAttemptsToShowBouncer(int attempts) {
1852         mAttemptsToShowBouncer = attempts;
1853     }
1854 
1855     /**
1856      * Delegate used to send show and hide events to an alternate authentication method instead of
1857      * the regular pin/pattern/password bouncer.
1858      */
1859     public interface OccludingAppBiometricUI {
1860         /**
1861          * Use when an app occluding the keyguard would like to give the user ability to
1862          * unlock the device using udfps.
1863          *
1864          * @param color of the udfps icon. should have proper contrast with its background. only
1865          *              used if requestUdfps = true
1866          */
requestUdfps(boolean requestUdfps, int color)1867         void requestUdfps(boolean requestUdfps, int color);
1868 
1869         /**
1870          * print information for the alternate bouncer registered
1871          */
dump(PrintWriter pw)1872         void dump(PrintWriter pw);
1873     }
1874 
1875     /**
1876      * Callback for KeyguardViewManager state changes.
1877      */
1878     public interface KeyguardViewManagerCallback {
1879         /**
1880          * Set the amount qs is expanded. For example, swipe down from the top of the
1881          * lock screen to start the full QS expansion.
1882          */
onQSExpansionChanged(float qsExpansion)1883         default void onQSExpansionChanged(float qsExpansion) { }
1884 
1885         /**
1886          * Forward touch events to callbacks
1887          */
onTouch(MotionEvent event)1888         default void onTouch(MotionEvent event) { }
1889     }
1890 }
1891