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.content.res.Resources;
22 import android.hardware.biometrics.BiometricSourceType;
23 import android.hardware.fingerprint.FingerprintManager;
24 import android.metrics.LogMaker;
25 import android.os.Handler;
26 import android.os.PowerManager;
27 import android.os.SystemClock;
28 import android.os.Trace;
29 import android.util.Log;
30 
31 import com.android.internal.annotations.VisibleForTesting;
32 import com.android.internal.logging.MetricsLogger;
33 import com.android.internal.logging.UiEvent;
34 import com.android.internal.logging.UiEventLogger;
35 import com.android.internal.logging.UiEventLoggerImpl;
36 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
37 import com.android.internal.util.LatencyTracker;
38 import com.android.keyguard.KeyguardConstants;
39 import com.android.keyguard.KeyguardUpdateMonitor;
40 import com.android.keyguard.KeyguardUpdateMonitorCallback;
41 import com.android.keyguard.KeyguardViewController;
42 import com.android.systemui.Dumpable;
43 import com.android.systemui.biometrics.AuthController;
44 import com.android.systemui.dagger.SysUISingleton;
45 import com.android.systemui.dagger.qualifiers.Main;
46 import com.android.systemui.dump.DumpManager;
47 import com.android.systemui.keyguard.KeyguardViewMediator;
48 import com.android.systemui.keyguard.ScreenLifecycle;
49 import com.android.systemui.keyguard.WakefulnessLifecycle;
50 import com.android.systemui.plugins.statusbar.StatusBarStateController;
51 import com.android.systemui.statusbar.CommandQueue;
52 import com.android.systemui.statusbar.NotificationMediaManager;
53 import com.android.systemui.statusbar.NotificationShadeWindowController;
54 import com.android.systemui.statusbar.StatusBarState;
55 import com.android.systemui.statusbar.policy.KeyguardStateController;
56 
57 import java.io.FileDescriptor;
58 import java.io.PrintWriter;
59 import java.lang.annotation.Retention;
60 import java.lang.annotation.RetentionPolicy;
61 import java.util.Map;
62 import java.util.Optional;
63 
64 import javax.inject.Inject;
65 
66 /**
67  * Controller which coordinates all the biometric unlocking actions with the UI.
68  */
69 @SysUISingleton
70 public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable {
71 
72     private static final String TAG = "BiometricUnlockCtrl";
73     private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
74     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
75     private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
76     private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
77     private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2;
78 
79     @IntDef(prefix = { "MODE_" }, value = {
80             MODE_NONE,
81             MODE_WAKE_AND_UNLOCK,
82             MODE_WAKE_AND_UNLOCK_PULSING,
83             MODE_SHOW_BOUNCER,
84             MODE_ONLY_WAKE,
85             MODE_UNLOCK_COLLAPSING,
86             MODE_UNLOCK_FADING,
87             MODE_DISMISS_BOUNCER,
88             MODE_WAKE_AND_UNLOCK_FROM_DREAM
89     })
90     @Retention(RetentionPolicy.SOURCE)
91     public @interface WakeAndUnlockMode {}
92 
93     /**
94      * Mode in which we don't need to wake up the device when we authenticate.
95      */
96     public static final int MODE_NONE = 0;
97 
98     /**
99      * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
100      * a fingerprint while the screen is off and the device was sleeping.
101      */
102     public static final int MODE_WAKE_AND_UNLOCK = 1;
103 
104     /**
105      * Mode in which we wake the device up, and fade out the Keyguard contents because they were
106      * already visible while pulsing in doze mode.
107      */
108     public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
109 
110     /**
111      * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
112      * acquire a fingerprint pulsing in doze mode.
113      */
114     public static final int MODE_SHOW_BOUNCER = 3;
115 
116     /**
117      * Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
118      * */
119     public static final int MODE_ONLY_WAKE = 4;
120 
121     /**
122      * Mode in which fingerprint unlocks the device or passive auth (ie face auth) unlocks the
123      * device while being requested when keyguard is occluded or showing.
124      */
125     public static final int MODE_UNLOCK_COLLAPSING = 5;
126 
127     /**
128      * Mode in which fingerprint wakes and unlocks the device from a dream.
129      */
130     public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 6;
131 
132     /**
133      * Faster mode of dismissing the lock screen when we cross fade to an app
134      * (used for keyguard bypass.)
135      */
136     public static final int MODE_UNLOCK_FADING = 7;
137 
138     /**
139      * When bouncer is visible and will be dismissed.
140      */
141     public static final int MODE_DISMISS_BOUNCER = 8;
142 
143     /**
144      * How much faster we collapse the lockscreen when authenticating with biometric.
145      */
146     private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
147 
148     private final NotificationMediaManager mMediaManager;
149     private final PowerManager mPowerManager;
150     private final Handler mHandler;
151     private final KeyguardBypassController mKeyguardBypassController;
152     private PowerManager.WakeLock mWakeLock;
153     private final ShadeController mShadeController;
154     private final KeyguardUpdateMonitor mUpdateMonitor;
155     private final DozeParameters mDozeParameters;
156     private final KeyguardStateController mKeyguardStateController;
157     private final NotificationShadeWindowController mNotificationShadeWindowController;
158     private final Context mContext;
159     private final int mWakeUpDelay;
160     private int mMode;
161     private BiometricSourceType mBiometricType;
162     private KeyguardViewController mKeyguardViewController;
163     private DozeScrimController mDozeScrimController;
164     private KeyguardViewMediator mKeyguardViewMediator;
165     private ScrimController mScrimController;
166     private PendingAuthenticated mPendingAuthenticated = null;
167     private boolean mPendingShowBouncer;
168     private boolean mHasScreenTurnedOnSinceAuthenticating;
169     private boolean mFadedAwayAfterWakeAndUnlock;
170     private BiometricModeListener mBiometricModeListener;
171 
172     private final MetricsLogger mMetricsLogger;
173     private final AuthController mAuthController;
174     private final StatusBarStateController mStatusBarStateController;
175 
176     private long mLastFpFailureUptimeMillis;
177     private int mNumConsecutiveFpFailures;
178 
179     private static final class PendingAuthenticated {
180         public final int userId;
181         public final BiometricSourceType biometricSourceType;
182         public final boolean isStrongBiometric;
183 
PendingAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric)184         PendingAuthenticated(int userId, BiometricSourceType biometricSourceType,
185                 boolean isStrongBiometric) {
186             this.userId = userId;
187             this.biometricSourceType = biometricSourceType;
188             this.isStrongBiometric = isStrongBiometric;
189         }
190     }
191 
192     @VisibleForTesting
193     public enum BiometricUiEvent implements UiEventLogger.UiEventEnum {
194 
195         @UiEvent(doc = "A biometric event of type fingerprint succeeded.")
196         BIOMETRIC_FINGERPRINT_SUCCESS(396),
197 
198         @UiEvent(doc = "A biometric event of type fingerprint failed.")
199         BIOMETRIC_FINGERPRINT_FAILURE(397),
200 
201         @UiEvent(doc = "A biometric event of type fingerprint errored.")
202         BIOMETRIC_FINGERPRINT_ERROR(398),
203 
204         @UiEvent(doc = "A biometric event of type face unlock succeeded.")
205         BIOMETRIC_FACE_SUCCESS(399),
206 
207         @UiEvent(doc = "A biometric event of type face unlock failed.")
208         BIOMETRIC_FACE_FAILURE(400),
209 
210         @UiEvent(doc = "A biometric event of type face unlock errored.")
211         BIOMETRIC_FACE_ERROR(401),
212 
213         @UiEvent(doc = "A biometric event of type iris succeeded.")
214         BIOMETRIC_IRIS_SUCCESS(402),
215 
216         @UiEvent(doc = "A biometric event of type iris failed.")
217         BIOMETRIC_IRIS_FAILURE(403),
218 
219         @UiEvent(doc = "A biometric event of type iris errored.")
220         BIOMETRIC_IRIS_ERROR(404),
221 
222         @UiEvent(doc = "Bouncer was shown as a result of consecutive failed UDFPS attempts.")
223         BIOMETRIC_BOUNCER_SHOWN(916);
224 
225         private final int mId;
226 
BiometricUiEvent(int id)227         BiometricUiEvent(int id) {
228             mId = id;
229         }
230 
231         @Override
getId()232         public int getId() {
233             return mId;
234         }
235 
236         static final Map<BiometricSourceType, BiometricUiEvent> ERROR_EVENT_BY_SOURCE_TYPE = Map.of(
237                 BiometricSourceType.FINGERPRINT, BiometricUiEvent.BIOMETRIC_FINGERPRINT_ERROR,
238                 BiometricSourceType.FACE, BiometricUiEvent.BIOMETRIC_FACE_ERROR,
239                 BiometricSourceType.IRIS, BiometricUiEvent.BIOMETRIC_IRIS_ERROR
240         );
241 
242         static final Map<BiometricSourceType, BiometricUiEvent> SUCCESS_EVENT_BY_SOURCE_TYPE =
243                 Map.of(
244                     BiometricSourceType.FINGERPRINT, BiometricUiEvent.BIOMETRIC_FINGERPRINT_SUCCESS,
245                     BiometricSourceType.FACE, BiometricUiEvent.BIOMETRIC_FACE_SUCCESS,
246                     BiometricSourceType.IRIS, BiometricUiEvent.BIOMETRIC_IRIS_SUCCESS
247                 );
248 
249         static final Map<BiometricSourceType, BiometricUiEvent> FAILURE_EVENT_BY_SOURCE_TYPE =
250                 Map.of(
251                     BiometricSourceType.FINGERPRINT, BiometricUiEvent.BIOMETRIC_FINGERPRINT_FAILURE,
252                     BiometricSourceType.FACE, BiometricUiEvent.BIOMETRIC_FACE_FAILURE,
253                     BiometricSourceType.IRIS, BiometricUiEvent.BIOMETRIC_IRIS_FAILURE
254                 );
255     }
256 
257     @Inject
BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, ShadeController shadeController, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, @Main Resources resources, KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters, MetricsLogger metricsLogger, DumpManager dumpManager, PowerManager powerManager, NotificationMediaManager notificationMediaManager, WakefulnessLifecycle wakefulnessLifecycle, ScreenLifecycle screenLifecycle, AuthController authController, StatusBarStateController statusBarStateController)258     public BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
259             KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
260             ShadeController shadeController,
261             NotificationShadeWindowController notificationShadeWindowController,
262             KeyguardStateController keyguardStateController, Handler handler,
263             KeyguardUpdateMonitor keyguardUpdateMonitor,
264             @Main Resources resources,
265             KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters,
266             MetricsLogger metricsLogger, DumpManager dumpManager,
267             PowerManager powerManager,
268             NotificationMediaManager notificationMediaManager,
269             WakefulnessLifecycle wakefulnessLifecycle,
270             ScreenLifecycle screenLifecycle,
271             AuthController authController,
272             StatusBarStateController statusBarStateController) {
273         mContext = context;
274         mPowerManager = powerManager;
275         mShadeController = shadeController;
276         mUpdateMonitor = keyguardUpdateMonitor;
277         mDozeParameters = dozeParameters;
278         mUpdateMonitor.registerCallback(this);
279         mMediaManager = notificationMediaManager;
280         wakefulnessLifecycle.addObserver(mWakefulnessObserver);
281         screenLifecycle.addObserver(mScreenObserver);
282 
283         mNotificationShadeWindowController = notificationShadeWindowController;
284         mDozeScrimController = dozeScrimController;
285         mKeyguardViewMediator = keyguardViewMediator;
286         mScrimController = scrimController;
287         mKeyguardStateController = keyguardStateController;
288         mHandler = handler;
289         mWakeUpDelay = resources.getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze);
290         mKeyguardBypassController = keyguardBypassController;
291         mKeyguardBypassController.setUnlockController(this);
292         mMetricsLogger = metricsLogger;
293         mAuthController = authController;
294         mStatusBarStateController = statusBarStateController;
295         dumpManager.registerDumpable(getClass().getName(), this);
296     }
297 
setKeyguardViewController(KeyguardViewController keyguardViewController)298     public void setKeyguardViewController(KeyguardViewController keyguardViewController) {
299         mKeyguardViewController = keyguardViewController;
300     }
301 
302     /** Sets a {@link BiometricModeListener}. */
setBiometricModeListener(BiometricModeListener biometricModeListener)303     public void setBiometricModeListener(BiometricModeListener biometricModeListener) {
304         mBiometricModeListener = biometricModeListener;
305     }
306 
307     private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
308         @Override
309         public void run() {
310             if (DEBUG_BIO_WAKELOCK) {
311                 Log.i(TAG, "biometric wakelock: TIMEOUT!!");
312             }
313             releaseBiometricWakeLock();
314         }
315     };
316 
releaseBiometricWakeLock()317     private void releaseBiometricWakeLock() {
318         if (mWakeLock != null) {
319             mHandler.removeCallbacks(mReleaseBiometricWakeLockRunnable);
320             if (DEBUG_BIO_WAKELOCK) {
321                 Log.i(TAG, "releasing biometric wakelock");
322             }
323             mWakeLock.release();
324             mWakeLock = null;
325         }
326     }
327 
328     @Override
onBiometricAcquired(BiometricSourceType biometricSourceType)329     public void onBiometricAcquired(BiometricSourceType biometricSourceType) {
330         Trace.beginSection("BiometricUnlockController#onBiometricAcquired");
331         releaseBiometricWakeLock();
332         if (!mUpdateMonitor.isDeviceInteractive()) {
333             if (LatencyTracker.isEnabled(mContext)) {
334                 int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
335                 if (biometricSourceType == BiometricSourceType.FACE) {
336                     action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK;
337                 }
338                 LatencyTracker.getInstance(mContext).onActionStart(action);
339             }
340             mWakeLock = mPowerManager.newWakeLock(
341                     PowerManager.PARTIAL_WAKE_LOCK, BIOMETRIC_WAKE_LOCK_NAME);
342             Trace.beginSection("acquiring wake-and-unlock");
343             mWakeLock.acquire();
344             Trace.endSection();
345             if (DEBUG_BIO_WAKELOCK) {
346                 Log.i(TAG, "biometric acquired, grabbing biometric wakelock");
347             }
348             mHandler.postDelayed(mReleaseBiometricWakeLockRunnable,
349                     BIOMETRIC_WAKELOCK_TIMEOUT_MS);
350         }
351         Trace.endSection();
352     }
353 
pulsingOrAod()354     private boolean pulsingOrAod() {
355         final ScrimState scrimState = mScrimController.getState();
356         return scrimState == ScrimState.AOD
357                 || scrimState == ScrimState.PULSING;
358     }
359 
360     @Override
onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric)361     public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
362             boolean isStrongBiometric) {
363         Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
364         if (mUpdateMonitor.isGoingToSleep()) {
365             mPendingAuthenticated = new PendingAuthenticated(userId, biometricSourceType,
366                     isStrongBiometric);
367             Trace.endSection();
368             return;
369         }
370         mBiometricType = biometricSourceType;
371         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
372                 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
373         Optional.ofNullable(BiometricUiEvent.SUCCESS_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
374                 .ifPresent(UI_EVENT_LOGGER::log);
375 
376         boolean unlockAllowed =
377                 mKeyguardStateController.isOccluded()
378                         || mKeyguardBypassController.onBiometricAuthenticated(
379                                 biometricSourceType, isStrongBiometric);
380         if (unlockAllowed) {
381             mKeyguardViewMediator.userActivity();
382             startWakeAndUnlock(biometricSourceType, isStrongBiometric);
383         } else {
384             Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
385         }
386     }
387 
startWakeAndUnlock(BiometricSourceType biometricSourceType, boolean isStrongBiometric)388     public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
389             boolean isStrongBiometric) {
390         startWakeAndUnlock(calculateMode(biometricSourceType, isStrongBiometric));
391     }
392 
startWakeAndUnlock(@akeAndUnlockMode int mode)393     public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
394         Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
395         boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
396         mMode = mode;
397         mHasScreenTurnedOnSinceAuthenticating = false;
398         if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
399             // If we are waking the device up while we are pulsing the clock and the
400             // notifications would light up first, creating an unpleasant animation.
401             // Defer changing the screen brightness by forcing doze brightness on our window
402             // until the clock and the notifications are faded out.
403             mNotificationShadeWindowController.setForceDozeBrightness(true);
404         }
405         // During wake and unlock, we need to draw black before waking up to avoid abrupt
406         // brightness changes due to display state transitions.
407         boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
408         boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
409         Runnable wakeUp = ()-> {
410             if (!wasDeviceInteractive) {
411                 if (DEBUG_BIO_WAKELOCK) {
412                     Log.i(TAG, "bio wakelock: Authenticated, waking up...");
413                 }
414                 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
415                         "android.policy:BIOMETRIC");
416             }
417             if (delayWakeUp) {
418                 mKeyguardViewMediator.onWakeAndUnlocking();
419             }
420             Trace.beginSection("release wake-and-unlock");
421             releaseBiometricWakeLock();
422             Trace.endSection();
423         };
424 
425         if (!delayWakeUp && mMode != MODE_NONE) {
426             wakeUp.run();
427         }
428         switch (mMode) {
429             case MODE_DISMISS_BOUNCER:
430             case MODE_UNLOCK_FADING:
431                 Trace.beginSection("MODE_DISMISS_BOUNCER or MODE_UNLOCK_FADING");
432                 mKeyguardViewController.notifyKeyguardAuthenticated(
433                         false /* strongAuth */);
434                 Trace.endSection();
435                 break;
436             case MODE_UNLOCK_COLLAPSING:
437                 Trace.beginSection("MODE_UNLOCK_COLLAPSING");
438                 if (!wasDeviceInteractive) {
439                     mPendingShowBouncer = true;
440                 } else {
441                     mShadeController.animateCollapsePanels(
442                             CommandQueue.FLAG_EXCLUDE_NONE,
443                             true /* force */,
444                             false /* delayed */,
445                             BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
446                     mPendingShowBouncer = false;
447                     mKeyguardViewController.notifyKeyguardAuthenticated(
448                             false /* strongAuth */);
449                 }
450                 Trace.endSection();
451                 break;
452             case MODE_SHOW_BOUNCER:
453                 Trace.beginSection("MODE_SHOW_BOUNCER");
454                 if (!wasDeviceInteractive) {
455                     mPendingShowBouncer = true;
456                 } else {
457                     showBouncer();
458                 }
459                 Trace.endSection();
460                 break;
461             case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
462             case MODE_WAKE_AND_UNLOCK_PULSING:
463             case MODE_WAKE_AND_UNLOCK:
464                 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
465                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
466                     mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
467                             true /* allowEnterAnimation */);
468                 } else if (mMode == MODE_WAKE_AND_UNLOCK){
469                     Trace.beginSection("MODE_WAKE_AND_UNLOCK");
470                 } else {
471                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
472                     mUpdateMonitor.awakenFromDream();
473                 }
474                 mNotificationShadeWindowController.setNotificationShadeFocusable(false);
475                 if (delayWakeUp) {
476                     mHandler.postDelayed(wakeUp, mWakeUpDelay);
477                 } else {
478                     mKeyguardViewMediator.onWakeAndUnlocking();
479                 }
480                 Trace.endSection();
481                 break;
482             case MODE_ONLY_WAKE:
483             case MODE_NONE:
484                 break;
485         }
486         onModeChanged(mMode);
487         if (mBiometricModeListener != null) {
488             mBiometricModeListener.notifyBiometricAuthModeChanged();
489         }
490         Trace.endSection();
491     }
492 
onModeChanged(@akeAndUnlockMode int mode)493     private void onModeChanged(@WakeAndUnlockMode int mode) {
494         if (mBiometricModeListener != null) {
495             mBiometricModeListener.onModeChanged(mode);
496         }
497     }
498 
showBouncer()499     private void showBouncer() {
500         if (mMode == MODE_SHOW_BOUNCER) {
501             mKeyguardViewController.showBouncer(true);
502         }
503         mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
504                 false /* delayed */, BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
505         mPendingShowBouncer = false;
506     }
507 
508     @Override
onStartedGoingToSleep(int why)509     public void onStartedGoingToSleep(int why) {
510         resetMode();
511         mFadedAwayAfterWakeAndUnlock = false;
512         mPendingAuthenticated = null;
513     }
514 
515     @Override
onFinishedGoingToSleep(int why)516     public void onFinishedGoingToSleep(int why) {
517         Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
518         if (mPendingAuthenticated != null) {
519             PendingAuthenticated pendingAuthenticated = mPendingAuthenticated;
520             // Post this to make sure it's executed after the device is fully locked.
521             mHandler.post(() -> onBiometricAuthenticated(pendingAuthenticated.userId,
522                     pendingAuthenticated.biometricSourceType,
523                     pendingAuthenticated.isStrongBiometric));
524             mPendingAuthenticated = null;
525         }
526         Trace.endSection();
527     }
528 
hasPendingAuthentication()529     public boolean hasPendingAuthentication() {
530         return mPendingAuthenticated != null
531                 && mUpdateMonitor
532                     .isUnlockingWithBiometricAllowed(mPendingAuthenticated.isStrongBiometric)
533                 && mPendingAuthenticated.userId == KeyguardUpdateMonitor.getCurrentUser();
534     }
535 
getMode()536     public int getMode() {
537         return mMode;
538     }
539 
calculateMode(BiometricSourceType biometricSourceType, boolean isStrongBiometric)540     private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType,
541             boolean isStrongBiometric) {
542         if (biometricSourceType == BiometricSourceType.FACE
543                 || biometricSourceType == BiometricSourceType.IRIS) {
544             return calculateModeForPassiveAuth(isStrongBiometric);
545         } else {
546             return calculateModeForFingerprint(isStrongBiometric);
547         }
548     }
549 
calculateModeForFingerprint(boolean isStrongBiometric)550     private @WakeAndUnlockMode int calculateModeForFingerprint(boolean isStrongBiometric) {
551         boolean unlockingAllowed =
552                 mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
553         boolean deviceDreaming = mUpdateMonitor.isDreaming();
554 
555         if (!mUpdateMonitor.isDeviceInteractive()) {
556             if (!mKeyguardViewController.isShowing()) {
557                 return MODE_ONLY_WAKE;
558             } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
559                 return MODE_WAKE_AND_UNLOCK_PULSING;
560             } else if (unlockingAllowed || !mKeyguardStateController.isMethodSecure()) {
561                 return MODE_WAKE_AND_UNLOCK;
562             } else {
563                 return MODE_SHOW_BOUNCER;
564             }
565         }
566         if (unlockingAllowed && deviceDreaming) {
567             return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
568         }
569         if (mKeyguardViewController.isShowing()) {
570             if (mKeyguardViewController.bouncerIsOrWillBeShowing() && unlockingAllowed) {
571                 return MODE_DISMISS_BOUNCER;
572             } else if (unlockingAllowed) {
573                 return MODE_UNLOCK_COLLAPSING;
574             } else if (!mKeyguardViewController.isBouncerShowing()) {
575                 return MODE_SHOW_BOUNCER;
576             }
577         }
578         return MODE_NONE;
579     }
580 
calculateModeForPassiveAuth(boolean isStrongBiometric)581     private @WakeAndUnlockMode int calculateModeForPassiveAuth(boolean isStrongBiometric) {
582         boolean unlockingAllowed =
583                 mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
584         boolean deviceDreaming = mUpdateMonitor.isDreaming();
585         boolean bypass = mKeyguardBypassController.getBypassEnabled()
586                 || mKeyguardBypassController.getUserHasDeviceEntryIntent();
587         if (!mUpdateMonitor.isDeviceInteractive()) {
588             if (!mKeyguardViewController.isShowing()) {
589                 return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE;
590             } else if (!unlockingAllowed) {
591                 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
592             } else if (mDozeScrimController.isPulsing()) {
593                 return bypass ? MODE_WAKE_AND_UNLOCK_PULSING : MODE_ONLY_WAKE;
594             } else {
595                 if (bypass) {
596                     // Wake-up fading out nicely
597                     return MODE_WAKE_AND_UNLOCK_PULSING;
598                 } else {
599                     // We could theoretically return MODE_NONE, but this means that the device
600                     // would be not interactive, unlocked, and the user would not see the device
601                     // state.
602                     return MODE_ONLY_WAKE;
603                 }
604             }
605         }
606         if (unlockingAllowed && deviceDreaming) {
607             return bypass ? MODE_WAKE_AND_UNLOCK_FROM_DREAM : MODE_ONLY_WAKE;
608         }
609         if (unlockingAllowed && mKeyguardStateController.isOccluded()) {
610             return MODE_UNLOCK_COLLAPSING;
611         }
612         if (mKeyguardViewController.isShowing()) {
613             if ((mKeyguardViewController.bouncerIsOrWillBeShowing()
614                     || mKeyguardBypassController.getAltBouncerShowing()) && unlockingAllowed) {
615                 if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
616                     return MODE_UNLOCK_FADING;
617                 } else {
618                     return MODE_DISMISS_BOUNCER;
619                 }
620             } else if (unlockingAllowed) {
621                 return bypass || mAuthController.isUdfpsFingerDown()
622                         ? MODE_UNLOCK_FADING : MODE_NONE;
623             } else {
624                 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
625             }
626         }
627         return MODE_NONE;
628     }
629 
630     @Override
onBiometricAuthFailed(BiometricSourceType biometricSourceType)631     public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
632         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
633                 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
634         Optional.ofNullable(BiometricUiEvent.FAILURE_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
635                 .ifPresent(UI_EVENT_LOGGER::log);
636 
637         long currUptimeMillis = SystemClock.uptimeMillis();
638         if (currUptimeMillis - mLastFpFailureUptimeMillis < 2000) { // attempt within 2 seconds
639             mNumConsecutiveFpFailures += 1;
640         } else {
641             mNumConsecutiveFpFailures = 1;
642         }
643         mLastFpFailureUptimeMillis = currUptimeMillis;
644 
645         if (biometricSourceType.equals(BiometricSourceType.FINGERPRINT)
646                 && mUpdateMonitor.isUdfpsSupported()
647                 && mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
648             startWakeAndUnlock(MODE_SHOW_BOUNCER);
649             UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN);
650             mNumConsecutiveFpFailures = 0;
651         }
652         cleanup();
653     }
654 
655     @Override
onBiometricError(int msgId, String errString, BiometricSourceType biometricSourceType)656     public void onBiometricError(int msgId, String errString,
657             BiometricSourceType biometricSourceType) {
658         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
659                 .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
660                 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
661         Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
662                 .ifPresent(UI_EVENT_LOGGER::log);
663 
664         // if we're on the shade and we're locked out, immediately show the bouncer
665         if (biometricSourceType == BiometricSourceType.FINGERPRINT
666                 && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
667                 || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
668                 && mUpdateMonitor.isUdfpsSupported()
669                 && (mStatusBarStateController.getState() == StatusBarState.SHADE
670                     || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) {
671             startWakeAndUnlock(MODE_SHOW_BOUNCER);
672             UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN);
673         }
674         cleanup();
675     }
676 
cleanup()677     private void cleanup() {
678         releaseBiometricWakeLock();
679     }
680 
startKeyguardFadingAway()681     public void startKeyguardFadingAway() {
682 
683         // Disable brightness override when the ambient contents are fully invisible.
684         mHandler.postDelayed(new Runnable() {
685             @Override
686             public void run() {
687                 mNotificationShadeWindowController.setForceDozeBrightness(false);
688             }
689         }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
690     }
691 
finishKeyguardFadingAway()692     public void finishKeyguardFadingAway() {
693         if (isWakeAndUnlock()) {
694             mFadedAwayAfterWakeAndUnlock = true;
695         }
696         resetMode();
697     }
698 
resetMode()699     private void resetMode() {
700         mMode = MODE_NONE;
701         mBiometricType = null;
702         mNotificationShadeWindowController.setForceDozeBrightness(false);
703         if (mBiometricModeListener != null) {
704             mBiometricModeListener.onResetMode();
705             mBiometricModeListener.notifyBiometricAuthModeChanged();
706         }
707         mNumConsecutiveFpFailures = 0;
708         mLastFpFailureUptimeMillis = 0;
709     }
710 
711     @VisibleForTesting
712     final WakefulnessLifecycle.Observer mWakefulnessObserver =
713             new WakefulnessLifecycle.Observer() {
714         @Override
715         public void onFinishedWakingUp() {
716             if (mPendingShowBouncer) {
717                 BiometricUnlockController.this.showBouncer();
718             }
719         }
720     };
721 
722     private final ScreenLifecycle.Observer mScreenObserver =
723             new ScreenLifecycle.Observer() {
724                 @Override
725                 public void onScreenTurnedOn() {
726                     mHasScreenTurnedOnSinceAuthenticating = true;
727                 }
728             };
729 
hasScreenTurnedOnSinceAuthenticating()730     public boolean hasScreenTurnedOnSinceAuthenticating() {
731         return mHasScreenTurnedOnSinceAuthenticating;
732     }
733 
734     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)735     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
736         pw.println(" BiometricUnlockController:");
737         pw.print("   mMode="); pw.println(mMode);
738         pw.print("   mWakeLock="); pw.println(mWakeLock);
739     }
740 
741     /**
742      * Successful authentication with fingerprint, face, or iris that wakes up the device.
743      */
isWakeAndUnlock()744     public boolean isWakeAndUnlock() {
745         return mMode == MODE_WAKE_AND_UNLOCK
746                 || mMode == MODE_WAKE_AND_UNLOCK_PULSING
747                 || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM;
748     }
749 
750     /**
751      * Successful authentication with fingerprint, face, or iris that wakes up the device.
752      * This will return {@code true} even after the keyguard fades away.
753      */
unlockedByWakeAndUnlock()754     public boolean unlockedByWakeAndUnlock() {
755         return  isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock;
756     }
757 
758     /**
759      * Successful authentication with fingerprint, face, or iris when the screen was either
760      * on or off.
761      */
isBiometricUnlock()762     public boolean isBiometricUnlock() {
763         return isWakeAndUnlock() || mMode == MODE_UNLOCK_COLLAPSING || mMode == MODE_UNLOCK_FADING;
764     }
765 
766     /**
767      * Successful authentication with fingerprint, face, or iris when the lockscreen fades away
768      */
getBiometricType()769     public BiometricSourceType getBiometricType() {
770         return mBiometricType;
771     }
772 
773     /**
774      * Translates biometric source type for logging purpose.
775      */
toSubtype(BiometricSourceType biometricSourceType)776     private int toSubtype(BiometricSourceType biometricSourceType) {
777         switch (biometricSourceType) {
778             case FINGERPRINT:
779                 return 0;
780             case FACE:
781                 return 1;
782             case IRIS:
783                 return 2;
784             default:
785                 return 3;
786         }
787     }
788 
789     /** An interface to interact with the {@link BiometricUnlockController}. */
790     public interface BiometricModeListener {
791         /** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
onResetMode()792         void onResetMode();
793         /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
onModeChanged(@akeAndUnlockMode int mode)794         void onModeChanged(@WakeAndUnlockMode int mode);
795         /** Called after processing {@link #onModeChanged(int)}. */
notifyBiometricAuthModeChanged()796         void notifyBiometricAuthModeChanged();
797     }
798 }
799