1 /*
2  * Copyright (C) 2015 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 android.annotation.IntDef;
20 import android.content.Context;
21 import android.hardware.biometrics.BiometricSourceType;
22 import android.metrics.LogMaker;
23 import android.os.Handler;
24 import android.os.PowerManager;
25 import android.os.SystemClock;
26 import android.os.Trace;
27 import android.util.Log;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 import com.android.internal.logging.MetricsLogger;
31 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
32 import com.android.internal.util.LatencyTracker;
33 import com.android.keyguard.KeyguardConstants;
34 import com.android.keyguard.KeyguardUpdateMonitor;
35 import com.android.keyguard.KeyguardUpdateMonitorCallback;
36 import com.android.systemui.Dependency;
37 import com.android.systemui.keyguard.KeyguardViewMediator;
38 import com.android.systemui.keyguard.ScreenLifecycle;
39 import com.android.systemui.keyguard.WakefulnessLifecycle;
40 import com.android.systemui.statusbar.NotificationMediaManager;
41 
42 import java.io.PrintWriter;
43 import java.lang.annotation.Retention;
44 import java.lang.annotation.RetentionPolicy;
45 
46 /**
47  * Controller which coordinates all the biometric unlocking actions with the UI.
48  */
49 public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
50 
51     private static final String TAG = "BiometricUnlockController";
52     private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
53     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
54     private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
55 
56     @IntDef(prefix = { "MODE_" }, value = {
57             MODE_NONE,
58             MODE_WAKE_AND_UNLOCK,
59             MODE_WAKE_AND_UNLOCK_PULSING,
60             MODE_SHOW_BOUNCER,
61             MODE_ONLY_WAKE,
62             MODE_UNLOCK_COLLAPSING,
63             MODE_UNLOCK_FADING,
64             MODE_DISMISS_BOUNCER,
65             MODE_WAKE_AND_UNLOCK_FROM_DREAM
66     })
67     @Retention(RetentionPolicy.SOURCE)
68     public @interface WakeAndUnlockMode {}
69 
70     /**
71      * Mode in which we don't need to wake up the device when we authenticate.
72      */
73     public static final int MODE_NONE = 0;
74 
75     /**
76      * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
77      * a fingerprint while the screen is off and the device was sleeping.
78      */
79     public static final int MODE_WAKE_AND_UNLOCK = 1;
80 
81     /**
82      * Mode in which we wake the device up, and fade out the Keyguard contents because they were
83      * already visible while pulsing in doze mode.
84      */
85     public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
86 
87     /**
88      * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
89      * acquire a fingerprint pulsing in doze mode.
90      */
91     public static final int MODE_SHOW_BOUNCER = 3;
92 
93     /**
94      * Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
95      * */
96     public static final int MODE_ONLY_WAKE = 4;
97 
98     /**
99      * Mode in which fingerprint unlocks the device.
100      */
101     public static final int MODE_UNLOCK_COLLAPSING = 5;
102 
103     /**
104      * Mode in which fingerprint wakes and unlocks the device from a dream.
105      */
106     public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 6;
107 
108     /**
109      * Faster mode of dismissing the lock screen when we cross fade to an app
110      * (used for keyguard bypass.)
111      */
112     public static final int MODE_UNLOCK_FADING = 7;
113 
114     /**
115      * When bouncer is visible and will be dismissed.
116      */
117     public static final int MODE_DISMISS_BOUNCER = 8;
118 
119     /**
120      * How much faster we collapse the lockscreen when authenticating with biometric.
121      */
122     private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
123 
124     private final NotificationMediaManager mMediaManager;
125     private final PowerManager mPowerManager;
126     private final Handler mHandler;
127     private final KeyguardBypassController mKeyguardBypassController;
128     private PowerManager.WakeLock mWakeLock;
129     private final KeyguardUpdateMonitor mUpdateMonitor;
130     private final UnlockMethodCache mUnlockMethodCache;
131     private final StatusBarWindowController mStatusBarWindowController;
132     private final Context mContext;
133     private final int mWakeUpDelay;
134     private int mMode;
135     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
136     private DozeScrimController mDozeScrimController;
137     private KeyguardViewMediator mKeyguardViewMediator;
138     private ScrimController mScrimController;
139     private StatusBar mStatusBar;
140     private int mPendingAuthenticatedUserId = -1;
141     private BiometricSourceType mPendingAuthenticatedBioSourceType = null;
142     private boolean mPendingShowBouncer;
143     private boolean mHasScreenTurnedOnSinceAuthenticating;
144     private boolean mFadedAwayAfterWakeAndUnlock;
145 
146     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
147 
BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, StatusBar statusBar, UnlockMethodCache unlockMethodCache, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, KeyguardBypassController keyguardBypassController)148     public BiometricUnlockController(Context context,
149             DozeScrimController dozeScrimController,
150             KeyguardViewMediator keyguardViewMediator,
151             ScrimController scrimController,
152             StatusBar statusBar,
153             UnlockMethodCache unlockMethodCache, Handler handler,
154             KeyguardUpdateMonitor keyguardUpdateMonitor,
155             KeyguardBypassController keyguardBypassController) {
156         this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
157                 unlockMethodCache, handler, keyguardUpdateMonitor,
158                 context.getResources()
159                         .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
160                 keyguardBypassController);
161     }
162 
163     @VisibleForTesting
BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, StatusBar statusBar, UnlockMethodCache unlockMethodCache, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, int wakeUpDelay, KeyguardBypassController keyguardBypassController)164     protected BiometricUnlockController(Context context,
165                                      DozeScrimController dozeScrimController,
166                                      KeyguardViewMediator keyguardViewMediator,
167                                      ScrimController scrimController,
168                                      StatusBar statusBar,
169                                      UnlockMethodCache unlockMethodCache, Handler handler,
170                                      KeyguardUpdateMonitor keyguardUpdateMonitor,
171                                      int wakeUpDelay,
172                                      KeyguardBypassController keyguardBypassController) {
173         mContext = context;
174         mPowerManager = context.getSystemService(PowerManager.class);
175         mUpdateMonitor = keyguardUpdateMonitor;
176         mUpdateMonitor.registerCallback(this);
177         mMediaManager = Dependency.get(NotificationMediaManager.class);
178         Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
179         Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
180         mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
181         mDozeScrimController = dozeScrimController;
182         mKeyguardViewMediator = keyguardViewMediator;
183         mScrimController = scrimController;
184         mStatusBar = statusBar;
185         mUnlockMethodCache = unlockMethodCache;
186         mHandler = handler;
187         mWakeUpDelay = wakeUpDelay;
188         mKeyguardBypassController = keyguardBypassController;
189         mKeyguardBypassController.setUnlockController(this);
190     }
191 
setStatusBarKeyguardViewManager( StatusBarKeyguardViewManager statusBarKeyguardViewManager)192     public void setStatusBarKeyguardViewManager(
193             StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
194         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
195     }
196 
197     private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
198         @Override
199         public void run() {
200             if (DEBUG_BIO_WAKELOCK) {
201                 Log.i(TAG, "biometric wakelock: TIMEOUT!!");
202             }
203             releaseBiometricWakeLock();
204         }
205     };
206 
releaseBiometricWakeLock()207     private void releaseBiometricWakeLock() {
208         if (mWakeLock != null) {
209             mHandler.removeCallbacks(mReleaseBiometricWakeLockRunnable);
210             if (DEBUG_BIO_WAKELOCK) {
211                 Log.i(TAG, "releasing biometric wakelock");
212             }
213             mWakeLock.release();
214             mWakeLock = null;
215         }
216     }
217 
218     @Override
onBiometricAcquired(BiometricSourceType biometricSourceType)219     public void onBiometricAcquired(BiometricSourceType biometricSourceType) {
220         Trace.beginSection("BiometricUnlockController#onBiometricAcquired");
221         releaseBiometricWakeLock();
222         if (!mUpdateMonitor.isDeviceInteractive()) {
223             if (LatencyTracker.isEnabled(mContext)) {
224                 int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
225                 if (biometricSourceType == BiometricSourceType.FACE) {
226                     action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK;
227                 }
228                 LatencyTracker.getInstance(mContext).onActionStart(action);
229             }
230             mWakeLock = mPowerManager.newWakeLock(
231                     PowerManager.PARTIAL_WAKE_LOCK, BIOMETRIC_WAKE_LOCK_NAME);
232             Trace.beginSection("acquiring wake-and-unlock");
233             mWakeLock.acquire();
234             Trace.endSection();
235             if (DEBUG_BIO_WAKELOCK) {
236                 Log.i(TAG, "biometric acquired, grabbing biometric wakelock");
237             }
238             mHandler.postDelayed(mReleaseBiometricWakeLockRunnable,
239                     BIOMETRIC_WAKELOCK_TIMEOUT_MS);
240         }
241         Trace.endSection();
242     }
243 
pulsingOrAod()244     private boolean pulsingOrAod() {
245         final ScrimState scrimState = mScrimController.getState();
246         return scrimState == ScrimState.AOD
247                 || scrimState == ScrimState.PULSING;
248     }
249 
250     @Override
onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType)251     public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
252         Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
253         if (mUpdateMonitor.isGoingToSleep()) {
254             mPendingAuthenticatedUserId = userId;
255             mPendingAuthenticatedBioSourceType = biometricSourceType;
256             Trace.endSection();
257             return;
258         }
259         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
260                 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
261         boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
262                 biometricSourceType);
263         if (unlockAllowed) {
264             mKeyguardViewMediator.userActivity();
265             startWakeAndUnlock(biometricSourceType);
266         } else {
267             Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
268         }
269     }
270 
startWakeAndUnlock(BiometricSourceType biometricSourceType)271     public void startWakeAndUnlock(BiometricSourceType biometricSourceType) {
272         startWakeAndUnlock(calculateMode(biometricSourceType));
273     }
274 
startWakeAndUnlock(@akeAndUnlockMode int mode)275     public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
276         Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
277         boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
278         mMode = mode;
279         mHasScreenTurnedOnSinceAuthenticating = false;
280         if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
281             // If we are waking the device up while we are pulsing the clock and the
282             // notifications would light up first, creating an unpleasant animation.
283             // Defer changing the screen brightness by forcing doze brightness on our window
284             // until the clock and the notifications are faded out.
285             mStatusBarWindowController.setForceDozeBrightness(true);
286         }
287         // During wake and unlock, we need to draw black before waking up to avoid abrupt
288         // brightness changes due to display state transitions.
289         boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
290         boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
291         Runnable wakeUp = ()-> {
292             if (!wasDeviceInteractive) {
293                 if (DEBUG_BIO_WAKELOCK) {
294                     Log.i(TAG, "bio wakelock: Authenticated, waking up...");
295                 }
296                 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
297                         "android.policy:BIOMETRIC");
298             }
299             if (delayWakeUp) {
300                 mKeyguardViewMediator.onWakeAndUnlocking();
301             }
302             Trace.beginSection("release wake-and-unlock");
303             releaseBiometricWakeLock();
304             Trace.endSection();
305         };
306 
307         if (!delayWakeUp && mMode != MODE_NONE) {
308             wakeUp.run();
309         }
310         switch (mMode) {
311             case MODE_DISMISS_BOUNCER:
312             case MODE_UNLOCK_FADING:
313                 Trace.beginSection("MODE_DISMISS_BOUNCER or MODE_UNLOCK_FADING");
314                 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
315                         false /* strongAuth */);
316                 Trace.endSection();
317                 break;
318             case MODE_UNLOCK_COLLAPSING:
319             case MODE_SHOW_BOUNCER:
320                 Trace.beginSection("MODE_UNLOCK_COLLAPSING or MODE_SHOW_BOUNCER");
321                 if (!wasDeviceInteractive) {
322                     mPendingShowBouncer = true;
323                 } else {
324                     showBouncer();
325                 }
326                 Trace.endSection();
327                 break;
328             case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
329             case MODE_WAKE_AND_UNLOCK_PULSING:
330             case MODE_WAKE_AND_UNLOCK:
331                 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
332                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
333                     mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
334                             true /* allowEnterAnimation */);
335                 } else if (mMode == MODE_WAKE_AND_UNLOCK){
336                     Trace.beginSection("MODE_WAKE_AND_UNLOCK");
337                 } else {
338                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
339                     mUpdateMonitor.awakenFromDream();
340                 }
341                 mStatusBarWindowController.setStatusBarFocusable(false);
342                 if (delayWakeUp) {
343                     mHandler.postDelayed(wakeUp, mWakeUpDelay);
344                 } else {
345                     mKeyguardViewMediator.onWakeAndUnlocking();
346                 }
347                 if (mStatusBar.getNavigationBarView() != null) {
348                     mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
349                 }
350                 Trace.endSection();
351                 break;
352             case MODE_ONLY_WAKE:
353             case MODE_NONE:
354                 break;
355         }
356         mStatusBar.notifyBiometricAuthModeChanged();
357         Trace.endSection();
358     }
359 
showBouncer()360     private void showBouncer() {
361         if (mMode == MODE_SHOW_BOUNCER) {
362             mStatusBarKeyguardViewManager.showBouncer(false);
363         }
364         mStatusBarKeyguardViewManager.animateCollapsePanels(
365                 BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
366         mPendingShowBouncer = false;
367     }
368 
369     @Override
onStartedGoingToSleep(int why)370     public void onStartedGoingToSleep(int why) {
371         resetMode();
372         mFadedAwayAfterWakeAndUnlock = false;
373         mPendingAuthenticatedUserId = -1;
374         mPendingAuthenticatedBioSourceType = null;
375     }
376 
377     @Override
onFinishedGoingToSleep(int why)378     public void onFinishedGoingToSleep(int why) {
379         Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
380         BiometricSourceType pendingType = mPendingAuthenticatedBioSourceType;
381         int pendingUserId = mPendingAuthenticatedUserId;
382         if (pendingUserId != -1 && pendingType != null) {
383             // Post this to make sure it's executed after the device is fully locked.
384             mHandler.post(() -> onBiometricAuthenticated(pendingUserId, pendingType));
385         }
386         mPendingAuthenticatedUserId = -1;
387         mPendingAuthenticatedBioSourceType = null;
388         Trace.endSection();
389     }
390 
hasPendingAuthentication()391     public boolean hasPendingAuthentication() {
392         return mPendingAuthenticatedUserId != -1
393                 && mUpdateMonitor.isUnlockingWithBiometricAllowed()
394                 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
395     }
396 
getMode()397     public int getMode() {
398         return mMode;
399     }
400 
calculateMode(BiometricSourceType biometricSourceType)401     private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType) {
402         if (biometricSourceType == BiometricSourceType.FACE
403                 || biometricSourceType == BiometricSourceType.IRIS) {
404             return calculateModeForPassiveAuth();
405         } else {
406             return calculateModeForFingerprint();
407         }
408     }
409 
calculateModeForFingerprint()410     private @WakeAndUnlockMode int calculateModeForFingerprint() {
411         boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
412         boolean deviceDreaming = mUpdateMonitor.isDreaming();
413 
414         if (!mUpdateMonitor.isDeviceInteractive()) {
415             if (!mStatusBarKeyguardViewManager.isShowing()) {
416                 return MODE_ONLY_WAKE;
417             } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
418                 return MODE_WAKE_AND_UNLOCK_PULSING;
419             } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
420                 return MODE_WAKE_AND_UNLOCK;
421             } else {
422                 return MODE_SHOW_BOUNCER;
423             }
424         }
425         if (unlockingAllowed && deviceDreaming) {
426             return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
427         }
428         if (mStatusBarKeyguardViewManager.isShowing()) {
429             if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) {
430                 return MODE_DISMISS_BOUNCER;
431             } else if (unlockingAllowed) {
432                 return MODE_UNLOCK_COLLAPSING;
433             } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
434                 return MODE_SHOW_BOUNCER;
435             }
436         }
437         return MODE_NONE;
438     }
439 
calculateModeForPassiveAuth()440     private @WakeAndUnlockMode int calculateModeForPassiveAuth() {
441         boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
442         boolean deviceDreaming = mUpdateMonitor.isDreaming();
443         boolean bypass = mKeyguardBypassController.getBypassEnabled();
444 
445         if (!mUpdateMonitor.isDeviceInteractive()) {
446             if (!mStatusBarKeyguardViewManager.isShowing()) {
447                 return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE;
448             } else if (!unlockingAllowed) {
449                 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
450             } else if (mDozeScrimController.isPulsing()) {
451                 // Let's not wake-up to lock screen when not bypassing, otherwise the notification
452                 // would move as the user tried to tap it.
453                 return bypass ? MODE_WAKE_AND_UNLOCK_PULSING : MODE_NONE;
454             } else {
455                 if (bypass) {
456                     // Wake-up fading out nicely
457                     return MODE_WAKE_AND_UNLOCK_PULSING;
458                 } else {
459                     // We could theoretically return MODE_NONE, but this means that the device
460                     // would be not interactive, unlocked, and the user would not see the device
461                     // state.
462                     return MODE_ONLY_WAKE;
463                 }
464             }
465         }
466         if (unlockingAllowed && deviceDreaming) {
467             return bypass ? MODE_WAKE_AND_UNLOCK_FROM_DREAM : MODE_ONLY_WAKE;
468         }
469         if (mStatusBarKeyguardViewManager.isShowing()) {
470             if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) {
471                 if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
472                     return MODE_UNLOCK_FADING;
473                 } else {
474                     return MODE_DISMISS_BOUNCER;
475                 }
476             } else if (unlockingAllowed) {
477                 return bypass ? MODE_UNLOCK_FADING : MODE_NONE;
478             } else {
479                 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
480             }
481         }
482         return MODE_NONE;
483     }
484 
485     @Override
onBiometricAuthFailed(BiometricSourceType biometricSourceType)486     public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
487         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
488                 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
489         cleanup();
490     }
491 
492     @Override
onBiometricError(int msgId, String errString, BiometricSourceType biometricSourceType)493     public void onBiometricError(int msgId, String errString,
494             BiometricSourceType biometricSourceType) {
495         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
496                 .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
497                 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
498         cleanup();
499     }
500 
cleanup()501     private void cleanup() {
502         releaseBiometricWakeLock();
503     }
504 
startKeyguardFadingAway()505     public void startKeyguardFadingAway() {
506 
507         // Disable brightness override when the ambient contents are fully invisible.
508         mHandler.postDelayed(new Runnable() {
509             @Override
510             public void run() {
511                 mStatusBarWindowController.setForceDozeBrightness(false);
512             }
513         }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
514     }
515 
finishKeyguardFadingAway()516     public void finishKeyguardFadingAway() {
517         if (isWakeAndUnlock()) {
518             mFadedAwayAfterWakeAndUnlock = true;
519         }
520         resetMode();
521     }
522 
resetMode()523     private void resetMode() {
524         mMode = MODE_NONE;
525         mStatusBarWindowController.setForceDozeBrightness(false);
526         if (mStatusBar.getNavigationBarView() != null) {
527             mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
528         }
529         mStatusBar.notifyBiometricAuthModeChanged();
530     }
531 
532     @VisibleForTesting
533     final WakefulnessLifecycle.Observer mWakefulnessObserver =
534             new WakefulnessLifecycle.Observer() {
535         @Override
536         public void onFinishedWakingUp() {
537             if (mPendingShowBouncer) {
538                 BiometricUnlockController.this.showBouncer();
539             }
540         }
541     };
542 
543     private final ScreenLifecycle.Observer mScreenObserver =
544             new ScreenLifecycle.Observer() {
545                 @Override
546                 public void onScreenTurnedOn() {
547                     mHasScreenTurnedOnSinceAuthenticating = true;
548                 }
549             };
550 
hasScreenTurnedOnSinceAuthenticating()551     public boolean hasScreenTurnedOnSinceAuthenticating() {
552         return mHasScreenTurnedOnSinceAuthenticating;
553     }
554 
dump(PrintWriter pw)555     public void dump(PrintWriter pw) {
556         pw.println(" BiometricUnlockController:");
557         pw.print("   mMode="); pw.println(mMode);
558         pw.print("   mWakeLock="); pw.println(mWakeLock);
559     }
560 
561     /**
562      * Successful authentication with fingerprint, face, or iris that wakes up the device.
563      */
isWakeAndUnlock()564     public boolean isWakeAndUnlock() {
565         return mMode == MODE_WAKE_AND_UNLOCK
566                 || mMode == MODE_WAKE_AND_UNLOCK_PULSING
567                 || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM;
568     }
569 
570     /**
571      * Successful authentication with fingerprint, face, or iris that wakes up the device.
572      * This will return {@code true} even after the keyguard fades away.
573      */
unlockedByWakeAndUnlock()574     public boolean unlockedByWakeAndUnlock() {
575         return  isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock;
576     }
577 
578     /**
579      * Successful authentication with fingerprint, face, or iris when the screen was either
580      * on or off.
581      */
isBiometricUnlock()582     public boolean isBiometricUnlock() {
583         return isWakeAndUnlock() || mMode == MODE_UNLOCK_COLLAPSING || mMode == MODE_UNLOCK_FADING;
584     }
585 
586     /**
587      * Successful authentication with fingerprint, face, or iris when the lockscreen fades away
588      */
isUnlockFading()589     public boolean isUnlockFading() {
590         return mMode == MODE_UNLOCK_FADING;
591     }
592 
593     /**
594      * Translates biometric source type for logging purpose.
595      */
toSubtype(BiometricSourceType biometricSourceType)596     private int toSubtype(BiometricSourceType biometricSourceType) {
597         switch (biometricSourceType) {
598             case FINGERPRINT:
599                 return 0;
600             case FACE:
601                 return 1;
602             case IRIS:
603                 return 2;
604             default:
605                 return 3;
606         }
607     }
608 }
609