FaceUnlock.java revision 5cf17879a31b7b78c09ec50b727f921840dcf783
19431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna/*
2dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Copyright (C) 2012 The Android Open Source Project
39431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna *
49431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * Licensed under the Apache License, Version 2.0 (the "License");
59431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * you may not use this file except in compliance with the License.
69431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * You may obtain a copy of the License at
79431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna *
89431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna *      http://www.apache.org/licenses/LICENSE-2.0
99431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna *
109431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * Unless required by applicable law or agreed to in writing, software
119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * distributed under the License is distributed on an "AS IS" BASIS,
129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * See the License for the specific language governing permissions and
149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * limitations under the License.
159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna */
169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
175ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard;
189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.policy.IFaceLockCallback;
209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.policy.IFaceLockInterface;
219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.widget.LockPatternUtils;
229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
233223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonnaimport android.app.admin.DevicePolicyManager;
249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.ComponentName;
259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.Context;
269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.Intent;
279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.ServiceConnection;
289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.Handler;
299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.IBinder;
3022001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonnaimport android.os.Looper;
319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.Message;
32acbe41fc1316cf16f03de80c84ea311cc4f55ffbSteven Rossimport android.os.PowerManager;
339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.RemoteException;
345eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonnaimport android.os.UserHandle;
359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.util.Log;
369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.view.View;
379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
383223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonnapublic class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
405cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi    private static final boolean DEBUG = KeyguardConstants.DEBUG;
419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final String TAG = "FULLockscreen";
425cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi    private static final String FACE_LOCK_PACKAGE = "com.android.facelock";
439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final Context mContext;
45ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final LockPatternUtils mLockPatternUtils;
469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
47ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
48ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private boolean mServiceRunning = false;
49257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    // TODO: now that the code has been restructure to do almost all operations from a handler, this
50257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    // lock may no longer be necessary.
51ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final Object mServiceRunningLock = new Object();
529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private IFaceLockInterface mService;
539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mBoundToService = false;
54ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private View mFaceUnlockView;
559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private Handler mHandler;
5761413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett    private final int MSG_SERVICE_CONNECTED = 0;
5861413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett    private final int MSG_SERVICE_DISCONNECTED = 1;
5961413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett    private final int MSG_UNLOCK = 2;
6061413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett    private final int MSG_CANCEL = 3;
6161413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett    private final int MSG_REPORT_FAILED_ATTEMPT = 4;
62667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna    private final int MSG_POKE_WAKELOCK = 5;
639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
64ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // TODO: This was added for the purpose of adhering to what the biometric interface expects
65ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // the isRunning() function to return.  However, it is probably not necessary to have both
66ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // mRunning and mServiceRunning.  I'd just rather wait to change that logic.
67257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private volatile boolean mIsRunning = false;
689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
69ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // So the user has a consistent amount of time when brought to the backup method from Face
70ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // Unlock
719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int BACKUP_LOCK_TIMEOUT = 5000;
729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
73dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    KeyguardSecurityCallback mKeyguardScreenCallback;
749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
75257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
76257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stores some of the structures that Face Unlock will need to access and creates the handler
77257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * will be used to execute messages on the UI thread.
78257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
79000464ac012471d301c6e48a8228291519915e17Jim Miller    public FaceUnlock(Context context) {
809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mContext = context;
81dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternUtils = new LockPatternUtils(context);
829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler = new Handler(this);
839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
85000464ac012471d301c6e48a8228291519915e17Jim Miller    public void setKeyguardCallback(KeyguardSecurityCallback keyguardScreenCallback) {
86000464ac012471d301c6e48a8228291519915e17Jim Miller        mKeyguardScreenCallback = keyguardScreenCallback;
87000464ac012471d301c6e48a8228291519915e17Jim Miller    }
88000464ac012471d301c6e48a8228291519915e17Jim Miller
89ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
90ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Stores and displays the view that Face Unlock is allowed to draw within.
91ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * TODO: since the layout object will eventually be shared by multiple biometric unlock
92ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * methods, we will have to add our other views (background, cancel button) here.
93ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
94ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public void initializeView(View biometricUnlockView) {
95257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        Log.d(TAG, "initializeView()");
96ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mFaceUnlockView = biometricUnlockView;
97ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
98ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
99ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
100ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Indicates whether Face Unlock is currently running.
101ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1023223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean isRunning() {
103ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mIsRunning;
1043223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1053223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
106ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
10761413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett     * Dismisses face unlock and goes to the backup lock
108ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
10961413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett    public void stopAndShowBackup() {
11061413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett        if (DEBUG) Log.d(TAG, "stopAndShowBackup()");
11161413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett        mHandler.sendEmptyMessage(MSG_CANCEL);
1123223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1133223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
114ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
115ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
116257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Face Unlock view is displayed to hide the backup lock while the service is starting up.
11722001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna     * Called on the UI thread.
118ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
119ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public boolean start() {
120257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "start()");
12122001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        if (mHandler.getLooper() != Looper.myLooper()) {
12222001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna            Log.e(TAG, "start() called off of the UI thread");
12322001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        }
12422001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna
125ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (mIsRunning) {
126ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "start() called when already running");
127ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
128ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
129ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (!mBoundToService) {
1304b4b954ddf34af51576441f0e3eca6d19150aadaAmith Yamasani            Log.d(TAG, "Binding to Face Unlock service for user="
1314b4b954ddf34af51576441f0e3eca6d19150aadaAmith Yamasani                    + mLockPatternUtils.getCurrentUser());
1325cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi            mContext.bindServiceAsUser(
1335cf17879a31b7b78c09ec50b727f921840dcf783Jorim Jaggi                    new Intent(IFaceLockInterface.class.getName()).setPackage(FACE_LOCK_PACKAGE),
134ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mConnection,
135ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Context.BIND_AUTO_CREATE,
13627b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    new UserHandle(mLockPatternUtils.getCurrentUser()));
137ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mBoundToService = true;
138ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        } else {
139ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
140ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
141ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
142ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = true;
143ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return true;
144ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
145ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
146ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
14722001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna     * Stops Face Unlock and unbinds from the service.  Called on the UI thread.
148ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1493223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean stop() {
150257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "stop()");
15122001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        if (mHandler.getLooper() != Looper.myLooper()) {
152a71984f3da47c6e6e3164c170735362a3222d3adJim Miller            Log.e(TAG, "stop() called from non-UI thread");
15322001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        }
15422001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna
155025fb93e3e5518b7db5fec049d285cfb2d28a074Steven Ross        // Clearing any old service connected messages.
156025fb93e3e5518b7db5fec049d285cfb2d28a074Steven Ross        mHandler.removeMessages(MSG_SERVICE_CONNECTED);
157025fb93e3e5518b7db5fec049d285cfb2d28a074Steven Ross
158ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        boolean mWasRunning = mIsRunning;
1591108a2cb412b054cc9e4acc48182c46c45180c0cDanielle Millett
160c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        stopUi();
161c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna
162c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        if (mBoundToService) {
163c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mService != null) {
164c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
165ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mService.unregisterCallback(mFaceUnlockCallback);
166c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
167c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    // Not much we can do
1683223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                }
1699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
170257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Unbinding from Face Unlock service");
171c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mContext.unbindService(mConnection);
172c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mBoundToService = false;
173c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        } else {
174c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // This is usually not an error when this happens.  Sometimes we will tell it to
175c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // unbind multiple times because it's called from both onWindowFocusChanged and
176c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // onDetachedFromWindow.
177ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
1789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
179ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = false;
180ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mWasRunning;
1819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1833223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    /**
184ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Frees up resources used by Face Unlock and stops it if it is still running.
1853223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     */
1863223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void cleanUp() {
187257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "cleanUp()");
1883223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (mService != null) {
1893223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            try {
190ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mService.unregisterCallback(mFaceUnlockCallback);
1913223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            } catch (RemoteException e) {
1923223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // Not much we can do
1933223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            }
1943223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stopUi();
1953223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mService = null;
1969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1973223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1983223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
199ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
200ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
201ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2023223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public int getQuality() {
2033223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
2049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
206ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
207257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Handles messages such that everything happens on the UI thread in a deterministic order.
208257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Calls from the Face Unlock service come from binder threads.  Calls from lockscreen typically
209257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * come from the UI thread.  This makes sure there are no race conditions between those calls.
210ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean handleMessage(Message msg) {
2129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        switch (msg.what) {
213257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SERVICE_CONNECTED:
214257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleServiceConnected();
215257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
216257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SERVICE_DISCONNECTED:
217257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleServiceDisconnected();
218257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
219257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_UNLOCK:
2205eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna                handleUnlock(msg.arg1);
221257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
222257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_CANCEL:
223257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleCancel();
224257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
225257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_REPORT_FAILED_ATTEMPT:
226257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleReportFailedAttempt();
227257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
228257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_POKE_WAKELOCK:
229dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                handlePokeWakelock(msg.arg1);
230257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
231257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            default:
232257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.e(TAG, "Unhandled message");
233257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                return false;
2349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return true;
2369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
238ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
239257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the service to start its UI via an AIDL interface.  Called when the
240257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * onServiceConnected() callback is received.
241257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
242257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleServiceConnected() {
243c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        Log.d(TAG, "handleServiceConnected()");
244c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna
245c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // It is possible that an unbind has occurred in the time between the bind and when this
246c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // function is reached.  If an unbind has already occurred, proceeding on to call startUi()
247c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // can result in a fatal error.  Note that the onServiceConnected() callback is
248c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // asynchronous, so this possibility would still exist if we executed this directly in
249c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // onServiceConnected() rather than using a handler.
250c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        if (!mBoundToService) {
251c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna            Log.d(TAG, "Dropping startUi() in handleServiceConnected() because no longer bound");
252c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna            return;
253c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        }
254c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna
255257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        try {
256257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService.registerCallback(mFaceUnlockCallback);
257257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } catch (RemoteException e) {
258257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
259257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService = null;
260257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mBoundToService = false;
261257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mIsRunning = false;
262257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            return;
263257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
264257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
265257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
266257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            IBinder windowToken = mFaceUnlockView.getWindowToken();
267257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            if (windowToken != null) {
268dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                // When switching between portrait and landscape view while Face Unlock is running,
269dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                // the screen will eventually go dark unless we poke the wakelock when Face Unlock
270dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                // is restarted.
271dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mKeyguardScreenCallback.userActivity(0);
272dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez
273257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                int[] position;
274257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                position = new int[2];
275257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                mFaceUnlockView.getLocationInWindow(position);
276257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
277257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                        mFaceUnlockView.getHeight());
278257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            } else {
279257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.e(TAG, "windowToken is null in handleServiceConnected()");
280257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            }
281257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
282257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
283257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
284257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
285257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Called when the onServiceDisconnected() callback is received.  This should not happen during
286257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * normal operation.  It indicates an error has occurred.
287257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
288257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleServiceDisconnected() {
289257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        Log.e(TAG, "handleServiceDisconnected()");
290257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        // TODO: this lock may no longer be needed now that everything is being called from a
291257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        // handler
292257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        synchronized (mServiceRunningLock) {
293257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService = null;
294257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mServiceRunning = false;
295257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
296257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mBoundToService = false;
297257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mIsRunning = false;
298257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
299257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
300257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
30161413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett     * Stops the Face Unlock service and tells the device to grant access to the user.
302257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
3035eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna    void handleUnlock(int authenticatedUserId) {
304257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleUnlock()");
305257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
3065eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna        int currentUserId = mLockPatternUtils.getCurrentUser();
3075eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna        if (authenticatedUserId == currentUserId) {
3085eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna            if (DEBUG) Log.d(TAG, "Unlocking for user " + authenticatedUserId);
3097751ff6cd079e59e3c1f2404198774cd371ea69fJim Miller            mKeyguardScreenCallback.reportUnlockAttempt(true);
3105eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna            mKeyguardScreenCallback.dismiss(true);
3115eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna        } else {
3125eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna            Log.d(TAG, "Ignoring unlock for authenticated user (" + authenticatedUserId +
3135eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna                    ") because the current user is " + currentUserId);
3145eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna        }
315257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
316257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
317257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
31861413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett     * Stops the Face Unlock service and goes to the backup lock.
319257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
320257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleCancel() {
321257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleCancel()");
322667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna        // We are going to the backup method, so we don't want to see Face Unlock again until the
323667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna        // next time the user visits keyguard.
324667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
325667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna
32661413b5ed215accd7b4f3eaf80edeab2f330aa49Danielle Millett        mKeyguardScreenCallback.showBackupSecurity();
327257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
328dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
329257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
330257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
331257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
3327019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna     * Increments the number of failed Face Unlock attempts.
333257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
334257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleReportFailedAttempt() {
335257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
336667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna        // We are going to the backup method, so we don't want to see Face Unlock again until the
337667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna        // next time the user visits keyguard.
338667b5d58b9e8b77221c87811c5c9aab1bfe44ffaBrian Colonna        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
339257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
3407751ff6cd079e59e3c1f2404198774cd371ea69fJim Miller        mKeyguardScreenCallback.reportUnlockAttempt(false);
341257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
342257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
343257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
344acbe41fc1316cf16f03de80c84ea311cc4f55ffbSteven Ross     * If the screen is on, pokes the wakelock to keep the screen alive and active for a specific
345acbe41fc1316cf16f03de80c84ea311cc4f55ffbSteven Ross     * amount of time.
346257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
347dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez    void handlePokeWakelock(int millis) {
348acbe41fc1316cf16f03de80c84ea311cc4f55ffbSteven Ross      PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
349acbe41fc1316cf16f03de80c84ea311cc4f55ffbSteven Ross      if (powerManager.isScreenOn()) {
350dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mKeyguardScreenCallback.userActivity(millis);
351acbe41fc1316cf16f03de80c84ea311cc4f55ffbSteven Ross      }
352257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
353257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
354257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
355257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Implements service connection methods.
356257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
3579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private ServiceConnection mConnection = new ServiceConnection() {
358ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
359257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when the Face Unlock service connects after calling bind().
360ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
3619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceConnected(ComponentName className, IBinder iservice) {
362257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Connected to Face Unlock service");
3639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = IFaceLockInterface.Stub.asInterface(iservice);
364257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
3659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
367ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
368257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called if the Face Unlock service unexpectedly disconnects.  This indicates an error.
369ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
3709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceDisconnected(ComponentName className) {
371257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "Unexpected disconnect from Face Unlock service");
372257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
3739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
3759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
376ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
377257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the Face Unlock service to start displaying its UI and start processing.
378ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
3793223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
380c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        if (DEBUG) Log.d(TAG, "startUi()");
381c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
382c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (!mServiceRunning) {
383c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna                Log.d(TAG, "Starting Face Unlock");
384c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
3854fa995a932d876b98c393c909c4eb2e303783e59Uriel Rodriguez                    mService.startUi(windowToken, x, y, w, h,
3864fa995a932d876b98c393c909c4eb2e303783e59Uriel Rodriguez                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
387c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
388ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
389c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    return;
3909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
391c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = true;
392c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            } else {
393257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.w(TAG, "startUi() attempted while running");
3949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
398ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
399257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the Face Unlock service to stop displaying its UI and stop processing.
400ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
4013223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void stopUi() {
402257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "stopUi()");
403ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Note that attempting to stop Face Unlock when it's not running is not an issue.
404ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock can return, which stops it and then we try to stop it when the
405c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        // screen is turned off.  That's why we check.
406c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
407c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mServiceRunning) {
408c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna                Log.d(TAG, "Stopping Face Unlock");
409c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
410c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    mService.stopUi();
411c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
412ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
4139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
414c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = false;
415257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            } else {
416257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // This is usually not an error when this happens.  Sometimes we will tell it to
417257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // stop multiple times because it's called from both onWindowFocusChanged and
418257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // onDetachedFromWindow.
419257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
4209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
4219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
424ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
425257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Implements the AIDL biometric unlock service callback interface.
426ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
427ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
428ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
429257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when Face Unlock wants to grant access to the user.
430ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void unlock() {
432ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "unlock()");
4335eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna            Message message = mHandler.obtainMessage(MSG_UNLOCK, UserHandle.getCallingUserId(), -1);
4345eb83aa8965835f75b13a535eafe7f6311e4f790Brian Colonna            mHandler.sendMessage(message);
4359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
437ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
4387019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna         * Called when Face Unlock wants to go to the backup.
439ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void cancel() {
441ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "cancel()");
442257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_CANCEL);
4439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
445ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
4467019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna         * Called when Face Unlock wants to increment the number of failed attempts.
447ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void reportFailedAttempt() {
449ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
450257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
4519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
453ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
454dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez         * Called when Face Unlock wants to keep the screen alive and active for a specific amount
455dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez         * of time.
456ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
457dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez        public void pokeWakelock(int millis) {
458dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez            if (DEBUG) Log.d(TAG, "pokeWakelock() for " + millis + "ms");
459dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez            Message message = mHandler.obtainMessage(MSG_POKE_WAKELOCK, millis, -1);
460dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez            mHandler.sendMessage(message);
4619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
462dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez
4639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
4649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna}
465