blob: fdf18e0c7912169e0d129f775e6263efb1279939 [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
19import android.content.Context;
Gus Prevasab336792018-11-14 13:52:20 -050020import android.hardware.biometrics.BiometricSourceType;
Steven Wue442acf2019-03-14 13:31:12 -040021import android.metrics.LogMaker;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070022import android.os.Handler;
23import android.os.PowerManager;
24import android.os.SystemClock;
Nick Desaulniers1d396752016-07-25 15:05:33 -070025import android.os.Trace;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070026import android.util.Log;
27
Lucas Dupinc94963f2019-03-07 14:54:05 -080028import com.android.internal.annotations.VisibleForTesting;
Steven Wue442acf2019-03-14 13:31:12 -040029import com.android.internal.logging.MetricsLogger;
30import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Gus Prevasab336792018-11-14 13:52:20 -050031import com.android.internal.util.LatencyTracker;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070032import com.android.keyguard.KeyguardConstants;
33import com.android.keyguard.KeyguardUpdateMonitor;
34import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jason Monk421a9412017-02-06 09:15:21 -080035import com.android.systemui.Dependency;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070036import com.android.systemui.keyguard.KeyguardViewMediator;
Adrian Roos7a5e4c92017-07-31 16:40:19 +020037import com.android.systemui.keyguard.ScreenLifecycle;
Adrian Roos58ba6852017-07-18 17:10:29 +020038import com.android.systemui.keyguard.WakefulnessLifecycle;
Jason Monk297c04e2018-08-23 17:16:59 -040039import com.android.systemui.statusbar.NotificationMediaManager;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070040
Adrian Roosba7ca592017-08-15 17:48:05 +020041import java.io.PrintWriter;
42
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070043/**
Gilad Brettercb51b8b2018-03-22 17:04:51 +020044 * Controller which coordinates all the biometric unlocking actions with the UI.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070045 */
Gilad Brettercb51b8b2018-03-22 17:04:51 +020046public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070047
Gilad Brettercb51b8b2018-03-22 17:04:51 +020048 private static final String TAG = "BiometricUnlockController";
49 private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
50 private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
51 private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070052
53 /**
Lucas Dupin3d053532019-01-29 12:35:22 -080054 * Mode in which we don't need to wake up the device when we authenticate.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070055 */
56 public static final int MODE_NONE = 0;
57
58 /**
59 * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
60 * a fingerprint while the screen is off and the device was sleeping.
61 */
62 public static final int MODE_WAKE_AND_UNLOCK = 1;
63
64 /**
65 * Mode in which we wake the device up, and fade out the Keyguard contents because they were
66 * already visible while pulsing in doze mode.
67 */
68 public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
69
70 /**
71 * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
72 * acquire a fingerprint pulsing in doze mode.
73 */
74 public static final int MODE_SHOW_BOUNCER = 3;
75
76 /**
Lucas Dupin3d053532019-01-29 12:35:22 -080077 * Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070078 * */
79 public static final int MODE_ONLY_WAKE = 4;
80
81 /**
82 * Mode in which fingerprint unlocks the device.
83 */
84 public static final int MODE_UNLOCK = 5;
85
86 /**
Kevin Chyn36778ff2017-09-07 19:55:38 -070087 * Mode in which fingerprint wakes and unlocks the device from a dream.
88 */
Lucas Dupine78794c2019-06-18 11:55:37 -070089 public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 6;
Kevin Chyn36778ff2017-09-07 19:55:38 -070090
91 /**
Gilad Brettercb51b8b2018-03-22 17:04:51 +020092 * How much faster we collapse the lockscreen when authenticating with biometric.
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070093 */
Gilad Brettercb51b8b2018-03-22 17:04:51 +020094 private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070095
Lucas Dupin3d053532019-01-29 12:35:22 -080096 private final NotificationMediaManager mMediaManager;
97 private final PowerManager mPowerManager;
98 private final Handler mHandler;
Selim Cinek2c890ee2019-05-20 19:16:43 -070099 private final KeyguardBypassController mKeyguardBypassController;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700100 private PowerManager.WakeLock mWakeLock;
Lucas Dupin3d053532019-01-29 12:35:22 -0800101 private final KeyguardUpdateMonitor mUpdateMonitor;
102 private final UnlockMethodCache mUnlockMethodCache;
103 private final StatusBarWindowController mStatusBarWindowController;
104 private final Context mContext;
105 private final int mWakeUpDelay;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700106 private int mMode;
107 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700108 private DozeScrimController mDozeScrimController;
109 private KeyguardViewMediator mKeyguardViewMediator;
110 private ScrimController mScrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500111 private StatusBar mStatusBar;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700112 private int mPendingAuthenticatedUserId = -1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200113 private BiometricSourceType mPendingAuthenticatedBioSourceType = null;
Adrian Roos58ba6852017-07-18 17:10:29 +0200114 private boolean mPendingShowBouncer;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200115 private boolean mHasScreenTurnedOnSinceAuthenticating;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700116
Steven Wue442acf2019-03-14 13:31:12 -0400117 private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
118
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200119 public BiometricUnlockController(Context context,
Lucas Dupinc94963f2019-03-07 14:54:05 -0800120 DozeScrimController dozeScrimController,
121 KeyguardViewMediator keyguardViewMediator,
122 ScrimController scrimController,
123 StatusBar statusBar,
124 UnlockMethodCache unlockMethodCache, Handler handler,
125 KeyguardUpdateMonitor keyguardUpdateMonitor,
Selim Cinek2c890ee2019-05-20 19:16:43 -0700126 KeyguardBypassController keyguardBypassController) {
Lucas Dupinc94963f2019-03-07 14:54:05 -0800127 this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar,
Selim Cinek2c890ee2019-05-20 19:16:43 -0700128 unlockMethodCache, handler, keyguardUpdateMonitor,
Lucas Dupinc94963f2019-03-07 14:54:05 -0800129 context.getResources()
130 .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze),
Selim Cinek2c890ee2019-05-20 19:16:43 -0700131 keyguardBypassController);
Lucas Dupinc94963f2019-03-07 14:54:05 -0800132 }
133
134 @VisibleForTesting
135 protected BiometricUnlockController(Context context,
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200136 DozeScrimController dozeScrimController,
137 KeyguardViewMediator keyguardViewMediator,
138 ScrimController scrimController,
139 StatusBar statusBar,
Lucas Dupin3d053532019-01-29 12:35:22 -0800140 UnlockMethodCache unlockMethodCache, Handler handler,
141 KeyguardUpdateMonitor keyguardUpdateMonitor,
Lucas Dupinc94963f2019-03-07 14:54:05 -0800142 int wakeUpDelay,
Selim Cinek2c890ee2019-05-20 19:16:43 -0700143 KeyguardBypassController keyguardBypassController) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700144 mContext = context;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700145 mPowerManager = context.getSystemService(PowerManager.class);
Lucas Dupin3d053532019-01-29 12:35:22 -0800146 mUpdateMonitor = keyguardUpdateMonitor;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700147 mUpdateMonitor.registerCallback(this);
Lucas Dupin3d053532019-01-29 12:35:22 -0800148 mMediaManager = Dependency.get(NotificationMediaManager.class);
Adrian Roos58ba6852017-07-18 17:10:29 +0200149 Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200150 Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700151 mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700152 mDozeScrimController = dozeScrimController;
153 mKeyguardViewMediator = keyguardViewMediator;
154 mScrimController = scrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500155 mStatusBar = statusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700156 mUnlockMethodCache = unlockMethodCache;
Lucas Dupin3d053532019-01-29 12:35:22 -0800157 mHandler = handler;
158 mWakeUpDelay = wakeUpDelay;
Selim Cinek2c890ee2019-05-20 19:16:43 -0700159 mKeyguardBypassController = keyguardBypassController;
Selim Cinekbd84c162019-06-11 16:23:23 -0700160 mKeyguardBypassController.setUnlockController(this);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700161 }
162
163 public void setStatusBarKeyguardViewManager(
164 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
165 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
166 }
167
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200168 private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700169 @Override
170 public void run() {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200171 if (DEBUG_BIO_WAKELOCK) {
172 Log.i(TAG, "biometric wakelock: TIMEOUT!!");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700173 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200174 releaseBiometricWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700175 }
176 };
177
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200178 private void releaseBiometricWakeLock() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700179 if (mWakeLock != null) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200180 mHandler.removeCallbacks(mReleaseBiometricWakeLockRunnable);
181 if (DEBUG_BIO_WAKELOCK) {
182 Log.i(TAG, "releasing biometric wakelock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700183 }
184 mWakeLock.release();
185 mWakeLock = null;
186 }
187 }
188
189 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200190 public void onBiometricAcquired(BiometricSourceType biometricSourceType) {
191 Trace.beginSection("BiometricUnlockController#onBiometricAcquired");
192 releaseBiometricWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700193 if (!mUpdateMonitor.isDeviceInteractive()) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700194 if (LatencyTracker.isEnabled(mContext)) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200195 int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK;
196 if (biometricSourceType == BiometricSourceType.FACE) {
197 action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK;
198 }
199 LatencyTracker.getInstance(mContext).onActionStart(action);
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700200 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700201 mWakeLock = mPowerManager.newWakeLock(
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200202 PowerManager.PARTIAL_WAKE_LOCK, BIOMETRIC_WAKE_LOCK_NAME);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700203 Trace.beginSection("acquiring wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700204 mWakeLock.acquire();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700205 Trace.endSection();
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200206 if (DEBUG_BIO_WAKELOCK) {
207 Log.i(TAG, "biometric acquired, grabbing biometric wakelock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700208 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200209 mHandler.postDelayed(mReleaseBiometricWakeLockRunnable,
210 BIOMETRIC_WAKELOCK_TIMEOUT_MS);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700211 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700212 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700213 }
214
Adrian Roos3e23eb52017-07-07 15:58:57 +0200215 private boolean pulsingOrAod() {
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800216 final ScrimState scrimState = mScrimController.getState();
217 return scrimState == ScrimState.AOD
218 || scrimState == ScrimState.PULSING;
Adrian Roos3e23eb52017-07-07 15:58:57 +0200219 }
220
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700221 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200222 public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
223 Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700224 if (mUpdateMonitor.isGoingToSleep()) {
225 mPendingAuthenticatedUserId = userId;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200226 mPendingAuthenticatedBioSourceType = biometricSourceType;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700227 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700228 return;
229 }
Steven Wue442acf2019-03-14 13:31:12 -0400230 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
231 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
Selim Cinekbd84c162019-06-11 16:23:23 -0700232 boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
233 biometricSourceType);
234 if (unlockAllowed) {
235 startWakeAndUnlock(biometricSourceType);
236 }
237 }
238
Selim Cinekb8cc6ef2019-06-14 16:37:53 -0700239 public void startWakeAndUnlock(BiometricSourceType biometricSourceType) {
Lucas Dupin3d053532019-01-29 12:35:22 -0800240 startWakeAndUnlock(calculateMode(biometricSourceType));
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200241 }
242
243 public void startWakeAndUnlock(int mode) {
Kevin Chyn0b508b42017-09-11 17:34:33 -0700244 // TODO(b/62444020): remove when this bug is fixed
245 Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700246 boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200247 mMode = mode;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200248 mHasScreenTurnedOnSinceAuthenticating = false;
Adrian Roosb880afe72017-07-25 17:02:46 +0200249 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
250 // If we are waking the device up while we are pulsing the clock and the
251 // notifications would light up first, creating an unpleasant animation.
252 // Defer changing the screen brightness by forcing doze brightness on our window
253 // until the clock and the notifications are faded out.
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700254 mStatusBarWindowController.setForceDozeBrightness(true);
Adrian Roosb880afe72017-07-25 17:02:46 +0200255 }
Lucas Dupine63abf72018-07-02 11:17:14 -0700256 // During wake and unlock, we need to draw black before waking up to avoid abrupt
257 // brightness changes due to display state transitions.
258 boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn();
Lucas Dupin2920eea2018-08-29 13:13:40 -0700259 boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
Lucas Dupine63abf72018-07-02 11:17:14 -0700260 Runnable wakeUp = ()-> {
261 if (!wasDeviceInteractive) {
262 if (DEBUG_BIO_WAKELOCK) {
263 Log.i(TAG, "bio wakelock: Authenticated, waking up...");
264 }
Michael Wrighte3001042019-02-05 00:13:14 +0000265 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
266 "android.policy:BIOMETRIC");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700267 }
Lucas Dupine63abf72018-07-02 11:17:14 -0700268 if (delayWakeUp) {
269 mKeyguardViewMediator.onWakeAndUnlocking();
270 }
271 Trace.beginSection("release wake-and-unlock");
272 releaseBiometricWakeLock();
273 Trace.endSection();
274 };
275
Lucas Dupin4108a9b2019-05-28 20:41:51 -0700276 if (!delayWakeUp && mMode != MODE_NONE) {
Lucas Dupine63abf72018-07-02 11:17:14 -0700277 wakeUp.run();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700278 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700279 switch (mMode) {
Lucas Dupine78794c2019-06-18 11:55:37 -0700280 case MODE_UNLOCK:
281 Trace.beginSection("MODE_UNLOCK");
282 if (!wasDeviceInteractive) {
283 mPendingShowBouncer = true;
284 } else {
285 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
286 false /* strongAuth */);
287 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700288 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700289 break;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700290 case MODE_SHOW_BOUNCER:
Lucas Dupine78794c2019-06-18 11:55:37 -0700291 Trace.beginSection("MODE_SHOW_BOUNCER");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700292 if (!wasDeviceInteractive) {
Adrian Roos58ba6852017-07-18 17:10:29 +0200293 mPendingShowBouncer = true;
294 } else {
295 showBouncer();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700296 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700297 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700298 break;
Kevin Chyn36778ff2017-09-07 19:55:38 -0700299 case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700300 case MODE_WAKE_AND_UNLOCK_PULSING:
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700301 case MODE_WAKE_AND_UNLOCK:
Adrian Roos88e61aa2017-05-23 16:16:50 -0700302 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
303 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
Jason Monk297c04e2018-08-23 17:16:59 -0400304 mMediaManager.updateMediaMetaData(false /* metaDataChanged */,
Adrian Roos88e61aa2017-05-23 16:16:50 -0700305 true /* allowEnterAnimation */);
Kevin Chyn36778ff2017-09-07 19:55:38 -0700306 } else if (mMode == MODE_WAKE_AND_UNLOCK){
Adrian Roos88e61aa2017-05-23 16:16:50 -0700307 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
Kevin Chyn36778ff2017-09-07 19:55:38 -0700308 } else {
309 Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
310 mUpdateMonitor.awakenFromDream();
Adrian Roos88e61aa2017-05-23 16:16:50 -0700311 }
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700312 mStatusBarWindowController.setStatusBarFocusable(false);
Lucas Dupine63abf72018-07-02 11:17:14 -0700313 if (delayWakeUp) {
Lucas Dupin2920eea2018-08-29 13:13:40 -0700314 mHandler.postDelayed(wakeUp, mWakeUpDelay);
Lucas Dupine63abf72018-07-02 11:17:14 -0700315 } else {
316 mKeyguardViewMediator.onWakeAndUnlocking();
317 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500318 if (mStatusBar.getNavigationBarView() != null) {
319 mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700320 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700321 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700322 break;
323 case MODE_ONLY_WAKE:
324 case MODE_NONE:
325 break;
326 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200327 mStatusBar.notifyBiometricAuthModeChanged();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700328 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700329 }
330
Adrian Roos58ba6852017-07-18 17:10:29 +0200331 private void showBouncer() {
Lucas Dupin3d053532019-01-29 12:35:22 -0800332 if (mMode == MODE_SHOW_BOUNCER) {
felkachangefebbc2f72018-05-14 12:22:40 +0800333 mStatusBarKeyguardViewManager.showBouncer(false);
334 }
Adrian Roos58ba6852017-07-18 17:10:29 +0200335 mStatusBarKeyguardViewManager.animateCollapsePanels(
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200336 BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR);
Adrian Roos58ba6852017-07-18 17:10:29 +0200337 mPendingShowBouncer = false;
338 }
339
Jorim Jaggi95e40382015-09-16 15:53:42 -0700340 @Override
341 public void onStartedGoingToSleep(int why) {
Adrian Roosba7ca592017-08-15 17:48:05 +0200342 resetMode();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700343 mPendingAuthenticatedUserId = -1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200344 mPendingAuthenticatedBioSourceType = null;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700345 }
346
347 @Override
348 public void onFinishedGoingToSleep(int why) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200349 Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
Lucas Dupin45142ba2019-04-10 13:13:20 -0700350 BiometricSourceType pendingType = mPendingAuthenticatedBioSourceType;
351 int pendingUserId = mPendingAuthenticatedUserId;
352 if (pendingUserId != -1 && pendingType != null) {
Jorim Jaggi95e40382015-09-16 15:53:42 -0700353 // Post this to make sure it's executed after the device is fully locked.
Lucas Dupin45142ba2019-04-10 13:13:20 -0700354 mHandler.post(() -> onBiometricAuthenticated(pendingUserId, pendingType));
Jorim Jaggi95e40382015-09-16 15:53:42 -0700355 }
356 mPendingAuthenticatedUserId = -1;
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200357 mPendingAuthenticatedBioSourceType = null;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700358 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700359 }
360
Adrian Roos710a0b12017-07-07 19:02:34 +0200361 public boolean hasPendingAuthentication() {
362 return mPendingAuthenticatedUserId != -1
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200363 && mUpdateMonitor.isUnlockingWithBiometricAllowed()
Adrian Roos710a0b12017-07-07 19:02:34 +0200364 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
365 }
366
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700367 public int getMode() {
368 return mMode;
369 }
370
Lucas Dupin3d053532019-01-29 12:35:22 -0800371 private int calculateMode(BiometricSourceType biometricSourceType) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200372 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
Kevin Chyn36778ff2017-09-07 19:55:38 -0700373 boolean deviceDreaming = mUpdateMonitor.isDreaming();
Lucas Dupin9bae9c22019-06-04 16:37:40 -0700374 boolean face = biometricSourceType == BiometricSourceType.FACE;
375 boolean faceStayingOnKeyguard = face && !mKeyguardBypassController.getBypassEnabled();
Adrian Roos02626662017-07-06 18:22:17 +0200376
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700377 if (!mUpdateMonitor.isDeviceInteractive()) {
378 if (!mStatusBarKeyguardViewManager.isShowing()) {
379 return MODE_ONLY_WAKE;
Adrian Roose4cb6c8a2017-07-19 18:08:07 +0200380 } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
Lucas Dupine78794c2019-06-18 11:55:37 -0700381 // Let's not wake-up to lock screen when not bypassing, otherwise the notification
382 // would move as the user tried to tap it.
Lucas Dupinc94963f2019-03-07 14:54:05 -0800383 return faceStayingOnKeyguard ? MODE_NONE : MODE_WAKE_AND_UNLOCK_PULSING;
Lucas Dupin9bae9c22019-06-04 16:37:40 -0700384 } else if (!face && (unlockingAllowed || !mUnlockMethodCache.isMethodSecure())) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700385 return MODE_WAKE_AND_UNLOCK;
Lucas Dupin9bae9c22019-06-04 16:37:40 -0700386 } else if (face) {
387 if (!(mDozeScrimController.isPulsing() && !unlockingAllowed)) {
388 Log.wtf(TAG, "Face somehow arrived when the device was not interactive");
389 }
Lucas Dupine78794c2019-06-18 11:55:37 -0700390 if (faceStayingOnKeyguard) {
391 // We could theoretically return MODE_NONE, but this means that the device
392 // would be not interactive, unlocked, and the user would not see the device
393 // state.
394 return MODE_ONLY_WAKE;
395 } else {
396 // Wake-up fading out nicely
397 return MODE_WAKE_AND_UNLOCK_PULSING;
398 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700399 } else {
400 return MODE_SHOW_BOUNCER;
401 }
402 }
Lucas Dupinc94963f2019-03-07 14:54:05 -0800403 if (unlockingAllowed && deviceDreaming && !faceStayingOnKeyguard) {
Kevin Chyn36778ff2017-09-07 19:55:38 -0700404 return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
405 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700406 if (mStatusBarKeyguardViewManager.isShowing()) {
Lucas Dupine78794c2019-06-18 11:55:37 -0700407 if ((mStatusBarKeyguardViewManager.isBouncerShowing())
Lucas Dupind61974d2019-03-29 16:09:26 -0700408 && unlockingAllowed) {
Lucas Dupine78794c2019-06-18 11:55:37 -0700409 return MODE_UNLOCK;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700410 } else if (unlockingAllowed) {
Lucas Dupinc94963f2019-03-07 14:54:05 -0800411 return faceStayingOnKeyguard ? MODE_ONLY_WAKE : MODE_UNLOCK;
Lucas Dupin9bae9c22019-06-04 16:37:40 -0700412 } else if (face) {
413 return MODE_NONE;
Jorim Jaggibf04cf52015-09-02 11:53:02 -0700414 } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700415 return MODE_SHOW_BOUNCER;
416 }
417 }
418 return MODE_NONE;
419 }
420
421 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200422 public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
Steven Wue442acf2019-03-14 13:31:12 -0400423 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
424 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700425 cleanup();
426 }
427
428 @Override
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200429 public void onBiometricError(int msgId, String errString,
430 BiometricSourceType biometricSourceType) {
Steven Wue442acf2019-03-14 13:31:12 -0400431 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
Steven Wu40cbada2019-05-16 10:56:40 -0400432 .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
433 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700434 cleanup();
435 }
436
437 private void cleanup() {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200438 releaseBiometricWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700439 }
440
441 public void startKeyguardFadingAway() {
442
443 // Disable brightness override when the ambient contents are fully invisible.
444 mHandler.postDelayed(new Runnable() {
445 @Override
446 public void run() {
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700447 mStatusBarWindowController.setForceDozeBrightness(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700448 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500449 }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700450 }
451
452 public void finishKeyguardFadingAway() {
Adrian Roosba7ca592017-08-15 17:48:05 +0200453 resetMode();
454 }
455
456 private void resetMode() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700457 mMode = MODE_NONE;
Lucas Dupin1a8588d2018-08-21 12:18:47 -0700458 mStatusBarWindowController.setForceDozeBrightness(false);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500459 if (mStatusBar.getNavigationBarView() != null) {
460 mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700461 }
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200462 mStatusBar.notifyBiometricAuthModeChanged();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700463 }
Adrian Roos58ba6852017-07-18 17:10:29 +0200464
465 private final WakefulnessLifecycle.Observer mWakefulnessObserver =
466 new WakefulnessLifecycle.Observer() {
467 @Override
468 public void onFinishedWakingUp() {
469 if (mPendingShowBouncer) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200470 BiometricUnlockController.this.showBouncer();
Adrian Roos58ba6852017-07-18 17:10:29 +0200471 }
472 }
473 };
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200474
475 private final ScreenLifecycle.Observer mScreenObserver =
476 new ScreenLifecycle.Observer() {
477 @Override
478 public void onScreenTurnedOn() {
479 mHasScreenTurnedOnSinceAuthenticating = true;
480 }
481 };
482
483 public boolean hasScreenTurnedOnSinceAuthenticating() {
484 return mHasScreenTurnedOnSinceAuthenticating;
485 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200486
487 public void dump(PrintWriter pw) {
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200488 pw.println(" BiometricUnlockController:");
Adrian Roosba7ca592017-08-15 17:48:05 +0200489 pw.print(" mMode="); pw.println(mMode);
490 pw.print(" mWakeLock="); pw.println(mWakeLock);
491 }
Lucas Dupin067136c2018-03-27 18:03:25 -0700492
Lucas Dupin52c21c82018-06-04 19:03:20 -0700493 /**
Lucas Dupin3d053532019-01-29 12:35:22 -0800494 * Successful authentication with fingerprint, face, or iris that wakes up the device.
Lucas Dupin52c21c82018-06-04 19:03:20 -0700495 */
Lucas Dupin067136c2018-03-27 18:03:25 -0700496 public boolean isWakeAndUnlock() {
Lucas Dupin52c21c82018-06-04 19:03:20 -0700497 return mMode == MODE_WAKE_AND_UNLOCK
Lucas Dupin067136c2018-03-27 18:03:25 -0700498 || mMode == MODE_WAKE_AND_UNLOCK_PULSING
499 || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM;
500 }
Lucas Dupin52c21c82018-06-04 19:03:20 -0700501
502 /**
Lucas Dupin3d053532019-01-29 12:35:22 -0800503 * Successful authentication with fingerprint, face, or iris when the screen was either
504 * on or off.
Lucas Dupin52c21c82018-06-04 19:03:20 -0700505 */
Gilad Brettercb51b8b2018-03-22 17:04:51 +0200506 public boolean isBiometricUnlock() {
Lucas Dupin52c21c82018-06-04 19:03:20 -0700507 return isWakeAndUnlock() || mMode == MODE_UNLOCK;
508 }
Steven Wue442acf2019-03-14 13:31:12 -0400509
510 /**
511 * Translates biometric source type for logging purpose.
512 */
513 private int toSubtype(BiometricSourceType biometricSourceType) {
514 switch (biometricSourceType) {
515 case FINGERPRINT:
516 return 0;
517 case FACE:
518 return 1;
519 case IRIS:
520 return 2;
521 default:
522 return 3;
523 }
524 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700525}