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