LockPatternKeyguardView.java revision 85b10b0dd0e568699f349ba500ddc8d3e6c1c12d
11f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project/*
21f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
31f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project *
41f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
51f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * you may not use this file except in compliance with the License.
61f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * You may obtain a copy of the License at
71f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project *
81f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
91f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project *
101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
111f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * See the License for the specific language governing permissions and
141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * limitations under the License.
151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project */
161f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
171f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectpackage com.android.internal.policy.impl;
181f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1924cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport com.android.internal.R;
204ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Millerimport com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
216edf2637e96139735df83907c221cce16d4d7eaaJim Millerimport com.android.internal.policy.IFaceLockCallback;
226edf2637e96139735df83907c221cce16d4d7eaaJim Millerimport com.android.internal.policy.IFaceLockInterface;
2324cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport com.android.internal.telephony.IccCard;
2424cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport com.android.internal.widget.LockPatternUtils;
251c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport com.android.internal.widget.LockScreenWidgetCallback;
26054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkeyimport com.android.internal.widget.LockScreenWidgetInterface;
271c18828d20807342d37000746b18a3c1696f3b2eJim Millerimport com.android.internal.widget.TransportControlView;
2824cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky
2963b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackbornimport android.accounts.Account;
304e8f62fbcb4c1edf0e6ef379ad231fa74b12a248Fred Quintanaimport android.accounts.AccountManager;
3163b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackbornimport android.accounts.AccountManagerCallback;
3263b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackbornimport android.accounts.AccountManagerFuture;
3363b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackbornimport android.accounts.AuthenticatorException;
3463b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackbornimport android.accounts.OperationCanceledException;
351f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.app.AlertDialog;
36f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Millerimport android.app.admin.DevicePolicyManager;
376edf2637e96139735df83907c221cce16d4d7eaaJim Millerimport android.content.ComponentName;
381f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.content.Context;
391f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.content.Intent;
403a1837e9947505edc41d3f422bf0e0d268e349c3Jim Millerimport android.content.res.Configuration;
414ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Millerimport android.content.res.Resources;
426edf2637e96139735df83907c221cce16d4d7eaaJim Millerimport android.content.ServiceConnection;
4324cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport android.graphics.Bitmap;
4424cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport android.graphics.Canvas;
4524cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport android.graphics.ColorFilter;
4624cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport android.graphics.PixelFormat;
4724cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinskyimport android.graphics.drawable.Drawable;
48cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanzimport android.os.Bundle;
494d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonnaimport android.os.Handler;
504d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonnaimport android.os.Message;
516edf2637e96139735df83907c221cce16d4d7eaaJim Millerimport android.os.IBinder;
526edf2637e96139735df83907c221cce16d4d7eaaJim Millerimport android.os.RemoteException;
535475906f53e2d79807548932dfabbf9945143740Jim Millerimport android.os.SystemClock;
541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.os.SystemProperties;
55c23024d32779b170dde32a50fbdd945ce521b874Jim Millerimport android.telephony.TelephonyManager;
561f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.text.TextUtils;
571f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.util.Log;
584f36995777a4136e8e63ea51cef2ff61df48790dJim Millerimport android.util.Slog;
591f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.view.KeyEvent;
602e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganovimport android.view.MotionEvent;
611f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.view.View;
621f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Projectimport android.view.WindowManager;
632e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganovimport android.view.accessibility.AccessibilityManager;
641f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
6563b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackbornimport java.io.IOException;
6663b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackborn
676edf2637e96139735df83907c221cce16d4d7eaaJim Miller
681f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project/**
691f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * The host view for all of the screens of the pattern unlock screen.  There are
701f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * two {@link Mode}s of operation, lock and unlock.  This will show the appropriate
7124cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky * screen, and listen for callbacks via
7224cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky * {@link com.android.internal.policy.impl.KeyguardScreenCallback}
731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * from the current screen.
741f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project *
7524cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky * This view, in turn, communicates back to
7624cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky * {@link com.android.internal.policy.impl.KeyguardViewManager}
771f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
781f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project */
794d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonnapublic class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback {
801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
811c18828d20807342d37000746b18a3c1696f3b2eJim Miller    private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
821c18828d20807342d37000746b18a3c1696f3b2eJim Miller
8375787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn    static final boolean DEBUG_CONFIGURATION = false;
84cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana
85c23024d32779b170dde32a50fbdd945ce521b874Jim Miller    // time after launching EmergencyDialer before the screen goes blank.
86c23024d32779b170dde32a50fbdd945ce521b874Jim Miller    private static final int EMERGENCY_CALL_TIMEOUT = 10000;
87c23024d32779b170dde32a50fbdd945ce521b874Jim Miller
881f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    // intent action for launching emergency dialer activity.
891f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
901f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
911f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private static final boolean DEBUG = false;
921f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private static final String TAG = "LockPatternKeyguardView";
931f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
941f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private final KeyguardUpdateMonitor mUpdateMonitor;
951f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private final KeyguardWindowController mWindowController;
9624cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky
971f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private View mLockScreen;
981f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private View mUnlockScreen;
991f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1001f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private boolean mScreenOn = false;
10124cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky    private boolean mEnableFallback = false; // assume no fallback UI until we know better
1021f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1034ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller    private boolean mShowLockBeforeUnlock = false;
1044ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller
1056edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // The following were added to support FaceLock
1066edf2637e96139735df83907c221cce16d4d7eaaJim Miller    private IFaceLockInterface mFaceLockService;
1076edf2637e96139735df83907c221cce16d4d7eaaJim Miller    private boolean mBoundToFaceLockService = false;
1086edf2637e96139735df83907c221cce16d4d7eaaJim Miller    private View mFaceLockAreaView;
1096edf2637e96139735df83907c221cce16d4d7eaaJim Miller
1104d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    private boolean mFaceLockServiceRunning = false;
1114d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    private final Object mFaceLockServiceRunningLock = new Object();
1124d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna
1134d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    private Handler mHandler;
1144d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0;
1154d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1;
1164d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna
117eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna    // Long enough to stay black while dialer comes up
118eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna    // Short enough to not be black if the user goes back immediately
119eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna    private final int FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT = 1000;
120eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna
1211f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
1221f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * The current {@link KeyguardScreen} will use this to communicate back to us.
1231f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1241f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    KeyguardScreenCallback mKeyguardScreenCallback;
1251f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1261f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1271f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private boolean mRequiresSim;
1281f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1291f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1301f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
1311f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * Either a lock screen (an informational keyguard screen), or an unlock
1321f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * screen (a means for unlocking the device) is shown at any given time.
1331f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1341f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    enum Mode {
1351f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        LockScreen,
1361f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        UnlockScreen
1371f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
1381f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1391f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
1401f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * The different types screens available for {@link Mode#UnlockScreen}.
1411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
1421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1431f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    enum UnlockMode {
1441f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1451f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        /**
1461f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         * Unlock by drawing a pattern.
1471f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         */
1481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        Pattern,
1491f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        /**
1511f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         * Unlock by entering a sim pin.
1521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         */
1531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        SimPin,
1541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1551f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        /**
1560f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang         * Unlock by entering a sim puk.
1570f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang         */
1580f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        SimPuk,
1590f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang
1600f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        /**
1611f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         * Unlock by entering an account's login and password.
1621f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         */
1635e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        Account,
1645e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
1655e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        /**
1665e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller         * Unlock by entering a password or PIN
1675e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller         */
1680d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        Password,
1690d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller
1700d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        /**
1710d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller         * Unknown (uninitialized) value
1720d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller         */
1730d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        Unknown
1741f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
1751f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1761f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
1771f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * The current mode.
1781f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1791f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private Mode mMode = Mode.LockScreen;
1801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1811f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
18284999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen     * Keeps track of what mode the current unlock screen is (cached from most recent computation in
18384999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen     * {@link #getUnlockMode}).
1841f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1854ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller    private UnlockMode mUnlockScreenMode = UnlockMode.Unknown;
1861f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
18784999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen    private boolean mForgotPattern;
18884999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen
1891f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
1901f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * If true, it means we are in the process of verifying that the user
1911f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * can get past the lock screen per {@link #verifyUnlock()}
1921f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1931f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private boolean mIsVerifyUnlockOnly = false;
1941f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1951f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
1961f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
1971f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * Used to lookup the state of the lock pattern
1981f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
1991f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private final LockPatternUtils mLockPatternUtils;
2001f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
2011f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
2025475906f53e2d79807548932dfabbf9945143740Jim Miller     * The current configuration.
2035475906f53e2d79807548932dfabbf9945143740Jim Miller     */
2045475906f53e2d79807548932dfabbf9945143740Jim Miller    private Configuration mConfiguration;
2055475906f53e2d79807548932dfabbf9945143740Jim Miller
2061e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson    private Runnable mRecreateRunnable = new Runnable() {
2071e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson        public void run() {
20862c3efd204acdf1f7bf3bde584e2a0dfd9ca046eJim Miller            updateScreen(mMode, true);
2091e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson        }
2101e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson    };
2111e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson
2121c18828d20807342d37000746b18a3c1696f3b2eJim Miller    private LockScreenWidgetCallback mWidgetCallback = new LockScreenWidgetCallback() {
2131c18828d20807342d37000746b18a3c1696f3b2eJim Miller        public void userActivity(View self) {
2141c18828d20807342d37000746b18a3c1696f3b2eJim Miller            mKeyguardScreenCallback.pokeWakelock(TRANSPORT_USERACTIVITY_TIMEOUT);
2151c18828d20807342d37000746b18a3c1696f3b2eJim Miller        }
2161c18828d20807342d37000746b18a3c1696f3b2eJim Miller
2171c18828d20807342d37000746b18a3c1696f3b2eJim Miller        public void requestShow(View view) {
2181c18828d20807342d37000746b18a3c1696f3b2eJim Miller            if (DEBUG) Log.v(TAG, "View " + view + " requested show transports");
2191c18828d20807342d37000746b18a3c1696f3b2eJim Miller            view.setVisibility(View.VISIBLE);
220054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey
221054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey            // TODO: examine all widgets to derive clock status
222054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey            mUpdateMonitor.reportClockVisible(false);
2231c18828d20807342d37000746b18a3c1696f3b2eJim Miller        }
2241c18828d20807342d37000746b18a3c1696f3b2eJim Miller
2251c18828d20807342d37000746b18a3c1696f3b2eJim Miller        public void requestHide(View view) {
2261c18828d20807342d37000746b18a3c1696f3b2eJim Miller            if (DEBUG) Log.v(TAG, "View " + view + " requested hide transports");
2271c18828d20807342d37000746b18a3c1696f3b2eJim Miller            view.setVisibility(View.GONE);
228054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey
229054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey            // TODO: examine all widgets to derive clock status
230054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey            mUpdateMonitor.reportClockVisible(true);
2311c18828d20807342d37000746b18a3c1696f3b2eJim Miller        }
2321c18828d20807342d37000746b18a3c1696f3b2eJim Miller    };
2331c18828d20807342d37000746b18a3c1696f3b2eJim Miller
23485b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller    private TransportControlView mTransportControlView;
23585b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller
2365475906f53e2d79807548932dfabbf9945143740Jim Miller    /**
2371f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * @return Whether we are stuck on the lock screen because the sim is
2381f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     *   missing.
2391f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
2401f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private boolean stuckOnLockScreenBecauseSimMissing() {
2411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        return mRequiresSim
2421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                && (!mUpdateMonitor.isDeviceProvisioned())
243b0b24b3df50988d23f571b83d829fecc986ec497John Wang                && (mUpdateMonitor.getSimState() == IccCard.State.ABSENT ||
244b0b24b3df50988d23f571b83d829fecc986ec497John Wang                    mUpdateMonitor.getSimState() == IccCard.State.PERM_DISABLED);
2451f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
2461f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
2471f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
2481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * @param context Used to inflate, and create views.
2491f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * @param updateMonitor Knows the state of the world, and passed along to each
2501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     *   screen so they can use the knowledge, and also register for callbacks
2511f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     *   on dynamic information.
2521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * @param lockPatternUtils Used to look up state of lock pattern.
2531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
2541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public LockPatternKeyguardView(
2551f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            Context context,
2561f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            KeyguardUpdateMonitor updateMonitor,
2571f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            LockPatternUtils lockPatternUtils,
2581f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            KeyguardWindowController controller) {
2591f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        super(context);
2604e8f62fbcb4c1edf0e6ef379ad231fa74b12a248Fred Quintana
2614d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        mHandler = new Handler(this);
2625475906f53e2d79807548932dfabbf9945143740Jim Miller        mConfiguration = context.getResources().getConfiguration();
26363b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackborn        mEnableFallback = false;
2644ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
2651f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mUpdateMonitor = updateMonitor;
2661f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mLockPatternUtils = lockPatternUtils;
2671f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mWindowController = controller;
2681f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
2691f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mKeyguardScreenCallback = new KeyguardScreenCallback() {
2701f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
2711f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void goToLockScreen() {
27284999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen                mForgotPattern = false;
2731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                if (mIsVerifyUnlockOnly) {
2741f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    // navigating away from unlock screen during verify mode means
2751f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    // we are done and the user failed to authenticate.
2761f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mIsVerifyUnlockOnly = false;
2771f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    getCallback().keyguardDone(false);
2781f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                } else {
2794ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                    updateScreen(Mode.LockScreen, false);
2801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                }
2811f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
2821f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
2831f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void goToUnlockScreen() {
28476c65a66884ae1b7ab06c908632dd2a66182422cWink Saville                final IccCard.State simState = mUpdateMonitor.getSimState();
2851f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                if (stuckOnLockScreenBecauseSimMissing()
2860f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                         || (simState == IccCard.State.PUK_REQUIRED
2870f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                             && !mLockPatternUtils.isPukUnlockScreenEnable())){
2880f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    // stuck on lock screen when sim missing or
2890f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    // puk'd but puk unlock screen is disabled
2901f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    return;
2911f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                }
2921f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                if (!isSecure()) {
2931f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    getCallback().keyguardDone(true);
2941f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                } else {
2954ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                    updateScreen(Mode.UnlockScreen, false);
2961f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                }
2971f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
2981f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
29984999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen            public void forgotPattern(boolean isForgotten) {
30084999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen                if (mEnableFallback) {
30184999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen                    mForgotPattern = isForgotten;
3024ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                    updateScreen(Mode.UnlockScreen, false);
30384999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen                }
30484999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen            }
30584999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen
3061f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public boolean isSecure() {
3071f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                return LockPatternKeyguardView.this.isSecure();
3081f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3091f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public boolean isVerifyUnlockOnly() {
3111f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                return mIsVerifyUnlockOnly;
3121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3145475906f53e2d79807548932dfabbf9945143740Jim Miller            public void recreateMe(Configuration config) {
3151e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson                removeCallbacks(mRecreateRunnable);
3161e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson                post(mRecreateRunnable);
3171f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3181f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3191f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void takeEmergencyCallAction() {
320eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna                // FaceLock must be stopped if it is running when emergency call is pressed
321eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna                stopAndUnbindFromFaceLock();
322eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna
323eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna                // Delay hiding FaceLock area so unlock doesn't display while dialer is coming up
324eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna                mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW,
325eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna                        FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT);
326eef1ae1d91d55341c25d01547ac9b952be5aa658Brian Colonna
327c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                pokeWakelock(EMERGENCY_CALL_TIMEOUT);
328c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                if (TelephonyManager.getDefault().getCallState()
329c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                        == TelephonyManager.CALL_STATE_OFFHOOK) {
330c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                    mLockPatternUtils.resumeCall();
331c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                } else {
332c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                    Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
333c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
334c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
335c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                    getContext().startActivity(intent);
336c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                }
3371f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3381f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3391f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void pokeWakelock() {
3401f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                getCallback().pokeWakelock();
3411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3431f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void pokeWakelock(int millis) {
3441f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                getCallback().pokeWakelock(millis);
3451f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3461f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3471f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void keyguardDone(boolean authenticated) {
3481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                getCallback().keyguardDone(authenticated);
3491f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3511f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public void keyguardDoneDrawing() {
3521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // irrelevant to keyguard screen, they shouldn't be calling this
3531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
3541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
3550340b4299282bcbddd29b26751186431cc4af17bJim Miller            public void reportFailedUnlockAttempt() {
3561f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                mUpdateMonitor.reportFailedAttempt();
3571f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                final int failedAttempts = mUpdateMonitor.getFailedAttempts();
3584f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts +
35916541e4f88bf645408de098d1368cb49dd09e4c3Daniel Sandler                    " (enableFallback=" + mEnableFallback + ")");
3604f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
3614f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
362f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller                        == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
3634f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
3644f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
3654f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        .getMaximumFailedPasswordsForWipe(null);
3664f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
3674f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
3684f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
3694f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
3704f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
3714f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        (failedAttemptsBeforeWipe - failedAttempts)
3724f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
3734f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
3744f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
3754f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    // If we reach this code, it means the user has installed a DevicePolicyManager
3764f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    // that requests device wipe after N attempts.  Once we get below the grace
3774f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    // period, we'll post this dialog every time as a clear warning until the
3784f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    // bombshell hits and the device is wiped.
3794f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    if (remainingBeforeWipe > 0) {
3804f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
3814f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    } else {
3824f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        // Too many attempts. The device will be wiped shortly.
3834f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
3844f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        showWipeDialog(failedAttempts);
3854f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    }
3864f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                } else if (usingPattern && mEnableFallback) {
3874f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    if (failedAttempts == failedAttemptWarning) {
3884f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        showAlmostAtAccountLoginDialog();
3894f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
3904f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        mLockPatternUtils.setPermanentlyLocked(true);
3914ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                        updateScreen(mMode, false);
3924f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    }
3934f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                } else {
3944f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    final boolean showTimeout =
3954f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
3964f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    if (showTimeout) {
3974f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                        showTimeoutDialog();
3984f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                    }
3991f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                }
4000340b4299282bcbddd29b26751186431cc4af17bJim Miller                mLockPatternUtils.reportFailedPasswordAttempt();
4011f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
40224cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky
4031f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            public boolean doesFallbackUnlockScreenExist() {
40424cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky                return mEnableFallback;
4051f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
4066fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller
4076fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller            public void reportSuccessfulUnlockAttempt() {
4086fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller                mLockPatternUtils.reportSuccessfulPasswordAttempt();
4096fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller            }
4101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        };
4111f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
4121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        /**
4131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         * We'll get key events the current screen doesn't use. see
4141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         * {@link KeyguardViewBase#onKeyDown(int, android.view.KeyEvent)}
4151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project         */
4161f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        setFocusableInTouchMode(true);
4171f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
4181f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
4194ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        updateScreen(getInitialMode(), false);
42018c59475445751e9ed24cacd7cfdbf86a94412fdJim Miller        maybeEnableFallback(context);
42118c59475445751e9ed24cacd7cfdbf86a94412fdJim Miller    }
42218c59475445751e9ed24cacd7cfdbf86a94412fdJim Miller
423cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
424cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        private final AccountManager mAccountManager;
425cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        private final Account[] mAccounts;
426cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        private int mAccountIndex;
427cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz
428cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        private AccountAnalyzer(AccountManager accountManager) {
429cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            mAccountManager = accountManager;
430cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            mAccounts = accountManager.getAccountsByType("com.google");
431cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        }
432cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz
433cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        private void next() {
434cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            // if we are ready to enable the fallback or if we depleted the list of accounts
435cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            // then finish and get out
436cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
437cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                if (mUnlockScreen == null) {
43862c3efd204acdf1f7bf3bde584e2a0dfd9ca046eJim Miller                    if (DEBUG) Log.w(TAG, "no unlock screen when trying to enable fallback");
439cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                } else if (mUnlockScreen instanceof PatternUnlockScreen) {
440cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                    ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
441cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz                }
442cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                return;
443cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            }
444cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana
445cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            // lookup the confirmCredentials intent for the current account
446cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
447cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        }
448cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana
449cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        public void start() {
450cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            mEnableFallback = false;
451cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            mAccountIndex = 0;
452cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            next();
453cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        }
454cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz
455cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        public void run(AccountManagerFuture<Bundle> future) {
456cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            try {
457cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                Bundle result = future.getResult();
458cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
459cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                    mEnableFallback = true;
460cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                }
461cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            } catch (OperationCanceledException e) {
462cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                // just skip the account if we are unable to query it
463cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz            } catch (IOException e) {
464cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                // just skip the account if we are unable to query it
465cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            } catch (AuthenticatorException e) {
466cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                // just skip the account if we are unable to query it
467cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana            } finally {
468cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                mAccountIndex++;
469cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana                next();
470cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz            }
471cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz        }
472cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana    }
473cf59a0b72d3fa6bfe21b3c4cab317ef06496961eDirk Balfanz
474cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana    private void maybeEnableFallback(Context context) {
475cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        // Ask the account manager if we have an account that can be used as a
476cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        // fallback in case the user forgets his pattern.
477cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
478cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana        accountAnalyzer.start();
4791f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
4801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
4811f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
4823a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    // TODO:
4833a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    // This overloaded method was added to workaround a race condition in the framework between
4843a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    // notification for orientation changed, layout() and switching resources.  This code attempts
4853a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    // to avoid drawing the incorrect layout while things are in transition.  The method can just
4863a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    // be removed once the race condition is fixed. See bugs 2262578 and 2292713.
4873a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    @Override
4883a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    protected void dispatchDraw(Canvas canvas) {
4895475906f53e2d79807548932dfabbf9945143740Jim Miller        if (DEBUG) Log.v(TAG, "*** dispatchDraw() time: " + SystemClock.elapsedRealtime());
4903a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller        super.dispatchDraw(canvas);
4913a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller    }
4923a1837e9947505edc41d3f422bf0e0d268e349c3Jim Miller
4931f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    @Override
4941f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public void reset() {
4951f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mIsVerifyUnlockOnly = false;
49684999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen        mForgotPattern = false;
49762c3efd204acdf1f7bf3bde584e2a0dfd9ca046eJim Miller        post(mRecreateRunnable);
4981f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
4991f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5001f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    @Override
5011f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public void onScreenTurnedOff() {
5021f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mScreenOn = false;
50384999d69e0a70f5e510577b09ea1e788142252a8Karl Rosaen        mForgotPattern = false;
5041f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (mMode == Mode.LockScreen) {
5054ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mLockScreen).onPause();
5061f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else {
5071f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            ((KeyguardScreen) mUnlockScreen).onPause();
5081f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
509267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna
510267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        // When screen is turned off, need to unbind from FaceLock service if using FaceLock
511267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        stopAndUnbindFromFaceLock();
5121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
5131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    @Override
5151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public void onScreenTurnedOn() {
5161f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mScreenOn = true;
5174284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna        show();
518267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna
519267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        // When screen is turned on, need to bind to FaceLock service if we are using FaceLock
520267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        // But only if not dealing with a call
52185b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller        final boolean transportInvisible = mTransportControlView == null ? true :
52285b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller                mTransportControlView.getVisibility() != View.VISIBLE;
52385b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
52485b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller                && transportInvisible) {
525267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            bindToFaceLock();
526267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        } else {
527267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
528267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        }
5291f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
5301f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5314284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna    @Override
5324284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna    public void show() {
5334284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna        if (mMode == Mode.LockScreen) {
5344284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna            ((KeyguardScreen) mLockScreen).onResume();
5354284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna        } else {
5364284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna            ((KeyguardScreen) mUnlockScreen).onResume();
5374284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna        }
538cfdd6242eb0c26373b9c57d2ad1ddc126708189eBrian Colonna
53958396984ef49080d5550919130fc0d869ccf840bDanielle Millett        if (mLockPatternUtils.usingBiometricWeak() &&
54058396984ef49080d5550919130fc0d869ccf840bDanielle Millett                mLockPatternUtils.isBiometricWeakInstalled()) {
541cfdd6242eb0c26373b9c57d2ad1ddc126708189eBrian Colonna            mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
542cfdd6242eb0c26373b9c57d2ad1ddc126708189eBrian Colonna        } else {
543cfdd6242eb0c26373b9c57d2ad1ddc126708189eBrian Colonna            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
544cfdd6242eb0c26373b9c57d2ad1ddc126708189eBrian Colonna        }
5454284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna    }
5464284e9d19a3f917b85e5eac4d6e304fc9b866139Brian Colonna
5470d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller    private void recreateLockScreen() {
5484ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (mLockScreen != null) {
54962c3efd204acdf1f7bf3bde584e2a0dfd9ca046eJim Miller            ((KeyguardScreen) mLockScreen).onPause();
5504ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mLockScreen).cleanUp();
5514ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            removeView(mLockScreen);
5521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
5531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mLockScreen = createLockScreen();
5551f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mLockScreen.setVisibility(View.INVISIBLE);
5561f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        addView(mLockScreen);
5570d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller    }
5581f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5594ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller    private void recreateUnlockScreen(UnlockMode unlockMode) {
5604ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (mUnlockScreen != null) {
56162c3efd204acdf1f7bf3bde584e2a0dfd9ca046eJim Miller            ((KeyguardScreen) mUnlockScreen).onPause();
5624ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mUnlockScreen).cleanUp();
5634ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            removeView(mUnlockScreen);
5641f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
5651f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5661f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mUnlockScreen = createUnlockScreenFor(unlockMode);
5671f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mUnlockScreen.setVisibility(View.INVISIBLE);
5681f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        addView(mUnlockScreen);
5690d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller    }
5701f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
5711f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    @Override
5721e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson    protected void onDetachedFromWindow() {
5731e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson        removeCallbacks(mRecreateRunnable);
574267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna
575267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        // When view is hidden, need to unbind from FaceLock service if we are using FaceLock
576267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        // e.g., when device becomes unlocked
577267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        stopAndUnbindFromFaceLock();
578267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna
5791e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson        super.onDetachedFromWindow();
5801e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson    }
5811e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson
5821c18828d20807342d37000746b18a3c1696f3b2eJim Miller    protected void onConfigurationChanged(Configuration newConfig) {
5831c18828d20807342d37000746b18a3c1696f3b2eJim Miller        Resources resources = getResources();
5841c18828d20807342d37000746b18a3c1696f3b2eJim Miller        mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
5851c18828d20807342d37000746b18a3c1696f3b2eJim Miller        mConfiguration = newConfig;
5861c18828d20807342d37000746b18a3c1696f3b2eJim Miller        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
58751e9d5c635b8882c1947122f1aa7e820d3a5f287Adam Cohen        removeCallbacks(mRecreateRunnable);
58851e9d5c635b8882c1947122f1aa7e820d3a5f287Adam Cohen        post(mRecreateRunnable);
5891c18828d20807342d37000746b18a3c1696f3b2eJim Miller    }
5901c18828d20807342d37000746b18a3c1696f3b2eJim Miller
5911e0c7ae184984051e8f42c71f89435fc1d40be35Kenneth Andersson    @Override
5922e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov    protected boolean dispatchHoverEvent(MotionEvent event) {
5932e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        // Do not let the screen to get locked while the user is disabled and touch
5942e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        // exploring. A blind user will need significantly more time to find and
5952e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        // interact with the lock screen views.
5962e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
5972e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        if (accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled()) {
5982e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov            getCallback().pokeWakelock();
5992e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        }
6002e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov        return super.dispatchHoverEvent(event);
6012e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov    }
6022e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov
6032e1db30d18a0ff6640bb0ad61f922ec1fdcf5a3cSvetoslav Ganov    @Override
6041f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public void wakeWhenReadyTq(int keyCode) {
6051f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (DEBUG) Log.d(TAG, "onWakeKey");
6061f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (keyCode == KeyEvent.KEYCODE_MENU && isSecure() && (mMode == Mode.LockScreen)
60776c65a66884ae1b7ab06c908632dd2a66182422cWink Saville                && (mUpdateMonitor.getSimState() != IccCard.State.PUK_REQUIRED)) {
6081f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
6094ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            updateScreen(Mode.UnlockScreen, false);
6101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            getCallback().pokeWakelock();
6111f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else {
6121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            if (DEBUG) Log.d(TAG, "poking wake lock immediately");
6131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            getCallback().pokeWakelock();
6141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
6151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
6161f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
6171f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    @Override
6181f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public void verifyUnlock() {
6191f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (!isSecure()) {
6201f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            // non-secure keyguard screens are successfull by default
6211f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            getCallback().keyguardDone(true);
6224ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        } else if (mUnlockScreenMode != UnlockMode.Pattern
6234ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                && mUnlockScreenMode != UnlockMode.Password) {
6244ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            // can only verify unlock when in pattern/password mode
6251f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            getCallback().keyguardDone(false);
6261f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else {
6271f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            // otherwise, go to the unlock screen, see if they can verify it
6281f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            mIsVerifyUnlockOnly = true;
6294ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            updateScreen(Mode.UnlockScreen, false);
6301f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
6311f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
6321f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
6331f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    @Override
6341f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    public void cleanUp() {
6354ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (mLockScreen != null) {
6364ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mLockScreen).onPause();
6374ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mLockScreen).cleanUp();
6384ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            this.removeView(mLockScreen);
6394ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            mLockScreen = null;
6404ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        }
6414ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (mUnlockScreen != null) {
6424ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mUnlockScreen).onPause();
6434ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            ((KeyguardScreen) mUnlockScreen).cleanUp();
6444ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            this.removeView(mUnlockScreen);
6454ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            mUnlockScreen = null;
6464ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        }
6471f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
6481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
6491f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private boolean isSecure() {
6501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        UnlockMode unlockMode = getUnlockMode();
6515e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        boolean secure = false;
6525e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        switch (unlockMode) {
6535e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            case Pattern:
6545e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                secure = mLockPatternUtils.isLockPatternEnabled();
6555e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                break;
6565e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            case SimPin:
6570f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                secure = mUpdateMonitor.getSimState() == IccCard.State.PIN_REQUIRED;
6580f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                break;
6590f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang            case SimPuk:
6600f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                secure = mUpdateMonitor.getSimState() == IccCard.State.PUK_REQUIRED;
6615e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                break;
6625e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            case Account:
6635e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                secure = true;
6645e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                break;
6655e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            case Password:
6665e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                secure = mLockPatternUtils.isLockPasswordEnabled();
6675e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                break;
6685e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            default:
6695e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                throw new IllegalStateException("unknown unlock mode " + unlockMode);
6701f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
6715e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        return secure;
6721f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
6731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
6744ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller    private void updateScreen(Mode mode, boolean force) {
6751f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
67675787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn        if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
67762c3efd204acdf1f7bf3bde584e2a0dfd9ca046eJim Miller                + " last mode=" + mMode + ", force = " + force, new RuntimeException());
678cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana
6791f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mMode = mode;
6801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
6814ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        // Re-create the lock screen if necessary
6824ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
6834ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            if (force || mLockScreen == null) {
6844ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                recreateLockScreen();
6854ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            }
6864ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        }
6874ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller
6880d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        // Re-create the unlock screen if necessary. This is primarily required to properly handle
6890d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        // SIM state changes. This typically happens when this method is called by reset()
6904ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (mode == Mode.UnlockScreen) {
6914ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            final UnlockMode unlockMode = getUnlockMode();
6924ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
6934ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                recreateUnlockScreen(unlockMode);
6944ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            }
6950d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        }
6960d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller
6974ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        // visibleScreen should never be null
6981f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
69942b432d84cd3bf860a03a10e9191738e05f2eaddJim Miller        final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
7001f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
7011f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        // do this before changing visibility so focus isn't requested before the input
7021f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        // flag is set
7031f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());
70424cfa450fa46a333ea9fa7de20a8755e592e1bedIlia Tulchinsky
70575787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn        if (DEBUG_CONFIGURATION) {
70675787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn            Log.v(TAG, "Gone=" + goneScreen);
70775787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn            Log.v(TAG, "Visible=" + visibleScreen);
70875787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn        }
709cd8aed8c503ee37fa36b7d14744c9d0271faf12dFred Quintana
7101f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (mScreenOn) {
7114ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            if (goneScreen != null && goneScreen.getVisibility() == View.VISIBLE) {
7121f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                ((KeyguardScreen) goneScreen).onPause();
7131f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
7141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            if (visibleScreen.getVisibility() != View.VISIBLE) {
7151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                ((KeyguardScreen) visibleScreen).onResume();
7161f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
7171f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
7181f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
7194ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        if (goneScreen != null) {
7204ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            goneScreen.setVisibility(View.GONE);
7214ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        }
7221f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        visibleScreen.setVisibility(View.VISIBLE);
72375787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn        requestLayout();
7241f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
7251f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (!visibleScreen.requestFocus()) {
7261f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            throw new IllegalStateException("keyguard screen must be able to take "
7271f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    + "focus when shown " + visibleScreen.getClass().getCanonicalName());
7281f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
7291f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
7301f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
7311f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    View createLockScreen() {
7321c18828d20807342d37000746b18a3c1696f3b2eJim Miller        View lockView = new LockScreen(
7331f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                mContext,
7345475906f53e2d79807548932dfabbf9945143740Jim Miller                mConfiguration,
7351f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                mLockPatternUtils,
7361f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                mUpdateMonitor,
7371f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                mKeyguardScreenCallback);
7381c18828d20807342d37000746b18a3c1696f3b2eJim Miller        initializeTransportControlView(lockView);
7391c18828d20807342d37000746b18a3c1696f3b2eJim Miller        return lockView;
7401f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
7411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
7421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    View createUnlockScreenFor(UnlockMode unlockMode) {
7430d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        View unlockView = null;
7440f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang
7450f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        if (DEBUG) Log.d(TAG,
7460f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
7470f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang
7481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        if (unlockMode == UnlockMode.Pattern) {
74942b432d84cd3bf860a03a10e9191738e05f2eaddJim Miller            PatternUnlockScreen view = new PatternUnlockScreen(
7501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mContext,
7515475906f53e2d79807548932dfabbf9945143740Jim Miller                    mConfiguration,
7521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mLockPatternUtils,
7531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mUpdateMonitor,
7541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mKeyguardScreenCallback,
75563b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackborn                    mUpdateMonitor.getFailedAttempts());
75663b90f28858b9d259a1d4a145f51bdd36ada8730Dianne Hackborn            view.setEnableFallback(mEnableFallback);
7570d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller            unlockView = view;
7580f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        } else if (unlockMode == UnlockMode.SimPuk) {
7590f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang            unlockView = new SimPukUnlockScreen(
7600f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    mContext,
7610f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    mConfiguration,
7620f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    mUpdateMonitor,
7630f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    mKeyguardScreenCallback,
7640f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                    mLockPatternUtils);
7651f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else if (unlockMode == UnlockMode.SimPin) {
7660d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller            unlockView = new SimUnlockScreen(
7671f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mContext,
7685475906f53e2d79807548932dfabbf9945143740Jim Miller                    mConfiguration,
7691f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mUpdateMonitor,
770c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                    mKeyguardScreenCallback,
771c23024d32779b170dde32a50fbdd945ce521b874Jim Miller                    mLockPatternUtils);
7721f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else if (unlockMode == UnlockMode.Account) {
7731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            try {
7740d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller                unlockView = new AccountUnlockScreen(
7751f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                        mContext,
7765475906f53e2d79807548932dfabbf9945143740Jim Miller                        mConfiguration,
777ecaced9a788910b3517bdab08b382c9d45e34dfeJim Miller                        mUpdateMonitor,
7781f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                        mKeyguardScreenCallback,
7791f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                        mLockPatternUtils);
7801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            } catch (IllegalStateException e) {
7811f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                Log.i(TAG, "Couldn't instantiate AccountUnlockScreen"
7821f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                      + " (IAccountsService isn't available)");
7831f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // TODO: Need a more general way to provide a
7841f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // platform-specific fallback UI here.
7851f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // For now, if we can't display the account login
7861f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // unlock UI, just bring back the regular "Pattern" unlock mode.
7871f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
7881f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // (We do this by simply returning a regular UnlockScreen
7891f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // here.  This means that the user will still see the
7901f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // regular pattern unlock UI, regardless of the value of
7911f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // mUnlockScreenMode or whether or not we're in the
7921f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                // "permanently locked" state.)
7934ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                return createUnlockScreenFor(UnlockMode.Pattern);
7941f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            }
7955e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        } else if (unlockMode == UnlockMode.Password) {
7960d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller            unlockView = new PasswordUnlockScreen(
7975e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    mContext,
7985475906f53e2d79807548932dfabbf9945143740Jim Miller                    mConfiguration,
7995e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    mLockPatternUtils,
8005e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    mUpdateMonitor,
8015e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    mKeyguardScreenCallback);
8021f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else {
8031f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
8041f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
8051c18828d20807342d37000746b18a3c1696f3b2eJim Miller        initializeTransportControlView(unlockView);
8064d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabled
8074d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna
8084ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller        mUnlockScreenMode = unlockMode;
8090d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller        return unlockView;
8100d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller    }
8110d9f798e9f76b13b07ac3dee3ff90b5530f53145Jim Miller
8121c18828d20807342d37000746b18a3c1696f3b2eJim Miller    private void initializeTransportControlView(View view) {
81385b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller        mTransportControlView = (TransportControlView) view.findViewById(R.id.transport);
81485b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller        if (mTransportControlView == null) {
8151c18828d20807342d37000746b18a3c1696f3b2eJim Miller            if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
8161c18828d20807342d37000746b18a3c1696f3b2eJim Miller        } else {
817054340d0a3f242efeaf898cca38625bdcb3b4b5aJeff Sharkey            mUpdateMonitor.reportClockVisible(true);
81885b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller            mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown.
81985b10b0dd0e568699f349ba500ddc8d3e6c1c12dJim Miller            mTransportControlView.setCallback(mWidgetCallback);
8201c18828d20807342d37000746b18a3c1696f3b2eJim Miller        }
8211c18828d20807342d37000746b18a3c1696f3b2eJim Miller    }
8221c18828d20807342d37000746b18a3c1696f3b2eJim Miller
8231f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
8241f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * Given the current state of things, what should be the initial mode of
8251f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * the lock screen (lock or unlock).
8261f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
8271f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private Mode getInitialMode() {
82876c65a66884ae1b7ab06c908632dd2a66182422cWink Saville        final IccCard.State simState = mUpdateMonitor.getSimState();
8290f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        if (stuckOnLockScreenBecauseSimMissing() ||
8300f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                (simState == IccCard.State.PUK_REQUIRED &&
8310f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang                        !mLockPatternUtils.isPukUnlockScreenEnable())) {
8321f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            return Mode.LockScreen;
8331f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else {
8344ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            if (!isSecure() || mShowLockBeforeUnlock) {
835466d77617ace8380ab8c52ede20790755d8ff092Jim Miller                return Mode.LockScreen;
8364ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller            } else {
8374ae8cb9e73b3b516434c9dc26fcc9697daff851dJim Miller                return Mode.UnlockScreen;
838466d77617ace8380ab8c52ede20790755d8ff092Jim Miller            }
8391f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
8401f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
8411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
8421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
8431f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     * Given the current state of things, what should the unlock screen be?
8441f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
8451f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private UnlockMode getUnlockMode() {
84676c65a66884ae1b7ab06c908632dd2a66182422cWink Saville        final IccCard.State simState = mUpdateMonitor.getSimState();
8475e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        UnlockMode currentMode;
8480f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        if (simState == IccCard.State.PIN_REQUIRED) {
8495e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            currentMode = UnlockMode.SimPin;
8500f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang        } else if (simState == IccCard.State.PUK_REQUIRED) {
8510f7b3f8ba5c2f0b8f96e072bd866c9fb374ebdebJohn Wang            currentMode = UnlockMode.SimPuk;
8521f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        } else {
853f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller            final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
8545e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            switch (mode) {
855f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
856f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
857f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
858a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
8595e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    currentMode = UnlockMode.Password;
8605e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    break;
861f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
862f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
8635e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    // "forgot pattern" button is only available in the pattern mode...
8640340b4299282bcbddd29b26751186431cc4af17bJim Miller                    if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) {
8655e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                        currentMode = UnlockMode.Account;
8665e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    } else {
8675e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                        currentMode = UnlockMode.Pattern;
8685e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    }
8695e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                    break;
8705e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                default:
8715e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller                   throw new IllegalStateException("Unknown unlock mode:" + mode);
8725e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            }
8731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
8745e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        return currentMode;
8751f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
8761f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
8774f36995777a4136e8e63ea51cef2ff61df48790dJim Miller    private void showDialog(String title, String message) {
8784f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        final AlertDialog dialog = new AlertDialog.Builder(mContext)
8794f36995777a4136e8e63ea51cef2ff61df48790dJim Miller            .setTitle(title)
8804f36995777a4136e8e63ea51cef2ff61df48790dJim Miller            .setMessage(message)
8814f36995777a4136e8e63ea51cef2ff61df48790dJim Miller            .setNeutralButton(R.string.ok, null)
8824f36995777a4136e8e63ea51cef2ff61df48790dJim Miller            .create();
8834f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
8844f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        dialog.show();
8854f36995777a4136e8e63ea51cef2ff61df48790dJim Miller    }
8864f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
8871f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private void showTimeoutDialog() {
8881f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
8898171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung        int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message;
8904f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        if (getUnlockMode() == UnlockMode.Password) {
891c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev            if(mLockPatternUtils.getKeyguardStoredPasswordQuality() ==
892c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
893c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev                messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message;
894c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev            } else {
895c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev                messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message;
896c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev            }
897c15dcf7ea1421305a54f256777212373c28c53c0Konstantin Lopyrev        }
8984f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(),
8991f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                timeoutInSeconds);
90067403e096e6f59b7cd18a90d0d3f5c3d17c31407Mathias Agopian
9014f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        showDialog(null, message);
9021f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
9031f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9041f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    private void showAlmostAtAccountLoginDialog() {
9054f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
9064f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
9074f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
9084f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        String message = mContext.getString(R.string.lockscreen_failed_attempts_almost_glogin,
9094f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
9104f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        showDialog(null, message);
9114f36995777a4136e8e63ea51cef2ff61df48790dJim Miller    }
9124f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
9134f36995777a4136e8e63ea51cef2ff61df48790dJim Miller    private void showAlmostAtWipeDialog(int attempts, int remaining) {
9141f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
9151f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        String message = mContext.getString(
9164f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining);
9174f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        showDialog(null, message);
9184f36995777a4136e8e63ea51cef2ff61df48790dJim Miller    }
9194f36995777a4136e8e63ea51cef2ff61df48790dJim Miller
9204f36995777a4136e8e63ea51cef2ff61df48790dJim Miller    private void showWipeDialog(int attempts) {
9214f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        String message = mContext.getString(
9224f36995777a4136e8e63ea51cef2ff61df48790dJim Miller                R.string.lockscreen_failed_attempts_now_wiping, attempts);
9234f36995777a4136e8e63ea51cef2ff61df48790dJim Miller        showDialog(null, message);
9241f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
9251f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9261f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    /**
927c4d9d21009db7b977a2201f6760d78786be3028dDianne Hackborn     * Used to put wallpaper on the background of the lock screen.  Centers it
928c4d9d21009db7b977a2201f6760d78786be3028dDianne Hackborn     * Horizontally and pins the bottom (assuming that the lock screen is aligned
929c4d9d21009db7b977a2201f6760d78786be3028dDianne Hackborn     * with the bottom, so the wallpaper should extend above the top into the
930c4d9d21009db7b977a2201f6760d78786be3028dDianne Hackborn     * status bar).
9311f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project     */
9321f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    static private class FastBitmapDrawable extends Drawable {
9331f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        private Bitmap mBitmap;
9349593e0a0073d77ab65cc97156da4d0e890e4cf27Romain Guy        private int mOpacity;
9351f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9361f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        private FastBitmapDrawable(Bitmap bitmap) {
9371f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            mBitmap = bitmap;
9389593e0a0073d77ab65cc97156da4d0e890e4cf27Romain Guy            mOpacity = mBitmap.hasAlpha() ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
9391f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9401f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9411f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9421f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public void draw(Canvas canvas) {
9431f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            canvas.drawBitmap(
9441f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    mBitmap,
9451f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    (getBounds().width() - mBitmap.getWidth()) / 2,
946c4d9d21009db7b977a2201f6760d78786be3028dDianne Hackborn                    (getBounds().height() - mBitmap.getHeight()),
9471f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project                    null);
9481f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9491f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9501f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9511f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public int getOpacity() {
9529593e0a0073d77ab65cc97156da4d0e890e4cf27Romain Guy            return mOpacity;
9531f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9541f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9551f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9561f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public void setAlpha(int alpha) {
9571f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9581f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9591f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9601f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public void setColorFilter(ColorFilter cf) {
9611f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9621f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9631f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9641f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public int getIntrinsicWidth() {
9651f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            return mBitmap.getWidth();
9661f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9671f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9681f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9691f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public int getIntrinsicHeight() {
9701f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            return mBitmap.getHeight();
9711f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9721f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9731f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9741f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public int getMinimumWidth() {
9751f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            return mBitmap.getWidth();
9761f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9771f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project
9781f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        @Override
9791f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        public int getMinimumHeight() {
9801f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project            return mBitmap.getHeight();
9811f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project        }
9821f838aaece3cd61d07ab9e41c5c6af761d643324The Android Open Source Project    }
98376c65a66884ae1b7ab06c908632dd2a66182422cWink Saville
9846edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // Everything below pertains to FaceLock - might want to separate this out
9856edf2637e96139735df83907c221cce16d4d7eaaJim Miller
9864d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    // Only pattern and pin unlock screens actually have a view for the FaceLock area, so it's not
987267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna    // uncommon for it to not exist.  But if it does exist, we need to make sure it's shown (hiding
988267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna    // the fallback) if FaceLock is enabled, and make sure it's hidden (showing the unlock) if
989267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna    // FaceLock is disabled
9904d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    private void initializeFaceLockAreaView(View view) {
9914d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView);
9924d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        if (mFaceLockAreaView == null) {
9934d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            if (DEBUG) Log.d(TAG, "Layout does not have faceLockAreaView");
9944d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        }
9954d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    }
9964d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna
9974d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
9984d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    // This needs to be done in a handler because the call could be coming from a callback from the
9994d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    // FaceLock service that is in a thread that can't modify the UI
10004d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    @Override
10014d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    public boolean handleMessage(Message msg) {
10024d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        switch (msg.what) {
10034d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        case MSG_SHOW_FACELOCK_AREA_VIEW:
1004b9a4b3c18aa0094bbbbc2858c765fb4aeafdee67Justin Ho            if (mFaceLockAreaView != null) {
1005b9a4b3c18aa0094bbbbc2858c765fb4aeafdee67Justin Ho                mFaceLockAreaView.setVisibility(View.VISIBLE);
1006b9a4b3c18aa0094bbbbc2858c765fb4aeafdee67Justin Ho            }
10074d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            break;
10084d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        case MSG_HIDE_FACELOCK_AREA_VIEW:
1009b9a4b3c18aa0094bbbbc2858c765fb4aeafdee67Justin Ho            if (mFaceLockAreaView != null) {
1010b9a4b3c18aa0094bbbbc2858c765fb4aeafdee67Justin Ho                mFaceLockAreaView.setVisibility(View.GONE);
1011b9a4b3c18aa0094bbbbc2858c765fb4aeafdee67Justin Ho            }
10124d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            break;
10134d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        default:
10144d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            Log.w(TAG, "Unhandled message");
10154d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            return false;
10164d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        }
10174d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna        return true;
10184d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna    }
10194d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna
10206edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // Binds to FaceLock service, but does not tell it to start
10216edf2637e96139735df83907c221cce16d4d7eaaJim Miller    public void bindToFaceLock() {
102258396984ef49080d5550919130fc0d869ccf840bDanielle Millett        if (mLockPatternUtils.usingBiometricWeak() &&
102358396984ef49080d5550919130fc0d869ccf840bDanielle Millett                mLockPatternUtils.isBiometricWeakInstalled()) {
10246edf2637e96139735df83907c221cce16d4d7eaaJim Miller            if (!mBoundToFaceLockService) {
10256edf2637e96139735df83907c221cce16d4d7eaaJim Miller                if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
10266edf2637e96139735df83907c221cce16d4d7eaaJim Miller                mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
10276edf2637e96139735df83907c221cce16d4d7eaaJim Miller                        mFaceLockConnection,
10286edf2637e96139735df83907c221cce16d4d7eaaJim Miller                        Context.BIND_AUTO_CREATE);
10296edf2637e96139735df83907c221cce16d4d7eaaJim Miller                if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
10306edf2637e96139735df83907c221cce16d4d7eaaJim Miller                mBoundToFaceLockService = true;
10316edf2637e96139735df83907c221cce16d4d7eaaJim Miller            } else {
1032267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna                Log.w(TAG, "Attempt to bind to FaceLock when already bound");
10336edf2637e96139735df83907c221cce16d4d7eaaJim Miller            }
10346edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
10356edf2637e96139735df83907c221cce16d4d7eaaJim Miller    }
10366edf2637e96139735df83907c221cce16d4d7eaaJim Miller
10376edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // Tells FaceLock to stop and then unbinds from the FaceLock service
10386edf2637e96139735df83907c221cce16d4d7eaaJim Miller    public void stopAndUnbindFromFaceLock() {
103958396984ef49080d5550919130fc0d869ccf840bDanielle Millett        if (mLockPatternUtils.usingBiometricWeak() &&
104058396984ef49080d5550919130fc0d869ccf840bDanielle Millett                mLockPatternUtils.isBiometricWeakInstalled()) {
10416edf2637e96139735df83907c221cce16d4d7eaaJim Miller            stopFaceLock();
10426edf2637e96139735df83907c221cce16d4d7eaaJim Miller
10436edf2637e96139735df83907c221cce16d4d7eaaJim Miller            if (mBoundToFaceLockService) {
10446edf2637e96139735df83907c221cce16d4d7eaaJim Miller                if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
10456edf2637e96139735df83907c221cce16d4d7eaaJim Miller                mContext.unbindService(mFaceLockConnection);
10466edf2637e96139735df83907c221cce16d4d7eaaJim Miller                if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
10476edf2637e96139735df83907c221cce16d4d7eaaJim Miller                mBoundToFaceLockService = false;
10486edf2637e96139735df83907c221cce16d4d7eaaJim Miller            } else {
10496edf2637e96139735df83907c221cce16d4d7eaaJim Miller                // This could probably happen after the session when someone activates FaceLock
10506edf2637e96139735df83907c221cce16d4d7eaaJim Miller                // because it wasn't active when the phone was turned on
1051267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna                Log.w(TAG, "Attempt to unbind from FaceLock when not bound");
10526edf2637e96139735df83907c221cce16d4d7eaaJim Miller            }
10536edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
10546edf2637e96139735df83907c221cce16d4d7eaaJim Miller    }
10556edf2637e96139735df83907c221cce16d4d7eaaJim Miller
10566edf2637e96139735df83907c221cce16d4d7eaaJim Miller    private ServiceConnection mFaceLockConnection = new ServiceConnection() {
10576edf2637e96139735df83907c221cce16d4d7eaaJim Miller        // Completes connection, registers callback and starts FaceLock when service is bound
10586edf2637e96139735df83907c221cce16d4d7eaaJim Miller        @Override
10596edf2637e96139735df83907c221cce16d4d7eaaJim Miller        public void onServiceConnected(ComponentName className, IBinder iservice) {
10606edf2637e96139735df83907c221cce16d4d7eaaJim Miller            mFaceLockService = IFaceLockInterface.Stub.asInterface(iservice);
10616edf2637e96139735df83907c221cce16d4d7eaaJim Miller            if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
10626edf2637e96139735df83907c221cce16d4d7eaaJim Miller            try {
10636edf2637e96139735df83907c221cce16d4d7eaaJim Miller                mFaceLockService.registerCallback(mFaceLockCallback);
10646edf2637e96139735df83907c221cce16d4d7eaaJim Miller            } catch (RemoteException e) {
10656edf2637e96139735df83907c221cce16d4d7eaaJim Miller                throw new RuntimeException("Remote exception");
10666edf2637e96139735df83907c221cce16d4d7eaaJim Miller            }
10676edf2637e96139735df83907c221cce16d4d7eaaJim Miller
10686edf2637e96139735df83907c221cce16d4d7eaaJim Miller            if (mFaceLockAreaView != null) {
10694d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                startFaceLock(mFaceLockAreaView.getWindowToken(),
10704d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        mFaceLockAreaView.getLeft(), mFaceLockAreaView.getTop(),
10714d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        mFaceLockAreaView.getWidth(), mFaceLockAreaView.getHeight());
10726edf2637e96139735df83907c221cce16d4d7eaaJim Miller            }
10736edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
10746edf2637e96139735df83907c221cce16d4d7eaaJim Miller
10756edf2637e96139735df83907c221cce16d4d7eaaJim Miller        // Cleans up if FaceLock service unexpectedly disconnects
10766edf2637e96139735df83907c221cce16d4d7eaaJim Miller        @Override
10776edf2637e96139735df83907c221cce16d4d7eaaJim Miller        public void onServiceDisconnected(ComponentName className) {
10784d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            synchronized(mFaceLockServiceRunningLock) {
10794d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                mFaceLockService = null;
10804d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                mFaceLockServiceRunning = false;
10814d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            }
1082267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            Log.w(TAG, "Unexpected disconnect from FaceLock service");
10836edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
10846edf2637e96139735df83907c221cce16d4d7eaaJim Miller    };
10856edf2637e96139735df83907c221cce16d4d7eaaJim Miller
10866edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // Tells the FaceLock service to start displaying its UI and perform recognition
10876edf2637e96139735df83907c221cce16d4d7eaaJim Miller    public void startFaceLock(IBinder windowToken, int x, int y, int h, int w)
10886edf2637e96139735df83907c221cce16d4d7eaaJim Miller    {
108958396984ef49080d5550919130fc0d869ccf840bDanielle Millett        if (mLockPatternUtils.usingBiometricWeak() &&
109058396984ef49080d5550919130fc0d869ccf840bDanielle Millett                mLockPatternUtils.isBiometricWeakInstalled()) {
10914d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            synchronized (mFaceLockServiceRunningLock) {
10924d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                if (!mFaceLockServiceRunning) {
10934d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    if (DEBUG) Log.d(TAG, "Starting FaceLock");
10944d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    try {
10954d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        mFaceLockService.startUi(windowToken, x, y, h, w);
10964d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    } catch (RemoteException e) {
10974d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        throw new RuntimeException("Remote exception");
10984d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    }
10994d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    mFaceLockServiceRunning = true;
11004d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                } else {
11014d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    if (DEBUG) Log.w(TAG, "startFaceLock() attempted while running");
11026edf2637e96139735df83907c221cce16d4d7eaaJim Miller                }
11036edf2637e96139735df83907c221cce16d4d7eaaJim Miller            }
11046edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
11056edf2637e96139735df83907c221cce16d4d7eaaJim Miller    }
11066edf2637e96139735df83907c221cce16d4d7eaaJim Miller
11076edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // Tells the FaceLock service to stop displaying its UI and stop recognition
11086edf2637e96139735df83907c221cce16d4d7eaaJim Miller    public void stopFaceLock()
11096edf2637e96139735df83907c221cce16d4d7eaaJim Miller    {
111058396984ef49080d5550919130fc0d869ccf840bDanielle Millett        if (mLockPatternUtils.usingBiometricWeak() &&
111158396984ef49080d5550919130fc0d869ccf840bDanielle Millett                mLockPatternUtils.isBiometricWeakInstalled()) {
11126edf2637e96139735df83907c221cce16d4d7eaaJim Miller            // Note that attempting to stop FaceLock when it's not running is not an issue.
11136edf2637e96139735df83907c221cce16d4d7eaaJim Miller            // FaceLock can return, which stops it and then we try to stop it when the
11146edf2637e96139735df83907c221cce16d4d7eaaJim Miller            // screen is turned off.  That's why we check.
11154d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna            synchronized (mFaceLockServiceRunningLock) {
11164d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                if (mFaceLockServiceRunning) {
11174d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    try {
11184d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        if (DEBUG) Log.d(TAG, "Stopping FaceLock");
11194d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        mFaceLockService.stopUi();
11204d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    } catch (RemoteException e) {
11214d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                        throw new RuntimeException("Remote exception");
11224d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    }
11234d7cee1e4b9ed17da8fc041be80369eb525901f1Brian Colonna                    mFaceLockServiceRunning = false;
11246edf2637e96139735df83907c221cce16d4d7eaaJim Miller                }
11256edf2637e96139735df83907c221cce16d4d7eaaJim Miller            }
11266edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
11276edf2637e96139735df83907c221cce16d4d7eaaJim Miller    }
11286edf2637e96139735df83907c221cce16d4d7eaaJim Miller
11296edf2637e96139735df83907c221cce16d4d7eaaJim Miller    // Implements the FaceLock service callback interface defined in AIDL
11306edf2637e96139735df83907c221cce16d4d7eaaJim Miller    private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
11316edf2637e96139735df83907c221cce16d4d7eaaJim Miller
11326edf2637e96139735df83907c221cce16d4d7eaaJim Miller        // Stops the FaceLock UI and indicates that the phone should be unlocked
11336edf2637e96139735df83907c221cce16d4d7eaaJim Miller        @Override
11346edf2637e96139735df83907c221cce16d4d7eaaJim Miller        public void unlock() {
1135267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock unlock()");
1136267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); // Keep fallback covered
11376edf2637e96139735df83907c221cce16d4d7eaaJim Miller            stopFaceLock();
1138267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna
11396edf2637e96139735df83907c221cce16d4d7eaaJim Miller            mKeyguardScreenCallback.keyguardDone(true);
11406edf2637e96139735df83907c221cce16d4d7eaaJim Miller            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
11416edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
11426edf2637e96139735df83907c221cce16d4d7eaaJim Miller
11436edf2637e96139735df83907c221cce16d4d7eaaJim Miller        // Stops the FaceLock UI and exposes the backup method without unlocking
1144267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna        // This means either the user has cancelled out or FaceLock failed to recognize them
11456edf2637e96139735df83907c221cce16d4d7eaaJim Miller        @Override
11466edf2637e96139735df83907c221cce16d4d7eaaJim Miller        public void cancel() {
1147267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            if (DEBUG) Log.d(TAG, "FaceLock cancel()");
1148267cb2b284626f910cf64352bfc494d0f8d3dc42Brian Colonna            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); // Expose fallback
11496edf2637e96139735df83907c221cce16d4d7eaaJim Miller            stopFaceLock();
11506edf2637e96139735df83907c221cce16d4d7eaaJim Miller        }
11516edf2637e96139735df83907c221cce16d4d7eaaJim Miller    };
11526edf2637e96139735df83907c221cce16d4d7eaaJim Miller}
1153