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