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