blob: 316d229e4f1a7b57fc29b393236649d7beb48278 [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
Adrian Roosba7ca592017-08-15 17:48:05 +020035import java.io.PrintWriter;
36
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070037/**
38 * Controller which coordinates all the fingerprint unlocking actions with the UI.
39 */
40public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
41
42 private static final String TAG = "FingerprintController";
43 private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK;
44 private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000;
45 private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
46
47 /**
48 * Mode in which we don't need to wake up the device when we get a fingerprint.
49 */
50 public static final int MODE_NONE = 0;
51
52 /**
53 * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
54 * a fingerprint while the screen is off and the device was sleeping.
55 */
56 public static final int MODE_WAKE_AND_UNLOCK = 1;
57
58 /**
59 * Mode in which we wake the device up, and fade out the Keyguard contents because they were
60 * already visible while pulsing in doze mode.
61 */
62 public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
63
64 /**
65 * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
66 * acquire a fingerprint pulsing in doze mode.
67 */
68 public static final int MODE_SHOW_BOUNCER = 3;
69
70 /**
71 * Mode in which we only wake up the device, and keyguard was not showing when we acquired a
72 * fingerprint.
73 * */
74 public static final int MODE_ONLY_WAKE = 4;
75
76 /**
77 * Mode in which fingerprint unlocks the device.
78 */
79 public static final int MODE_UNLOCK = 5;
80
81 /**
82 * Mode in which fingerprint brings up the bouncer because fingerprint unlocking is currently
83 * not allowed.
84 */
85 public static final int MODE_DISMISS_BOUNCER = 6;
86
87 /**
88 * How much faster we collapse the lockscreen when authenticating with fingerprint.
89 */
Selim Cinekdf5501b2017-04-14 20:01:27 -070090 private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070091
92 private PowerManager mPowerManager;
93 private Handler mHandler = new Handler();
94 private PowerManager.WakeLock mWakeLock;
95 private KeyguardUpdateMonitor mUpdateMonitor;
96 private int mMode;
97 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
98 private StatusBarWindowManager mStatusBarWindowManager;
99 private DozeScrimController mDozeScrimController;
100 private KeyguardViewMediator mKeyguardViewMediator;
101 private ScrimController mScrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500102 private StatusBar mStatusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700103 private final UnlockMethodCache mUnlockMethodCache;
104 private final Context mContext;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700105 private int mPendingAuthenticatedUserId = -1;
Adrian Roos58ba6852017-07-18 17:10:29 +0200106 private boolean mPendingShowBouncer;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200107 private boolean mHasScreenTurnedOnSinceAuthenticating;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700108
109 public FingerprintUnlockController(Context context,
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700110 DozeScrimController dozeScrimController,
111 KeyguardViewMediator keyguardViewMediator,
112 ScrimController scrimController,
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500113 StatusBar statusBar,
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700114 UnlockMethodCache unlockMethodCache) {
115 mContext = context;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700116 mPowerManager = context.getSystemService(PowerManager.class);
117 mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
118 mUpdateMonitor.registerCallback(this);
Adrian Roos58ba6852017-07-18 17:10:29 +0200119 Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200120 Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
Jason Monk421a9412017-02-06 09:15:21 -0800121 mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700122 mDozeScrimController = dozeScrimController;
123 mKeyguardViewMediator = keyguardViewMediator;
124 mScrimController = scrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500125 mStatusBar = statusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700126 mUnlockMethodCache = unlockMethodCache;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700127 }
128
129 public void setStatusBarKeyguardViewManager(
130 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
131 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
132 }
133
134 private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() {
135 @Override
136 public void run() {
137 if (DEBUG_FP_WAKELOCK) {
138 Log.i(TAG, "fp wakelock: TIMEOUT!!");
139 }
140 releaseFingerprintWakeLock();
141 }
142 };
143
144 private void releaseFingerprintWakeLock() {
145 if (mWakeLock != null) {
146 mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable);
147 if (DEBUG_FP_WAKELOCK) {
148 Log.i(TAG, "releasing fp wakelock");
149 }
150 mWakeLock.release();
151 mWakeLock = null;
152 }
153 }
154
155 @Override
156 public void onFingerprintAcquired() {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700157 Trace.beginSection("FingerprintUnlockController#onFingerprintAcquired");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700158 releaseFingerprintWakeLock();
159 if (!mUpdateMonitor.isDeviceInteractive()) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700160 if (LatencyTracker.isEnabled(mContext)) {
161 LatencyTracker.getInstance(mContext).onActionStart(
162 LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK);
163 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700164 mWakeLock = mPowerManager.newWakeLock(
165 PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700166 Trace.beginSection("acquiring wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700167 mWakeLock.acquire();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700168 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700169 if (DEBUG_FP_WAKELOCK) {
170 Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
171 }
172 mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
173 FINGERPRINT_WAKELOCK_TIMEOUT_MS);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700174 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700175 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700176 }
177
Adrian Roos3e23eb52017-07-07 15:58:57 +0200178 private boolean pulsingOrAod() {
179 boolean pulsing = mDozeScrimController.isPulsing();
180 boolean dozingWithScreenOn = mStatusBar.isDozing() && !mStatusBar.isScreenFullyOff();
181 return pulsing || dozingWithScreenOn;
182 }
183
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700184 @Override
185 public void onFingerprintAuthenticated(int userId) {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700186 Trace.beginSection("FingerprintUnlockController#onFingerprintAuthenticated");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700187 if (mUpdateMonitor.isGoingToSleep()) {
188 mPendingAuthenticatedUserId = userId;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700189 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700190 return;
191 }
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200192 startWakeAndUnlock(calculateMode());
193 }
194
195 public void startWakeAndUnlock(int mode) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700196 boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200197 mMode = mode;
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200198 mHasScreenTurnedOnSinceAuthenticating = false;
Adrian Roosb880afe72017-07-25 17:02:46 +0200199 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING && pulsingOrAod()) {
200 // If we are waking the device up while we are pulsing the clock and the
201 // notifications would light up first, creating an unpleasant animation.
202 // Defer changing the screen brightness by forcing doze brightness on our window
203 // until the clock and the notifications are faded out.
204 mStatusBarWindowManager.setForceDozeBrightness(true);
205 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700206 if (!wasDeviceInteractive) {
207 if (DEBUG_FP_WAKELOCK) {
208 Log.i(TAG, "fp wakelock: Authenticated, waking up...");
209 }
Adam Lesinski5bcb8bb2015-11-03 16:31:25 -0800210 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700211 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700212 Trace.beginSection("release wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700213 releaseFingerprintWakeLock();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700214 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700215 switch (mMode) {
216 case MODE_DISMISS_BOUNCER:
Nick Desaulniers1d396752016-07-25 15:05:33 -0700217 Trace.beginSection("MODE_DISMISS");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700218 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
219 false /* strongAuth */);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700220 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700221 break;
222 case MODE_UNLOCK:
223 case MODE_SHOW_BOUNCER:
Nick Desaulniers1d396752016-07-25 15:05:33 -0700224 Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700225 if (!wasDeviceInteractive) {
226 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
Adrian Roos58ba6852017-07-18 17:10:29 +0200227 mPendingShowBouncer = true;
228 } else {
229 showBouncer();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700230 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700231 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700232 break;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700233 case MODE_WAKE_AND_UNLOCK_PULSING:
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700234 case MODE_WAKE_AND_UNLOCK:
Adrian Roos88e61aa2017-05-23 16:16:50 -0700235 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
236 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
237 mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
238 true /* allowEnterAnimation */);
239 } else {
240 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200241
Adrian Roos88e61aa2017-05-23 16:16:50 -0700242 mDozeScrimController.abortDoze();
243 }
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700244 mStatusBarWindowManager.setStatusBarFocusable(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700245 mKeyguardViewMediator.onWakeAndUnlocking();
246 mScrimController.setWakeAndUnlocking();
Adrian Roos88e61aa2017-05-23 16:16:50 -0700247 mDozeScrimController.setWakeAndUnlocking();
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500248 if (mStatusBar.getNavigationBarView() != null) {
249 mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700250 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700251 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700252 break;
253 case MODE_ONLY_WAKE:
254 case MODE_NONE:
255 break;
256 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500257 mStatusBar.notifyFpAuthModeChanged();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700258 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700259 }
260
Adrian Roos58ba6852017-07-18 17:10:29 +0200261 private void showBouncer() {
262 mStatusBarKeyguardViewManager.animateCollapsePanels(
263 FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
264 mPendingShowBouncer = false;
265 }
266
Jorim Jaggi95e40382015-09-16 15:53:42 -0700267 @Override
268 public void onStartedGoingToSleep(int why) {
Adrian Roosba7ca592017-08-15 17:48:05 +0200269 resetMode();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700270 mPendingAuthenticatedUserId = -1;
271 }
272
273 @Override
274 public void onFinishedGoingToSleep(int why) {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700275 Trace.beginSection("FingerprintUnlockController#onFinishedGoingToSleep");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700276 if (mPendingAuthenticatedUserId != -1) {
277
278 // Post this to make sure it's executed after the device is fully locked.
279 mHandler.post(new Runnable() {
280 @Override
281 public void run() {
282 onFingerprintAuthenticated(mPendingAuthenticatedUserId);
283 }
284 });
285 }
286 mPendingAuthenticatedUserId = -1;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700287 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700288 }
289
Adrian Roos710a0b12017-07-07 19:02:34 +0200290 public boolean hasPendingAuthentication() {
291 return mPendingAuthenticatedUserId != -1
292 && mUpdateMonitor.isUnlockingWithFingerprintAllowed()
293 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
294 }
295
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700296 public int getMode() {
297 return mMode;
298 }
299
300 private int calculateMode() {
301 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
Adrian Roos02626662017-07-06 18:22:17 +0200302
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700303 if (!mUpdateMonitor.isDeviceInteractive()) {
304 if (!mStatusBarKeyguardViewManager.isShowing()) {
305 return MODE_ONLY_WAKE;
Adrian Roose4cb6c8a2017-07-19 18:08:07 +0200306 } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700307 return MODE_WAKE_AND_UNLOCK_PULSING;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700308 } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700309 return MODE_WAKE_AND_UNLOCK;
310 } else {
311 return MODE_SHOW_BOUNCER;
312 }
313 }
314 if (mStatusBarKeyguardViewManager.isShowing()) {
315 if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
316 return MODE_DISMISS_BOUNCER;
317 } else if (unlockingAllowed) {
318 return MODE_UNLOCK;
Jorim Jaggibf04cf52015-09-02 11:53:02 -0700319 } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700320 return MODE_SHOW_BOUNCER;
321 }
322 }
323 return MODE_NONE;
324 }
325
326 @Override
327 public void onFingerprintAuthFailed() {
328 cleanup();
329 }
330
331 @Override
332 public void onFingerprintError(int msgId, String errString) {
333 cleanup();
334 }
335
336 private void cleanup() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700337 releaseFingerprintWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700338 }
339
340 public void startKeyguardFadingAway() {
341
342 // Disable brightness override when the ambient contents are fully invisible.
343 mHandler.postDelayed(new Runnable() {
344 @Override
345 public void run() {
346 mStatusBarWindowManager.setForceDozeBrightness(false);
347 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500348 }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700349 }
350
351 public void finishKeyguardFadingAway() {
Adrian Roosba7ca592017-08-15 17:48:05 +0200352 resetMode();
353 }
354
355 private void resetMode() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700356 mMode = MODE_NONE;
Adrian Roos88e61aa2017-05-23 16:16:50 -0700357 mStatusBarWindowManager.setForceDozeBrightness(false);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500358 if (mStatusBar.getNavigationBarView() != null) {
359 mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700360 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500361 mStatusBar.notifyFpAuthModeChanged();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700362 }
Adrian Roos58ba6852017-07-18 17:10:29 +0200363
364 private final WakefulnessLifecycle.Observer mWakefulnessObserver =
365 new WakefulnessLifecycle.Observer() {
366 @Override
367 public void onFinishedWakingUp() {
368 if (mPendingShowBouncer) {
369 FingerprintUnlockController.this.showBouncer();
370 }
371 }
372 };
Adrian Roos7a5e4c92017-07-31 16:40:19 +0200373
374 private final ScreenLifecycle.Observer mScreenObserver =
375 new ScreenLifecycle.Observer() {
376 @Override
377 public void onScreenTurnedOn() {
378 mHasScreenTurnedOnSinceAuthenticating = true;
379 }
380 };
381
382 public boolean hasScreenTurnedOnSinceAuthenticating() {
383 return mHasScreenTurnedOnSinceAuthenticating;
384 }
Adrian Roosba7ca592017-08-15 17:48:05 +0200385
386 public void dump(PrintWriter pw) {
387 pw.println(" FingerprintUnlockController:");
388 pw.print(" mMode="); pw.println(mMode);
389 pw.print(" mWakeLock="); pw.println(mWakeLock);
390 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700391}