FaceUnlock.java revision 4b4b954ddf34af51576441f0e3eca6d19150aada
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
17dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerpackage com.android.internal.policy.impl.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;
329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.RemoteException;
339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.util.Log;
349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.view.View;
359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
363223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonnapublic class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final boolean DEBUG = false;
399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final String TAG = "FULLockscreen";
409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final Context mContext;
42ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final LockPatternUtils mLockPatternUtils;
439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
44ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
45ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private boolean mServiceRunning = false;
46257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    // TODO: now that the code has been restructure to do almost all operations from a handler, this
47257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    // lock may no longer be necessary.
48ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final Object mServiceRunningLock = new Object();
499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private IFaceLockInterface mService;
509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mBoundToService = false;
51ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private View mFaceUnlockView;
529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private Handler mHandler;
54257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0;
55257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1;
56257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_SERVICE_CONNECTED = 2;
57257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_SERVICE_DISCONNECTED = 3;
58257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_UNLOCK = 4;
59257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_CANCEL = 5;
60257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_REPORT_FAILED_ATTEMPT = 6;
61257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_EXPOSE_FALLBACK = 7;
62257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_POKE_WAKELOCK = 8;
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
699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Long enough to stay visible while the service starts
709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Short enough to not have to wait long for backup if service fails to start or crashes
719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // The service can take a couple of seconds to start on the first try after boot
72257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int SERVICE_STARTUP_VIEW_TIMEOUT = 3000;
739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
74ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // So the user has a consistent amount of time when brought to the backup method from Face
75ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // Unlock
769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int BACKUP_LOCK_TIMEOUT = 5000;
779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
78dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    KeyguardSecurityCallback mKeyguardScreenCallback;
799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
80257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
81257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stores some of the structures that Face Unlock will need to access and creates the handler
82257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * will be used to execute messages on the UI thread.
83257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
84000464ac012471d301c6e48a8228291519915e17Jim Miller    public FaceUnlock(Context context) {
859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mContext = context;
86dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternUtils = new LockPatternUtils(context);
879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler = new Handler(this);
889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
90000464ac012471d301c6e48a8228291519915e17Jim Miller    public void setKeyguardCallback(KeyguardSecurityCallback keyguardScreenCallback) {
91000464ac012471d301c6e48a8228291519915e17Jim Miller        mKeyguardScreenCallback = keyguardScreenCallback;
92000464ac012471d301c6e48a8228291519915e17Jim Miller    }
93000464ac012471d301c6e48a8228291519915e17Jim Miller
94ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
95ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Stores and displays the view that Face Unlock is allowed to draw within.
96ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * TODO: since the layout object will eventually be shared by multiple biometric unlock
97ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * methods, we will have to add our other views (background, cancel button) here.
98ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
99ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public void initializeView(View biometricUnlockView) {
100257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        Log.d(TAG, "initializeView()");
101ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mFaceUnlockView = biometricUnlockView;
102ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
103ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
104ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
105ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Indicates whether Face Unlock is currently running.
106ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1073223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean isRunning() {
108ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mIsRunning;
1093223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1103223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
111ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
112ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Sets the Face Unlock view to visible, hiding it after the specified amount of time.  If
11322001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna     * timeoutMillis is 0, no hide is performed.  Called on the UI thread.
114ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1153223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void show(long timeoutMillis) {
116257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "show()");
11722001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        if (mHandler.getLooper() != Looper.myLooper()) {
11822001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna            Log.e(TAG, "show() called off of the UI thread");
11922001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        }
120257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        removeDisplayMessages();
121ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (timeoutMillis > 0) {
122257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
123ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
1243223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1253223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
126ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
127ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Hides the Face Unlock view.
128ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1293223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void hide() {
130257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "hide()");
1313223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        // Remove messages to prevent a delayed show message from undo-ing the hide
132257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        removeDisplayMessages();
133257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW);
1343223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1353223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
136ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
137ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
138257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Face Unlock view is displayed to hide the backup lock while the service is starting up.
13922001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna     * Called on the UI thread.
140ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
141ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public boolean start() {
142257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "start()");
14322001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        if (mHandler.getLooper() != Looper.myLooper()) {
14422001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna            Log.e(TAG, "start() called off of the UI thread");
14522001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        }
14622001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna
147ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (mIsRunning) {
148ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "start() called when already running");
149ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
150ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
151ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
152ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock fails to start or crashes
153ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // This must show before bind to guarantee that Face Unlock has a place to display
154257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        show(SERVICE_STARTUP_VIEW_TIMEOUT);
155ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (!mBoundToService) {
1564b4b954ddf34af51576441f0e3eca6d19150aadaAmith Yamasani            Log.d(TAG, "Binding to Face Unlock service for user="
1574b4b954ddf34af51576441f0e3eca6d19150aadaAmith Yamasani                    + mLockPatternUtils.getCurrentUser());
158ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
159ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mConnection,
160ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Context.BIND_AUTO_CREATE,
161ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mLockPatternUtils.getCurrentUser());
162ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mBoundToService = true;
163ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        } else {
164ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
165ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
166ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
167ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = true;
168ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return true;
169ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
170ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
171ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
17222001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna     * Stops Face Unlock and unbinds from the service.  Called on the UI thread.
173ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1743223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean stop() {
175257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "stop()");
17622001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        if (mHandler.getLooper() != Looper.myLooper()) {
17722001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna            Log.e(TAG, "stop() called off of the UI thread");
17822001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna        }
17922001c1f96984655f7205ecbc93dd982c47b4e97Brian Colonna
180ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        boolean mWasRunning = mIsRunning;
181c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        stopUi();
182c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna
183c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        if (mBoundToService) {
184c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mService != null) {
185c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
186ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mService.unregisterCallback(mFaceUnlockCallback);
187c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
188c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    // Not much we can do
1893223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                }
1909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
191257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Unbinding from Face Unlock service");
192c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mContext.unbindService(mConnection);
193c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mBoundToService = false;
194c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        } else {
195c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // This is usually not an error when this happens.  Sometimes we will tell it to
196c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // unbind multiple times because it's called from both onWindowFocusChanged and
197c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // onDetachedFromWindow.
198ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
1999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
200ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = false;
201ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mWasRunning;
2029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2043223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    /**
205ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Frees up resources used by Face Unlock and stops it if it is still running.
2063223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     */
2073223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void cleanUp() {
208257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "cleanUp()");
2093223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (mService != null) {
2103223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            try {
211ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mService.unregisterCallback(mFaceUnlockCallback);
2123223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            } catch (RemoteException e) {
2133223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // Not much we can do
2143223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            }
2153223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stopUi();
2163223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mService = null;
2179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2183223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
2193223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
220ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
221ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
222ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2233223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public int getQuality() {
2243223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
2259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
227ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
228257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Handles messages such that everything happens on the UI thread in a deterministic order.
229257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Calls from the Face Unlock service come from binder threads.  Calls from lockscreen typically
230257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * come from the UI thread.  This makes sure there are no race conditions between those calls.
231ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean handleMessage(Message msg) {
2339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        switch (msg.what) {
234257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SHOW_FACE_UNLOCK_VIEW:
235257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleShowFaceUnlockView();
236257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
237257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_HIDE_FACE_UNLOCK_VIEW:
238257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleHideFaceUnlockView();
239257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
240257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SERVICE_CONNECTED:
241257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleServiceConnected();
242257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
243257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SERVICE_DISCONNECTED:
244257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleServiceDisconnected();
245257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
246257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_UNLOCK:
247257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleUnlock();
248257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
249257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_CANCEL:
250257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleCancel();
251257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
252257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_REPORT_FAILED_ATTEMPT:
253257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleReportFailedAttempt();
254257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
255257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_EXPOSE_FALLBACK:
256257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleExposeFallback();
257257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
258257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_POKE_WAKELOCK:
259dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                handlePokeWakelock(msg.arg1);
260257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
261257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            default:
262257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.e(TAG, "Unhandled message");
263257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                return false;
2649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return true;
2669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
268ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
269257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Sets the Face Unlock view to visible, thus covering the backup lock.
270257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
271257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleShowFaceUnlockView() {
272257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()");
273000464ac012471d301c6e48a8228291519915e17Jim Miller        // Not required
274257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
275257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
276257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
277000464ac012471d301c6e48a8228291519915e17Jim Miller     * Hide face unlock and show backup
278257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
279257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleHideFaceUnlockView() {
280257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
281000464ac012471d301c6e48a8228291519915e17Jim Miller        mKeyguardScreenCallback.showBackupSecurity();
282257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
283257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
284257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
285257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the service to start its UI via an AIDL interface.  Called when the
286257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * onServiceConnected() callback is received.
287257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
288257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleServiceConnected() {
289c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        Log.d(TAG, "handleServiceConnected()");
290c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna
291c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // It is possible that an unbind has occurred in the time between the bind and when this
292c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // function is reached.  If an unbind has already occurred, proceeding on to call startUi()
293c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // can result in a fatal error.  Note that the onServiceConnected() callback is
294c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // asynchronous, so this possibility would still exist if we executed this directly in
295c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        // onServiceConnected() rather than using a handler.
296c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        if (!mBoundToService) {
297c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna            Log.d(TAG, "Dropping startUi() in handleServiceConnected() because no longer bound");
298c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna            return;
299c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        }
300c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna
301257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        try {
302257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService.registerCallback(mFaceUnlockCallback);
303257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } catch (RemoteException e) {
304257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
305257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService = null;
306257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mBoundToService = false;
307257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mIsRunning = false;
308257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            return;
309257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
310257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
311257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
312257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            IBinder windowToken = mFaceUnlockView.getWindowToken();
313257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            if (windowToken != null) {
314dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                // When switching between portrait and landscape view while Face Unlock is running,
315dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                // the screen will eventually go dark unless we poke the wakelock when Face Unlock
316dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez                // is restarted.
317dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mKeyguardScreenCallback.userActivity(0);
318dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez
319257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                int[] position;
320257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                position = new int[2];
321257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                mFaceUnlockView.getLocationInWindow(position);
322257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
323257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                        mFaceUnlockView.getHeight());
324257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            } else {
325257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.e(TAG, "windowToken is null in handleServiceConnected()");
326257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            }
327257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
328257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
329257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
330257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
331257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Called when the onServiceDisconnected() callback is received.  This should not happen during
332257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * normal operation.  It indicates an error has occurred.
333257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
334257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleServiceDisconnected() {
335257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        Log.e(TAG, "handleServiceDisconnected()");
336257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        // TODO: this lock may no longer be needed now that everything is being called from a
337257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        // handler
338257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        synchronized (mServiceRunningLock) {
339257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService = null;
340257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mServiceRunning = false;
341257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
342257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mBoundToService = false;
343257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mIsRunning = false;
344257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
345257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
346257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
347257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stops the Face Unlock service and tells the device to grant access to the user.  Shows the
348257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Face Unlock view to keep the backup lock covered while the device unlocks.
349257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
350257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleUnlock() {
351257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleUnlock()");
352257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        removeDisplayMessages();
353257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
354257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
355dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mKeyguardScreenCallback.dismiss(true);
356257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
357257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
358257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
3597019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna     * Stops the Face Unlock service and exposes the backup lock.
360257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
361257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleCancel() {
362257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleCancel()");
363000464ac012471d301c6e48a8228291519915e17Jim Miller        mKeyguardScreenCallback.dismiss(false);
364257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
365dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
366257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
367257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
368257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
3697019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna     * Increments the number of failed Face Unlock attempts.
370257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
371257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleReportFailedAttempt() {
372257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
373dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mKeyguardScreenCallback.reportFailedUnlockAttempt();
374257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
375257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
376257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
377257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Hides the Face Unlock view to expose the backup lock.  Called when the Face Unlock service UI
378257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * is started, indicating there is no need to continue displaying the underlying view because
379257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * the service UI is now covering the backup lock.
380257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
381257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleExposeFallback() {
382257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleExposeFallback()");
383000464ac012471d301c6e48a8228291519915e17Jim Miller        // No longer required because face unlock doesn't cover backup unlock.
384257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
385257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
386257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
387dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez     * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
388257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
389dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez    void handlePokeWakelock(int millis) {
390dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mKeyguardScreenCallback.userActivity(millis);
391257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
392257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
393257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
394257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Removes show and hide messages from the message queue.  Called to prevent delayed show/hide
395257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * messages from undoing a new message.
396ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
397257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private void removeDisplayMessages() {
398257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW);
399257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW);
4009431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4019431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
402257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
403257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Implements service connection methods.
404257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
4059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private ServiceConnection mConnection = new ServiceConnection() {
406ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
407257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when the Face Unlock service connects after calling bind().
408ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceConnected(ComponentName className, IBinder iservice) {
410257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Connected to Face Unlock service");
4119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = IFaceLockInterface.Stub.asInterface(iservice);
412257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
4139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
415ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
416257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called if the Face Unlock service unexpectedly disconnects.  This indicates an error.
417ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceDisconnected(ComponentName className) {
419257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "Unexpected disconnect from Face Unlock service");
420257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
4219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
4239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
424ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
425257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the Face Unlock service to start displaying its UI and start processing.
426ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
4273223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
428c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna        if (DEBUG) Log.d(TAG, "startUi()");
429c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
430c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (!mServiceRunning) {
431c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna                Log.d(TAG, "Starting Face Unlock");
432c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
4334fa995a932d876b98c393c909c4eb2e303783e59Uriel Rodriguez                    mService.startUi(windowToken, x, y, w, h,
4344fa995a932d876b98c393c909c4eb2e303783e59Uriel Rodriguez                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
435c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
436ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
437c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    return;
4389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
439c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = true;
440c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            } else {
441257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.w(TAG, "startUi() attempted while running");
4429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
4439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
446ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
447257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the Face Unlock service to stop displaying its UI and stop processing.
448ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
4493223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void stopUi() {
450257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "stopUi()");
451ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Note that attempting to stop Face Unlock when it's not running is not an issue.
452ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock can return, which stops it and then we try to stop it when the
453c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        // screen is turned off.  That's why we check.
454c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
455c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mServiceRunning) {
456c266070aec3d99c9a4d422325fbceae44c37a4d3Brian Colonna                Log.d(TAG, "Stopping Face Unlock");
457c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
458c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    mService.stopUi();
459c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
460ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
4619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
462c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = false;
463257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            } else {
464257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // This is usually not an error when this happens.  Sometimes we will tell it to
465257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // stop multiple times because it's called from both onWindowFocusChanged and
466257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // onDetachedFromWindow.
467257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
4689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
4699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
472ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
473257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Implements the AIDL biometric unlock service callback interface.
474ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
475ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
476ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
477257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when Face Unlock wants to grant access to the user.
478ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void unlock() {
480ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "unlock()");
481257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_UNLOCK);
4829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
484ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
4857019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna         * Called when Face Unlock wants to go to the backup.
486ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void cancel() {
488ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "cancel()");
489257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_CANCEL);
4909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4919431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
492ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
4937019325e183ba1abf1869ccffc4b1ecd8c771a44Brian Colonna         * Called when Face Unlock wants to increment the number of failed attempts.
494ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void reportFailedAttempt() {
496ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
497257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
4989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
500ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
501257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when the Face Unlock service starts displaying the UI, indicating that the backup
502257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * unlock can be exposed because the Face Unlock service is now covering the backup with its
503257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * UI.
504ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         **/
5059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void exposeFallback() {
506ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "exposeFallback()");
507257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
5089431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
5099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
510ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
511dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez         * Called when Face Unlock wants to keep the screen alive and active for a specific amount
512dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez         * of time.
513ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
514dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez        public void pokeWakelock(int millis) {
515dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez            if (DEBUG) Log.d(TAG, "pokeWakelock() for " + millis + "ms");
516dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez            Message message = mHandler.obtainMessage(MSG_POKE_WAKELOCK, millis, -1);
517dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez            mHandler.sendMessage(message);
5189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
519dff307697d7a7482efe4c10cb3b07b9249524a42Uriel Rodriguez
5209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
5219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna}
522