• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.app.StatusBarManager.SESSION_KEYGUARD;
20 
21 import static com.android.systemui.keyguard.WakefulnessLifecycle.UNKNOWN_LAST_WAKE_TIME;
22 
23 import android.annotation.IntDef;
24 import android.content.res.Resources;
25 import android.hardware.biometrics.BiometricFaceConstants;
26 import android.hardware.biometrics.BiometricFingerprintConstants;
27 import android.hardware.biometrics.BiometricSourceType;
28 import android.hardware.fingerprint.FingerprintManager;
29 import android.metrics.LogMaker;
30 import android.os.Handler;
31 import android.os.PowerManager;
32 import android.os.Trace;
33 
34 import androidx.annotation.Nullable;
35 
36 import com.android.internal.annotations.VisibleForTesting;
37 import com.android.internal.logging.InstanceId;
38 import com.android.internal.logging.MetricsLogger;
39 import com.android.internal.logging.UiEvent;
40 import com.android.internal.logging.UiEventLogger;
41 import com.android.internal.logging.UiEventLoggerImpl;
42 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
43 import com.android.internal.util.LatencyTracker;
44 import com.android.keyguard.KeyguardUpdateMonitor;
45 import com.android.keyguard.KeyguardUpdateMonitorCallback;
46 import com.android.keyguard.KeyguardViewController;
47 import com.android.keyguard.logging.BiometricUnlockLogger;
48 import com.android.systemui.Dumpable;
49 import com.android.systemui.R;
50 import com.android.systemui.biometrics.AuthController;
51 import com.android.systemui.dagger.SysUISingleton;
52 import com.android.systemui.dagger.qualifiers.Main;
53 import com.android.systemui.dump.DumpManager;
54 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
55 import com.android.systemui.keyguard.KeyguardViewMediator;
56 import com.android.systemui.keyguard.ScreenLifecycle;
57 import com.android.systemui.keyguard.WakefulnessLifecycle;
58 import com.android.systemui.log.SessionTracker;
59 import com.android.systemui.plugins.statusbar.StatusBarStateController;
60 import com.android.systemui.shade.ShadeController;
61 import com.android.systemui.statusbar.CommandQueue;
62 import com.android.systemui.statusbar.NotificationMediaManager;
63 import com.android.systemui.statusbar.NotificationShadeWindowController;
64 import com.android.systemui.statusbar.VibratorHelper;
65 import com.android.systemui.statusbar.policy.KeyguardStateController;
66 import com.android.systemui.util.time.SystemClock;
67 
68 import java.io.PrintWriter;
69 import java.lang.annotation.Retention;
70 import java.lang.annotation.RetentionPolicy;
71 import java.util.HashSet;
72 import java.util.Map;
73 import java.util.Optional;
74 import java.util.Set;
75 
76 import javax.inject.Inject;
77 
78 /**
79  * Controller which coordinates all the biometric unlocking actions with the UI.
80  */
81 @SysUISingleton
82 public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable {
83     private static final long RECENT_POWER_BUTTON_PRESS_THRESHOLD_MS = 400L;
84     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
85     private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
86     private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
87     private static final int UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
88 
89     @IntDef(prefix = { "MODE_" }, value = {
90             MODE_NONE,
91             MODE_WAKE_AND_UNLOCK,
92             MODE_WAKE_AND_UNLOCK_PULSING,
93             MODE_SHOW_BOUNCER,
94             MODE_ONLY_WAKE,
95             MODE_UNLOCK_COLLAPSING,
96             MODE_DISMISS_BOUNCER,
97             MODE_WAKE_AND_UNLOCK_FROM_DREAM
98     })
99     @Retention(RetentionPolicy.SOURCE)
100     public @interface WakeAndUnlockMode {}
101 
102     /**
103      * Mode in which we don't need to wake up the device when we authenticate.
104      */
105     public static final int MODE_NONE = 0;
106 
107     /**
108      * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
109      * a fingerprint while the screen is off and the device was sleeping.
110      */
111     public static final int MODE_WAKE_AND_UNLOCK = 1;
112 
113     /**
114      * Mode in which we wake the device up, and fade out the Keyguard contents because they were
115      * already visible while pulsing in doze mode.
116      */
117     public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
118 
119     /**
120      * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
121      * acquire a fingerprint pulsing in doze mode.
122      */
123     public static final int MODE_SHOW_BOUNCER = 3;
124 
125     /**
126      * Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
127      * */
128     public static final int MODE_ONLY_WAKE = 4;
129 
130     /**
131      * Mode in which fingerprint unlocks the device or passive auth (ie face auth) unlocks the
132      * device while being requested when keyguard is occluded or showing.
133      */
134     public static final int MODE_UNLOCK_COLLAPSING = 5;
135 
136     /**
137      * Mode in which fingerprint wakes and unlocks the device from a dream.
138      */
139     public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 6;
140 
141     /**
142      * When bouncer is visible and will be dismissed.
143      */
144     public static final int MODE_DISMISS_BOUNCER = 7;
145 
146     /**
147      * How much faster we collapse the lockscreen when authenticating with biometric.
148      */
149     private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
150 
151     private final NotificationMediaManager mMediaManager;
152     private final PowerManager mPowerManager;
153     private final Handler mHandler;
154     private final KeyguardBypassController mKeyguardBypassController;
155     private PowerManager.WakeLock mWakeLock;
156     private final com.android.systemui.shade.ShadeController mShadeController;
157     private final KeyguardUpdateMonitor mUpdateMonitor;
158     private final KeyguardStateController mKeyguardStateController;
159     private final NotificationShadeWindowController mNotificationShadeWindowController;
160     private final SessionTracker mSessionTracker;
161     private final int mConsecutiveFpFailureThreshold;
162     private int mMode;
163     private BiometricSourceType mBiometricType;
164     private KeyguardViewController mKeyguardViewController;
165     private DozeScrimController mDozeScrimController;
166     private KeyguardViewMediator mKeyguardViewMediator;
167     private PendingAuthenticated mPendingAuthenticated = null;
168     private boolean mHasScreenTurnedOnSinceAuthenticating;
169     private boolean mFadedAwayAfterWakeAndUnlock;
170     private Set<BiometricModeListener> mBiometricModeListeners = new HashSet<>();
171 
172     private final MetricsLogger mMetricsLogger;
173     private final AuthController mAuthController;
174     private final StatusBarStateController mStatusBarStateController;
175     private final WakefulnessLifecycle mWakefulnessLifecycle;
176     private final LatencyTracker mLatencyTracker;
177     private final VibratorHelper mVibratorHelper;
178     private final BiometricUnlockLogger mLogger;
179     private final SystemClock mSystemClock;
180 
181     private long mLastFpFailureUptimeMillis;
182     private int mNumConsecutiveFpFailures;
183 
184     private static final class PendingAuthenticated {
185         public final int userId;
186         public final BiometricSourceType biometricSourceType;
187         public final boolean isStrongBiometric;
188 
PendingAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric)189         PendingAuthenticated(int userId, BiometricSourceType biometricSourceType,
190                 boolean isStrongBiometric) {
191             this.userId = userId;
192             this.biometricSourceType = biometricSourceType;
193             this.isStrongBiometric = isStrongBiometric;
194         }
195     }
196 
197     @VisibleForTesting
198     public enum BiometricUiEvent implements UiEventLogger.UiEventEnum {
199 
200         @UiEvent(doc = "A biometric event of type fingerprint succeeded.")
201         BIOMETRIC_FINGERPRINT_SUCCESS(396),
202 
203         @UiEvent(doc = "A biometric event of type fingerprint failed.")
204         BIOMETRIC_FINGERPRINT_FAILURE(397),
205 
206         @UiEvent(doc = "A biometric event of type fingerprint errored.")
207         BIOMETRIC_FINGERPRINT_ERROR(398),
208 
209         @UiEvent(doc = "A biometric event of type face unlock succeeded.")
210         BIOMETRIC_FACE_SUCCESS(399),
211 
212         @UiEvent(doc = "A biometric event of type face unlock failed.")
213         BIOMETRIC_FACE_FAILURE(400),
214 
215         @UiEvent(doc = "A biometric event of type face unlock errored.")
216         BIOMETRIC_FACE_ERROR(401),
217 
218         @UiEvent(doc = "A biometric event of type iris succeeded.")
219         BIOMETRIC_IRIS_SUCCESS(402),
220 
221         @UiEvent(doc = "A biometric event of type iris failed.")
222         BIOMETRIC_IRIS_FAILURE(403),
223 
224         @UiEvent(doc = "A biometric event of type iris errored.")
225         BIOMETRIC_IRIS_ERROR(404),
226 
227         @UiEvent(doc = "Bouncer was shown as a result of consecutive failed UDFPS attempts.")
228         BIOMETRIC_BOUNCER_SHOWN(916);
229 
230         private final int mId;
231 
BiometricUiEvent(int id)232         BiometricUiEvent(int id) {
233             mId = id;
234         }
235 
236         @Override
getId()237         public int getId() {
238             return mId;
239         }
240 
241         static final Map<BiometricSourceType, BiometricUiEvent> ERROR_EVENT_BY_SOURCE_TYPE = Map.of(
242                 BiometricSourceType.FINGERPRINT, BiometricUiEvent.BIOMETRIC_FINGERPRINT_ERROR,
243                 BiometricSourceType.FACE, BiometricUiEvent.BIOMETRIC_FACE_ERROR,
244                 BiometricSourceType.IRIS, BiometricUiEvent.BIOMETRIC_IRIS_ERROR
245         );
246 
247         static final Map<BiometricSourceType, BiometricUiEvent> SUCCESS_EVENT_BY_SOURCE_TYPE =
248                 Map.of(
249                     BiometricSourceType.FINGERPRINT, BiometricUiEvent.BIOMETRIC_FINGERPRINT_SUCCESS,
250                     BiometricSourceType.FACE, BiometricUiEvent.BIOMETRIC_FACE_SUCCESS,
251                     BiometricSourceType.IRIS, BiometricUiEvent.BIOMETRIC_IRIS_SUCCESS
252                 );
253 
254         static final Map<BiometricSourceType, BiometricUiEvent> FAILURE_EVENT_BY_SOURCE_TYPE =
255                 Map.of(
256                     BiometricSourceType.FINGERPRINT, BiometricUiEvent.BIOMETRIC_FINGERPRINT_FAILURE,
257                     BiometricSourceType.FACE, BiometricUiEvent.BIOMETRIC_FACE_FAILURE,
258                     BiometricSourceType.IRIS, BiometricUiEvent.BIOMETRIC_IRIS_FAILURE
259                 );
260     }
261 
262     private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
263     private final ScreenOffAnimationController mScreenOffAnimationController;
264 
265     @Inject
BiometricUnlockController( DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ShadeController shadeController, NotificationShadeWindowController notificationShadeWindowController, KeyguardStateController keyguardStateController, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, @Main Resources resources, KeyguardBypassController keyguardBypassController, MetricsLogger metricsLogger, DumpManager dumpManager, PowerManager powerManager, BiometricUnlockLogger biometricUnlockLogger, NotificationMediaManager notificationMediaManager, WakefulnessLifecycle wakefulnessLifecycle, ScreenLifecycle screenLifecycle, AuthController authController, StatusBarStateController statusBarStateController, KeyguardUnlockAnimationController keyguardUnlockAnimationController, SessionTracker sessionTracker, LatencyTracker latencyTracker, ScreenOffAnimationController screenOffAnimationController, VibratorHelper vibrator, SystemClock systemClock )266     public BiometricUnlockController(
267             DozeScrimController dozeScrimController,
268             KeyguardViewMediator keyguardViewMediator,
269             ShadeController shadeController,
270             NotificationShadeWindowController notificationShadeWindowController,
271             KeyguardStateController keyguardStateController, Handler handler,
272             KeyguardUpdateMonitor keyguardUpdateMonitor,
273             @Main Resources resources,
274             KeyguardBypassController keyguardBypassController,
275             MetricsLogger metricsLogger, DumpManager dumpManager,
276             PowerManager powerManager,
277             BiometricUnlockLogger biometricUnlockLogger,
278             NotificationMediaManager notificationMediaManager,
279             WakefulnessLifecycle wakefulnessLifecycle,
280             ScreenLifecycle screenLifecycle,
281             AuthController authController,
282             StatusBarStateController statusBarStateController,
283             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
284             SessionTracker sessionTracker,
285             LatencyTracker latencyTracker,
286             ScreenOffAnimationController screenOffAnimationController,
287             VibratorHelper vibrator,
288             SystemClock systemClock
289     ) {
290         mPowerManager = powerManager;
291         mShadeController = shadeController;
292         mUpdateMonitor = keyguardUpdateMonitor;
293         mUpdateMonitor.registerCallback(this);
294         mMediaManager = notificationMediaManager;
295         mLatencyTracker = latencyTracker;
296         mWakefulnessLifecycle = wakefulnessLifecycle;
297         mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
298         screenLifecycle.addObserver(mScreenObserver);
299 
300         mNotificationShadeWindowController = notificationShadeWindowController;
301         mDozeScrimController = dozeScrimController;
302         mKeyguardViewMediator = keyguardViewMediator;
303         mKeyguardStateController = keyguardStateController;
304         mHandler = handler;
305         mConsecutiveFpFailureThreshold = resources.getInteger(
306                 R.integer.fp_consecutive_failure_time_ms);
307         mKeyguardBypassController = keyguardBypassController;
308         mKeyguardBypassController.setUnlockController(this);
309         mMetricsLogger = metricsLogger;
310         mAuthController = authController;
311         mStatusBarStateController = statusBarStateController;
312         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
313         mSessionTracker = sessionTracker;
314         mScreenOffAnimationController = screenOffAnimationController;
315         mVibratorHelper = vibrator;
316         mLogger = biometricUnlockLogger;
317         mSystemClock = systemClock;
318 
319         dumpManager.registerDumpable(getClass().getName(), this);
320     }
321 
setKeyguardViewController(KeyguardViewController keyguardViewController)322     public void setKeyguardViewController(KeyguardViewController keyguardViewController) {
323         mKeyguardViewController = keyguardViewController;
324     }
325 
326     /** Adds a {@link BiometricModeListener}. */
addBiometricModeListener(BiometricModeListener listener)327     public void addBiometricModeListener(BiometricModeListener listener) {
328         mBiometricModeListeners.add(listener);
329     }
330 
331     /** Removes a {@link BiometricModeListener}. */
removeBiometricModeListener(BiometricModeListener listener)332     public void removeBiometricModeListener(BiometricModeListener listener) {
333         mBiometricModeListeners.remove(listener);
334     }
335 
336     private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
337         @Override
338         public void run() {
339             mLogger.i("biometric wakelock: TIMEOUT!!");
340             releaseBiometricWakeLock();
341         }
342     };
343 
releaseBiometricWakeLock()344     private void releaseBiometricWakeLock() {
345         if (mWakeLock != null) {
346             mHandler.removeCallbacks(mReleaseBiometricWakeLockRunnable);
347             mLogger.i("releasing biometric wakelock");
348             mWakeLock.release();
349             mWakeLock = null;
350         }
351     }
352 
353     @Override
onBiometricAcquired(BiometricSourceType biometricSourceType, int acquireInfo)354     public void onBiometricAcquired(BiometricSourceType biometricSourceType,
355             int acquireInfo) {
356         if (BiometricSourceType.FINGERPRINT == biometricSourceType
357                 && acquireInfo != BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD) {
358             return;
359         } else if (BiometricSourceType.FACE == biometricSourceType
360                 && acquireInfo != BiometricFaceConstants.FACE_ACQUIRED_GOOD) {
361             return;
362         }
363         Trace.beginSection("BiometricUnlockController#onBiometricAcquired");
364         releaseBiometricWakeLock();
365         if (mStatusBarStateController.isDozing()) {
366             if (mLatencyTracker.isEnabled()) {
367                 int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
368                 if (biometricSourceType == BiometricSourceType.FACE) {
369                     action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK;
370                 }
371                 mLatencyTracker.onActionStart(action);
372             }
373             mWakeLock = mPowerManager.newWakeLock(
374                     PowerManager.PARTIAL_WAKE_LOCK, BIOMETRIC_WAKE_LOCK_NAME);
375             Trace.beginSection("acquiring wake-and-unlock");
376             mWakeLock.acquire();
377             Trace.endSection();
378             mLogger.i("biometric acquired, grabbing biometric wakelock");
379             mHandler.postDelayed(mReleaseBiometricWakeLockRunnable,
380                     BIOMETRIC_WAKELOCK_TIMEOUT_MS);
381         }
382         Trace.endSection();
383     }
384 
385     @Override
onBiometricDetected(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric)386     public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
387             boolean isStrongBiometric) {
388         Trace.beginSection("BiometricUnlockController#onBiometricDetected");
389         if (mUpdateMonitor.isGoingToSleep()) {
390             Trace.endSection();
391             return;
392         }
393         startWakeAndUnlock(MODE_SHOW_BOUNCER);
394     }
395 
396     @Override
onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric)397     public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
398             boolean isStrongBiometric) {
399         Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
400         if (mUpdateMonitor.isGoingToSleep()) {
401             mLogger.deferringAuthenticationDueToSleep(userId,
402                     biometricSourceType,
403                     mPendingAuthenticated != null);
404             mPendingAuthenticated = new PendingAuthenticated(userId, biometricSourceType,
405                     isStrongBiometric);
406             Trace.endSection();
407             return;
408         }
409         mBiometricType = biometricSourceType;
410         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
411                 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
412         Optional.ofNullable(BiometricUiEvent.SUCCESS_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
413                 .ifPresent(event -> UI_EVENT_LOGGER.log(event, getSessionId()));
414 
415         boolean unlockAllowed =
416                 mKeyguardStateController.isOccluded()
417                         || mKeyguardBypassController.onBiometricAuthenticated(
418                                 biometricSourceType, isStrongBiometric);
419         if (unlockAllowed) {
420             mKeyguardViewMediator.userActivity();
421             startWakeAndUnlock(biometricSourceType, isStrongBiometric);
422         } else {
423             mLogger.d("onBiometricAuthenticated aborted by bypass controller");
424         }
425     }
426 
startWakeAndUnlock(BiometricSourceType biometricSourceType, boolean isStrongBiometric)427     public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
428                                    boolean isStrongBiometric) {
429         int mode = calculateMode(biometricSourceType, isStrongBiometric);
430         if (mode == MODE_WAKE_AND_UNLOCK
431                 || mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING
432                 || mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) {
433             vibrateSuccess(biometricSourceType);
434         }
435         startWakeAndUnlock(mode);
436     }
437 
startWakeAndUnlock(@akeAndUnlockMode int mode)438     public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
439         mLogger.logStartWakeAndUnlock(mode);
440         boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
441         mMode = mode;
442         mHasScreenTurnedOnSinceAuthenticating = false;
443         if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
444             // If we are waking the device up while we are pulsing the clock and the
445             // notifications would light up first, creating an unpleasant animation.
446             // Defer changing the screen brightness by forcing doze brightness on our window
447             // until the clock and the notifications are faded out.
448             mNotificationShadeWindowController.setForceDozeBrightness(true);
449         }
450         // During wake and unlock, we need to draw black before waking up to avoid abrupt
451         // brightness changes due to display state transitions.
452         Runnable wakeUp = ()-> {
453             if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
454                 mLogger.i("bio wakelock: Authenticated, waking up...");
455                 mPowerManager.wakeUp(
456                         mSystemClock.uptimeMillis(),
457                         PowerManager.WAKE_REASON_BIOMETRIC,
458                         "android.policy:BIOMETRIC"
459                 );
460             }
461             Trace.beginSection("release wake-and-unlock");
462             releaseBiometricWakeLock();
463             Trace.endSection();
464         };
465 
466         if (mMode != MODE_NONE) {
467             wakeUp.run();
468         }
469         switch (mMode) {
470             case MODE_DISMISS_BOUNCER:
471                 Trace.beginSection("MODE_DISMISS_BOUNCER");
472                 mKeyguardViewController.notifyKeyguardAuthenticated(
473                         false /* strongAuth */);
474                 Trace.endSection();
475                 break;
476             case MODE_UNLOCK_COLLAPSING:
477                 Trace.beginSection("MODE_UNLOCK_COLLAPSING");
478                 // If the keyguard unlock controller is going to handle the unlock animation, it
479                 // will fling the panel collapsed when it's ready.
480                 if (!mKeyguardUnlockAnimationController.willHandleUnlockAnimation()) {
481                     mShadeController.animateCollapsePanels(
482                             CommandQueue.FLAG_EXCLUDE_NONE,
483                             true /* force */,
484                             false /* delayed */,
485                             BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
486                 }
487                 mKeyguardViewController.notifyKeyguardAuthenticated(
488                         false /* strongAuth */);
489                 Trace.endSection();
490                 break;
491             case MODE_SHOW_BOUNCER:
492                 Trace.beginSection("MODE_SHOW_BOUNCER");
493                 mKeyguardViewController.showPrimaryBouncer(true);
494                 Trace.endSection();
495                 break;
496             case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
497             case MODE_WAKE_AND_UNLOCK_PULSING:
498             case MODE_WAKE_AND_UNLOCK:
499                 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
500                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
501                     mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
502                             true /* allowEnterAnimation */);
503                 } else if (mMode == MODE_WAKE_AND_UNLOCK){
504                     Trace.beginSection("MODE_WAKE_AND_UNLOCK");
505                 } else {
506                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
507                     // Don't call awaken from Dream here. In order to avoid flickering, wait until
508                     // later to awaken.
509                 }
510                 mNotificationShadeWindowController.setNotificationShadeFocusable(false);
511                 mKeyguardViewMediator.onWakeAndUnlocking();
512                 Trace.endSection();
513                 break;
514             case MODE_ONLY_WAKE:
515             case MODE_NONE:
516                 break;
517         }
518         onModeChanged(mMode);
519         Trace.endSection();
520     }
521 
onModeChanged(@akeAndUnlockMode int mode)522     private void onModeChanged(@WakeAndUnlockMode int mode) {
523         for (BiometricModeListener listener : mBiometricModeListeners) {
524             listener.onModeChanged(mode);
525         }
526     }
527 
hasPendingAuthentication()528     public boolean hasPendingAuthentication() {
529         return mPendingAuthenticated != null
530                 && mUpdateMonitor
531                     .isUnlockingWithBiometricAllowed(mPendingAuthenticated.isStrongBiometric)
532                 && mPendingAuthenticated.userId == KeyguardUpdateMonitor.getCurrentUser();
533     }
534 
getMode()535     public @WakeAndUnlockMode int getMode() {
536         return mMode;
537     }
538 
calculateMode(BiometricSourceType biometricSourceType, boolean isStrongBiometric)539     private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType,
540             boolean isStrongBiometric) {
541         if (biometricSourceType == BiometricSourceType.FACE
542                 || biometricSourceType == BiometricSourceType.IRIS) {
543             return calculateModeForPassiveAuth(isStrongBiometric);
544         } else {
545             return calculateModeForFingerprint(isStrongBiometric);
546         }
547     }
548 
calculateModeForFingerprint(boolean isStrongBiometric)549     private @WakeAndUnlockMode int calculateModeForFingerprint(boolean isStrongBiometric) {
550         final boolean unlockingAllowed =
551                 mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
552         final boolean deviceInteractive = mUpdateMonitor.isDeviceInteractive();
553         final boolean keyguardShowing = mKeyguardStateController.isShowing();
554         final boolean deviceDreaming = mUpdateMonitor.isDreaming();
555 
556         logCalculateModeForFingerprint(unlockingAllowed, deviceInteractive,
557                 keyguardShowing, deviceDreaming, isStrongBiometric);
558         if (!deviceInteractive) {
559             if (!keyguardShowing && !mScreenOffAnimationController.isKeyguardShowDelayed()) {
560                 if (mKeyguardStateController.isUnlocked()) {
561                     return MODE_WAKE_AND_UNLOCK;
562                 }
563                 return MODE_ONLY_WAKE;
564             } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
565                 return MODE_WAKE_AND_UNLOCK_PULSING;
566             } else if (unlockingAllowed || !mKeyguardStateController.isMethodSecure()) {
567                 return MODE_WAKE_AND_UNLOCK;
568             } else {
569                 return MODE_SHOW_BOUNCER;
570             }
571         }
572         if (unlockingAllowed && deviceDreaming) {
573             return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
574         }
575         if (keyguardShowing) {
576             if (mKeyguardViewController.primaryBouncerIsOrWillBeShowing() && unlockingAllowed) {
577                 return MODE_DISMISS_BOUNCER;
578             } else if (unlockingAllowed) {
579                 return MODE_UNLOCK_COLLAPSING;
580             } else if (!mKeyguardViewController.isBouncerShowing()) {
581                 return MODE_SHOW_BOUNCER;
582             }
583         }
584         return MODE_NONE;
585     }
586 
logCalculateModeForFingerprint(boolean unlockingAllowed, boolean deviceInteractive, boolean keyguardShowing, boolean deviceDreaming, boolean strongBiometric)587     private void logCalculateModeForFingerprint(boolean unlockingAllowed, boolean deviceInteractive,
588             boolean keyguardShowing, boolean deviceDreaming, boolean strongBiometric) {
589         if (unlockingAllowed) {
590             mLogger.logCalculateModeForFingerprintUnlockingAllowed(deviceInteractive,
591                     keyguardShowing, deviceDreaming);
592         } else {
593             // if unlocking isn't allowed, log more information about why unlocking may not
594             // have been allowed
595             final int strongAuthFlags = mUpdateMonitor.getStrongAuthTracker().getStrongAuthForUser(
596                     KeyguardUpdateMonitor.getCurrentUser());
597             final boolean nonStrongBiometricAllowed =
598                     mUpdateMonitor.getStrongAuthTracker()
599                             .isNonStrongBiometricAllowedAfterIdleTimeout(
600                                     KeyguardUpdateMonitor.getCurrentUser());
601 
602             mLogger.logCalculateModeForFingerprintUnlockingNotAllowed(strongBiometric,
603                     strongAuthFlags, nonStrongBiometricAllowed, deviceInteractive, keyguardShowing);
604         }
605     }
606 
calculateModeForPassiveAuth(boolean isStrongBiometric)607     private @WakeAndUnlockMode int calculateModeForPassiveAuth(boolean isStrongBiometric) {
608         final boolean deviceInteractive = mUpdateMonitor.isDeviceInteractive();
609         final boolean isKeyguardShowing = mKeyguardStateController.isShowing();
610         final boolean unlockingAllowed =
611                 mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
612         final boolean deviceDreaming = mUpdateMonitor.isDreaming();
613         final boolean bypass = mKeyguardBypassController.getBypassEnabled()
614                 || mAuthController.isUdfpsFingerDown();
615 
616         logCalculateModeForPassiveAuth(unlockingAllowed, deviceInteractive, isKeyguardShowing,
617                 deviceDreaming, bypass, isStrongBiometric);
618         if (!deviceInteractive) {
619             if (!isKeyguardShowing) {
620                 return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE;
621             } else if (!unlockingAllowed) {
622                 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
623             } else if (mDozeScrimController.isPulsing()) {
624                 return bypass ? MODE_WAKE_AND_UNLOCK_PULSING : MODE_ONLY_WAKE;
625             } else {
626                 if (bypass) {
627                     // Wake-up fading out nicely
628                     return MODE_WAKE_AND_UNLOCK_PULSING;
629                 } else {
630                     // We could theoretically return MODE_NONE, but this means that the device
631                     // would be not interactive, unlocked, and the user would not see the device
632                     // state.
633                     return MODE_ONLY_WAKE;
634                 }
635             }
636         }
637         if (unlockingAllowed && deviceDreaming) {
638             return bypass ? MODE_WAKE_AND_UNLOCK_FROM_DREAM : MODE_ONLY_WAKE;
639         }
640         if (unlockingAllowed && mKeyguardStateController.isOccluded()) {
641             return MODE_UNLOCK_COLLAPSING;
642         }
643         if (isKeyguardShowing) {
644             if ((mKeyguardViewController.primaryBouncerIsOrWillBeShowing()
645                     || mKeyguardBypassController.getAltBouncerShowing()) && unlockingAllowed) {
646                 return MODE_DISMISS_BOUNCER;
647             } else if (unlockingAllowed && bypass) {
648                 return MODE_UNLOCK_COLLAPSING;
649             } else {
650                 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
651             }
652         }
653         return MODE_NONE;
654     }
655 
logCalculateModeForPassiveAuth(boolean unlockingAllowed, boolean deviceInteractive, boolean keyguardShowing, boolean deviceDreaming, boolean bypass, boolean strongBiometric)656     private void logCalculateModeForPassiveAuth(boolean unlockingAllowed,
657             boolean deviceInteractive, boolean keyguardShowing, boolean deviceDreaming,
658             boolean bypass, boolean strongBiometric) {
659         if (unlockingAllowed) {
660             mLogger.logCalculateModeForPassiveAuthUnlockingAllowed(
661                     deviceInteractive, keyguardShowing, deviceDreaming, bypass);
662         } else {
663             // if unlocking isn't allowed, log more information about why unlocking may not
664             // have been allowed
665             final int strongAuthFlags = mUpdateMonitor.getStrongAuthTracker().getStrongAuthForUser(
666                     KeyguardUpdateMonitor.getCurrentUser());
667             final boolean nonStrongBiometricAllowed =
668                     mUpdateMonitor.getStrongAuthTracker()
669                             .isNonStrongBiometricAllowedAfterIdleTimeout(
670                                     KeyguardUpdateMonitor.getCurrentUser());
671 
672             mLogger.logCalculateModeForPassiveAuthUnlockingNotAllowed(
673                     strongBiometric, strongAuthFlags, nonStrongBiometricAllowed,
674                     deviceInteractive, keyguardShowing, bypass);
675         }
676     }
677 
678     @Override
onBiometricAuthFailed(BiometricSourceType biometricSourceType)679     public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
680         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
681                 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
682         Optional.ofNullable(BiometricUiEvent.FAILURE_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
683                 .ifPresent(event -> UI_EVENT_LOGGER.log(event, getSessionId()));
684 
685         if (mLatencyTracker.isEnabled()) {
686             int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
687             if (biometricSourceType == BiometricSourceType.FACE) {
688                 action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK;
689             }
690             mLatencyTracker.onActionCancel(action);
691         }
692 
693         if (!mVibratorHelper.hasVibrator()
694                 && (!mUpdateMonitor.isDeviceInteractive() || mUpdateMonitor.isDreaming())) {
695             mLogger.d("wakeup device on authentication failure (device doesn't have a vibrator)");
696             startWakeAndUnlock(MODE_ONLY_WAKE);
697         } else if (biometricSourceType == BiometricSourceType.FINGERPRINT
698                 && mUpdateMonitor.isUdfpsSupported()) {
699             long currUptimeMillis = mSystemClock.uptimeMillis();
700             if (currUptimeMillis - mLastFpFailureUptimeMillis < mConsecutiveFpFailureThreshold) {
701                 mNumConsecutiveFpFailures += 1;
702             } else {
703                 mNumConsecutiveFpFailures = 1;
704             }
705             mLastFpFailureUptimeMillis = currUptimeMillis;
706 
707             if (mNumConsecutiveFpFailures >= UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
708                 mLogger.logUdfpsAttemptThresholdMet(mNumConsecutiveFpFailures);
709                 startWakeAndUnlock(MODE_SHOW_BOUNCER);
710                 UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
711                 mNumConsecutiveFpFailures = 0;
712             }
713         }
714 
715         // Suppress all face auth errors if fingerprint can be used to authenticate
716         if ((biometricSourceType == BiometricSourceType.FACE
717                 && !mUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
718                 KeyguardUpdateMonitor.getCurrentUser()))
719                 || (biometricSourceType == BiometricSourceType.FINGERPRINT)) {
720             vibrateError(biometricSourceType);
721         }
722 
723         cleanup();
724     }
725 
726     @Override
onBiometricError(int msgId, String errString, BiometricSourceType biometricSourceType)727     public void onBiometricError(int msgId, String errString,
728             BiometricSourceType biometricSourceType) {
729         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
730                 .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
731                 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
732         Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
733                 .ifPresent(event -> UI_EVENT_LOGGER.log(event, getSessionId()));
734 
735         final boolean fingerprintLockout = biometricSourceType == BiometricSourceType.FINGERPRINT
736                 && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
737                 || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT);
738         if (fingerprintLockout) {
739             mLogger.d("fingerprint locked out");
740             startWakeAndUnlock(MODE_SHOW_BOUNCER);
741             UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId());
742         }
743 
744         cleanup();
745     }
746 
747     // these haptics are for device-entry only
vibrateSuccess(BiometricSourceType type)748     private void vibrateSuccess(BiometricSourceType type) {
749         if (mAuthController.isSfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())
750                 && lastWakeupFromPowerButtonWithinHapticThreshold()) {
751             mLogger.d("Skip auth success haptic. Power button was recently pressed.");
752             return;
753         }
754         mVibratorHelper.vibrateAuthSuccess(
755                 getClass().getSimpleName() + ", type =" + type + "device-entry::success");
756     }
757 
lastWakeupFromPowerButtonWithinHapticThreshold()758     private boolean lastWakeupFromPowerButtonWithinHapticThreshold() {
759         final boolean lastWakeupFromPowerButton = mWakefulnessLifecycle.getLastWakeReason()
760                 == PowerManager.WAKE_REASON_POWER_BUTTON;
761         return lastWakeupFromPowerButton
762                 && mWakefulnessLifecycle.getLastWakeTime() != UNKNOWN_LAST_WAKE_TIME
763                 && mSystemClock.uptimeMillis() - mWakefulnessLifecycle.getLastWakeTime()
764                 < RECENT_POWER_BUTTON_PRESS_THRESHOLD_MS;
765     }
766 
vibrateError(BiometricSourceType type)767     private void vibrateError(BiometricSourceType type) {
768         mVibratorHelper.vibrateAuthError(
769                 getClass().getSimpleName() + ", type =" + type + "device-entry::error");
770     }
771 
cleanup()772     private void cleanup() {
773         releaseBiometricWakeLock();
774     }
775 
startKeyguardFadingAway()776     public void startKeyguardFadingAway() {
777 
778         // Disable brightness override when the ambient contents are fully invisible.
779         mHandler.postDelayed(new Runnable() {
780             @Override
781             public void run() {
782                 mNotificationShadeWindowController.setForceDozeBrightness(false);
783             }
784         }, CentralSurfaces.FADE_KEYGUARD_DURATION_PULSING);
785     }
786 
finishKeyguardFadingAway()787     public void finishKeyguardFadingAway() {
788         if (isWakeAndUnlock()) {
789             mFadedAwayAfterWakeAndUnlock = true;
790         }
791         resetMode();
792     }
793 
resetMode()794     private void resetMode() {
795         mMode = MODE_NONE;
796         mBiometricType = null;
797         mNotificationShadeWindowController.setForceDozeBrightness(false);
798         for (BiometricModeListener listener : mBiometricModeListeners) {
799             listener.onResetMode();
800         }
801         mNumConsecutiveFpFailures = 0;
802         mLastFpFailureUptimeMillis = 0;
803     }
804 
805     @VisibleForTesting
806     final WakefulnessLifecycle.Observer mWakefulnessObserver =
807             new WakefulnessLifecycle.Observer() {
808                 @Override
809                 public void onStartedGoingToSleep() {
810                     resetMode();
811                     mFadedAwayAfterWakeAndUnlock = false;
812                     mPendingAuthenticated = null;
813                 }
814 
815                 @Override
816                 public void onFinishedGoingToSleep() {
817                     Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
818                     if (mPendingAuthenticated != null) {
819                         mLogger.finishedGoingToSleepWithPendingAuth();
820                         PendingAuthenticated pendingAuthenticated = mPendingAuthenticated;
821                         // Post this to make sure it's executed after the device is fully locked.
822                         mHandler.post(() -> onBiometricAuthenticated(pendingAuthenticated.userId,
823                                 pendingAuthenticated.biometricSourceType,
824                                 pendingAuthenticated.isStrongBiometric));
825                         mPendingAuthenticated = null;
826                     }
827                     Trace.endSection();
828                 }
829             };
830 
831     private final ScreenLifecycle.Observer mScreenObserver =
832             new ScreenLifecycle.Observer() {
833                 @Override
834                 public void onScreenTurnedOn() {
835                     mHasScreenTurnedOnSinceAuthenticating = true;
836                 }
837             };
838 
hasScreenTurnedOnSinceAuthenticating()839     public boolean hasScreenTurnedOnSinceAuthenticating() {
840         return mHasScreenTurnedOnSinceAuthenticating;
841     }
842 
843     @Override
onKeyguardBouncerStateChanged(boolean bouncerIsOrWillBeShowing)844     public void onKeyguardBouncerStateChanged(boolean bouncerIsOrWillBeShowing) {
845         // When the bouncer is dismissed, treat this as a reset of the unlock mode. The user
846         // may have gone back instead of successfully unlocking
847         if (!bouncerIsOrWillBeShowing) {
848             resetMode();
849         }
850     }
851 
852     @Override
dump(PrintWriter pw, String[] args)853     public void dump(PrintWriter pw, String[] args) {
854         pw.println(" BiometricUnlockController:");
855         pw.print("   mMode="); pw.println(mMode);
856         pw.print("   mWakeLock="); pw.println(mWakeLock);
857         if (mUpdateMonitor.isUdfpsSupported()) {
858             pw.print("   mNumConsecutiveFpFailures="); pw.println(mNumConsecutiveFpFailures);
859             pw.print("   time since last failure=");
860             pw.println(mSystemClock.uptimeMillis() - mLastFpFailureUptimeMillis);
861         }
862     }
863 
864     /**
865      * Successful authentication with fingerprint, face, or iris that wakes up the device.
866      */
isWakeAndUnlock()867     public boolean isWakeAndUnlock() {
868         return mMode == MODE_WAKE_AND_UNLOCK
869                 || mMode == MODE_WAKE_AND_UNLOCK_PULSING
870                 || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM;
871     }
872 
873     /**
874      * Successful authentication with fingerprint, face, or iris that wakes up the device.
875      * This will return {@code true} even after the keyguard fades away.
876      */
unlockedByWakeAndUnlock()877     public boolean unlockedByWakeAndUnlock() {
878         return  isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock;
879     }
880 
881     /**
882      * Successful authentication with fingerprint, face, or iris when the screen was either
883      * on or off.
884      */
isBiometricUnlock()885     public boolean isBiometricUnlock() {
886         return isWakeAndUnlock() || mMode == MODE_UNLOCK_COLLAPSING;
887     }
888 
889     /**
890      * Successful authentication with fingerprint, face, or iris when the lockscreen fades away
891      */
getBiometricType()892     public BiometricSourceType getBiometricType() {
893         return mBiometricType;
894     }
895 
getSessionId()896     private @Nullable InstanceId getSessionId() {
897         return mSessionTracker.getSessionId(SESSION_KEYGUARD);
898     }
899     /**
900      * Translates biometric source type for logging purpose.
901      */
toSubtype(BiometricSourceType biometricSourceType)902     private int toSubtype(BiometricSourceType biometricSourceType) {
903         switch (biometricSourceType) {
904             case FINGERPRINT:
905                 return 0;
906             case FACE:
907                 return 1;
908             case IRIS:
909                 return 2;
910             default:
911                 return 3;
912         }
913     }
914 
915     /** An interface to interact with the {@link BiometricUnlockController}. */
916     public interface BiometricModeListener {
917         /** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
onResetMode()918         default void onResetMode() {}
919         /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
onModeChanged(@akeAndUnlockMode int mode)920         default void onModeChanged(@WakeAndUnlockMode int mode) {}
921     }
922 }
923