blob: 6cb722fa65ce43735d513cb7bebd62d58a5f5add [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;
32
33/**
34 * Controller which coordinates all the fingerprint unlocking actions with the UI.
35 */
36public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
37
38 private static final String TAG = "FingerprintController";
39 private static final boolean DEBUG_FP_WAKELOCK = KeyguardConstants.DEBUG_FP_WAKELOCK;
40 private static final long FINGERPRINT_WAKELOCK_TIMEOUT_MS = 15 * 1000;
41 private static final String FINGERPRINT_WAKE_LOCK_NAME = "wake-and-unlock wakelock";
42
43 /**
44 * Mode in which we don't need to wake up the device when we get a fingerprint.
45 */
46 public static final int MODE_NONE = 0;
47
48 /**
49 * Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire
50 * a fingerprint while the screen is off and the device was sleeping.
51 */
52 public static final int MODE_WAKE_AND_UNLOCK = 1;
53
54 /**
55 * Mode in which we wake the device up, and fade out the Keyguard contents because they were
56 * already visible while pulsing in doze mode.
57 */
58 public static final int MODE_WAKE_AND_UNLOCK_PULSING = 2;
59
60 /**
61 * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
62 * acquire a fingerprint pulsing in doze mode.
63 */
64 public static final int MODE_SHOW_BOUNCER = 3;
65
66 /**
67 * Mode in which we only wake up the device, and keyguard was not showing when we acquired a
68 * fingerprint.
69 * */
70 public static final int MODE_ONLY_WAKE = 4;
71
72 /**
73 * Mode in which fingerprint unlocks the device.
74 */
75 public static final int MODE_UNLOCK = 5;
76
77 /**
78 * Mode in which fingerprint brings up the bouncer because fingerprint unlocking is currently
79 * not allowed.
80 */
81 public static final int MODE_DISMISS_BOUNCER = 6;
82
83 /**
84 * How much faster we collapse the lockscreen when authenticating with fingerprint.
85 */
Selim Cinekdf5501b2017-04-14 20:01:27 -070086 private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070087
88 private PowerManager mPowerManager;
89 private Handler mHandler = new Handler();
90 private PowerManager.WakeLock mWakeLock;
91 private KeyguardUpdateMonitor mUpdateMonitor;
92 private int mMode;
93 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
94 private StatusBarWindowManager mStatusBarWindowManager;
95 private DozeScrimController mDozeScrimController;
96 private KeyguardViewMediator mKeyguardViewMediator;
97 private ScrimController mScrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050098 private StatusBar mStatusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -070099 private final UnlockMethodCache mUnlockMethodCache;
100 private final Context mContext;
Jorim Jaggi95e40382015-09-16 15:53:42 -0700101 private int mPendingAuthenticatedUserId = -1;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700102
103 public FingerprintUnlockController(Context context,
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700104 DozeScrimController dozeScrimController,
105 KeyguardViewMediator keyguardViewMediator,
106 ScrimController scrimController,
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500107 StatusBar statusBar,
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700108 UnlockMethodCache unlockMethodCache) {
109 mContext = context;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700110 mPowerManager = context.getSystemService(PowerManager.class);
111 mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
112 mUpdateMonitor.registerCallback(this);
Jason Monk421a9412017-02-06 09:15:21 -0800113 mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700114 mDozeScrimController = dozeScrimController;
115 mKeyguardViewMediator = keyguardViewMediator;
116 mScrimController = scrimController;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500117 mStatusBar = statusBar;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700118 mUnlockMethodCache = unlockMethodCache;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700119 }
120
121 public void setStatusBarKeyguardViewManager(
122 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
123 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
124 }
125
126 private final Runnable mReleaseFingerprintWakeLockRunnable = new Runnable() {
127 @Override
128 public void run() {
129 if (DEBUG_FP_WAKELOCK) {
130 Log.i(TAG, "fp wakelock: TIMEOUT!!");
131 }
132 releaseFingerprintWakeLock();
133 }
134 };
135
136 private void releaseFingerprintWakeLock() {
137 if (mWakeLock != null) {
138 mHandler.removeCallbacks(mReleaseFingerprintWakeLockRunnable);
139 if (DEBUG_FP_WAKELOCK) {
140 Log.i(TAG, "releasing fp wakelock");
141 }
142 mWakeLock.release();
143 mWakeLock = null;
144 }
145 }
146
147 @Override
148 public void onFingerprintAcquired() {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700149 Trace.beginSection("FingerprintUnlockController#onFingerprintAcquired");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700150 releaseFingerprintWakeLock();
151 if (!mUpdateMonitor.isDeviceInteractive()) {
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700152 if (LatencyTracker.isEnabled(mContext)) {
153 LatencyTracker.getInstance(mContext).onActionStart(
154 LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK);
155 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700156 mWakeLock = mPowerManager.newWakeLock(
157 PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700158 Trace.beginSection("acquiring wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700159 mWakeLock.acquire();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700160 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700161 if (DEBUG_FP_WAKELOCK) {
162 Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
163 }
164 mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
165 FINGERPRINT_WAKELOCK_TIMEOUT_MS);
166 if (mDozeScrimController.isPulsing()) {
167
168 // If we are waking the device up while we are pulsing the clock and the
169 // notifications would light up first, creating an unpleasant animation.
170 // Defer changing the screen brightness by forcing doze brightness on our window
171 // until the clock and the notifications are faded out.
172 mStatusBarWindowManager.setForceDozeBrightness(true);
173 }
174 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700175 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700176 }
177
178 @Override
179 public void onFingerprintAuthenticated(int userId) {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700180 Trace.beginSection("FingerprintUnlockController#onFingerprintAuthenticated");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700181 if (mUpdateMonitor.isGoingToSleep()) {
182 mPendingAuthenticatedUserId = userId;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700183 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700184 return;
185 }
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700186 boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
187 mMode = calculateMode();
188 if (!wasDeviceInteractive) {
189 if (DEBUG_FP_WAKELOCK) {
190 Log.i(TAG, "fp wakelock: Authenticated, waking up...");
191 }
Adam Lesinski5bcb8bb2015-11-03 16:31:25 -0800192 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700193 }
Nick Desaulniers1d396752016-07-25 15:05:33 -0700194 Trace.beginSection("release wake-and-unlock");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700195 releaseFingerprintWakeLock();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700196 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700197 switch (mMode) {
198 case MODE_DISMISS_BOUNCER:
Nick Desaulniers1d396752016-07-25 15:05:33 -0700199 Trace.beginSection("MODE_DISMISS");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700200 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
201 false /* strongAuth */);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700202 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700203 break;
204 case MODE_UNLOCK:
205 case MODE_SHOW_BOUNCER:
Nick Desaulniers1d396752016-07-25 15:05:33 -0700206 Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700207 if (!wasDeviceInteractive) {
208 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
209 }
210 mStatusBarKeyguardViewManager.animateCollapsePanels(
211 FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
Nick Desaulniers1d396752016-07-25 15:05:33 -0700212 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700213 break;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700214 case MODE_WAKE_AND_UNLOCK_PULSING:
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700215 case MODE_WAKE_AND_UNLOCK:
Adrian Roos88e61aa2017-05-23 16:16:50 -0700216 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
217 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
218 mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
219 true /* allowEnterAnimation */);
220 } else {
221 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
222 mDozeScrimController.abortDoze();
223 }
Jorim Jaggid94d3a22015-08-21 16:52:55 -0700224 mStatusBarWindowManager.setStatusBarFocusable(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700225 mKeyguardViewMediator.onWakeAndUnlocking();
226 mScrimController.setWakeAndUnlocking();
Adrian Roos88e61aa2017-05-23 16:16:50 -0700227 mDozeScrimController.setWakeAndUnlocking();
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500228 if (mStatusBar.getNavigationBarView() != null) {
229 mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
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;
233 case MODE_ONLY_WAKE:
234 case MODE_NONE:
235 break;
236 }
237 if (mMode != MODE_WAKE_AND_UNLOCK_PULSING) {
238 mStatusBarWindowManager.setForceDozeBrightness(false);
239 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500240 mStatusBar.notifyFpAuthModeChanged();
Nick Desaulniers1d396752016-07-25 15:05:33 -0700241 Trace.endSection();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700242 }
243
Jorim Jaggi95e40382015-09-16 15:53:42 -0700244 @Override
245 public void onStartedGoingToSleep(int why) {
246 mPendingAuthenticatedUserId = -1;
247 }
248
249 @Override
250 public void onFinishedGoingToSleep(int why) {
Nick Desaulniers1d396752016-07-25 15:05:33 -0700251 Trace.beginSection("FingerprintUnlockController#onFinishedGoingToSleep");
Jorim Jaggi95e40382015-09-16 15:53:42 -0700252 if (mPendingAuthenticatedUserId != -1) {
253
254 // Post this to make sure it's executed after the device is fully locked.
255 mHandler.post(new Runnable() {
256 @Override
257 public void run() {
258 onFingerprintAuthenticated(mPendingAuthenticatedUserId);
259 }
260 });
261 }
262 mPendingAuthenticatedUserId = -1;
Nick Desaulniers1d396752016-07-25 15:05:33 -0700263 Trace.endSection();
Jorim Jaggi95e40382015-09-16 15:53:42 -0700264 }
265
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700266 public int getMode() {
267 return mMode;
268 }
269
270 private int calculateMode() {
271 boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
272 if (!mUpdateMonitor.isDeviceInteractive()) {
273 if (!mStatusBarKeyguardViewManager.isShowing()) {
274 return MODE_ONLY_WAKE;
275 } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
276 return MODE_WAKE_AND_UNLOCK_PULSING;
Jorim Jaggi8adb30c2016-09-13 15:02:22 -0700277 } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700278 return MODE_WAKE_AND_UNLOCK;
279 } else {
280 return MODE_SHOW_BOUNCER;
281 }
282 }
283 if (mStatusBarKeyguardViewManager.isShowing()) {
284 if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
285 return MODE_DISMISS_BOUNCER;
286 } else if (unlockingAllowed) {
287 return MODE_UNLOCK;
Jorim Jaggibf04cf52015-09-02 11:53:02 -0700288 } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700289 return MODE_SHOW_BOUNCER;
290 }
291 }
292 return MODE_NONE;
293 }
294
295 @Override
296 public void onFingerprintAuthFailed() {
297 cleanup();
298 }
299
300 @Override
301 public void onFingerprintError(int msgId, String errString) {
302 cleanup();
303 }
304
305 private void cleanup() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700306 releaseFingerprintWakeLock();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700307 }
308
309 public void startKeyguardFadingAway() {
310
311 // Disable brightness override when the ambient contents are fully invisible.
312 mHandler.postDelayed(new Runnable() {
313 @Override
314 public void run() {
315 mStatusBarWindowManager.setForceDozeBrightness(false);
316 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500317 }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700318 }
319
320 public void finishKeyguardFadingAway() {
321 mMode = MODE_NONE;
Adrian Roos88e61aa2017-05-23 16:16:50 -0700322 mStatusBarWindowManager.setForceDozeBrightness(false);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500323 if (mStatusBar.getNavigationBarView() != null) {
324 mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700325 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500326 mStatusBar.notifyFpAuthModeChanged();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700327 }
328}