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.content.Context; 20 import android.hardware.biometrics.BiometricSourceType; 21 import android.metrics.LogMaker; 22 import android.os.Handler; 23 import android.os.PowerManager; 24 import android.os.SystemClock; 25 import android.os.Trace; 26 import android.provider.Settings; 27 import android.util.Log; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.logging.MetricsLogger; 31 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 32 import com.android.internal.util.LatencyTracker; 33 import com.android.keyguard.KeyguardConstants; 34 import com.android.keyguard.KeyguardUpdateMonitor; 35 import com.android.keyguard.KeyguardUpdateMonitorCallback; 36 import com.android.systemui.Dependency; 37 import com.android.systemui.R; 38 import com.android.systemui.keyguard.KeyguardViewMediator; 39 import com.android.systemui.keyguard.ScreenLifecycle; 40 import com.android.systemui.keyguard.WakefulnessLifecycle; 41 import com.android.systemui.statusbar.NotificationMediaManager; 42 import com.android.systemui.tuner.TunerService; 43 44 import java.io.PrintWriter; 45 46 /** 47 * Controller which coordinates all the biometric unlocking actions with the UI. 48 */ 49 public class BiometricUnlockController extends KeyguardUpdateMonitorCallback { 50 51 private static final String TAG = "BiometricUnlockController"; 52 private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK; 53 private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000; 54 private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock wakelock"; 55 56 /** 57 * Mode in which we don't need to wake up the device when we authenticate. 58 */ 59 public static final int MODE_NONE = 0; 60 61 /** 62 * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire 63 * a fingerprint while the screen is off and the device was sleeping. 64 */ 65 public static final int MODE_WAKE_AND_UNLOCK = 1; 66 67 /** 68 * Mode in which we wake the device up, and fade out the Keyguard contents because they were 69 * already visible while pulsing in doze mode. 70 */ 71 public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2; 72 73 /** 74 * Mode in which we wake up the device, but play the normal dismiss animation. Active when we 75 * acquire a fingerprint pulsing in doze mode. 76 */ 77 public static final int MODE_SHOW_BOUNCER = 3; 78 79 /** 80 * Mode in which we only wake up the device, and keyguard was not showing when we authenticated. 81 * */ 82 public static final int MODE_ONLY_WAKE = 4; 83 84 /** 85 * Mode in which fingerprint unlocks the device. 86 */ 87 public static final int MODE_UNLOCK = 5; 88 89 /** 90 * Mode in which fingerprint brings up the bouncer because fingerprint unlocking is currently 91 * not allowed. 92 */ 93 public static final int MODE_DISMISS_BOUNCER = 6; 94 95 /** 96 * Mode in which fingerprint wakes and unlocks the device from a dream. 97 */ 98 public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 7; 99 100 /** 101 * How much faster we collapse the lockscreen when authenticating with biometric. 102 */ 103 private static final float BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR = 1.1f; 104 105 /** 106 * If face unlock dismisses the lock screen or keeps user on keyguard by default on this device. 107 */ 108 private final boolean mFaceDismissesKeyguardByDefault; 109 110 /** 111 * If face unlock dismisses the lock screen or keeps user on keyguard for the current user. 112 */ 113 @VisibleForTesting 114 protected boolean mFaceDismissesKeyguard; 115 116 private final NotificationMediaManager mMediaManager; 117 private final PowerManager mPowerManager; 118 private final Handler mHandler; 119 private PowerManager.WakeLock mWakeLock; 120 private final KeyguardUpdateMonitor mUpdateMonitor; 121 private final UnlockMethodCache mUnlockMethodCache; 122 private final StatusBarWindowController mStatusBarWindowController; 123 private final Context mContext; 124 private final int mWakeUpDelay; 125 private int mMode; 126 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; 127 private DozeScrimController mDozeScrimController; 128 private KeyguardViewMediator mKeyguardViewMediator; 129 private ScrimController mScrimController; 130 private StatusBar mStatusBar; 131 private int mPendingAuthenticatedUserId = -1; 132 private BiometricSourceType mPendingAuthenticatedBioSourceType = null; 133 private boolean mPendingShowBouncer; 134 private boolean mHasScreenTurnedOnSinceAuthenticating; 135 private boolean mFadedAwayAfterWakeAndUnlock; 136 137 private final TunerService.Tunable mFaceDismissedKeyguardTunable = new TunerService.Tunable() { 138 @Override 139 public void onTuningChanged(String key, String newValue) { 140 int defaultValue = mFaceDismissesKeyguardByDefault ? 1 : 0; 141 mFaceDismissesKeyguard = Settings.Secure.getIntForUser(mContext.getContentResolver(), 142 Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 143 defaultValue, KeyguardUpdateMonitor.getCurrentUser()) != 0; 144 } 145 }; 146 147 private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); 148 BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, StatusBar statusBar, UnlockMethodCache unlockMethodCache, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, TunerService tunerService)149 public BiometricUnlockController(Context context, 150 DozeScrimController dozeScrimController, 151 KeyguardViewMediator keyguardViewMediator, 152 ScrimController scrimController, 153 StatusBar statusBar, 154 UnlockMethodCache unlockMethodCache, Handler handler, 155 KeyguardUpdateMonitor keyguardUpdateMonitor, 156 TunerService tunerService) { 157 this(context, dozeScrimController, keyguardViewMediator, scrimController, statusBar, 158 unlockMethodCache, handler, keyguardUpdateMonitor, tunerService, 159 context.getResources() 160 .getInteger(com.android.internal.R.integer.config_wakeUpDelayDoze), 161 context.getResources().getBoolean(R.bool.config_faceAuthDismissesKeyguard)); 162 } 163 164 @VisibleForTesting BiometricUnlockController(Context context, DozeScrimController dozeScrimController, KeyguardViewMediator keyguardViewMediator, ScrimController scrimController, StatusBar statusBar, UnlockMethodCache unlockMethodCache, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, TunerService tunerService, int wakeUpDelay, boolean faceDismissesKeyguard)165 protected BiometricUnlockController(Context context, 166 DozeScrimController dozeScrimController, 167 KeyguardViewMediator keyguardViewMediator, 168 ScrimController scrimController, 169 StatusBar statusBar, 170 UnlockMethodCache unlockMethodCache, Handler handler, 171 KeyguardUpdateMonitor keyguardUpdateMonitor, 172 TunerService tunerService, 173 int wakeUpDelay, 174 boolean faceDismissesKeyguard) { 175 mContext = context; 176 mPowerManager = context.getSystemService(PowerManager.class); 177 mUpdateMonitor = keyguardUpdateMonitor; 178 mUpdateMonitor.registerCallback(this); 179 mMediaManager = Dependency.get(NotificationMediaManager.class); 180 Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver); 181 Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver); 182 mStatusBarWindowController = Dependency.get(StatusBarWindowController.class); 183 mDozeScrimController = dozeScrimController; 184 mKeyguardViewMediator = keyguardViewMediator; 185 mScrimController = scrimController; 186 mStatusBar = statusBar; 187 mUnlockMethodCache = unlockMethodCache; 188 mHandler = handler; 189 mWakeUpDelay = wakeUpDelay; 190 mFaceDismissesKeyguardByDefault = faceDismissesKeyguard; 191 tunerService.addTunable(mFaceDismissedKeyguardTunable, 192 Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD); 193 } 194 setStatusBarKeyguardViewManager( StatusBarKeyguardViewManager statusBarKeyguardViewManager)195 public void setStatusBarKeyguardViewManager( 196 StatusBarKeyguardViewManager statusBarKeyguardViewManager) { 197 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; 198 } 199 200 private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() { 201 @Override 202 public void run() { 203 if (DEBUG_BIO_WAKELOCK) { 204 Log.i(TAG, "biometric wakelock: TIMEOUT!!"); 205 } 206 releaseBiometricWakeLock(); 207 } 208 }; 209 releaseBiometricWakeLock()210 private void releaseBiometricWakeLock() { 211 if (mWakeLock != null) { 212 mHandler.removeCallbacks(mReleaseBiometricWakeLockRunnable); 213 if (DEBUG_BIO_WAKELOCK) { 214 Log.i(TAG, "releasing biometric wakelock"); 215 } 216 mWakeLock.release(); 217 mWakeLock = null; 218 } 219 } 220 221 @Override onBiometricAcquired(BiometricSourceType biometricSourceType)222 public void onBiometricAcquired(BiometricSourceType biometricSourceType) { 223 Trace.beginSection("BiometricUnlockController#onBiometricAcquired"); 224 releaseBiometricWakeLock(); 225 if (!mUpdateMonitor.isDeviceInteractive()) { 226 if (LatencyTracker.isEnabled(mContext)) { 227 int action = LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK; 228 if (biometricSourceType == BiometricSourceType.FACE) { 229 action = LatencyTracker.ACTION_FACE_WAKE_AND_UNLOCK; 230 } 231 LatencyTracker.getInstance(mContext).onActionStart(action); 232 } 233 mWakeLock = mPowerManager.newWakeLock( 234 PowerManager.PARTIAL_WAKE_LOCK, BIOMETRIC_WAKE_LOCK_NAME); 235 Trace.beginSection("acquiring wake-and-unlock"); 236 mWakeLock.acquire(); 237 Trace.endSection(); 238 if (DEBUG_BIO_WAKELOCK) { 239 Log.i(TAG, "biometric acquired, grabbing biometric wakelock"); 240 } 241 mHandler.postDelayed(mReleaseBiometricWakeLockRunnable, 242 BIOMETRIC_WAKELOCK_TIMEOUT_MS); 243 } 244 Trace.endSection(); 245 } 246 pulsingOrAod()247 private boolean pulsingOrAod() { 248 final ScrimState scrimState = mScrimController.getState(); 249 return scrimState == ScrimState.AOD 250 || scrimState == ScrimState.PULSING; 251 } 252 253 @Override onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType)254 public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) { 255 Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated"); 256 if (mUpdateMonitor.isGoingToSleep()) { 257 mPendingAuthenticatedUserId = userId; 258 mPendingAuthenticatedBioSourceType = biometricSourceType; 259 Trace.endSection(); 260 return; 261 } 262 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH) 263 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType))); 264 startWakeAndUnlock(calculateMode(biometricSourceType)); 265 } 266 startWakeAndUnlock(int mode)267 public void startWakeAndUnlock(int mode) { 268 // TODO(b/62444020): remove when this bug is fixed 269 Log.v(TAG, "startWakeAndUnlock(" + mode + ")"); 270 boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive(); 271 mMode = mode; 272 mHasScreenTurnedOnSinceAuthenticating = false; 273 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) { 274 // If we are waking the device up while we are pulsing the clock and the 275 // notifications would light up first, creating an unpleasant animation. 276 // Defer changing the screen brightness by forcing doze brightness on our window 277 // until the clock and the notifications are faded out. 278 mStatusBarWindowController.setForceDozeBrightness(true); 279 } 280 // During wake and unlock, we need to draw black before waking up to avoid abrupt 281 // brightness changes due to display state transitions. 282 boolean alwaysOnEnabled = DozeParameters.getInstance(mContext).getAlwaysOn(); 283 boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0; 284 Runnable wakeUp = ()-> { 285 if (!wasDeviceInteractive) { 286 if (DEBUG_BIO_WAKELOCK) { 287 Log.i(TAG, "bio wakelock: Authenticated, waking up..."); 288 } 289 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, 290 "android.policy:BIOMETRIC"); 291 } 292 if (delayWakeUp) { 293 mKeyguardViewMediator.onWakeAndUnlocking(); 294 } 295 Trace.beginSection("release wake-and-unlock"); 296 releaseBiometricWakeLock(); 297 Trace.endSection(); 298 }; 299 300 if (!delayWakeUp) { 301 wakeUp.run(); 302 } 303 switch (mMode) { 304 case MODE_DISMISS_BOUNCER: 305 Trace.beginSection("MODE_DISMISS"); 306 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated( 307 false /* strongAuth */); 308 Trace.endSection(); 309 break; 310 case MODE_UNLOCK: 311 case MODE_SHOW_BOUNCER: 312 Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER"); 313 if (!wasDeviceInteractive) { 314 mPendingShowBouncer = true; 315 } else { 316 showBouncer(); 317 } 318 Trace.endSection(); 319 break; 320 case MODE_WAKE_AND_UNLOCK_FROM_DREAM: 321 case MODE_WAKE_AND_UNLOCK_PULSING: 322 case MODE_WAKE_AND_UNLOCK: 323 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) { 324 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING"); 325 mMediaManager.updateMediaMetaData(false /* metaDataChanged */, 326 true /* allowEnterAnimation */); 327 } else if (mMode == MODE_WAKE_AND_UNLOCK){ 328 Trace.beginSection("MODE_WAKE_AND_UNLOCK"); 329 } else { 330 Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM"); 331 mUpdateMonitor.awakenFromDream(); 332 } 333 mStatusBarWindowController.setStatusBarFocusable(false); 334 if (delayWakeUp) { 335 mHandler.postDelayed(wakeUp, mWakeUpDelay); 336 } else { 337 mKeyguardViewMediator.onWakeAndUnlocking(); 338 } 339 if (mStatusBar.getNavigationBarView() != null) { 340 mStatusBar.getNavigationBarView().setWakeAndUnlocking(true); 341 } 342 Trace.endSection(); 343 break; 344 case MODE_ONLY_WAKE: 345 case MODE_NONE: 346 break; 347 } 348 mStatusBar.notifyBiometricAuthModeChanged(); 349 Trace.endSection(); 350 } 351 showBouncer()352 private void showBouncer() { 353 if (mMode == MODE_SHOW_BOUNCER) { 354 mStatusBarKeyguardViewManager.showBouncer(false); 355 } 356 mStatusBarKeyguardViewManager.animateCollapsePanels( 357 BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR); 358 mPendingShowBouncer = false; 359 } 360 361 @Override onStartedGoingToSleep(int why)362 public void onStartedGoingToSleep(int why) { 363 resetMode(); 364 mFadedAwayAfterWakeAndUnlock = false; 365 mPendingAuthenticatedUserId = -1; 366 mPendingAuthenticatedBioSourceType = null; 367 } 368 369 @Override onFinishedGoingToSleep(int why)370 public void onFinishedGoingToSleep(int why) { 371 Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep"); 372 BiometricSourceType pendingType = mPendingAuthenticatedBioSourceType; 373 int pendingUserId = mPendingAuthenticatedUserId; 374 if (pendingUserId != -1 && pendingType != null) { 375 // Post this to make sure it's executed after the device is fully locked. 376 mHandler.post(() -> onBiometricAuthenticated(pendingUserId, pendingType)); 377 } 378 mPendingAuthenticatedUserId = -1; 379 mPendingAuthenticatedBioSourceType = null; 380 Trace.endSection(); 381 } 382 hasPendingAuthentication()383 public boolean hasPendingAuthentication() { 384 return mPendingAuthenticatedUserId != -1 385 && mUpdateMonitor.isUnlockingWithBiometricAllowed() 386 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser(); 387 } 388 getMode()389 public int getMode() { 390 return mMode; 391 } 392 calculateMode(BiometricSourceType biometricSourceType)393 private int calculateMode(BiometricSourceType biometricSourceType) { 394 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed(); 395 boolean deviceDreaming = mUpdateMonitor.isDreaming(); 396 boolean faceStayingOnKeyguard = biometricSourceType == BiometricSourceType.FACE 397 && !mFaceDismissesKeyguard; 398 399 if (!mUpdateMonitor.isDeviceInteractive()) { 400 if (!mStatusBarKeyguardViewManager.isShowing()) { 401 return MODE_ONLY_WAKE; 402 } else if (mDozeScrimController.isPulsing() && unlockingAllowed) { 403 return faceStayingOnKeyguard ? MODE_NONE : MODE_WAKE_AND_UNLOCK_PULSING; 404 } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) { 405 return MODE_WAKE_AND_UNLOCK; 406 } else { 407 return MODE_SHOW_BOUNCER; 408 } 409 } 410 if (unlockingAllowed && deviceDreaming && !faceStayingOnKeyguard) { 411 return MODE_WAKE_AND_UNLOCK_FROM_DREAM; 412 } 413 if (mStatusBarKeyguardViewManager.isShowing()) { 414 if ((mStatusBarKeyguardViewManager.isBouncerShowing() 415 || mStatusBarKeyguardViewManager.isBouncerPartiallyVisible()) 416 && unlockingAllowed) { 417 return MODE_DISMISS_BOUNCER; 418 } else if (unlockingAllowed) { 419 return faceStayingOnKeyguard ? MODE_ONLY_WAKE : MODE_UNLOCK; 420 } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) { 421 return MODE_SHOW_BOUNCER; 422 } 423 } 424 return MODE_NONE; 425 } 426 427 @Override onBiometricAuthFailed(BiometricSourceType biometricSourceType)428 public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { 429 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH) 430 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType))); 431 cleanup(); 432 } 433 434 @Override onBiometricError(int msgId, String errString, BiometricSourceType biometricSourceType)435 public void onBiometricError(int msgId, String errString, 436 BiometricSourceType biometricSourceType) { 437 mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH) 438 .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType)) 439 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId)); 440 cleanup(); 441 } 442 cleanup()443 private void cleanup() { 444 releaseBiometricWakeLock(); 445 } 446 startKeyguardFadingAway()447 public void startKeyguardFadingAway() { 448 449 // Disable brightness override when the ambient contents are fully invisible. 450 mHandler.postDelayed(new Runnable() { 451 @Override 452 public void run() { 453 mStatusBarWindowController.setForceDozeBrightness(false); 454 } 455 }, StatusBar.FADE_KEYGUARD_DURATION_PULSING); 456 } 457 finishKeyguardFadingAway()458 public void finishKeyguardFadingAway() { 459 if (isWakeAndUnlock()) { 460 mFadedAwayAfterWakeAndUnlock = true; 461 } 462 resetMode(); 463 } 464 resetMode()465 private void resetMode() { 466 mMode = MODE_NONE; 467 mStatusBarWindowController.setForceDozeBrightness(false); 468 if (mStatusBar.getNavigationBarView() != null) { 469 mStatusBar.getNavigationBarView().setWakeAndUnlocking(false); 470 } 471 mStatusBar.notifyBiometricAuthModeChanged(); 472 } 473 474 private final WakefulnessLifecycle.Observer mWakefulnessObserver = 475 new WakefulnessLifecycle.Observer() { 476 @Override 477 public void onFinishedWakingUp() { 478 if (mPendingShowBouncer) { 479 BiometricUnlockController.this.showBouncer(); 480 } 481 } 482 }; 483 484 private final ScreenLifecycle.Observer mScreenObserver = 485 new ScreenLifecycle.Observer() { 486 @Override 487 public void onScreenTurnedOn() { 488 mHasScreenTurnedOnSinceAuthenticating = true; 489 } 490 }; 491 hasScreenTurnedOnSinceAuthenticating()492 public boolean hasScreenTurnedOnSinceAuthenticating() { 493 return mHasScreenTurnedOnSinceAuthenticating; 494 } 495 dump(PrintWriter pw)496 public void dump(PrintWriter pw) { 497 pw.println(" BiometricUnlockController:"); 498 pw.print(" mMode="); pw.println(mMode); 499 pw.print(" mWakeLock="); pw.println(mWakeLock); 500 } 501 502 /** 503 * Successful authentication with fingerprint, face, or iris that wakes up the device. 504 */ isWakeAndUnlock()505 public boolean isWakeAndUnlock() { 506 return mMode == MODE_WAKE_AND_UNLOCK 507 || mMode == MODE_WAKE_AND_UNLOCK_PULSING 508 || mMode == MODE_WAKE_AND_UNLOCK_FROM_DREAM; 509 } 510 511 /** 512 * Successful authentication with fingerprint, face, or iris that wakes up the device. 513 * This will return {@code true} even after the keyguard fades away. 514 */ unlockedByWakeAndUnlock()515 public boolean unlockedByWakeAndUnlock() { 516 return isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock; 517 } 518 519 /** 520 * Successful authentication with fingerprint, face, or iris when the screen was either 521 * on or off. 522 */ isBiometricUnlock()523 public boolean isBiometricUnlock() { 524 return isWakeAndUnlock() || mMode == MODE_UNLOCK; 525 } 526 527 /** 528 * Translates biometric source type for logging purpose. 529 */ toSubtype(BiometricSourceType biometricSourceType)530 private int toSubtype(BiometricSourceType biometricSourceType) { 531 switch (biometricSourceType) { 532 case FINGERPRINT: 533 return 0; 534 case FACE: 535 return 1; 536 case IRIS: 537 return 2; 538 default: 539 return 3; 540 } 541 } 542 } 543