• 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 com.android.keyguard.KeyguardSecurityModel.SecurityMode;
20 import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
21 
22 import android.content.Context;
23 import android.content.res.ColorStateList;
24 import android.os.Handler;
25 import android.os.UserHandle;
26 import android.os.UserManager;
27 import android.util.Log;
28 import android.view.KeyEvent;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.view.WindowInsets;
32 
33 import com.android.keyguard.KeyguardHostViewController;
34 import com.android.keyguard.KeyguardRootViewController;
35 import com.android.keyguard.KeyguardSecurityModel;
36 import com.android.keyguard.KeyguardSecurityView;
37 import com.android.keyguard.KeyguardUpdateMonitor;
38 import com.android.keyguard.KeyguardUpdateMonitorCallback;
39 import com.android.keyguard.ViewMediatorCallback;
40 import com.android.keyguard.dagger.KeyguardBouncerComponent;
41 import com.android.systemui.DejankUtils;
42 import com.android.systemui.classifier.FalsingCollector;
43 import com.android.systemui.dagger.qualifiers.RootView;
44 import com.android.systemui.keyguard.DismissCallbackRegistry;
45 import com.android.systemui.shared.system.SysUiStatsLog;
46 import com.android.systemui.statusbar.policy.KeyguardStateController;
47 
48 import java.io.PrintWriter;
49 import java.util.ArrayList;
50 import java.util.List;
51 
52 import javax.inject.Inject;
53 
54 /**
55  * A class which manages the bouncer on the lockscreen.
56  */
57 public class KeyguardBouncer {
58 
59     private static final String TAG = "KeyguardBouncer";
60     static final long BOUNCER_FACE_DELAY = 1200;
61     public static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
62     public static final float EXPANSION_HIDDEN = 1f;
63     public static final float EXPANSION_VISIBLE = 0f;
64 
65     protected final Context mContext;
66     protected final ViewMediatorCallback mCallback;
67     protected final ViewGroup mContainer;
68     private final FalsingCollector mFalsingCollector;
69     private final DismissCallbackRegistry mDismissCallbackRegistry;
70     private final Handler mHandler;
71     private final List<BouncerExpansionCallback> mExpansionCallbacks = new ArrayList<>();
72     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
73     private final KeyguardStateController mKeyguardStateController;
74     private final KeyguardSecurityModel mKeyguardSecurityModel;
75     private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
76     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
77             new KeyguardUpdateMonitorCallback() {
78                 @Override
79                 public void onStrongAuthStateChanged(int userId) {
80                     mBouncerPromptReason = mCallback.getBouncerPromptReason();
81                 }
82             };
83     private final Runnable mRemoveViewRunnable = this::removeView;
84     private final KeyguardBypassController mKeyguardBypassController;
85     private KeyguardHostViewController mKeyguardViewController;
86     private final List<KeyguardResetCallback> mResetCallbacks = new ArrayList<>();
87     private final Runnable mResetRunnable = ()-> {
88         if (mKeyguardViewController != null) {
89             mKeyguardViewController.resetSecurityContainer();
90             for (KeyguardResetCallback callback : new ArrayList<>(mResetCallbacks)) {
91                 callback.onKeyguardReset();
92             }
93         }
94     };
95 
96     private int mStatusBarHeight;
97     private float mExpansion = EXPANSION_HIDDEN;
98     protected ViewGroup mRoot;
99     private KeyguardRootViewController mRootViewController;
100     private boolean mShowingSoon;
101     private int mBouncerPromptReason;
102     private boolean mIsAnimatingAway;
103     private boolean mIsScrimmed;
104 
KeyguardBouncer(Context context, ViewMediatorCallback callback, ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry, FalsingCollector falsingCollector, BouncerExpansionCallback expansionCallback, KeyguardStateController keyguardStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, KeyguardBypassController keyguardBypassController, Handler handler, KeyguardSecurityModel keyguardSecurityModel, KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory)105     private KeyguardBouncer(Context context, ViewMediatorCallback callback,
106             ViewGroup container,
107             DismissCallbackRegistry dismissCallbackRegistry, FalsingCollector falsingCollector,
108             BouncerExpansionCallback expansionCallback,
109             KeyguardStateController keyguardStateController,
110             KeyguardUpdateMonitor keyguardUpdateMonitor,
111             KeyguardBypassController keyguardBypassController, Handler handler,
112             KeyguardSecurityModel keyguardSecurityModel,
113             KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
114         mContext = context;
115         mCallback = callback;
116         mContainer = container;
117         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
118         mFalsingCollector = falsingCollector;
119         mDismissCallbackRegistry = dismissCallbackRegistry;
120         mHandler = handler;
121         mKeyguardStateController = keyguardStateController;
122         mKeyguardSecurityModel = keyguardSecurityModel;
123         mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
124         mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
125         mKeyguardBypassController = keyguardBypassController;
126         mExpansionCallbacks.add(expansionCallback);
127     }
128 
show(boolean resetSecuritySelection)129     public void show(boolean resetSecuritySelection) {
130         show(resetSecuritySelection, true /* scrimmed */);
131     }
132 
133     /**
134      * Shows the bouncer.
135      *
136      * @param resetSecuritySelection Cleans keyguard view
137      * @param isScrimmed true when the bouncer show show scrimmed, false when the user will be
138      *                 dragging it and translation should be deferred.
139      */
show(boolean resetSecuritySelection, boolean isScrimmed)140     public void show(boolean resetSecuritySelection, boolean isScrimmed) {
141         final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
142         if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
143             // In split system user mode, we never unlock system user.
144             return;
145         }
146         ensureView();
147         mIsScrimmed = isScrimmed;
148 
149         // On the keyguard, we want to show the bouncer when the user drags up, but it's
150         // not correct to end the falsing session. We still need to verify if those touches
151         // are valid.
152         // Later, at the end of the animation, when the bouncer is at the top of the screen,
153         // onFullyShown() will be called and FalsingManager will stop recording touches.
154         if (isScrimmed) {
155             setExpansion(EXPANSION_VISIBLE);
156         }
157 
158         if (resetSecuritySelection) {
159             // showPrimarySecurityScreen() updates the current security method. This is needed in
160             // case we are already showing and the current security method changed.
161             showPrimarySecurityScreen();
162         }
163 
164         if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
165             return;
166         }
167 
168         final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
169         final boolean isSystemUser =
170                 UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
171         final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
172 
173         // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
174         // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
175         if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) {
176             return;
177         }
178 
179         // This condition may indicate an error on Android, so log it.
180         if (!allowDismissKeyguard) {
181             Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
182         }
183 
184         mShowingSoon = true;
185 
186         // Split up the work over multiple frames.
187         DejankUtils.removeCallbacks(mResetRunnable);
188         if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer()
189                 && !mKeyguardUpdateMonitor.userNeedsStrongAuth()
190                 && !mKeyguardBypassController.getBypassEnabled()) {
191             mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
192         } else {
193             DejankUtils.postAfterTraversal(mShowRunnable);
194         }
195 
196         mCallback.onBouncerVisiblityChanged(true /* shown */);
197         dispatchStartingToShow();
198     }
199 
isScrimmed()200     public boolean isScrimmed() {
201         return mIsScrimmed;
202     }
203 
204     /**
205      * This method must be called at the end of the bouncer animation when
206      * the translation is performed manually by the user, otherwise FalsingManager
207      * will never be notified and its internal state will be out of sync.
208      */
onFullyShown()209     private void onFullyShown() {
210         mFalsingCollector.onBouncerShown();
211         if (mKeyguardViewController == null) {
212             Log.wtf(TAG, "onFullyShown when view was null");
213         } else {
214             mKeyguardViewController.onResume();
215             if (mRoot != null) {
216                 mRoot.announceForAccessibility(
217                         mKeyguardViewController.getAccessibilityTitleForCurrentMode());
218             }
219         }
220     }
221 
222     /**
223      * @see #onFullyShown()
224      */
onFullyHidden()225     private void onFullyHidden() {
226         cancelShowRunnable();
227         setVisibility(View.INVISIBLE);
228         mFalsingCollector.onBouncerHidden();
229         DejankUtils.postAfterTraversal(mResetRunnable);
230     }
231 
setVisibility(@iew.Visibility int visibility)232     private void setVisibility(@View.Visibility int visibility) {
233         if (mRoot != null) {
234             mRoot.setVisibility(visibility);
235             dispatchVisibilityChanged();
236         }
237     }
238 
239     private final Runnable mShowRunnable = new Runnable() {
240         @Override
241         public void run() {
242             setVisibility(View.VISIBLE);
243             showPromptReason(mBouncerPromptReason);
244             final CharSequence customMessage = mCallback.consumeCustomMessage();
245             if (customMessage != null) {
246                 mKeyguardViewController.showErrorMessage(customMessage);
247             }
248             mKeyguardViewController.appear(mStatusBarHeight);
249             mShowingSoon = false;
250             if (mExpansion == EXPANSION_VISIBLE) {
251                 mKeyguardViewController.onResume();
252                 mKeyguardViewController.resetSecurityContainer();
253                 showPromptReason(mBouncerPromptReason);
254             }
255             SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
256                     SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);
257         }
258     };
259 
260     /**
261      * Show a string explaining why the security view needs to be solved.
262      *
263      * @param reason a flag indicating which string should be shown, see
264      *               {@link KeyguardSecurityView#PROMPT_REASON_NONE}
265      *               and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
266      */
showPromptReason(int reason)267     public void showPromptReason(int reason) {
268         if (mKeyguardViewController != null) {
269             mKeyguardViewController.showPromptReason(reason);
270         } else {
271             Log.w(TAG, "Trying to show prompt reason on empty bouncer");
272         }
273     }
274 
showMessage(String message, ColorStateList colorState)275     public void showMessage(String message, ColorStateList colorState) {
276         if (mKeyguardViewController != null) {
277             mKeyguardViewController.showMessage(message, colorState);
278         } else {
279             Log.w(TAG, "Trying to show message on empty bouncer");
280         }
281     }
282 
cancelShowRunnable()283     private void cancelShowRunnable() {
284         DejankUtils.removeCallbacks(mShowRunnable);
285         mHandler.removeCallbacks(mShowRunnable);
286         mShowingSoon = false;
287     }
288 
showWithDismissAction(OnDismissAction r, Runnable cancelAction)289     public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
290         ensureView();
291         setDismissAction(r, cancelAction);
292         show(false /* resetSecuritySelection */);
293     }
294 
295     /**
296      * Set the actions to run when the keyguard is dismissed or when the dismiss is cancelled. Those
297      * actions will still be run even if this bouncer is not shown, for instance when authenticating
298      * with an alternate authenticator like the UDFPS.
299      */
setDismissAction(OnDismissAction r, Runnable cancelAction)300     public void setDismissAction(OnDismissAction r, Runnable cancelAction) {
301         mKeyguardViewController.setOnDismissAction(r, cancelAction);
302     }
303 
hide(boolean destroyView)304     public void hide(boolean destroyView) {
305         if (isShowing()) {
306             SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
307                     SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
308             mDismissCallbackRegistry.notifyDismissCancelled();
309         }
310         mIsScrimmed = false;
311         mFalsingCollector.onBouncerHidden();
312         mCallback.onBouncerVisiblityChanged(false /* shown */);
313         cancelShowRunnable();
314         if (mKeyguardViewController != null) {
315             mKeyguardViewController.cancelDismissAction();
316             mKeyguardViewController.cleanUp();
317         }
318         mIsAnimatingAway = false;
319         if (mRoot != null) {
320             setVisibility(View.INVISIBLE);
321             if (destroyView) {
322 
323                 // We have a ViewFlipper that unregisters a broadcast when being detached, which may
324                 // be slow because of AM lock contention during unlocking. We can delay it a bit.
325                 mHandler.postDelayed(mRemoveViewRunnable, 50);
326             }
327         }
328     }
329 
330     /**
331      * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
332      */
startPreHideAnimation(Runnable runnable)333     public void startPreHideAnimation(Runnable runnable) {
334         mIsAnimatingAway = true;
335         if (mKeyguardViewController != null) {
336             mKeyguardViewController.startDisappearAnimation(runnable);
337         } else if (runnable != null) {
338             runnable.run();
339         }
340     }
341 
342     /**
343      * Reset the state of the view.
344      */
reset()345     public void reset() {
346         cancelShowRunnable();
347         inflateView();
348         mFalsingCollector.onBouncerHidden();
349     }
350 
onScreenTurnedOff()351     public void onScreenTurnedOff() {
352         if (mKeyguardViewController != null
353                 && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
354             mKeyguardViewController.onPause();
355         }
356     }
357 
isShowing()358     public boolean isShowing() {
359         return (mShowingSoon || (mRoot != null && mRoot.getVisibility() == View.VISIBLE))
360                 && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
361     }
362 
363     /**
364      * {@link #show(boolean)} was called but we're not showing yet, or being dragged.
365      */
inTransit()366     public boolean inTransit() {
367         return mShowingSoon || mExpansion != EXPANSION_HIDDEN && mExpansion != EXPANSION_VISIBLE;
368     }
369 
getShowingSoon()370     public boolean getShowingSoon() {
371         return mShowingSoon;
372     }
373 
374     /**
375      * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
376      *         hidden yet, {@code false} otherwise.
377      */
isAnimatingAway()378     public boolean isAnimatingAway() {
379         return mIsAnimatingAway;
380     }
381 
prepare()382     public void prepare() {
383         boolean wasInitialized = mRoot != null;
384         ensureView();
385         if (wasInitialized) {
386             showPrimarySecurityScreen();
387         }
388         mBouncerPromptReason = mCallback.getBouncerPromptReason();
389     }
390 
showPrimarySecurityScreen()391     private void showPrimarySecurityScreen() {
392         mKeyguardViewController.showPrimarySecurityScreen();
393     }
394 
395     /**
396      * Current notification panel expansion
397      * @param fraction 0 when notification panel is collapsed and 1 when expanded.
398      * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
399      */
setExpansion(float fraction)400     public void setExpansion(float fraction) {
401         float oldExpansion = mExpansion;
402         boolean expansionChanged = mExpansion != fraction;
403         mExpansion = fraction;
404         if (mKeyguardViewController != null && !mIsAnimatingAway) {
405             mKeyguardViewController.setExpansion(fraction);
406         }
407 
408         if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
409             onFullyShown();
410             dispatchFullyShown();
411         } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
412             onFullyHidden();
413             dispatchFullyHidden();
414         } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
415             dispatchStartingToHide();
416             if (mKeyguardViewController != null) {
417                 mKeyguardViewController.onStartingToHide();
418             }
419         }
420 
421         if (expansionChanged) {
422             dispatchExpansionChanged();
423         }
424     }
425 
willDismissWithAction()426     public boolean willDismissWithAction() {
427         return mKeyguardViewController != null && mKeyguardViewController.hasDismissActions();
428     }
429 
getTop()430     public int getTop() {
431         if (mKeyguardViewController == null) {
432             return 0;
433         }
434 
435         return mKeyguardViewController.getTop();
436     }
437 
ensureView()438     protected void ensureView() {
439         // Removal of the view might be deferred to reduce unlock latency,
440         // in this case we need to force the removal, otherwise we'll
441         // end up in an unpredictable state.
442         boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
443         if (mRoot == null || forceRemoval) {
444             inflateView();
445         }
446     }
447 
inflateView()448     protected void inflateView() {
449         removeView();
450         mHandler.removeCallbacks(mRemoveViewRunnable);
451         KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create();
452         mRootViewController = component.getKeyguardRootViewController();
453         mRootViewController.init();
454         mRoot = mRootViewController.getView();  // TODO(b/166448040): Don't access root view here.
455         mKeyguardViewController = component.getKeyguardHostViewController();
456         mKeyguardViewController.init();
457 
458         mContainer.addView(mRoot, mContainer.getChildCount());
459         mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
460                 com.android.systemui.R.dimen.status_bar_height);
461         setVisibility(View.INVISIBLE);
462 
463         final WindowInsets rootInsets = mRoot.getRootWindowInsets();
464         if (rootInsets != null) {
465             mRoot.dispatchApplyWindowInsets(rootInsets);
466         }
467     }
468 
removeView()469     protected void removeView() {
470         if (mRoot != null && mRoot.getParent() == mContainer) {
471             mContainer.removeView(mRoot);
472             mRoot = null;
473         }
474     }
475 
476     /**
477      * @return True if and only if the security method should be shown before showing the
478      * notifications on Keyguard, like SIM PIN/PUK.
479      */
needsFullscreenBouncer()480     public boolean needsFullscreenBouncer() {
481         SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
482                 KeyguardUpdateMonitor.getCurrentUser());
483         return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
484     }
485 
486     /**
487      * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
488      * makes this method much faster.
489      */
isFullscreenBouncer()490     public boolean isFullscreenBouncer() {
491         if (mKeyguardViewController != null) {
492             SecurityMode mode = mKeyguardViewController.getCurrentSecurityMode();
493             return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
494         }
495         return false;
496     }
497 
498     /**
499      * WARNING: This method might cause Binder calls.
500      */
isSecure()501     public boolean isSecure() {
502         return mKeyguardSecurityModel.getSecurityMode(
503                 KeyguardUpdateMonitor.getCurrentUser()) != SecurityMode.None;
504     }
505 
shouldDismissOnMenuPressed()506     public boolean shouldDismissOnMenuPressed() {
507         return mKeyguardViewController.shouldEnableMenuKey();
508     }
509 
interceptMediaKey(KeyEvent event)510     public boolean interceptMediaKey(KeyEvent event) {
511         ensureView();
512         return mKeyguardViewController.interceptMediaKey(event);
513     }
514 
515     /**
516      * @return true if the pre IME back event should be handled
517      */
dispatchBackKeyEventPreIme()518     public boolean dispatchBackKeyEventPreIme() {
519         ensureView();
520         return mKeyguardViewController.dispatchBackKeyEventPreIme();
521     }
522 
notifyKeyguardAuthenticated(boolean strongAuth)523     public void notifyKeyguardAuthenticated(boolean strongAuth) {
524         ensureView();
525         mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
526     }
527 
dispatchFullyShown()528     private void dispatchFullyShown() {
529         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
530             callback.onFullyShown();
531         }
532     }
533 
dispatchStartingToHide()534     private void dispatchStartingToHide() {
535         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
536             callback.onStartingToHide();
537         }
538     }
539 
dispatchStartingToShow()540     private void dispatchStartingToShow() {
541         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
542             callback.onStartingToShow();
543         }
544     }
545 
dispatchFullyHidden()546     private void dispatchFullyHidden() {
547         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
548             callback.onFullyHidden();
549         }
550     }
551 
dispatchExpansionChanged()552     private void dispatchExpansionChanged() {
553         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
554             callback.onExpansionChanged(mExpansion);
555         }
556     }
557 
dispatchVisibilityChanged()558     private void dispatchVisibilityChanged() {
559         for (BouncerExpansionCallback callback : mExpansionCallbacks) {
560             callback.onVisibilityChanged(mRoot.getVisibility() == View.VISIBLE);
561         }
562     }
563 
564     /**
565      * Apply keyguard configuration from the currently active resources. This can be called when the
566      * device configuration changes, to re-apply some resources that are qualified on the device
567      * configuration.
568      */
updateResources()569     public void updateResources() {
570         if (mKeyguardViewController != null) {
571             mKeyguardViewController.updateResources();
572         }
573     }
574 
dump(PrintWriter pw)575     public void dump(PrintWriter pw) {
576         pw.println("KeyguardBouncer");
577         pw.println("  isShowing(): " + isShowing());
578         pw.println("  mStatusBarHeight: " + mStatusBarHeight);
579         pw.println("  mExpansion: " + mExpansion);
580         pw.println("  mKeyguardViewController; " + mKeyguardViewController);
581         pw.println("  mShowingSoon: " + mShowingSoon);
582         pw.println("  mBouncerPromptReason: " + mBouncerPromptReason);
583         pw.println("  mIsAnimatingAway: " + mIsAnimatingAway);
584     }
585 
586     /** Update keyguard position based on a tapped X coordinate. */
updateKeyguardPosition(float x)587     public void updateKeyguardPosition(float x) {
588         if (mKeyguardViewController != null) {
589             mKeyguardViewController.updateKeyguardPosition(x);
590         }
591     }
592 
addKeyguardResetCallback(KeyguardResetCallback callback)593     public void addKeyguardResetCallback(KeyguardResetCallback callback) {
594         mResetCallbacks.add(callback);
595     }
596 
removeKeyguardResetCallback(KeyguardResetCallback callback)597     public void removeKeyguardResetCallback(KeyguardResetCallback callback) {
598         mResetCallbacks.remove(callback);
599     }
600 
601     public interface BouncerExpansionCallback {
onFullyShown()602         void onFullyShown();
onStartingToHide()603         void onStartingToHide();
onStartingToShow()604         void onStartingToShow();
onFullyHidden()605         void onFullyHidden();
606 
607         /**
608          * From 0f {@link KeyguardBouncer#EXPANSION_VISIBLE} when fully visible
609          * to 1f {@link KeyguardBouncer#EXPANSION_HIDDEN} when fully hidden
610          */
onExpansionChanged(float bouncerHideAmount)611         default void onExpansionChanged(float bouncerHideAmount) {}
612 
613         /**
614          * Invoked when visibility of KeyguardBouncer has changed.
615          * Note the bouncer expansion can be {@link KeyguardBouncer#EXPANSION_VISIBLE}, but the
616          * view's visibility can be {@link View.INVISIBLE}.
617          */
onVisibilityChanged(boolean isVisible)618         default void onVisibilityChanged(boolean isVisible) {}
619     }
620 
621     public interface KeyguardResetCallback {
onKeyguardReset()622         void onKeyguardReset();
623     }
624 
625     /** Create a {@link KeyguardBouncer} once a container and bouncer callback are available. */
626     public static class Factory {
627         private final Context mContext;
628         private final ViewMediatorCallback mCallback;
629         private final DismissCallbackRegistry mDismissCallbackRegistry;
630         private final FalsingCollector mFalsingCollector;
631         private final KeyguardStateController mKeyguardStateController;
632         private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
633         private final KeyguardBypassController mKeyguardBypassController;
634         private final Handler mHandler;
635         private final KeyguardSecurityModel mKeyguardSecurityModel;
636         private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
637 
638         @Inject
Factory(Context context, ViewMediatorCallback callback, DismissCallbackRegistry dismissCallbackRegistry, FalsingCollector falsingCollector, KeyguardStateController keyguardStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, KeyguardBypassController keyguardBypassController, Handler handler, KeyguardSecurityModel keyguardSecurityModel, KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory)639         public Factory(Context context, ViewMediatorCallback callback,
640                 DismissCallbackRegistry dismissCallbackRegistry, FalsingCollector falsingCollector,
641                 KeyguardStateController keyguardStateController,
642                 KeyguardUpdateMonitor keyguardUpdateMonitor,
643                 KeyguardBypassController keyguardBypassController, Handler handler,
644                 KeyguardSecurityModel keyguardSecurityModel,
645                 KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
646             mContext = context;
647             mCallback = callback;
648             mDismissCallbackRegistry = dismissCallbackRegistry;
649             mFalsingCollector = falsingCollector;
650             mKeyguardStateController = keyguardStateController;
651             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
652             mKeyguardBypassController = keyguardBypassController;
653             mHandler = handler;
654             mKeyguardSecurityModel = keyguardSecurityModel;
655             mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
656         }
657 
create(@ootView ViewGroup container, BouncerExpansionCallback expansionCallback)658         public KeyguardBouncer create(@RootView ViewGroup container,
659                 BouncerExpansionCallback expansionCallback) {
660             return new KeyguardBouncer(mContext, mCallback, container,
661                     mDismissCallbackRegistry, mFalsingCollector, expansionCallback,
662                     mKeyguardStateController, mKeyguardUpdateMonitor,
663                     mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
664                     mKeyguardBouncerComponentFactory);
665         }
666     }
667 }
668