FaceUnlock.java revision 3223e2537d5f4e2eceeb321405dbd6da50df66b6
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;
439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final KeyguardUpdateMonitor mUpdateMonitor;
449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private IFaceLockInterface mService;
469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mBoundToService = false;
479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private View mAreaView;
489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private Handler mHandler;
509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int MSG_SHOW_AREA_VIEW = 0;
519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int MSG_HIDE_AREA_VIEW = 1;
529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mServiceRunning = false;
549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final Object mServiceRunningLock = new Object();
559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Long enough to stay visible while the service starts
579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Short enough to not have to wait long for backup if service fails to start or crashes
589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // The service can take a couple of seconds to start on the first try after boot
599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int VIEW_AREA_SERVICE_TIMEOUT = 3000;
609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // So the user has a consistent amount of time when brought to the backup method from FaceLock
629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int BACKUP_LOCK_TIMEOUT = 5000;
639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    /**
659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna     * Used to lookup the state of the lock pattern
669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna     */
679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final LockPatternUtils mLockPatternUtils;
689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    KeyguardScreenCallback mKeyguardScreenCallback;
709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mContext = context;
749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mUpdateMonitor = updateMonitor;
759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mLockPatternUtils = lockPatternUtils;
769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mKeyguardScreenCallback = keyguardScreenCallback;
779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler = new Handler(this);
789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
803223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    // Indicates whether FaceLock is in use
813223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean installedAndSelected() {
823223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return (mLockPatternUtils.usingBiometricWeak() &&
833223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                mLockPatternUtils.isBiometricWeakInstalled());
843223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
853223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
863223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean isRunning() {
873223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return mServiceRunning;
883223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
893223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
903223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    // Shows the FaceLock area for a period of time
913223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void show(long timeoutMillis) {
923223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        showArea();
933223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (timeoutMillis > 0)
943223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis);
953223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
963223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
973223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    // Hides the FaceLock area immediately
983223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void hide() {
993223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        // Remove messages to prevent a delayed show message from undo-ing the hide
1003223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        removeAreaDisplayMessages();
1013223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW);
1023223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1033223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
1043223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    // Tells FaceLock to stop and then unbinds from the FaceLock service
1053223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean stop() {
1063223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        boolean wasRunning = false;
1073223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (installedAndSelected()) {
1083223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stopUi();
1093223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
1103223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            if (mBoundToService) {
1113223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                wasRunning = true;
1123223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
1133223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                if (mService != null) {
1143223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                    try {
1153223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                        mService.unregisterCallback(mFaceLockCallback);
1163223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                    } catch (RemoteException e) {
1173223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                        // Not much we can do
1183223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                    }
1193223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                }
1203223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                mContext.unbindService(mConnection);
1213223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
1223223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                mBoundToService = false;
1233223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            } else {
1243223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // This is usually not an error when this happens.  Sometimes we will tell it to
1253223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // unbind multiple times because it's called from both onWindowFocusChanged and
1263223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // onDetachedFromWindow.
1273223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
1289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
1299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1303223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
1313223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return wasRunning;
1329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1343223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    /**
1353223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     * When screen is turned on and focused, need to bind to FaceLock service if we are using
1363223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     * FaceLock, but only if we're not dealing with a call
1373223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna     */
1383223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public boolean start(boolean suppressBiometricUnlock) {
1399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
1409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
1419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        final boolean backupIsTimedOut =
1429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
1439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
1449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
1459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && installedAndSelected()
1463223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                && !suppressBiometricUnlock
1479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && !tooManyFaceUnlockTries
1489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && !backupIsTimedOut) {
1499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            bind();
1509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // Show FaceLock area, but only for a little bit so lockpattern will become visible if
1529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // FaceLock fails to start or crashes
1533223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            show(VIEW_AREA_SERVICE_TIMEOUT);
1549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // When switching between portrait and landscape view while FaceLock is running, the
1569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // screen will eventually go dark unless we poke the wakelock when FaceLock is
1579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // restarted
1589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock();
1599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        } else {
1603223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide();
1613223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            return false;
1629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1643223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return true;
1659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Takes care of FaceLock area when layout is created
1683223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void initializeAreaView(View topView) {
1699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
1703223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mAreaView = topView.findViewById(R.id.faceLockAreaView);
1719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView == null) {
1729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                Log.e(TAG, "Layout does not have areaView and FaceLock is enabled");
1739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
1749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        } else {
1759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mAreaView = null; // Set to null if not using FaceLock
1769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1793223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public void cleanUp() {
1803223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        if (mService != null) {
1813223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            try {
1823223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                mService.unregisterCallback(mFaceLockCallback);
1833223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            } catch (RemoteException e) {
1843223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                // Not much we can do
1853223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            }
1863223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stopUi();
1873223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            mService = null;
1889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1893223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    }
1903223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna
1913223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    public int getQuality() {
1923223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna        return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
1939431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
1969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // This needs to be done in a handler because the call could be coming from a callback from the
1979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // FaceLock service that is in a thread that can't modify the UI
1989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    @Override
1999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean handleMessage(Message msg) {
2009431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        switch (msg.what) {
2019431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        case MSG_SHOW_AREA_VIEW:
2029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView != null) {
2039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mAreaView.setVisibility(View.VISIBLE);
2049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            break;
2069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        case MSG_HIDE_AREA_VIEW:
2079431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView != null) {
2089431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mAreaView.setVisibility(View.INVISIBLE);
2099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2109431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            break;
2119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        default:
2129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            Log.w(TAG, "Unhandled message");
2139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            return false;
2149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return true;
2169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Removes show and hide messages from the message queue
2199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private void removeAreaDisplayMessages() {
2209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.removeMessages(MSG_SHOW_AREA_VIEW);
2219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.removeMessages(MSG_HIDE_AREA_VIEW);
2229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Shows the FaceLock area immediately
2253223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void showArea() {
2269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Remove messages to prevent a delayed hide message from undo-ing the show
2279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        removeAreaDisplayMessages();
2289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.sendEmptyMessage(MSG_SHOW_AREA_VIEW);
2299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Binds to FaceLock service.  This call does not tell it to start, but it causes the service
2329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // to call the onServiceConnected callback, which then starts FaceLock.
2333223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void bind() {
2349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
2359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (!mBoundToService) {
2369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
2379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
2389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mConnection,
239f882f1ad4edd790483924e7bf485fd7c7240d110Amith Yamasani                        Context.BIND_AUTO_CREATE,
240f882f1ad4edd790483924e7bf485fd7c7240d110Amith Yamasani                        mLockPatternUtils.getCurrentUser());
2419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
2429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mBoundToService = true;
2439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } else {
2449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                Log.w(TAG, "Attempt to bind to FaceLock when already bound");
2459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private ServiceConnection mConnection = new ServiceConnection() {
2509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Completes connection, registers callback and starts FaceLock when service is bound
2519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
2529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceConnected(ComponentName className, IBinder iservice) {
2539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = IFaceLockInterface.Stub.asInterface(iservice);
2549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
2559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            try {
2569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService.registerCallback(mFaceLockCallback);
2579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } catch (RemoteException e) {
2589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
2599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService = null;
2609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mBoundToService = false;
2619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                return;
2629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView != null) {
2659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                int[] position;
2669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                position = new int[2];
2679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mAreaView.getLocationInWindow(position);
2683223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                startUi(mAreaView.getWindowToken(), position[0], position[1],
2699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mAreaView.getWidth(), mAreaView.getHeight());
2709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Cleans up if FaceLock service unexpectedly disconnects
2749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
2759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceDisconnected(ComponentName className) {
2769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized(mServiceRunningLock) {
2779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService = null;
2789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mServiceRunning = false;
2799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mBoundToService = false;
2819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            Log.w(TAG, "Unexpected disconnect from FaceLock service");
2829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
2849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Tells the FaceLock service to start displaying its UI and perform recognition
2863223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void startUi(IBinder windowToken, int x, int y, int w, int h) {
2879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
2889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized (mServiceRunningLock) {
2899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (!mServiceRunning) {
2909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    if (DEBUG) Log.d(TAG, "Starting FaceLock");
2919431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    try {
292f66e930e726f4caf49b7d47c08d160b14628c99fBrian Colonna                        mService.startUi(windowToken, x, y, w, h,
293f66e930e726f4caf49b7d47c08d160b14628c99fBrian Colonna                                mLockPatternUtils.isBiometricWeakLivelinessEnabled());
2949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    } catch (RemoteException e) {
2959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
2969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        return;
2979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    }
2989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    mServiceRunning = true;
2999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                } else {
3003223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna                    if (DEBUG) Log.w(TAG, "startUi() attempted while running");
3019431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
3029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Tells the FaceLock service to stop displaying its UI and stop recognition
3073223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna    private void stopUi() {
3089431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
3099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // Note that attempting to stop FaceLock when it's not running is not an issue.
3109431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // FaceLock can return, which stops it and then we try to stop it when the
3119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // screen is turned off.  That's why we check.
3129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized (mServiceRunningLock) {
3139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (mServiceRunning) {
3149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    try {
3159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        if (DEBUG) Log.d(TAG, "Stopping FaceLock");
3169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mService.stopUi();
3179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    } catch (RemoteException e) {
3189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
3199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    }
3209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    mServiceRunning = false;
3219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
3229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Implements the FaceLock service callback interface defined in AIDL
3279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
3289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Stops the FaceLock UI and indicates that the phone should be unlocked
3299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void unlock() {
3319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock unlock()");
3329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            showArea(); // Keep fallback covered
3333223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stop();
3349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.keyguardDone(true);
3369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
3379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Stops the FaceLock UI and exposes the backup method without unlocking
3409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // This means the user has cancelled out
3419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void cancel() {
3439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock cancel()");
3443223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide(); // Expose fallback
3453223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stop();
3469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
3479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Stops the FaceLock UI and exposes the backup method without unlocking
3509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // This means FaceLock failed to recognize them
3519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void reportFailedAttempt() {
3539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
3549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mUpdateMonitor.reportFailedFaceUnlockAttempt();
3553223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide(); // Expose fallback
3563223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            stop();
3579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
3589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Removes the black area that covers the backup unlock method
3619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void exposeFallback() {
3639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()");
3643223e2537d5f4e2eceeb321405dbd6da50df66b6Brian Colonna            hide(); // Expose fallback
3659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
3689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void pokeWakelock() {
3709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()");
3719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock();
3729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
3749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna}
375