blob: cb96dea08ae0e73ee6e5deb0ae9d5133de801f0f [file] [log] [blame]
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07001/*
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
17package com.android.systemui.statusbar.phone;
18
19import android.content.Context;
20import android.os.Handler;
21import android.os.PowerManager;
22import android.os.SystemClock;
Nick Desaulniers1d396752016-07-25 15:05:33 -070023import android.os.Trace;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070024import android.util.Log;
25
26import com.android.keyguard.KeyguardConstants;
27import com.android.keyguard.KeyguardUpdateMonitor;
28import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jorim Jaggid0565172016-09-15 16:31:14 -070029import com.android.keyguard.LatencyTracker;
Jason Monk421a9412017-02-06 09:15:21 -080030import com.android.systemui.Dependency;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070031import com.android.systemui.keyguard.KeyguardViewMediator;
Adrian Roos7a5e4c92017-07-31 16:40:19 +020032import com.android.systemui.keyguard.ScreenLifecycle;
Adrian Roos58ba6852017-07-18 17:10:29 +020033import com.android.systemui.keyguard.WakefulnessLifecycle;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070034
35/**
36 * Controller which coordinates all the fingerprint unlocking actions with the UI.
37 */
38public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
39
40 private static final String TAG = "FingerprintController";
41 private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK;
42 private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000;
43 private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
44
45 /**
46 * Mode in which we don't need to wake up the device when we get a fingerprint.
47 */
48 public static final int MODE_NONE = 0;
49
50 /**
51 * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
52 * a fingerprint while the screen is off and the device was sleeping.
53 */
54 public static final int MODE_WAKE_AND_UNLOCK = 1;
55
56 /**
57 * Mode in which we wake the device up, and fade out the Keyguard contents because they were
58 * already visible while pulsing in doze mode.
59 */
60 public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
61
62 /**
63 * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
64 * acquire a fingerprint pulsing in doze mode.
65 */
66 public static final int MODE_SHOW_BOUNCER = 3;
67
68 /**
69 * Mode in which we only wake up the device, and keyguard was not showing when we acquired a
70 * fingerprint.
71 * */
72 public static final int MODE_ONLY_WAKE = 4;
73
74 /**
75 * Mode in which fingerprint unlocks the device.
76 */
77 public static final int MODE_UNLOCK = 5;
78
79 /**
80 * Mode in which fingerprint brings up the bouncer because fingerprint unlocking is currently
81 * not allowed.
82 */
83 public static final int MODE_DISMISS_BOUNCER = 6;
84
85 /**
86 * How much faster we collapse the lockscreen when authenticating with fingerprint.
87 */
Selim Cinekdf5501b2017-04-14 20:01:27 -070088 private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070089
90 private PowerManager mPowerManager;
91 private Handler mHandler = new Handler();
92 private PowerManager.WakeLock mWakeLock;
93 private KeyguardUpdateMonitor mUpdateMonitor;
94 private int mMode;
95 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
96 private StatusBarWindowManager mStatusBarWindowManager;
97 private DozeScrimController mDozeScrimController;
98 private KeyguardViewMediator mKeyguardViewMediator;
99 private ScrimController mScrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500100 private StatusBar mStatusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700101 private final UnlockMethodCache mUnlockMethodCache;
102 private final Context mContext;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700103 private int mPendingAuthenticatedUserId = -1;
Adrian Roos58ba6852017-07-18 17:10:29 +0200104 private boolean mPendingShowBouncer;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200105 private boolean mHasScreenTurnedOnSinceAuthenticating;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700106
107 public FingerprintUnlockController(Context context,
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700108 DozeScrimController dozeScrimController,
109 KeyguardViewMediator keyguardViewMediator,
110 ScrimController scrimController,
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500111 StatusBar statusBar,
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700112 UnlockMethodCache unlockMethodCache) {
113 mContext = context;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700114 mPowerManager = context.getSystemService(PowerManager.class);
115 mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
116 mUpdateMonitor.registerCallback(this);
Adrian Roos58ba6852017-07-18 17:10:29 +0200117 Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200118 Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
Jason Monk421a9412017-02-06 09:15:21 -0800119 mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700120 mDozeScrimController = dozeScrimController;
121 mKeyguardViewMediator = keyguardViewMediator;
122 mScrimController = scrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500123 mStatusBar = statusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700124 mUnlockMethodCache = unlockMethodCache;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700125 }
126
127 public void setStatusBarKeyguardViewManager(
128 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
129 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
130 }
131
132 private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() {
133 @Override
134 public void run() {
135 if (DEBUG_FP_WAKELOCK) {
136 Log.i(TAG, "fp wakelock: TIMEOUT!!");
137 }
138 releaseFingerprintWakeLock();
139 }
140 };
141
142 private void releaseFingerprintWakeLock() {
143 if (mWakeLock != null) {
144 mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable);
145 if (DEBUG_FP_WAKELOCK) {
146 Log.i(TAG, "releasing fp wakelock");
147 }
148 mWakeLock.release();
149 mWakeLock = null;
150 }
151 }
152
153 @Override
154 public void onFingerprintAcquired() {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700155 Trace.beginSection("FingerprintUnlockController#onFingerprintAcquired");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700156 releaseFingerprintWakeLock();
157 if (!mUpdateMonitor.isDeviceInteractive()) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700158 if (LatencyTracker.isEnabled(mContext)) {
159 LatencyTracker.getInstance(mContext).onActionStart(
160 LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK);
161 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700162 mWakeLock = mPowerManager.newWakeLock(
163 PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700164 Trace.beginSection("acquiring wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700165 mWakeLock.acquire();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700166 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700167 if (DEBUG_FP_WAKELOCK) {
168 Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
169 }
170 mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
171 FINGERPRINT_WAKELOCK_TIMEOUT_MS);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700172 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700173 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700174 }
175
Adrian Roos3e23eb52017-07-07 15:58:57 +0200176 private boolean pulsingOrAod() {
177 boolean pulsing = mDozeScrimController.isPulsing();
178 boolean dozingWithScreenOn = mStatusBar.isDozing() && !mStatusBar.isScreenFullyOff();
179 return pulsing || dozingWithScreenOn;
180 }
181
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700182 @Override
183 public void onFingerprintAuthenticated(int userId) {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700184 Trace.beginSection("FingerprintUnlockController#onFingerprintAuthenticated");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700185 if (mUpdateMonitor.isGoingToSleep()) {
186 mPendingAuthenticatedUserId = userId;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700187 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700188 return;
189 }
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200190 startWakeAndUnlock(calculateMode());
191 }
192
193 public void startWakeAndUnlock(int mode) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700194 boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200195 mMode = mode;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200196 mHasScreenTurnedOnSinceAuthenticating = false;
Adrian Roosb880afe72017-07-25 17:02:46 +0200197 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
198 // If we are waking the device up while we are pulsing the clock and the
199 // notifications would light up first, creating an unpleasant animation.
200 // Defer changing the screen brightness by forcing doze brightness on our window
201 // until the clock and the notifications are faded out.
202 mStatusBarWindowManager.setForceDozeBrightness(true);
203 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700204 if (!wasDeviceInteractive) {
205 if (DEBUG_FP_WAKELOCK) {
206 Log.i(TAG, "fp wakelock: Authenticated, waking up...");
207 }
Adam Lesinski5bcb8bb2015-11-03 16:31:25 -0800208 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700209 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700210 Trace.beginSection("release wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700211 releaseFingerprintWakeLock();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700212 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700213 switch (mMode) {
214 case MODE_DISMISS_BOUNCER:
Nick Desaulniers1d396752016-07-25 15:05:33 -0700215 Trace.beginSection("MODE_DISMISS");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700216 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
217 false /* strongAuth */);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700218 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700219 break;
220 case MODE_UNLOCK:
221 case MODE_SHOW_BOUNCER:
Nick Desaulniers1d396752016-07-25 15:05:33 -0700222 Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700223 if (!wasDeviceInteractive) {
224 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
Adrian Roos58ba6852017-07-18 17:10:29 +0200225 mPendingShowBouncer = true;
226 } else {
227 showBouncer();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700228 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700229 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700230 break;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700231 case MODE_WAKE_AND_UNLOCK_PULSING:
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700232 case MODE_WAKE_AND_UNLOCK:
Adrian Roos88e61aa2017-05-23 16:16:50 -0700233 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
234 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
235 mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
236 true /* allowEnterAnimation */);
237 } else {
238 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200239
Adrian Roos88e61aa2017-05-23 16:16:50 -0700240 mDozeScrimController.abortDoze();
241 }
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700242 mStatusBarWindowManager.setStatusBarFocusable(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700243 mKeyguardViewMediator.onWakeAndUnlocking();
244 mScrimController.setWakeAndUnlocking();
Adrian Roos88e61aa2017-05-23 16:16:50 -0700245 mDozeScrimController.setWakeAndUnlocking();
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500246 if (mStatusBar.getNavigationBarView() != null) {
247 mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700248 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700249 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700250 break;
251 case MODE_ONLY_WAKE:
252 case MODE_NONE:
253 break;
254 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500255 mStatusBar.notifyFpAuthModeChanged();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700256 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700257 }
258
Adrian Roos58ba6852017-07-18 17:10:29 +0200259 private void showBouncer() {
260 mStatusBarKeyguardViewManager.animateCollapsePanels(
261 FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
262 mPendingShowBouncer = false;
263 }
264
Jorim Jaggi95e40382015-09-16 15:53:42 -0700265 @Override
266 public void onStartedGoingToSleep(int why) {
267 mPendingAuthenticatedUserId = -1;
268 }
269
270 @Override
271 public void onFinishedGoingToSleep(int why) {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700272 Trace.beginSection("FingerprintUnlockController#onFinishedGoingToSleep");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700273 if (mPendingAuthenticatedUserId != -1) {
274
275 // Post this to make sure it's executed after the device is fully locked.
276 mHandler.post(new Runnable() {
277 @Override
278 public void run() {
279 onFingerprintAuthenticated(mPendingAuthenticatedUserId);
280 }
281 });
282 }
283 mPendingAuthenticatedUserId = -1;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700284 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700285 }
286
Adrian Roos710a0b12017-07-07 19:02:34 +0200287 public boolean hasPendingAuthentication() {
288 return mPendingAuthenticatedUserId != -1
289 && mUpdateMonitor.isUnlockingWithFingerprintAllowed()
290 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
291 }
292
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700293 public int getMode() {
294 return mMode;
295 }
296
297 private int calculateMode() {
298 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
Adrian Roos02626662017-07-06 18:22:17 +0200299
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700300 if (!mUpdateMonitor.isDeviceInteractive()) {
301 if (!mStatusBarKeyguardViewManager.isShowing()) {
302 return MODE_ONLY_WAKE;
Adrian Roose4cb6c8a2017-07-19 18:08:07 +0200303 } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700304 return MODE_WAKE_AND_UNLOCK_PULSING;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700305 } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700306 return MODE_WAKE_AND_UNLOCK;
307 } else {
308 return MODE_SHOW_BOUNCER;
309 }
310 }
311 if (mStatusBarKeyguardViewManager.isShowing()) {
312 if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
313 return MODE_DISMISS_BOUNCER;
314 } else if (unlockingAllowed) {
315 return MODE_UNLOCK;
Jorim Jaggibf04cf52015-09-02 11:53:02 -0700316 } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700317 return MODE_SHOW_BOUNCER;
318 }
319 }
320 return MODE_NONE;
321 }
322
323 @Override
324 public void onFingerprintAuthFailed() {
325 cleanup();
326 }
327
328 @Override
329 public void onFingerprintError(int msgId, String errString) {
330 cleanup();
331 }
332
333 private void cleanup() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700334 releaseFingerprintWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700335 }
336
337 public void startKeyguardFadingAway() {
338
339 // Disable brightness override when the ambient contents are fully invisible.
340 mHandler.postDelayed(new Runnable() {
341 @Override
342 public void run() {
343 mStatusBarWindowManager.setForceDozeBrightness(false);
344 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500345 }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700346 }
347
348 public void finishKeyguardFadingAway() {
349 mMode = MODE_NONE;
Adrian Roos88e61aa2017-05-23 16:16:50 -0700350 mStatusBarWindowManager.setForceDozeBrightness(false);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500351 if (mStatusBar.getNavigationBarView() != null) {
352 mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700353 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500354 mStatusBar.notifyFpAuthModeChanged();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700355 }
Adrian Roos58ba6852017-07-18 17:10:29 +0200356
357 private final WakefulnessLifecycle.Observer mWakefulnessObserver =
358 new WakefulnessLifecycle.Observer() {
359 @Override
360 public void onFinishedWakingUp() {
361 if (mPendingShowBouncer) {
362 FingerprintUnlockController.this.showBouncer();
363 }
364 }
365 };
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200366
367 private final ScreenLifecycle.Observer mScreenObserver =
368 new ScreenLifecycle.Observer() {
369 @Override
370 public void onScreenTurnedOn() {
371 mHasScreenTurnedOnSinceAuthenticating = true;
372 }
373 };
374
375 public boolean hasScreenTurnedOnSinceAuthenticating() {
376 return mHasScreenTurnedOnSinceAuthenticating;
377 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700378}