• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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