FaceUnlock.java revision 257f2ecc97d294e95b069547466d2054926d960f
19431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna/*
29431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna * Copyright (C) 2011 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
179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnapackage com.android.internal.policy.impl;
189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.R;
209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.policy.IFaceLockCallback;
219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.policy.IFaceLockInterface;
229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport com.android.internal.widget.LockPatternUtils;
239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
243223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonnaimport android.app.admin.DevicePolicyManager;
259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.ComponentName;
269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.Context;
279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.Intent;
289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.ServiceConnection;
299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.Handler;
309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.IBinder;
319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.Message;
329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.RemoteException;
339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.telephony.TelephonyManager;
349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.util.Log;
359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.view.View;
369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
373223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonnapublic class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final boolean DEBUG = false;
409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final String TAG = "FULLockscreen";
419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final Context mContext;
43ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final LockPatternUtils mLockPatternUtils;
449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final KeyguardUpdateMonitor mUpdateMonitor;
459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
46ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
47ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private boolean mServiceRunning = false;
48257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    // TODO: now that the code has been restructure to do almost all operations from a handler, this
49257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    // lock may no longer be necessary.
50ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final Object mServiceRunningLock = new Object();
519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private IFaceLockInterface mService;
529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mBoundToService = false;
53ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private View mFaceUnlockView;
549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private Handler mHandler;
56257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0;
57257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1;
58257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_SERVICE_CONNECTED = 2;
59257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_SERVICE_DISCONNECTED = 3;
60257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_UNLOCK = 4;
61257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_CANCEL = 5;
62257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_REPORT_FAILED_ATTEMPT = 6;
63257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_EXPOSE_FALLBACK = 7;
64257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int MSG_POKE_WAKELOCK = 8;
659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
66ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // TODO: This was added for the purpose of adhering to what the biometric interface expects
67ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // the isRunning() function to return.  However, it is probably not necessary to have both
68ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // mRunning and mServiceRunning.  I'd just rather wait to change that logic.
69257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private volatile boolean mIsRunning = false;
709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Long enough to stay visible while the service starts
729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Short enough to not have to wait long for backup if service fails to start or crashes
739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // The service can take a couple of seconds to start on the first try after boot
74257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private final int SERVICE_STARTUP_VIEW_TIMEOUT = 3000;
759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
76ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // So the user has a consistent amount of time when brought to the backup method from Face
77ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // Unlock
789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int BACKUP_LOCK_TIMEOUT = 5000;
799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    KeyguardScreenCallback mKeyguardScreenCallback;
819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
82257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
83257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stores some of the structures that Face Unlock will need to access and creates the handler
84257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * will be used to execute messages on the UI thread.
85257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
869431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mContext = context;
899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mUpdateMonitor = updateMonitor;
909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mLockPatternUtils = lockPatternUtils;
919431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mKeyguardScreenCallback = keyguardScreenCallback;
929431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler = new Handler(this);
939431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
95ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
96ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Stores and displays the view that Face Unlock is allowed to draw within.
97ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * TODO: since the layout object will eventually be shared by multiple biometric unlock
98ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * methods, we will have to add our other views (background, cancel button) here.
99ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
100ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public void initializeView(View biometricUnlockView) {
101257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        Log.d(TAG, "initializeView()");
102ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mFaceUnlockView = biometricUnlockView;
103ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        show(0);
104ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
105ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
106ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
107ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Indicates whether Face Unlock is currently running.
108ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1093223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean isRunning() {
110ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mIsRunning;
1113223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1123223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
113ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
114ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Sets the Face Unlock view to visible, hiding it after the specified amount of time.  If
115ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * timeoutMillis is 0, no hide is performed.
116ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1173223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void show(long timeoutMillis) {
118257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "show()");
119257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        removeDisplayMessages();
120ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (mFaceUnlockView != null) {
121ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mFaceUnlockView.setVisibility(View.VISIBLE);
122ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
123ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (timeoutMillis > 0) {
124257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
125ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
1263223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1273223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
128ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
129ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Hides the Face Unlock view.
130ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1313223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void hide() {
132257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "hide()");
1333223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        // Remove messages to prevent a delayed show message from undo-ing the hide
134257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        removeDisplayMessages();
135257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW);
1363223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1373223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
138ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
139ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
140257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Face Unlock view is displayed to hide the backup lock while the service is starting up.
141ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
142ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public boolean start() {
143257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "start()");
144ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (mIsRunning) {
145ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "start() called when already running");
146ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
147ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
148ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
149ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock fails to start or crashes
150ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // This must show before bind to guarantee that Face Unlock has a place to display
151257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        show(SERVICE_STARTUP_VIEW_TIMEOUT);
152ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (!mBoundToService) {
153257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Binding to Face Unlock service");
154ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
155ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mConnection,
156ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Context.BIND_AUTO_CREATE,
157ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mLockPatternUtils.getCurrentUser());
158ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mBoundToService = true;
159ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        } else {
160ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
161ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
162ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
163ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // When switching between portrait and landscape view while Face Unlock is running, the
164ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // screen will eventually go dark unless we poke the wakelock when Face Unlock is
165ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // restarted
166ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mKeyguardScreenCallback.pokeWakelock();
167ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
168ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = true;
169ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return true;
170ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
171ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
172ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
173ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Stops Face Unlock and unbinds from the service.
174ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1753223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean stop() {
176257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "stop()");
177ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        boolean mWasRunning = mIsRunning;
178c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        stopUi();
179c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna
180c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        if (mBoundToService) {
181c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mService != null) {
182c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
183ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mService.unregisterCallback(mFaceUnlockCallback);
184c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
185c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    // Not much we can do
1863223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                }
1879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
188257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Unbinding from Face Unlock service");
189c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mContext.unbindService(mConnection);
190c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mBoundToService = false;
191c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        } else {
192c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // This is usually not an error when this happens.  Sometimes we will tell it to
193c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // unbind multiple times because it's called from both onWindowFocusChanged and
194c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // onDetachedFromWindow.
195ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
1969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
197ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = false;
198ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mWasRunning;
1999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2009431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2013223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    /**
202ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Frees up resources used by Face Unlock and stops it if it is still running.
2033223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     */
2043223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void cleanUp() {
205257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "cleanUp()");
2063223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (mService != null) {
2073223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            try {
208ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mService.unregisterCallback(mFaceUnlockCallback);
2093223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            } catch (RemoteException e) {
2103223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // Not much we can do
2113223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            }
2123223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stopUi();
2133223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mService = null;
2149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2153223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
2163223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
217ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
218ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
219ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2203223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public int getQuality() {
2213223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
2229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
224ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
225257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Handles messages such that everything happens on the UI thread in a deterministic order.
226257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Calls from the Face Unlock service come from binder threads.  Calls from lockscreen typically
227257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * come from the UI thread.  This makes sure there are no race conditions between those calls.
228ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    @Override
2309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean handleMessage(Message msg) {
2319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        switch (msg.what) {
232257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SHOW_FACE_UNLOCK_VIEW:
233257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleShowFaceUnlockView();
234257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
235257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_HIDE_FACE_UNLOCK_VIEW:
236257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleHideFaceUnlockView();
237257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
238257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SERVICE_CONNECTED:
239257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleServiceConnected();
240257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
241257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_SERVICE_DISCONNECTED:
242257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleServiceDisconnected();
243257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
244257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_UNLOCK:
245257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleUnlock();
246257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
247257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_CANCEL:
248257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleCancel();
249257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
250257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_REPORT_FAILED_ATTEMPT:
251257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleReportFailedAttempt();
252257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
253257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_EXPOSE_FALLBACK:
254257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handleExposeFallback();
255257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
256257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            case MSG_POKE_WAKELOCK:
257257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                handlePokeWakelock();
258257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                break;
259257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            default:
260257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.e(TAG, "Unhandled message");
261257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                return false;
2629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return true;
2649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
266ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
267257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Sets the Face Unlock view to visible, thus covering the backup lock.
268257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
269257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleShowFaceUnlockView() {
270257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()");
271257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
272257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mFaceUnlockView.setVisibility(View.VISIBLE);
273257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } else {
274257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "mFaceUnlockView is null in handleShowFaceUnlockView()");
275257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
276257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
277257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
278257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
279257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Sets the Face Unlock view to invisible, thus exposing the backup lock.
280257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
281257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleHideFaceUnlockView() {
282257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
283257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
284257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mFaceUnlockView.setVisibility(View.INVISIBLE);
285257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } else {
286257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "mFaceUnlockView is null in handleHideFaceUnlockView()");
287257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
288257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
289257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
290257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
291257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the service to start its UI via an AIDL interface.  Called when the
292257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * onServiceConnected() callback is received.
293257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
294257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleServiceConnected() {
295257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleServiceConnected()");
296257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        try {
297257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService.registerCallback(mFaceUnlockCallback);
298257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } catch (RemoteException e) {
299257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
300257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService = null;
301257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mBoundToService = false;
302257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mIsRunning = false;
303257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            return;
304257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
305257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
306257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
307257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            IBinder windowToken = mFaceUnlockView.getWindowToken();
308257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            if (windowToken != null) {
309257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                int[] position;
310257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                position = new int[2];
311257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                mFaceUnlockView.getLocationInWindow(position);
312257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
313257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                        mFaceUnlockView.getHeight());
314257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            } else {
315257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.e(TAG, "windowToken is null in handleServiceConnected()");
316257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            }
317257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
318257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
319257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
320257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
321257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Called when the onServiceDisconnected() callback is received.  This should not happen during
322257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * normal operation.  It indicates an error has occurred.
323257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
324257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleServiceDisconnected() {
325257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        Log.e(TAG, "handleServiceDisconnected()");
326257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        // TODO: this lock may no longer be needed now that everything is being called from a
327257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        // handler
328257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        synchronized (mServiceRunningLock) {
329257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mService = null;
330257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mServiceRunning = false;
331257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
332257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mBoundToService = false;
333257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mIsRunning = false;
334257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
335257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
336257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
337257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stops the Face Unlock service and tells the device to grant access to the user.  Shows the
338257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Face Unlock view to keep the backup lock covered while the device unlocks.
339257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
340257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleUnlock() {
341257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleUnlock()");
342257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        removeDisplayMessages();
343257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
344257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mFaceUnlockView.setVisibility(View.VISIBLE);
345257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } else {
346257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "mFaceUnlockView is null in handleUnlock()");
347257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
348257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
349257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mKeyguardScreenCallback.keyguardDone(true);
350257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
351257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
352257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
353257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
354257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stops the Face Unlock service and exposes the backup lock.  Called when the user presses the
355257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * cancel button to skip Face Unlock or no face is detected.
356257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
357257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleCancel() {
358257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleCancel()");
359257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
360257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mFaceUnlockView.setVisibility(View.INVISIBLE);
361257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } else {
362257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "mFaceUnlockView is null in handleCancel()");
363257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
364257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
365257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
366257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
367257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
368257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
369257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Stops the Face Unlock service and exposes the backup lock, reporting a failed unlock attempt.
370257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Called when Face Unlock denies access to the user.
371257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
372257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleReportFailedAttempt() {
373257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
374257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mUpdateMonitor.reportFailedBiometricUnlockAttempt();
375257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
376257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mFaceUnlockView.setVisibility(View.INVISIBLE);
377257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } else {
378257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "mFaceUnlockView is null in handleReportFailedAttempt()");
379257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
380257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        stop();
381257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
382257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
383257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
384257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
385257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Hides the Face Unlock view to expose the backup lock.  Called when the Face Unlock service UI
386257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * is started, indicating there is no need to continue displaying the underlying view because
387257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * the service UI is now covering the backup lock.
388257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
389257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handleExposeFallback() {
390257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "handleExposeFallback()");
391257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (mFaceUnlockView != null) {
392257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mFaceUnlockView.setVisibility(View.INVISIBLE);
393257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        } else {
394257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "mFaceUnlockView is null in handleExposeFallback()");
395257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        }
396257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
397257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
398257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
399257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Pokes the wakelock to keep the screen alive and active.
400257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
401257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    void handlePokeWakelock() {
402257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mKeyguardScreenCallback.pokeWakelock();
403257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    }
404257f2ecc97d294e95b069547466d2054926d960fBrian Colonna
405257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
406257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Removes show and hide messages from the message queue.  Called to prevent delayed show/hide
407257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * messages from undoing a new message.
408ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
409257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    private void removeDisplayMessages() {
410257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW);
411257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW);
4129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
414257f2ecc97d294e95b069547466d2054926d960fBrian Colonna    /**
415257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Implements service connection methods.
416257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     */
4179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private ServiceConnection mConnection = new ServiceConnection() {
418ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
419257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when the Face Unlock service connects after calling bind().
420ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
4229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceConnected(ComponentName className, IBinder iservice) {
423257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.d(TAG, "Connected to Face Unlock service");
4249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = IFaceLockInterface.Stub.asInterface(iservice);
425257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
4269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
428ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
429257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called if the Face Unlock service unexpectedly disconnects.  This indicates an error.
430ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
4329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceDisconnected(ComponentName className) {
433257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            Log.e(TAG, "Unexpected disconnect from Face Unlock service");
434257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
4359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
4379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
438ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
439257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the Face Unlock service to start displaying its UI and start processing.
440ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
4413223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
442257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "startUi()");
443c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
444c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (!mServiceRunning) {
445ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                if (DEBUG) Log.d(TAG, "Starting Face Unlock");
446c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
447c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    mService.startUi(windowToken, x, y, w, h,
448c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
449c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
450ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
451c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    return;
4529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
453c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = true;
454c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            } else {
455257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                Log.w(TAG, "startUi() attempted while running");
4569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
4579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
460ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
461257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Tells the Face Unlock service to stop displaying its UI and stop processing.
462ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
4633223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void stopUi() {
464257f2ecc97d294e95b069547466d2054926d960fBrian Colonna        if (DEBUG) Log.d(TAG, "stopUi()");
465ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Note that attempting to stop Face Unlock when it's not running is not an issue.
466ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock can return, which stops it and then we try to stop it when the
467c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        // screen is turned off.  That's why we check.
468c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
469c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mServiceRunning) {
470257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                if (DEBUG) Log.d(TAG, "Stopping Face Unlock");
471c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
472c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    mService.stopUi();
473c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
474ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
4759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
476c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = false;
477257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            } else {
478257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // This is usually not an error when this happens.  Sometimes we will tell it to
479257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // stop multiple times because it's called from both onWindowFocusChanged and
480257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                // onDetachedFromWindow.
481257f2ecc97d294e95b069547466d2054926d960fBrian Colonna                if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
4829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
4839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
4859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
486ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
487257f2ecc97d294e95b069547466d2054926d960fBrian Colonna     * Implements the AIDL biometric unlock service callback interface.
488ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
489ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
490ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
491257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when Face Unlock wants to grant access to the user.
492ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
4939431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
4949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void unlock() {
495ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "unlock()");
496257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_UNLOCK);
4979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
4989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
499ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
500257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when the user presses cancel to skip Face Unlock or a face cannot be found.
501ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
5029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
5039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void cancel() {
504ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "cancel()");
505257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_CANCEL);
5069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
5079431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
508ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
509257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when Face Unlock denies access to the user.
510ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
5119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
5129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void reportFailedAttempt() {
513ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
514257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
5159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
5169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
517ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
518257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when the Face Unlock service starts displaying the UI, indicating that the backup
519257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * unlock can be exposed because the Face Unlock service is now covering the backup with its
520257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * UI.
521ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         **/
5229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
5239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void exposeFallback() {
524ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "exposeFallback()");
525257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
5269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
5279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
528ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
529257f2ecc97d294e95b069547466d2054926d960fBrian Colonna         * Called when Face Unlock wants to keep the screen alive and active.
530ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
5319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
5329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void pokeWakelock() {
533ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "pokeWakelock()");
534257f2ecc97d294e95b069547466d2054926d960fBrian Colonna            mHandler.sendEmptyMessage(MSG_POKE_WAKELOCK);
5359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
5369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
5379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna}
538