• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.biometrics;
18 
19 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
20 
21 import android.annotation.NonNull;
22 import android.content.res.Configuration;
23 import android.util.MathUtils;
24 import android.view.MotionEvent;
25 
26 import com.android.keyguard.KeyguardUpdateMonitor;
27 import com.android.systemui.R;
28 import com.android.systemui.dump.DumpManager;
29 import com.android.systemui.keyguard.KeyguardViewMediator;
30 import com.android.systemui.plugins.statusbar.StatusBarStateController;
31 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
32 import com.android.systemui.statusbar.StatusBarState;
33 import com.android.systemui.statusbar.phone.KeyguardBouncer;
34 import com.android.systemui.statusbar.phone.StatusBar;
35 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
36 import com.android.systemui.statusbar.policy.ConfigurationController;
37 import com.android.systemui.util.concurrency.DelayableExecutor;
38 
39 import java.io.FileDescriptor;
40 import java.io.PrintWriter;
41 
42 
43 /**
44  * Class that coordinates non-HBM animations during keyguard authentication.
45  */
46 public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
47     @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
48     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
49     @NonNull private final DelayableExecutor mExecutor;
50     @NonNull private final KeyguardViewMediator mKeyguardViewMediator;
51     @NonNull private final LockscreenShadeTransitionController mLockScreenShadeTransitionController;
52     @NonNull private final ConfigurationController mConfigurationController;
53     @NonNull private final UdfpsController mUdfpsController;
54 
55     private boolean mShowingUdfpsBouncer;
56     private boolean mUdfpsRequested;
57     private boolean mQsExpanded;
58     private boolean mFaceDetectRunning;
59     private int mStatusBarState;
60     private float mTransitionToFullShadeProgress;
61     private float mLastDozeAmount;
62 
63     /**
64      * hidden amount of pin/pattern/password bouncer
65      * {@link KeyguardBouncer#EXPANSION_VISIBLE} (0f) to
66      * {@link KeyguardBouncer#EXPANSION_HIDDEN} (1f)
67      */
68     private float mInputBouncerHiddenAmount;
69     private boolean mIsBouncerVisible;
70 
UdfpsKeyguardViewController( @onNull UdfpsKeyguardView view, @NonNull StatusBarStateController statusBarStateController, @NonNull StatusBar statusBar, @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull DelayableExecutor mainDelayableExecutor, @NonNull DumpManager dumpManager, @NonNull KeyguardViewMediator keyguardViewMediator, @NonNull LockscreenShadeTransitionController transitionController, @NonNull ConfigurationController configurationController, @NonNull UdfpsController udfpsController)71     protected UdfpsKeyguardViewController(
72             @NonNull UdfpsKeyguardView view,
73             @NonNull StatusBarStateController statusBarStateController,
74             @NonNull StatusBar statusBar,
75             @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
76             @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
77             @NonNull DelayableExecutor mainDelayableExecutor,
78             @NonNull DumpManager dumpManager,
79             @NonNull KeyguardViewMediator keyguardViewMediator,
80             @NonNull LockscreenShadeTransitionController transitionController,
81             @NonNull ConfigurationController configurationController,
82             @NonNull UdfpsController udfpsController) {
83         super(view, statusBarStateController, statusBar, dumpManager);
84         mKeyguardViewManager = statusBarKeyguardViewManager;
85         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
86         mExecutor = mainDelayableExecutor;
87         mKeyguardViewMediator = keyguardViewMediator;
88         mLockScreenShadeTransitionController = transitionController;
89         mConfigurationController = configurationController;
90         mUdfpsController = udfpsController;
91     }
92 
93     @Override
getTag()94     @NonNull String getTag() {
95         return "UdfpsKeyguardViewController";
96     }
97 
98     @Override
onViewAttached()99     protected void onViewAttached() {
100         super.onViewAttached();
101         final float dozeAmount = mStatusBarStateController.getDozeAmount();
102         mLastDozeAmount = dozeAmount;
103         mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
104         mStatusBarStateController.addCallback(mStateListener);
105 
106         mUdfpsRequested = false;
107 
108         mStatusBarState = mStatusBarStateController.getState();
109         mQsExpanded = mKeyguardViewManager.isQsExpanded();
110         mInputBouncerHiddenAmount = KeyguardBouncer.EXPANSION_HIDDEN;
111         mIsBouncerVisible = mKeyguardViewManager.bouncerIsOrWillBeShowing();
112         mConfigurationController.addCallback(mConfigurationListener);
113         updateAlpha();
114         updatePauseAuth();
115 
116         mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
117         mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this);
118     }
119 
120     @Override
onViewDetached()121     protected void onViewDetached() {
122         super.onViewDetached();
123         mFaceDetectRunning = false;
124 
125         mStatusBarStateController.removeCallback(mStateListener);
126         mKeyguardViewManager.removeAlternateAuthInterceptor(mAlternateAuthInterceptor);
127         mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false);
128         mConfigurationController.removeCallback(mConfigurationListener);
129         if (mLockScreenShadeTransitionController.getUdfpsKeyguardViewController() == this) {
130             mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
131         }
132     }
133 
134     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)135     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
136         super.dump(fd, pw, args);
137         pw.println("mShowingUdfpsBouncer=" + mShowingUdfpsBouncer);
138         pw.println("mFaceDetectRunning=" + mFaceDetectRunning);
139         pw.println("mStatusBarState=" + StatusBarState.toShortString(mStatusBarState));
140         pw.println("mQsExpanded=" + mQsExpanded);
141         pw.println("mIsBouncerVisible=" + mIsBouncerVisible);
142         pw.println("mInputBouncerHiddenAmount=" + mInputBouncerHiddenAmount);
143         pw.println("mAlpha=" + mView.getAlpha());
144         pw.println("mUdfpsRequested=" + mUdfpsRequested);
145         pw.println("mView.mUdfpsRequested=" + mView.mUdfpsRequested);
146     }
147 
148     /**
149      * Overrides non-bouncer show logic in shouldPauseAuth to still show icon.
150      * @return whether the udfpsBouncer has been newly shown or hidden
151      */
showUdfpsBouncer(boolean show)152     private boolean showUdfpsBouncer(boolean show) {
153         if (mShowingUdfpsBouncer == show) {
154             return false;
155         }
156 
157         mShowingUdfpsBouncer = show;
158         updatePauseAuth();
159         if (mShowingUdfpsBouncer) {
160             if (mStatusBarState == StatusBarState.SHADE_LOCKED) {
161                 mView.animateInUdfpsBouncer(null);
162             }
163 
164             if (mKeyguardViewManager.isOccluded()) {
165                 mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(true);
166             }
167 
168             mView.announceForAccessibility(mView.getContext().getString(
169                     R.string.accessibility_fingerprint_bouncer));
170         } else {
171             mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(false);
172         }
173         return true;
174     }
175 
176     /**
177      * Returns true if the fingerprint manager is running but we want to temporarily pause
178      * authentication. On the keyguard, we may want to show udfps when the shade
179      * is expanded, so this can be overridden with the showBouncer method.
180      */
shouldPauseAuth()181     public boolean shouldPauseAuth() {
182         if (mShowingUdfpsBouncer) {
183             return false;
184         }
185 
186         if (mUdfpsRequested && !mNotificationShadeExpanded
187                 && (!mIsBouncerVisible
188                 || mInputBouncerHiddenAmount != KeyguardBouncer.EXPANSION_VISIBLE)) {
189             return false;
190         }
191 
192         if (mStatusBarState != KEYGUARD) {
193             return true;
194         }
195 
196         if (mQsExpanded) {
197             return true;
198         }
199 
200         if (mInputBouncerHiddenAmount < .5f || mIsBouncerVisible) {
201             return true;
202         }
203 
204         return false;
205     }
206 
207     @Override
listenForTouchesOutsideView()208     public boolean listenForTouchesOutsideView() {
209         return true;
210     }
211 
212     @Override
onTouchOutsideView()213     public void onTouchOutsideView() {
214         maybeShowInputBouncer();
215     }
216 
217     /**
218      * If we were previously showing the udfps bouncer, hide it and instead show the regular
219      * (pin/pattern/password) bouncer.
220      *
221      * Does nothing if we weren't previously showing the udfps bouncer.
222      */
maybeShowInputBouncer()223     private void maybeShowInputBouncer() {
224         if (mShowingUdfpsBouncer) {
225             mKeyguardViewManager.showBouncer(true);
226             mKeyguardViewManager.resetAlternateAuth(false);
227         }
228     }
229 
230     /**
231      * Set the progress we're currently transitioning to the full shade. 0.0f means we're not
232      * transitioning yet, while 1.0f means we've fully dragged down.
233      */
setTransitionToFullShadeProgress(float progress)234     public void setTransitionToFullShadeProgress(float progress) {
235         mTransitionToFullShadeProgress = progress;
236         updateAlpha();
237     }
238 
updateAlpha()239     private void updateAlpha() {
240         // fade icon on transition to showing bouncer
241         int alpha = mShowingUdfpsBouncer ? 255
242                 : (int) MathUtils.constrain(
243                     MathUtils.map(.5f, .9f, 0f, 255f, mInputBouncerHiddenAmount),
244                     0f, 255f);
245         alpha *= (1.0f - mTransitionToFullShadeProgress);
246         mView.setUnpausedAlpha(alpha);
247     }
248 
249     private final StatusBarStateController.StateListener mStateListener =
250             new StatusBarStateController.StateListener() {
251         @Override
252         public void onDozeAmountChanged(float linear, float eased) {
253             if (mLastDozeAmount < linear) {
254                 showUdfpsBouncer(false);
255             }
256             mView.onDozeAmountChanged(linear, eased);
257             mLastDozeAmount = linear;
258             updatePauseAuth();
259         }
260 
261         @Override
262         public void onStateChanged(int statusBarState) {
263             mStatusBarState = statusBarState;
264             mView.setStatusBarState(statusBarState);
265             updatePauseAuth();
266         }
267     };
268 
269     private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor =
270             new StatusBarKeyguardViewManager.AlternateAuthInterceptor() {
271                 @Override
272                 public boolean showAlternateAuthBouncer() {
273                     return showUdfpsBouncer(true);
274                 }
275 
276                 @Override
277                 public boolean hideAlternateAuthBouncer() {
278                     return showUdfpsBouncer(false);
279                 }
280 
281                 @Override
282                 public boolean isShowingAlternateAuthBouncer() {
283                     return mShowingUdfpsBouncer;
284                 }
285 
286                 @Override
287                 public void requestUdfps(boolean request, int color) {
288                     mUdfpsRequested = request;
289                     mView.requestUdfps(request, color);
290                     updatePauseAuth();
291                 }
292 
293                 @Override
294                 public boolean isAnimating() {
295                     return false;
296                 }
297 
298                 @Override
299                 public void setQsExpanded(boolean expanded) {
300                     mQsExpanded = expanded;
301                     updatePauseAuth();
302                 }
303 
304                 @Override
305                 public boolean onTouch(MotionEvent event) {
306                     if (mTransitionToFullShadeProgress != 0) {
307                         return false;
308                     }
309                     return mUdfpsController.onTouch(event);
310                 }
311 
312                 @Override
313                 public void setBouncerExpansionChanged(float expansion) {
314                     mInputBouncerHiddenAmount = expansion;
315                     updateAlpha();
316                     updatePauseAuth();
317                 }
318 
319                 @Override
320                 public void onBouncerVisibilityChanged() {
321                     mIsBouncerVisible = mKeyguardViewManager.isBouncerShowing();
322                     if (!mIsBouncerVisible) {
323                         mInputBouncerHiddenAmount = 1f;
324                     } else if (mKeyguardViewManager.isBouncerShowing()) {
325                         mInputBouncerHiddenAmount = 0f;
326                     }
327                     updateAlpha();
328                     updatePauseAuth();
329                 }
330 
331                 @Override
332                 public void dump(PrintWriter pw) {
333                     pw.println(getTag());
334                 }
335             };
336 
337     private final ConfigurationController.ConfigurationListener mConfigurationListener =
338             new ConfigurationController.ConfigurationListener() {
339                 @Override
340                 public void onUiModeChanged() {
341                     mView.updateColor();
342                 }
343 
344                 @Override
345                 public void onThemeChanged() {
346                     mView.updateColor();
347                 }
348 
349                 @Override
350                 public void onOverlayChanged() {
351                     mView.updateColor();
352                 }
353 
354                 @Override
355                 public void onConfigChanged(Configuration newConfig) {
356                     mView.updateColor();
357                 }
358             };
359 }
360