FaceUnlock.java revision ea8441e22a4316cb6e78dd8bf461d3e658545b64
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;
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;
549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int MSG_SHOW_AREA_VIEW = 0;
559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int MSG_HIDE_AREA_VIEW = 1;
569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
57ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // TODO: This was added for the purpose of adhering to what the biometric interface expects
58ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // the isRunning() function to return.  However, it is probably not necessary to have both
59ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // mRunning and mServiceRunning.  I'd just rather wait to change that logic.
60ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private boolean mIsRunning = false;
619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Long enough to stay visible while the service starts
639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Short enough to not have to wait long for backup if service fails to start or crashes
649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // The service can take a couple of seconds to start on the first try after boot
659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int VIEW_AREA_SERVICE_TIMEOUT = 3000;
669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
67ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // So the user has a consistent amount of time when brought to the backup method from Face
68ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    // Unlock
699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int BACKUP_LOCK_TIMEOUT = 5000;
709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    KeyguardScreenCallback mKeyguardScreenCallback;
739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mContext = context;
779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mUpdateMonitor = updateMonitor;
789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mLockPatternUtils = lockPatternUtils;
799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mKeyguardScreenCallback = keyguardScreenCallback;
809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler = new Handler(this);
819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
83ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
84ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Stores and displays the view that Face Unlock is allowed to draw within.
85ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * TODO: since the layout object will eventually be shared by multiple biometric unlock
86ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * methods, we will have to add our other views (background, cancel button) here.
87ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
88ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public void initializeView(View biometricUnlockView) {
89ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mFaceUnlockView = biometricUnlockView;
90ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        show(0);
91ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
92ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
93ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
94ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Indicates whether Face Unlock is currently running.
95ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
963223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean isRunning() {
97ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mIsRunning;
983223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
993223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
100ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
101ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Sets the Face Unlock view to visible, hiding it after the specified amount of time.  If
102ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * timeoutMillis is 0, no hide is performed.
103ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1043223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void show(long timeoutMillis) {
105fe444b48bac83bd5472b1102dae87661bafcfccbSteven Ross        removeAreaDisplayMessages();
106ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (mFaceUnlockView != null) {
107ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mFaceUnlockView.setVisibility(View.VISIBLE);
108ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
109ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (timeoutMillis > 0) {
1103223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis);
111ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
1123223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1133223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
114ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
115ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Hides the Face Unlock view.
116ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1173223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void hide() {
1183223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        // Remove messages to prevent a delayed show message from undo-ing the hide
1193223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        removeAreaDisplayMessages();
1203223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW);
1213223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1223223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
123ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
124ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Binds to the Face Unlock service.  Face Unlock will be started when the bind completes.  The
125ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Face Unlock area is displayed to hide the backup while the service is starting up.
126ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
127ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    public boolean start() {
128ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (mIsRunning) {
129ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "start() called when already running");
130ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
131ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
132ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
133ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock fails to start or crashes
134ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // This must show before bind to guarantee that Face Unlock has a place to display
135ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        show(VIEW_AREA_SERVICE_TIMEOUT);
136ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        if (!mBoundToService) {
137ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "before bind to Face Unlock service");
138ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
139ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mConnection,
140ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Context.BIND_AUTO_CREATE,
141ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mLockPatternUtils.getCurrentUser());
142ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "after bind to Face Unlock service");
143ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mBoundToService = true;
144ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        } else {
145ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
146ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        }
147ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
148ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // When switching between portrait and landscape view while Face Unlock is running, the
149ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // screen will eventually go dark unless we poke the wakelock when Face Unlock is
150ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // restarted
151ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mKeyguardScreenCallback.pokeWakelock();
152ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
153ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = true;
154ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return true;
155ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    }
156ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna
157ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
158ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Stops Face Unlock and unbinds from the service.
159ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
1603223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean stop() {
161ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        boolean mWasRunning = mIsRunning;
162c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        stopUi();
163c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna
164c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        if (mBoundToService) {
165ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "before unbind from Face Unlock service");
166c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mService != null) {
167c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
168ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    mService.unregisterCallback(mFaceUnlockCallback);
169c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
170c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    // Not much we can do
1713223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                }
1729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
173c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mContext.unbindService(mConnection);
174ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "after unbind from Face Unlock service");
175c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            mBoundToService = false;
176c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        } else {
177c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // This is usually not an error when this happens.  Sometimes we will tell it to
178c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // unbind multiple times because it's called from both onWindowFocusChanged and
179c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            // onDetachedFromWindow.
180ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
1819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
182ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        mIsRunning = false;
183ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        return mWasRunning;
1849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1863223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    /**
187ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Frees up resources used by Face Unlock and stops it if it is still running.
1883223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     */
1893223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void cleanUp() {
1903223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (mService != null) {
1913223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            try {
192ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mService.unregisterCallback(mFaceUnlockCallback);
1933223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            } catch (RemoteException e) {
1943223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // Not much we can do
1953223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            }
1963223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stopUi();
1973223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mService = null;
1989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1993223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
2003223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
201ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
202ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
203ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2043223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public int getQuality() {
2053223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
2069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2079431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
208ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
209ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Handles showing the Face Unlock view (hiding the backup lock) and hiding the Face Unlock view
210ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * (exposing the backup lock).  In cases where 'show' needs to happen immediately,
211ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * setVisibility() is called directly (without using this handler).  This handler is used when
212ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * 'show' needs to happen from a non-UI thread.  It also handles hide() messages since they
213ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * often require a delay.
214ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    @Override
2169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean handleMessage(Message msg) {
2179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        switch (msg.what) {
2189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        case MSG_SHOW_AREA_VIEW:
219ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (mFaceUnlockView != null) {
220ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mFaceUnlockView.setVisibility(View.VISIBLE);
221ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            }
2229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            break;
2239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        case MSG_HIDE_AREA_VIEW:
224ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (mFaceUnlockView != null) {
225ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mFaceUnlockView.setVisibility(View.INVISIBLE);
2269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            break;
2289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        default:
2299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            Log.w(TAG, "Unhandled message");
2309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            return false;
2319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return true;
2339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
235ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
236ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Removes show and hide messages from the message queue
237ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private void removeAreaDisplayMessages() {
2399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.removeMessages(MSG_SHOW_AREA_VIEW);
2409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.removeMessages(MSG_HIDE_AREA_VIEW);
2419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private ServiceConnection mConnection = new ServiceConnection() {
244ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
245ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Completes connection, registers callback, and starts Face Unlock when service is bound
246ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
2479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
2489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceConnected(ComponentName className, IBinder iservice) {
2499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = IFaceLockInterface.Stub.asInterface(iservice);
250ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "Connected to Face Unlock service");
2519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            try {
252ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mService.registerCallback(mFaceUnlockCallback);
2539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } catch (RemoteException e) {
254ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
2559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService = null;
2569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mBoundToService = false;
257ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mIsRunning = false;
2589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                return;
2599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
261ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (mFaceUnlockView != null) {
2629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                int[] position;
2639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                position = new int[2];
264ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                mFaceUnlockView.getLocationInWindow(position);
265ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                startUi(mFaceUnlockView.getWindowToken(), position[0], position[1],
266ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                        mFaceUnlockView.getWidth(), mFaceUnlockView.getHeight());
2679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
270ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
271ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Cleans up if Face Unlock service unexpectedly disconnects
272ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
2739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
2749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceDisconnected(ComponentName className) {
2759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized(mServiceRunningLock) {
2769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService = null;
2779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mServiceRunning = false;
2789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mBoundToService = false;
280ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mIsRunning = false;
281ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            Log.w(TAG, "Unexpected disconnect from Face Unlock service");
2829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
2849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
285ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
286ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Tells the Face Unlock service to start displaying its UI and perform recognition
287ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
2883223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
289c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
290c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (!mServiceRunning) {
291ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                if (DEBUG) Log.d(TAG, "Starting Face Unlock");
292c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
293c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    mService.startUi(windowToken, x, y, w, h,
294c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                            mLockPatternUtils.isBiometricWeakLivelinessEnabled());
295c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
296ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
297c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    return;
2989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
299c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = true;
300c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            } else {
301c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                if (DEBUG) Log.w(TAG, "startUi() attempted while running");
3029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
306ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
307ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Tells the Face Unlock service to stop displaying its UI and stop recognition
308ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
3093223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void stopUi() {
310ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Note that attempting to stop Face Unlock when it's not running is not an issue.
311ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        // Face Unlock can return, which stops it and then we try to stop it when the
312c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        // screen is turned off.  That's why we check.
313c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna        synchronized (mServiceRunningLock) {
314c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna            if (mServiceRunning) {
315c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                try {
316ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    if (DEBUG) Log.d(TAG, "Stopping Face Unlock");
317c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                    mService.stopUi();
318c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                } catch (RemoteException e) {
319ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna                    Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
3209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
321c169366f2cc44fc395dba76c763505ac2bd61640Brian Colonna                mServiceRunning = false;
3229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
326ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    /**
327ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     * Implements the biometric unlock service callback interface defined in AIDL
328ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna     */
329ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna    private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
330ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
331ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Stops the Face Unlock UI and indicates that the phone should be unlocked
332ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
3339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void unlock() {
335ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "unlock()");
336fe444b48bac83bd5472b1102dae87661bafcfccbSteven Ross
337fe444b48bac83bd5472b1102dae87661bafcfccbSteven Ross            // Keep fallback covered
338fe444b48bac83bd5472b1102dae87661bafcfccbSteven Ross            removeAreaDisplayMessages();
339fe444b48bac83bd5472b1102dae87661bafcfccbSteven Ross            mHandler.sendEmptyMessage(MSG_SHOW_AREA_VIEW);
340fe444b48bac83bd5472b1102dae87661bafcfccbSteven Ross
3413223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stop();
3429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.keyguardDone(true);
3449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
3459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
347ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
348ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Stops the Face Unlock UI and exposes the backup method without unlocking
349ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * This means the user has cancelled out
350ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
3519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void cancel() {
353ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "cancel()");
3543223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide(); // Expose fallback
3553223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stop();
3569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
3579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
359ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
360ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Stops the Face Unlock UI and exposes the backup method without unlocking
361ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * This means Face Unlock failed to recognize them
362ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
3639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void reportFailedAttempt() {
365ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
366ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            mUpdateMonitor.reportFailedBiometricUnlockAttempt();
3673223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide(); // Expose fallback
3683223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stop();
3699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
3709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
372ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
373ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Removes the black area that covers the backup unlock method
374ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         **/
3759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void exposeFallback() {
377ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "exposeFallback()");
3783223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide(); // Expose fallback
3799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
381ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna        /**
382ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         * Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
383ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna         */
3849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void pokeWakelock() {
386ea8441e22a4316cb6e78dd8bf461d3e658545b64Brian Colonna            if (DEBUG) Log.d(TAG, "pokeWakelock()");
3879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock();
3889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
3909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna}
391