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