OSDN Git Service

FingerprintController: Make sure to reset the fingerprint mode when going to sleep
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / statusbar / phone / FingerprintUnlockController.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.os.Handler;
21 import android.os.PowerManager;
22 import android.os.SystemClock;
23 import android.os.Trace;
24 import android.util.Log;
25
26 import com.android.keyguard.KeyguardConstants;
27 import com.android.keyguard.KeyguardUpdateMonitor;
28 import com.android.keyguard.KeyguardUpdateMonitorCallback;
29 import com.android.keyguard.LatencyTracker;
30 import com.android.systemui.Dependency;
31 import com.android.systemui.keyguard.KeyguardViewMediator;
32 import com.android.systemui.keyguard.ScreenLifecycle;
33 import com.android.systemui.keyguard.WakefulnessLifecycle;
34
35 import java.io.PrintWriter;
36
37 /**
38  * Controller which coordinates all the fingerprint unlocking actions with the UI.
39  */
40 public 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      */
90     private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
91
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;
102     private StatusBar mStatusBar;
103     private final UnlockMethodCache mUnlockMethodCache;
104     private final Context mContext;
105     private int mPendingAuthenticatedUserId = -1;
106     private boolean mPendingShowBouncer;
107     private boolean mHasScreenTurnedOnSinceAuthenticating;
108
109     public FingerprintUnlockController(Context context,
110             DozeScrimController dozeScrimController,
111             KeyguardViewMediator keyguardViewMediator,
112             ScrimController scrimController,
113             StatusBar statusBar,
114             UnlockMethodCache unlockMethodCache) {
115         mContext = context;
116         mPowerManager = context.getSystemService(PowerManager.class);
117         mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
118         mUpdateMonitor.registerCallback(this);
119         Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
120         Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
121         mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
122         mDozeScrimController = dozeScrimController;
123         mKeyguardViewMediator = keyguardViewMediator;
124         mScrimController = scrimController;
125         mStatusBar = statusBar;
126         mUnlockMethodCache = unlockMethodCache;
127     }
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() {
157         Trace.beginSection("FingerprintUnlockController#onFingerprintAcquired");
158         releaseFingerprintWakeLock();
159         if (!mUpdateMonitor.isDeviceInteractive()) {
160             if (LatencyTracker.isEnabled(mContext)) {
161                 LatencyTracker.getInstance(mContext).onActionStart(
162                         LatencyTracker.ACTION_FINGERPRINT_WAKE_AND_UNLOCK);
163             }
164             mWakeLock = mPowerManager.newWakeLock(
165                     PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
166             Trace.beginSection("acquiring wake-and-unlock");
167             mWakeLock.acquire();
168             Trace.endSection();
169             if (DEBUG_FP_WAKELOCK) {
170                 Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
171             }
172             mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
173                     FINGERPRINT_WAKELOCK_TIMEOUT_MS);
174         }
175         Trace.endSection();
176     }
177
178     private boolean pulsingOrAod() {
179         boolean pulsing = mDozeScrimController.isPulsing();
180         boolean dozingWithScreenOn = mStatusBar.isDozing() && !mStatusBar.isScreenFullyOff();
181         return pulsing || dozingWithScreenOn;
182     }
183
184     @Override
185     public void onFingerprintAuthenticated(int userId) {
186         Trace.beginSection("FingerprintUnlockController#onFingerprintAuthenticated");
187         if (mUpdateMonitor.isGoingToSleep()) {
188             mPendingAuthenticatedUserId = userId;
189             Trace.endSection();
190             return;
191         }
192         startWakeAndUnlock(calculateMode());
193     }
194
195     public void startWakeAndUnlock(int mode) {
196         boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
197         mMode = mode;
198         mHasScreenTurnedOnSinceAuthenticating = false;
199         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         }
206         if (!wasDeviceInteractive) {
207             if (DEBUG_FP_WAKELOCK) {
208                 Log.i(TAG, "fp wakelock: Authenticated, waking up...");
209             }
210             mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT");
211         }
212         Trace.beginSection("release wake-and-unlock");
213         releaseFingerprintWakeLock();
214         Trace.endSection();
215         switch (mMode) {
216             case MODE_DISMISS_BOUNCER:
217                 Trace.beginSection("MODE_DISMISS");
218                 mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
219                         false /* strongAuth */);
220                 Trace.endSection();
221                 break;
222             case MODE_UNLOCK:
223             case MODE_SHOW_BOUNCER:
224                 Trace.beginSection("MODE_UNLOCK or MODE_SHOW_BOUNCER");
225                 if (!wasDeviceInteractive) {
226                     mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
227                     mPendingShowBouncer = true;
228                 } else {
229                     showBouncer();
230                 }
231                 Trace.endSection();
232                 break;
233             case MODE_WAKE_AND_UNLOCK_PULSING:
234             case MODE_WAKE_AND_UNLOCK:
235                 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");
241
242                     mDozeScrimController.abortDoze();
243                 }
244                 mStatusBarWindowManager.setStatusBarFocusable(false);
245                 mKeyguardViewMediator.onWakeAndUnlocking();
246                 mScrimController.setWakeAndUnlocking();
247                 mDozeScrimController.setWakeAndUnlocking();
248                 if (mStatusBar.getNavigationBarView() != null) {
249                     mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
250                 }
251                 Trace.endSection();
252                 break;
253             case MODE_ONLY_WAKE:
254             case MODE_NONE:
255                 break;
256         }
257         mStatusBar.notifyFpAuthModeChanged();
258         Trace.endSection();
259     }
260
261     private void showBouncer() {
262         mStatusBarKeyguardViewManager.animateCollapsePanels(
263                 FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
264         mPendingShowBouncer = false;
265     }
266
267     @Override
268     public void onStartedGoingToSleep(int why) {
269         resetMode();
270         mPendingAuthenticatedUserId = -1;
271     }
272
273     @Override
274     public void onFinishedGoingToSleep(int why) {
275         Trace.beginSection("FingerprintUnlockController#onFinishedGoingToSleep");
276         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;
287         Trace.endSection();
288     }
289
290     public boolean hasPendingAuthentication() {
291         return mPendingAuthenticatedUserId != -1
292                 && mUpdateMonitor.isUnlockingWithFingerprintAllowed()
293                 && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
294     }
295
296     public int getMode() {
297         return mMode;
298     }
299
300     private int calculateMode() {
301         boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
302
303         if (!mUpdateMonitor.isDeviceInteractive()) {
304             if (!mStatusBarKeyguardViewManager.isShowing()) {
305                 return MODE_ONLY_WAKE;
306             } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
307                 return MODE_WAKE_AND_UNLOCK_PULSING;
308             } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
309                 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;
319             } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
320                 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() {
337         releaseFingerprintWakeLock();
338     }
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             }
348         }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
349     }
350
351     public void finishKeyguardFadingAway() {
352         resetMode();
353     }
354
355     private void resetMode() {
356         mMode = MODE_NONE;
357         mStatusBarWindowManager.setForceDozeBrightness(false);
358         if (mStatusBar.getNavigationBarView() != null) {
359             mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
360         }
361         mStatusBar.notifyFpAuthModeChanged();
362     }
363
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     };
373
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     }
385
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     }
391 }