FaceUnlock.java revision 9431366ecb4b6e4a87c0047c36548aa0bc23f2b1
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
249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.ComponentName;
259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.Context;
269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.Intent;
279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.content.ServiceConnection;
289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.Handler;
299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.IBinder;
309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.Message;
319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.os.RemoteException;
329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.telephony.TelephonyManager;
339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.util.Log;
349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnaimport android.view.View;
359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonnapublic class FaceUnlock implements Handler.Callback {
379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final boolean DEBUG = false;
399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private static final String TAG = "FULLockscreen";
409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final Context mContext;
429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final KeyguardUpdateMonitor mUpdateMonitor;
439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private IFaceLockInterface mService;
459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mBoundToService = false;
469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private View mAreaView;
479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private Handler mHandler;
499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int MSG_SHOW_AREA_VIEW = 0;
509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int MSG_HIDE_AREA_VIEW = 1;
519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private boolean mServiceRunning = false;
539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final Object mServiceRunningLock = new Object();
549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Long enough to stay visible while dialer comes up
569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Short enough to not be visible if the user goes back immediately
579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Long enough to stay visible while the service starts
609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Short enough to not have to wait long for backup if service fails to start or crashes
619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // The service can take a couple of seconds to start on the first try after boot
629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int VIEW_AREA_SERVICE_TIMEOUT = 3000;
639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // So the user has a consistent amount of time when brought to the backup method from FaceLock
659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final int BACKUP_LOCK_TIMEOUT = 5000;
669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    /**
689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna     * Used to lookup the state of the lock pattern
699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna     */
709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final LockPatternUtils mLockPatternUtils;
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
839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void cleanUp() {
849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (mService != null) {
859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            try {
869431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService.unregisterCallback(mFaceLockCallback);
879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } catch (RemoteException e) {
889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                // Not much we can do
899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            stop();
919431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = null;
929431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
939431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    /** When screen is turned on and focused, need to bind to FaceLock service if we are using
969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna     *  FaceLock, but only if we're not dealing with a call
979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    */
989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void activateIfAble(boolean hasOverlay) {
999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
1009431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
1019431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        final boolean backupIsTimedOut =
1029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
1039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
1049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
1059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && installedAndSelected()
1069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && !hasOverlay
1079431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && !tooManyFaceUnlockTries
1089431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                && !backupIsTimedOut) {
1099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            bind();
1109431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // Show FaceLock area, but only for a little bit so lockpattern will become visible if
1129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // FaceLock fails to start or crashes
1139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            showAreaWithTimeout(VIEW_AREA_SERVICE_TIMEOUT);
1149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // When switching between portrait and landscape view while FaceLock is running, the
1169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // screen will eventually go dark unless we poke the wakelock when FaceLock is
1179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // restarted
1189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock();
1199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        } else {
1209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            hideArea();
1219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean isServiceRunning() {
1259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return mServiceRunning;
1269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public int viewAreaEmergencyDialerTimeout() {
1299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return VIEW_AREA_EMERGENCY_DIALER_TIMEOUT;
1309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Indicates whether FaceLock is in use
1339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean installedAndSelected() {
1349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return (mLockPatternUtils.usingBiometricWeak() &&
1359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mLockPatternUtils.isBiometricWeakInstalled());
1369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Takes care of FaceLock area when layout is created
1399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void initializeAreaView(View view) {
1409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
1419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mAreaView = view.findViewById(R.id.faceLockAreaView);
1429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView == null) {
1439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                Log.e(TAG, "Layout does not have areaView and FaceLock is enabled");
1449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
1459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        } else {
1469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mAreaView = null; // Set to null if not using FaceLock
1479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Stops FaceLock if it is running and reports back whether it was running or not
1519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean stopIfRunning() {
1529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected() && mBoundToService) {
1539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            stopAndUnbind();
1549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            return true;
1559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return false;
1579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
1609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // This needs to be done in a handler because the call could be coming from a callback from the
1619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // FaceLock service that is in a thread that can't modify the UI
1629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    @Override
1639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public boolean handleMessage(Message msg) {
1649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        switch (msg.what) {
1659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        case MSG_SHOW_AREA_VIEW:
1669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView != null) {
1679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mAreaView.setVisibility(View.VISIBLE);
1689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
1699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            break;
1709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        case MSG_HIDE_AREA_VIEW:
1719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView != null) {
1729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mAreaView.setVisibility(View.INVISIBLE);
1739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
1749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            break;
1759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        default:
1769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            Log.w(TAG, "Unhandled message");
1779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            return false;
1789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
1799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        return true;
1809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Removes show and hide messages from the message queue
1839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private void removeAreaDisplayMessages() {
1849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.removeMessages(MSG_SHOW_AREA_VIEW);
1859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.removeMessages(MSG_HIDE_AREA_VIEW);
1869431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Shows the FaceLock area immediately
1899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void showArea() {
1909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Remove messages to prevent a delayed hide message from undo-ing the show
1919431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        removeAreaDisplayMessages();
1929431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.sendEmptyMessage(MSG_SHOW_AREA_VIEW);
1939431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
1949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
1959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Hides the FaceLock area immediately
1969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void hideArea() {
1979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Remove messages to prevent a delayed show message from undo-ing the hide
1989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        removeAreaDisplayMessages();
1999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW);
2009431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2019431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Shows the FaceLock area for a period of time
2039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void showAreaWithTimeout(long timeoutMillis) {
2049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        showArea();
2059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis);
2069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2079431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2089431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Binds to FaceLock service.  This call does not tell it to start, but it causes the service
2099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // to call the onServiceConnected callback, which then starts FaceLock.
2109431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void bind() {
2119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
2129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (!mBoundToService) {
2139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
2149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
2159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mConnection,
2169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        Context.BIND_AUTO_CREATE);
2179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
2189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mBoundToService = true;
2199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } else {
2209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                Log.w(TAG, "Attempt to bind to FaceLock when already bound");
2219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Tells FaceLock to stop and then unbinds from the FaceLock service
2269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void stopAndUnbind() {
2279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
2289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            stop();
2299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mBoundToService) {
2319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
2329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (mService != null) {
2339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    try {
2349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mService.unregisterCallback(mFaceLockCallback);
2359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    } catch (RemoteException e) {
2369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        // Not much we can do
2379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    }
2389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
2399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mContext.unbindService(mConnection);
2409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
2419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mBoundToService = false;
2429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } else {
2439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                // This is usually not an error when this happens.  Sometimes we will tell it to
2449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                // unbind multiple times because it's called from both onWindowFocusChanged and
2459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                // onDetachedFromWindow.
2469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
2479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
2509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private ServiceConnection mConnection = new ServiceConnection() {
2529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Completes connection, registers callback and starts FaceLock when service is bound
2539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
2549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceConnected(ComponentName className, IBinder iservice) {
2559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mService = IFaceLockInterface.Stub.asInterface(iservice);
2569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
2579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            try {
2589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService.registerCallback(mFaceLockCallback);
2599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            } catch (RemoteException e) {
2609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
2619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService = null;
2629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mBoundToService = false;
2639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                return;
2649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (mAreaView != null) {
2679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                int[] position;
2689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                position = new int[2];
2699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mAreaView.getLocationInWindow(position);
2709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                start(mAreaView.getWindowToken(), position[0], position[1],
2719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mAreaView.getWidth(), mAreaView.getHeight());
2729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Cleans up if FaceLock service unexpectedly disconnects
2769431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
2779431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void onServiceDisconnected(ComponentName className) {
2789431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized(mServiceRunningLock) {
2799431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mService = null;
2809431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                mServiceRunning = false;
2819431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
2829431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mBoundToService = false;
2839431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            Log.w(TAG, "Unexpected disconnect from FaceLock service");
2849431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
2859431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
2869431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
2879431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Tells the FaceLock service to start displaying its UI and perform recognition
2889431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void start(IBinder windowToken, int x, int y, int w, int h) {
2899431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
2909431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized (mServiceRunningLock) {
2919431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (!mServiceRunning) {
2929431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    if (DEBUG) Log.d(TAG, "Starting FaceLock");
2939431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    try {
2949431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mService.startUi(windowToken, x, y, w, h);
2959431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    } catch (RemoteException e) {
2969431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
2979431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        return;
2989431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    }
2999431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    mServiceRunning = true;
3009431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                } else {
3019431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    if (DEBUG) Log.w(TAG, "start() attempted while running");
3029431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
3039431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3049431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3059431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3069431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3079431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Tells the FaceLock service to stop displaying its UI and stop recognition
3089431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    public void stop() {
3099431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        if (installedAndSelected()) {
3109431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // Note that attempting to stop FaceLock when it's not running is not an issue.
3119431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // FaceLock can return, which stops it and then we try to stop it when the
3129431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            // screen is turned off.  That's why we check.
3139431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            synchronized (mServiceRunningLock) {
3149431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                if (mServiceRunning) {
3159431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    try {
3169431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        if (DEBUG) Log.d(TAG, "Stopping FaceLock");
3179431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        mService.stopUi();
3189431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    } catch (RemoteException e) {
3199431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                        Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
3209431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    }
3219431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                    mServiceRunning = false;
3229431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna                }
3239431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            }
3249431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3259431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    }
3269431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3279431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    // Implements the FaceLock service callback interface defined in AIDL
3289431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
3299431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Stops the FaceLock UI and indicates that the phone should be unlocked
3309431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3319431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void unlock() {
3329431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock unlock()");
3339431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            showArea(); // Keep fallback covered
3349431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            stopAndUnbind();
3359431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3369431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.keyguardDone(true);
3379431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
3389431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3399431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3409431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Stops the FaceLock UI and exposes the backup method without unlocking
3419431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // This means the user has cancelled out
3429431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3439431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void cancel() {
3449431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock cancel()");
3459431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            hideArea(); // Expose fallback
3469431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            stopAndUnbind();
3479431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
3489431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3499431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3509431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Stops the FaceLock UI and exposes the backup method without unlocking
3519431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // This means FaceLock failed to recognize them
3529431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3539431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void reportFailedAttempt() {
3549431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
3559431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mUpdateMonitor.reportFailedFaceUnlockAttempt();
3569431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            hideArea(); // Expose fallback
3579431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            stopAndUnbind();
3589431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
3599431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3609431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3619431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Removes the black area that covers the backup unlock method
3629431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3639431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void exposeFallback() {
3649431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()");
3659431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            hideArea(); // Expose fallback
3669431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3679431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna
3689431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
3699431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        @Override
3709431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        public void pokeWakelock() {
3719431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()");
3729431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna            mKeyguardScreenCallback.pokeWakelock();
3739431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna        }
3749431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna    };
3759431366ecb4b6e4a87c0047c36548aa0bc23f2b1Brian Colonna}
376