OSDN Git Service

Merge "docs: Add documentation for equals() method" into qt-dev
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / statusbar / phone / BiometricUnlockController.java
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
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
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
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
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
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
247     private boolean pulsingOrAod() {
248         final ScrimState scrimState = mScrimController.getState();
249         return scrimState == ScrimState.AOD
250                 || scrimState == ScrimState.PULSING;
251     }
252
253     @Override
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
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
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
362     public void onStartedGoingToSleep(int why) {
363         resetMode();
364         mFadedAwayAfterWakeAndUnlock = false;
365         mPendingAuthenticatedUserId = -1;
366         mPendingAuthenticatedBioSourceType = null;
367     }
368
369     @Override
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
383     public boolean hasPendingAuthentication() {
384         return mPendingAuthenticatedUserId != -1
385                 && mUpdateMonitor.isUnlockingWithBiometricAllowed()
386                 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
387     }
388
389     public int getMode() {
390         return mMode;
391     }
392
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
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
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
443     private void cleanup() {
444         releaseBiometricWakeLock();
445     }
446
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
458     public void finishKeyguardFadingAway() {
459         if (isWakeAndUnlock()) {
460             mFadedAwayAfterWakeAndUnlock = true;
461         }
462         resetMode();
463     }
464
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
492     public boolean hasScreenTurnedOnSinceAuthenticating() {
493         return mHasScreenTurnedOnSinceAuthenticating;
494     }
495
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      */
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      */
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      */
523     public boolean isBiometricUnlock() {
524         return isWakeAndUnlock() || mMode == MODE_UNLOCK;
525     }
526
527     /**
528      * Translates biometric source type for logging purpose.
529      */
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 }