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