blob: 7cbdfb0b12f44d3491dedd29d6b869485daed72a [file] [log] [blame]
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07001/*
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
17package com.android.systemui.statusbar.phone;
18
Lucas Dupinfa817a02019-07-02 15:22:54 -070019import android.annotation.IntDef;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070020import android.content.Context;
Gus Prevasab336792018-11-14 13:52:20 -050021import android.hardware.biometrics.BiometricSourceType;
Steven Wue442acf2019-03-14 13:31:12 -040022import android.metrics.LogMaker;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070023import android.os.Handler;
24import android.os.PowerManager;
25import android.os.SystemClock;
Nick Desaulniers1d396752016-07-25 15:05:33 -070026import android.os.Trace;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070027import android.util.Log;
28
Lucas Dupinc94963f2019-03-07 14:54:05 -080029import com.android.internal.annotations.VisibleForTesting;
Steven Wue442acf2019-03-14 13:31:12 -040030import com.android.internal.logging.MetricsLogger;
31import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Gus Prevasab336792018-11-14 13:52:20 -050032import com.android.internal.util.LatencyTracker;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070033import com.android.keyguard.KeyguardConstants;
34import com.android.keyguard.KeyguardUpdateMonitor;
35import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jason Monk421a9412017-02-06 09:15:21 -080036import com.android.systemui.Dependency;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070037import com.android.systemui.keyguard.KeyguardViewMediator;
Adrian Roos7a5e4c92017-07-31 16:40:19 +020038import com.android.systemui.keyguard.ScreenLifecycle;
Adrian Roos58ba6852017-07-18 17:10:29 +020039import com.android.systemui.keyguard.WakefulnessLifecycle;
Jason Monk297c04e2018-08-23 17:16:59 -040040import com.android.systemui.statusbar.NotificationMediaManager;
Lucas Dupinc8f16e82019-09-17 18:24:50 -040041import com.android.systemui.statusbar.policy.KeyguardStateController;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070042
Adrian Roosba7ca592017-08-15 17:48:05 +020043import java.io.PrintWriter;
Lucas Dupinfa817a02019-07-02 15:22:54 -070044import java.lang.annotation.Retention;
45import java.lang.annotation.RetentionPolicy;
Adrian Roosba7ca592017-08-15 17:48:05 +020046
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070047/**
Gilad Brettercb51b8b2018-03-22 17:04:51 +020048 * Controller which coordinates all the biometric unlocking actions with the UI.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070049 */
Gilad Brettercb51b8b2018-03-22 17:04:51 +020050public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070051
Gilad Brettercb51b8b2018-03-22 17:04:51 +020052 private static final String TAG = "BiometricUnlockController";
53 private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
54 private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
55 private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070056
Lucas Dupinfa817a02019-07-02 15:22:54 -070057 @IntDef(prefix = { "MODE_" }, value = {
58 MODE_NONE,
59 MODE_WAKE_AND_UNLOCK,
60 MODE_WAKE_AND_UNLOCK_PULSING,
61 MODE_SHOW_BOUNCER,
62 MODE_ONLY_WAKE,
63 MODE_UNLOCK_COLLAPSING,
64 MODE_UNLOCK_FADING,
65 MODE_DISMISS_BOUNCER,
66 MODE_WAKE_AND_UNLOCK_FROM_DREAM
67 })
68 @Retention(RetentionPolicy.SOURCE)
69 public @interface WakeAndUnlockMode {}
70
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070071 /**
Lucas Dupin3d053532019-01-29 12:35:22 -080072 * Mode in which we don't need to wake up the device when we authenticate.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070073 */
74 public static final int MODE_NONE = 0;
75
76 /**
77 * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
78 * a fingerprint while the screen is off and the device was sleeping.
79 */
80 public static final int MODE_WAKE_AND_UNLOCK = 1;
81
82 /**
83 * Mode in which we wake the device up, and fade out the Keyguard contents because they were
84 * already visible while pulsing in doze mode.
85 */
86 public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
87
88 /**
89 * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
90 * acquire a fingerprint pulsing in doze mode.
91 */
92 public static final int MODE_SHOW_BOUNCER = 3;
93
94 /**
Lucas Dupin3d053532019-01-29 12:35:22 -080095 * Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070096 * */
97 public static final int MODE_ONLY_WAKE = 4;
98
99 /**
100 * Mode in which fingerprint unlocks the device.
101 */
Lucas Dupinfa817a02019-07-02 15:22:54 -0700102 public static final int MODE_UNLOCK_COLLAPSING = 5;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700103
104 /**
Kevin Chyn36778ff2017-09-07 19:55:38 -0700105 * Mode in which fingerprint wakes and unlocks the device from a dream.
106 */
Lucas Dupine78794c2019-06-18 11:55:37 -0700107 public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 6;
Kevin Chyn36778ff2017-09-07 19:55:38 -0700108
109 /**
Lucas Dupinfa817a02019-07-02 15:22:54 -0700110 * Faster mode of dismissing the lock screen when we cross fade to an app
111 * (used for keyguard bypass.)
112 */
113 public static final int MODE_UNLOCK_FADING = 7;
114
115 /**
116 * When bouncer is visible and will be dismissed.
117 */
118 public static final int MODE_DISMISS_BOUNCER = 8;
119
120 /**
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200121 * How much faster we collapse the lockscreen when authenticating with biometric.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700122 */
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200123 private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700124
Lucas Dupin3d053532019-01-29 12:35:22 -0800125 private final NotificationMediaManager mMediaManager;
126 private final PowerManager mPowerManager;
127 private final Handler mHandler;
Selim Cinek2c890ee2019-05-20 19:16:43 -0700128 private final KeyguardBypassController mKeyguardBypassController;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700129 private PowerManager.WakeLock mWakeLock;
Lucas Dupin3d053532019-01-29 12:35:22 -0800130 private final KeyguardUpdateMonitor mUpdateMonitor;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400131 private final KeyguardStateController mKeyguardStateController;
Lucas Dupin3d053532019-01-29 12:35:22 -0800132 private final StatusBarWindowController mStatusBarWindowController;
133 private final Context mContext;
134 private final int mWakeUpDelay;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700135 private int mMode;
136 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700137 private DozeScrimController mDozeScrimController;
138 private KeyguardViewMediator mKeyguardViewMediator;
139 private ScrimController mScrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500140 private StatusBar mStatusBar;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700141 private int mPendingAuthenticatedUserId = -1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200142 private BiometricSourceType mPendingAuthenticatedBioSourceType = null;
Adrian Roos58ba6852017-07-18 17:10:29 +0200143 private boolean mPendingShowBouncer;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200144 private boolean mHasScreenTurnedOnSinceAuthenticating;
Lucas Dupinbd6c92b2019-07-17 09:49:52 -0700145 private boolean mFadedAwayAfterWakeAndUnlock;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700146
Steven Wue442acf2019-03-14 13:31:12 -0400147 private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
148
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200149 public BiometricUnlockController(Context context,
Lucas Dupinc94963f2019-03-07 14:54:05 -0800150 DozeScrimController dozeScrimController,
151 KeyguardViewMediator keyguardViewMediator,
152 ScrimController scrimController,
153 StatusBar statusBar,
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400154 KeyguardStateController keyguardStateController, Handler handler,
Lucas Dupinc94963f2019-03-07 14:54:05 -0800155 KeyguardUpdateMonitor keyguardUpdateMonitor,
Selim Cinek2c890ee2019-05-20 19:16:43 -0700156 KeyguardBypassController keyguardBypassController) {
Lucas Dupinc94963f2019-03-07 14:54:05 -0800157 this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400158 keyguardStateController, handler, keyguardUpdateMonitor,
Lucas Dupinc94963f2019-03-07 14:54:05 -0800159 context.getResources()
160 .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
Selim Cinek2c890ee2019-05-20 19:16:43 -0700161 keyguardBypassController);
Lucas Dupinc94963f2019-03-07 14:54:05 -0800162 }
163
164 @VisibleForTesting
165 protected BiometricUnlockController(Context context,
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400166 DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator,
167 ScrimController scrimController, StatusBar statusBar,
168 KeyguardStateController keyguardStateController, Handler handler,
169 KeyguardUpdateMonitor keyguardUpdateMonitor, int wakeUpDelay,
170 KeyguardBypassController keyguardBypassController) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700171 mContext = context;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700172 mPowerManager = context.getSystemService(PowerManager.class);
Lucas Dupin3d053532019-01-29 12:35:22 -0800173 mUpdateMonitor = keyguardUpdateMonitor;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700174 mUpdateMonitor.registerCallback(this);
Lucas Dupin3d053532019-01-29 12:35:22 -0800175 mMediaManager = Dependency.get(NotificationMediaManager.class);
Adrian Roos58ba6852017-07-18 17:10:29 +0200176 Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200177 Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700178 mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700179 mDozeScrimController = dozeScrimController;
180 mKeyguardViewMediator = keyguardViewMediator;
181 mScrimController = scrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500182 mStatusBar = statusBar;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400183 mKeyguardStateController = keyguardStateController;
Lucas Dupin3d053532019-01-29 12:35:22 -0800184 mHandler = handler;
185 mWakeUpDelay = wakeUpDelay;
Selim Cinek2c890ee2019-05-20 19:16:43 -0700186 mKeyguardBypassController = keyguardBypassController;
Selim Cinekbd84c162019-06-11 16:23:23 -0700187 mKeyguardBypassController.setUnlockController(this);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700188 }
189
190 public void setStatusBarKeyguardViewManager(
191 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
192 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
193 }
194
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200195 private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700196 @Override
197 public void run() {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200198 if (DEBUG_BIO_WAKELOCK) {
199 Log.i(TAG, "biometric wakelock: TIMEOUT!!");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700200 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200201 releaseBiometricWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700202 }
203 };
204
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200205 private void releaseBiometricWakeLock() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700206 if (mWakeLock != null) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200207 mHandler.removeCallbacks(mReleaseBiometricWakeLockRunnable);
208 if (DEBUG_BIO_WAKELOCK) {
209 Log.i(TAG, "releasing biometric wakelock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700210 }
211 mWakeLock.release();
212 mWakeLock = null;
213 }
214 }
215
216 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200217 public void onBiometricAcquired(BiometricSourceType biometricSourceType) {
218 Trace.beginSection("BiometricUnlockController#onBiometricAcquired");
219 releaseBiometricWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700220 if (!mUpdateMonitor.isDeviceInteractive()) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700221 if (LatencyTracker.isEnabled(mContext)) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200222 int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
223 if (biometricSourceType == BiometricSourceType.FACE) {
224 action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK;
225 }
226 LatencyTracker.getInstance(mContext).onActionStart(action);
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700227 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700228 mWakeLock = mPowerManager.newWakeLock(
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200229 PowerManager.PARTIAL_WAKE_LOCK, BIOMETRIC_WAKE_LOCK_NAME);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700230 Trace.beginSection("acquiring wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700231 mWakeLock.acquire();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700232 Trace.endSection();
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200233 if (DEBUG_BIO_WAKELOCK) {
234 Log.i(TAG, "biometric acquired, grabbing biometric wakelock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700235 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200236 mHandler.postDelayed(mReleaseBiometricWakeLockRunnable,
237 BIOMETRIC_WAKELOCK_TIMEOUT_MS);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700238 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700239 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700240 }
241
Adrian Roos3e23eb52017-07-07 15:58:57 +0200242 private boolean pulsingOrAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800243 final ScrimState scrimState = mScrimController.getState();
244 return scrimState == ScrimState.AOD
245 || scrimState == ScrimState.PULSING;
Adrian Roos3e23eb52017-07-07 15:58:57 +0200246 }
247
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700248 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200249 public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
250 Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700251 if (mUpdateMonitor.isGoingToSleep()) {
252 mPendingAuthenticatedUserId = userId;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200253 mPendingAuthenticatedBioSourceType = biometricSourceType;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700254 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700255 return;
256 }
Steven Wue442acf2019-03-14 13:31:12 -0400257 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
258 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
Selim Cinekbd84c162019-06-11 16:23:23 -0700259 boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
260 biometricSourceType);
261 if (unlockAllowed) {
Lucas Dupinaad98832019-07-14 13:23:24 +0900262 mKeyguardViewMediator.userActivity();
Selim Cinekbd84c162019-06-11 16:23:23 -0700263 startWakeAndUnlock(biometricSourceType);
Lucas Dupin5a5e0bd2019-07-11 14:19:11 +0900264 } else {
265 Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
Selim Cinekbd84c162019-06-11 16:23:23 -0700266 }
267 }
268
Selim Cinekb8cc6ef2019-06-14 16:37:53 -0700269 public void startWakeAndUnlock(BiometricSourceType biometricSourceType) {
Lucas Dupin3d053532019-01-29 12:35:22 -0800270 startWakeAndUnlock(calculateMode(biometricSourceType));
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200271 }
272
Lucas Dupinfa817a02019-07-02 15:22:54 -0700273 public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
Kevin Chyn0b508b42017-09-11 17:34:33 -0700274 Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700275 boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200276 mMode = mode;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200277 mHasScreenTurnedOnSinceAuthenticating = false;
Adrian Roosb880afe72017-07-25 17:02:46 +0200278 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
279 // If we are waking the device up while we are pulsing the clock and the
280 // notifications would light up first, creating an unpleasant animation.
281 // Defer changing the screen brightness by forcing doze brightness on our window
282 // until the clock and the notifications are faded out.
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700283 mStatusBarWindowController.setForceDozeBrightness(true);
Adrian Roosb880afe72017-07-25 17:02:46 +0200284 }
Lucas Dupine63abf72018-07-02 11:17:14 -0700285 // During wake and unlock, we need to draw black before waking up to avoid abrupt
286 // brightness changes due to display state transitions.
287 boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
Lucas Dupin2920eea2018-08-29 13:13:40 -0700288 boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
Lucas Dupine63abf72018-07-02 11:17:14 -0700289 Runnable wakeUp = ()-> {
290 if (!wasDeviceInteractive) {
291 if (DEBUG_BIO_WAKELOCK) {
292 Log.i(TAG, "bio wakelock: Authenticated, waking up...");
293 }
Michael Wrighte3001042019-02-05 00:13:14 +0000294 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
295 "android.policy:BIOMETRIC");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700296 }
Lucas Dupine63abf72018-07-02 11:17:14 -0700297 if (delayWakeUp) {
298 mKeyguardViewMediator.onWakeAndUnlocking();
299 }
300 Trace.beginSection("release wake-and-unlock");
301 releaseBiometricWakeLock();
302 Trace.endSection();
303 };
304
Lucas Dupin4108a9b2019-05-28 20:41:51 -0700305 if (!delayWakeUp && mMode != MODE_NONE) {
Lucas Dupine63abf72018-07-02 11:17:14 -0700306 wakeUp.run();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700307 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700308 switch (mMode) {
Lucas Dupinfa817a02019-07-02 15:22:54 -0700309 case MODE_DISMISS_BOUNCER:
310 case MODE_UNLOCK_FADING:
311 Trace.beginSection("MODE_DISMISS_BOUNCER or MODE_UNLOCK_FADING");
312 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
313 false /* strongAuth */);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700314 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700315 break;
Lucas Dupinfa817a02019-07-02 15:22:54 -0700316 case MODE_UNLOCK_COLLAPSING:
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700317 case MODE_SHOW_BOUNCER:
Lucas Dupinfa817a02019-07-02 15:22:54 -0700318 Trace.beginSection("MODE_UNLOCK_COLLAPSING or MODE_SHOW_BOUNCER");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700319 if (!wasDeviceInteractive) {
Adrian Roos58ba6852017-07-18 17:10:29 +0200320 mPendingShowBouncer = true;
321 } else {
322 showBouncer();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700323 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700324 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700325 break;
Kevin Chyn36778ff2017-09-07 19:55:38 -0700326 case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700327 case MODE_WAKE_AND_UNLOCK_PULSING:
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700328 case MODE_WAKE_AND_UNLOCK:
Adrian Roos88e61aa2017-05-23 16:16:50 -0700329 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
330 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
Jason Monk297c04e2018-08-23 17:16:59 -0400331 mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
Adrian Roos88e61aa2017-05-23 16:16:50 -0700332 true /* allowEnterAnimation */);
Kevin Chyn36778ff2017-09-07 19:55:38 -0700333 } else if (mMode == MODE_WAKE_AND_UNLOCK){
Adrian Roos88e61aa2017-05-23 16:16:50 -0700334 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
Kevin Chyn36778ff2017-09-07 19:55:38 -0700335 } else {
336 Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
337 mUpdateMonitor.awakenFromDream();
Adrian Roos88e61aa2017-05-23 16:16:50 -0700338 }
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700339 mStatusBarWindowController.setStatusBarFocusable(false);
Lucas Dupine63abf72018-07-02 11:17:14 -0700340 if (delayWakeUp) {
Lucas Dupin2920eea2018-08-29 13:13:40 -0700341 mHandler.postDelayed(wakeUp, mWakeUpDelay);
Lucas Dupine63abf72018-07-02 11:17:14 -0700342 } else {
343 mKeyguardViewMediator.onWakeAndUnlocking();
344 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500345 if (mStatusBar.getNavigationBarView() != null) {
346 mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700347 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700348 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700349 break;
350 case MODE_ONLY_WAKE:
351 case MODE_NONE:
352 break;
353 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200354 mStatusBar.notifyBiometricAuthModeChanged();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700355 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700356 }
357
Adrian Roos58ba6852017-07-18 17:10:29 +0200358 private void showBouncer() {
Lucas Dupin3d053532019-01-29 12:35:22 -0800359 if (mMode == MODE_SHOW_BOUNCER) {
felkachangefebbc2f72018-05-14 12:22:40 +0800360 mStatusBarKeyguardViewManager.showBouncer(false);
361 }
Adrian Roos58ba6852017-07-18 17:10:29 +0200362 mStatusBarKeyguardViewManager.animateCollapsePanels(
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200363 BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
Adrian Roos58ba6852017-07-18 17:10:29 +0200364 mPendingShowBouncer = false;
365 }
366
Jorim Jaggi95e40382015-09-16 15:53:42 -0700367 @Override
368 public void onStartedGoingToSleep(int why) {
Adrian Roosba7ca592017-08-15 17:48:05 +0200369 resetMode();
Lucas Dupinbd6c92b2019-07-17 09:49:52 -0700370 mFadedAwayAfterWakeAndUnlock = false;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700371 mPendingAuthenticatedUserId = -1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200372 mPendingAuthenticatedBioSourceType = null;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700373 }
374
375 @Override
376 public void onFinishedGoingToSleep(int why) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200377 Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
Lucas Dupin45142ba2019-04-10 13:13:20 -0700378 BiometricSourceType pendingType = mPendingAuthenticatedBioSourceType;
379 int pendingUserId = mPendingAuthenticatedUserId;
380 if (pendingUserId != -1 && pendingType != null) {
Jorim Jaggi95e40382015-09-16 15:53:42 -0700381 // Post this to make sure it's executed after the device is fully locked.
Lucas Dupin45142ba2019-04-10 13:13:20 -0700382 mHandler.post(() -> onBiometricAuthenticated(pendingUserId, pendingType));
Jorim Jaggi95e40382015-09-16 15:53:42 -0700383 }
384 mPendingAuthenticatedUserId = -1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200385 mPendingAuthenticatedBioSourceType = null;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700386 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700387 }
388
Adrian Roos710a0b12017-07-07 19:02:34 +0200389 public boolean hasPendingAuthentication() {
390 return mPendingAuthenticatedUserId != -1
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200391 && mUpdateMonitor.isUnlockingWithBiometricAllowed()
Adrian Roos710a0b12017-07-07 19:02:34 +0200392 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
393 }
394
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700395 public int getMode() {
396 return mMode;
397 }
398
Lucas Dupinfa817a02019-07-02 15:22:54 -0700399 private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType) {
400 if (biometricSourceType == BiometricSourceType.FACE
401 || biometricSourceType == BiometricSourceType.IRIS) {
402 return calculateModeForPassiveAuth();
403 } else {
404 return calculateModeForFingerprint();
405 }
406 }
407
408 private @WakeAndUnlockMode int calculateModeForFingerprint() {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200409 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
Kevin Chyn36778ff2017-09-07 19:55:38 -0700410 boolean deviceDreaming = mUpdateMonitor.isDreaming();
Adrian Roos02626662017-07-06 18:22:17 +0200411
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700412 if (!mUpdateMonitor.isDeviceInteractive()) {
413 if (!mStatusBarKeyguardViewManager.isShowing()) {
414 return MODE_ONLY_WAKE;
Adrian Roose4cb6c8a2017-07-19 18:08:07 +0200415 } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
Lucas Dupinfa817a02019-07-02 15:22:54 -0700416 return MODE_WAKE_AND_UNLOCK_PULSING;
Lucas Dupinc8f16e82019-09-17 18:24:50 -0400417 } else if (unlockingAllowed || !mKeyguardStateController.isMethodSecure()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700418 return MODE_WAKE_AND_UNLOCK;
419 } else {
420 return MODE_SHOW_BOUNCER;
421 }
422 }
Lucas Dupinfa817a02019-07-02 15:22:54 -0700423 if (unlockingAllowed && deviceDreaming) {
Kevin Chyn36778ff2017-09-07 19:55:38 -0700424 return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
425 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700426 if (mStatusBarKeyguardViewManager.isShowing()) {
Lucas Dupinfa817a02019-07-02 15:22:54 -0700427 if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) {
428 return MODE_DISMISS_BOUNCER;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700429 } else if (unlockingAllowed) {
Lucas Dupinfa817a02019-07-02 15:22:54 -0700430 return MODE_UNLOCK_COLLAPSING;
Jorim Jaggibf04cf52015-09-02 11:53:02 -0700431 } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700432 return MODE_SHOW_BOUNCER;
433 }
434 }
435 return MODE_NONE;
436 }
437
Lucas Dupinfa817a02019-07-02 15:22:54 -0700438 private @WakeAndUnlockMode int calculateModeForPassiveAuth() {
439 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
440 boolean deviceDreaming = mUpdateMonitor.isDreaming();
441 boolean bypass = mKeyguardBypassController.getBypassEnabled();
442
443 if (!mUpdateMonitor.isDeviceInteractive()) {
444 if (!mStatusBarKeyguardViewManager.isShowing()) {
445 return bypass ? MODE_WAKE_AND_UNLOCK : MODE_ONLY_WAKE;
Lucas Dupin81cdfa42019-07-25 20:28:28 -0700446 } else if (!unlockingAllowed) {
447 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
448 } else if (mDozeScrimController.isPulsing()) {
Lucas Dupind5b19b72019-09-12 14:00:45 -0700449 return bypass ? MODE_WAKE_AND_UNLOCK_PULSING : MODE_ONLY_WAKE;
Lucas Dupinfa817a02019-07-02 15:22:54 -0700450 } else {
Lucas Dupinfa817a02019-07-02 15:22:54 -0700451 if (bypass) {
452 // Wake-up fading out nicely
453 return MODE_WAKE_AND_UNLOCK_PULSING;
454 } else {
455 // We could theoretically return MODE_NONE, but this means that the device
456 // would be not interactive, unlocked, and the user would not see the device
457 // state.
458 return MODE_ONLY_WAKE;
459 }
460 }
461 }
462 if (unlockingAllowed && deviceDreaming) {
463 return bypass ? MODE_WAKE_AND_UNLOCK_FROM_DREAM : MODE_ONLY_WAKE;
464 }
465 if (mStatusBarKeyguardViewManager.isShowing()) {
466 if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) {
Lucas Dupina055a672019-07-16 13:46:25 -0700467 if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
468 return MODE_UNLOCK_FADING;
469 } else {
470 return MODE_DISMISS_BOUNCER;
471 }
Lucas Dupinfa817a02019-07-02 15:22:54 -0700472 } else if (unlockingAllowed) {
473 return bypass ? MODE_UNLOCK_FADING : MODE_NONE;
474 } else {
475 return bypass ? MODE_SHOW_BOUNCER : MODE_NONE;
476 }
477 }
478 return MODE_NONE;
479 }
480
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700481 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200482 public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
Steven Wue442acf2019-03-14 13:31:12 -0400483 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
484 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700485 cleanup();
486 }
487
488 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200489 public void onBiometricError(int msgId, String errString,
490 BiometricSourceType biometricSourceType) {
Steven Wue442acf2019-03-14 13:31:12 -0400491 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
Steven Wu40cbada2019-05-16 10:56:40 -0400492 .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
493 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700494 cleanup();
495 }
496
497 private void cleanup() {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200498 releaseBiometricWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700499 }
500
501 public void startKeyguardFadingAway() {
502
503 // Disable brightness override when the ambient contents are fully invisible.
504 mHandler.postDelayed(new Runnable() {
505 @Override
506 public void run() {
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700507 mStatusBarWindowController.setForceDozeBrightness(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700508 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500509 }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700510 }
511
512 public void finishKeyguardFadingAway() {
Lucas Dupinbd6c92b2019-07-17 09:49:52 -0700513 if (isWakeAndUnlock()) {
514 mFadedAwayAfterWakeAndUnlock = true;
515 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200516 resetMode();
517 }
518
519 private void resetMode() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700520 mMode = MODE_NONE;
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700521 mStatusBarWindowController.setForceDozeBrightness(false);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500522 if (mStatusBar.getNavigationBarView() != null) {
523 mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700524 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200525 mStatusBar.notifyBiometricAuthModeChanged();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700526 }
Adrian Roos58ba6852017-07-18 17:10:29 +0200527
Lucas Dupin81cdfa42019-07-25 20:28:28 -0700528 @VisibleForTesting
529 final WakefulnessLifecycle.Observer mWakefulnessObserver =
Adrian Roos58ba6852017-07-18 17:10:29 +0200530 new WakefulnessLifecycle.Observer() {
531 @Override
532 public void onFinishedWakingUp() {
533 if (mPendingShowBouncer) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200534 BiometricUnlockController.this.showBouncer();
Adrian Roos58ba6852017-07-18 17:10:29 +0200535 }
536 }
537 };
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200538
539 private final ScreenLifecycle.Observer mScreenObserver =
540 new ScreenLifecycle.Observer() {
541 @Override
542 public void onScreenTurnedOn() {
543 mHasScreenTurnedOnSinceAuthenticating = true;
544 }
545 };
546
547 public boolean hasScreenTurnedOnSinceAuthenticating() {
548 return mHasScreenTurnedOnSinceAuthenticating;
549 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200550
551 public void dump(PrintWriter pw) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200552 pw.println(" BiometricUnlockController:");
Adrian Roosba7ca592017-08-15 17:48:05 +0200553 pw.print(" mMode="); pw.println(mMode);
554 pw.print(" mWakeLock="); pw.println(mWakeLock);
555 }
Lucas Dupin067136c2018-03-27 18:03:25 -0700556
Lucas Dupin52c21c82018-06-04 19:03:20 -0700557 /**
Lucas Dupin3d053532019-01-29 12:35:22 -0800558 * Successful authentication with fingerprint, face, or iris that wakes up the device.
Lucas Dupin52c21c82018-06-04 19:03:20 -0700559 */
Lucas Dupin067136c2018-03-27 18:03:25 -0700560 public boolean isWakeAndUnlock() {
Lucas Dupin52c21c82018-06-04 19:03:20 -0700561 return mMode == MODE_WAKE_AND_UNLOCK
Lucas Dupin067136c2018-03-27 18:03:25 -0700562 || mMode == MODE_WAKE_AND_UNLOCK_PULSING
563 || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM;
564 }
Lucas Dupin52c21c82018-06-04 19:03:20 -0700565
566 /**
Lucas Dupinbd6c92b2019-07-17 09:49:52 -0700567 * Successful authentication with fingerprint, face, or iris that wakes up the device.
568 * This will return {@code true} even after the keyguard fades away.
569 */
570 public boolean unlockedByWakeAndUnlock() {
571 return isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock;
572 }
573
574 /**
Lucas Dupin3d053532019-01-29 12:35:22 -0800575 * Successful authentication with fingerprint, face, or iris when the screen was either
576 * on or off.
Lucas Dupin52c21c82018-06-04 19:03:20 -0700577 */
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200578 public boolean isBiometricUnlock() {
Lucas Dupinfa817a02019-07-02 15:22:54 -0700579 return isWakeAndUnlock() || mMode == MODE_UNLOCK_COLLAPSING || mMode == MODE_UNLOCK_FADING;
Lucas Dupin52c21c82018-06-04 19:03:20 -0700580 }
Steven Wue442acf2019-03-14 13:31:12 -0400581
582 /**
Selim Cinek84b2acc2019-07-07 00:40:38 -0700583 * Successful authentication with fingerprint, face, or iris when the lockscreen fades away
584 */
585 public boolean isUnlockFading() {
586 return mMode == MODE_UNLOCK_FADING;
587 }
588
589 /**
Steven Wue442acf2019-03-14 13:31:12 -0400590 * Translates biometric source type for logging purpose.
591 */
592 private int toSubtype(BiometricSourceType biometricSourceType) {
593 switch (biometricSourceType) {
594 case FINGERPRINT:
595 return 0;
596 case FACE:
597 return 1;
598 case IRIS:
599 return 2;
600 default:
601 return 3;
602 }
603 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700604}