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