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