15e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller/*
25e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * Copyright (C) 2010 The Android Open Source Project
35e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller *
45e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * Licensed under the Apache License, Version 2.0 (the "License");
55e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * you may not use this file except in compliance with the License.
65e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * You may obtain a copy of the License at
75e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller *
85e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller *      http://www.apache.org/licenses/LICENSE-2.0
95e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller *
105e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * Unless required by applicable law or agreed to in writing, software
115e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * distributed under the License is distributed on an "AS IS" BASIS,
125e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * See the License for the specific language governing permissions and
145e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * limitations under the License.
155e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller */
165e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
17dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerpackage com.android.internal.policy.impl.keyguard_obsolete;
185e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
19858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport java.util.List;
20858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
21f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Millerimport android.app.admin.DevicePolicyManager;
225e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport android.content.Context;
235475906f53e2d79807548932dfabbf9945143740Jim Millerimport android.content.res.Configuration;
24148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Millerimport android.graphics.Rect;
255e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
265e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport com.android.internal.widget.LockPatternUtils;
27a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport com.android.internal.widget.PasswordEntryKeyboardView;
285e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
29f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Millerimport android.os.CountDownTimer;
30f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Millerimport android.os.SystemClock;
31aef555bcf26e770e37f2065913084588fb92c6fbJim Millerimport android.provider.Settings;
325cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstromimport android.security.KeyStore;
338ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Millerimport android.text.Editable;
34da3ae8fba865e4b02016bcb65b87a1fbfa000158Jim Millerimport android.text.InputType;
358ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Millerimport android.text.TextWatcher;
368b9dda28c9850b4a68b6958b8d4f751dd64157adJim Millerimport android.text.method.DigitsKeyListener;
378b9dda28c9850b4a68b6958b8d4f751dd64157adJim Millerimport android.text.method.TextKeyListener;
38d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Millerimport android.view.Gravity;
395e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport android.view.KeyEvent;
405e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport android.view.LayoutInflater;
415e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport android.view.View;
42d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Millerimport android.view.ViewGroup.LayoutParams;
43a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport android.view.inputmethod.EditorInfo;
44858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport android.view.inputmethod.InputMethodInfo;
45858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport android.view.inputmethod.InputMethodManager;
46858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Millerimport android.view.inputmethod.InputMethodSubtype;
47a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport android.widget.EditText;
485e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport android.widget.LinearLayout;
49d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Millerimport android.widget.Space;
505e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport android.widget.TextView;
51a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport android.widget.TextView.OnEditorActionListener;
52a781d016108d64b2735740d42b5a7c57eb420406Jim Miller
535e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Millerimport com.android.internal.R;
54a781d016108d64b2735740d42b5a7c57eb420406Jim Millerimport com.android.internal.widget.PasswordEntryKeyboardHelper;
555e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
565e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller/**
575e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * Displays a dialer-like interface or alphanumeric (latin-1) key entry for the user to enter
585e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller * an unlock password
595e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller */
605475906f53e2d79807548932dfabbf9945143740Jim Millerpublic class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen,
616b05d58018c2806459c121e507c005639b74aee9Jim Miller        OnEditorActionListener {
625e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
638171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung    private static final String TAG = "PasswordUnlockScreen";
645e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    private final KeyguardUpdateMonitor mUpdateMonitor;
655e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    private final KeyguardScreenCallback mCallback;
665e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
6751ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final boolean mIsAlpha;
68f9a166ab8236b5824049f5103c4365e12b52b4acKonstantin Lopyrev
6951ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final EditText mPasswordEntry;
7051ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final LockPatternUtils mLockPatternUtils;
7151ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final PasswordEntryKeyboardView mKeyboardView;
7251ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final PasswordEntryKeyboardHelper mKeyboardHelper;
735e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
7451ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final int mCreationOrientation;
7551ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final int mCreationHardKeyboardHidden;
768171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung
7751ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final KeyguardStatusViewManager mStatusViewManager;
7851ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo    private final boolean mUseSystemIME = true; // TODO: Make configurable
79dcb9376913a954266d07733e5e33bd846230cff8Jim Miller    private boolean mResuming; // used to prevent poking the wakelock during onResume()
805475906f53e2d79807548932dfabbf9945143740Jim Miller
816fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller    // To avoid accidental lockout due to events while the device in in the pocket, ignore
826fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller    // any passwords with length less than or equal to this length.
836fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller    private static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
846fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller
855475906f53e2d79807548932dfabbf9945143740Jim Miller    public PasswordUnlockScreen(Context context, Configuration configuration,
865475906f53e2d79807548932dfabbf9945143740Jim Miller            LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor,
875475906f53e2d79807548932dfabbf9945143740Jim Miller            KeyguardScreenCallback callback) {
885e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        super(context);
895475906f53e2d79807548932dfabbf9945143740Jim Miller
905169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller        mCreationHardKeyboardHidden = configuration.hardKeyboardHidden;
915475906f53e2d79807548932dfabbf9945143740Jim Miller        mCreationOrientation = configuration.orientation;
925e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        mUpdateMonitor = updateMonitor;
935e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        mCallback = callback;
94c23024d32779b170dde32a50fbdd945ce521b874Jim Miller        mLockPatternUtils = lockPatternUtils;
955e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
965e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        LayoutInflater layoutInflater = LayoutInflater.from(context);
975475906f53e2d79807548932dfabbf9945143740Jim Miller        if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
985e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
9942b432d84cd3bf860a03a10e9191738e05f2eaddJim Miller        } else {
10042b432d84cd3bf860a03a10e9191738e05f2eaddJim Miller            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
1015e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        }
1025e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
1036b05d58018c2806459c121e507c005639b74aee9Jim Miller        mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
104ebcd6bb1b9ac5f898621ba25c37f2e3ccd2ff33bAdam Cohen                mCallback, true);
1058171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung
106f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller        final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
107f9a166ab8236b5824049f5103c4365e12b52b4acKonstantin Lopyrev        mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
108a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
109a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97Konstantin Lopyrev                || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
110f7c5d0e46ced3ec3edb6f656acd82900b9ac988cJim Miller
111a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
112a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
113a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mPasswordEntry.setOnEditorActionListener(this);
1145e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
1158171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung        mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
1163fb0af38a1de9258cc80b227361c9a8ded88cfefJeff Sharkey        mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
117d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller        boolean imeOrDeleteButtonVisible = false;
1186b05d58018c2806459c121e507c005639b74aee9Jim Miller        if (mIsAlpha) {
1196b05d58018c2806459c121e507c005639b74aee9Jim Miller            // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
1206b05d58018c2806459c121e507c005639b74aee9Jim Miller            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
1216b05d58018c2806459c121e507c005639b74aee9Jim Miller            mKeyboardView.setVisibility(View.GONE);
1228171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung        } else {
1236b05d58018c2806459c121e507c005639b74aee9Jim Miller            // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
1248171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung            mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
1256b05d58018c2806459c121e507c005639b74aee9Jim Miller            mKeyboardView.setVisibility(mCreationHardKeyboardHidden
1266b05d58018c2806459c121e507c005639b74aee9Jim Miller                    == Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE);
12751ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo
12851ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo            // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
12951ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo            // not a separate view
13051ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo            View pinDelete = findViewById(R.id.pinDel);
13151ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo            if (pinDelete != null) {
13251ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                pinDelete.setVisibility(View.VISIBLE);
133d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller                imeOrDeleteButtonVisible = true;
13451ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                pinDelete.setOnClickListener(new OnClickListener() {
13551ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                    @Override
13651ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                    public void onClick(View v) {
13751ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                        mKeyboardHelper.handleBackspace();
13851ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                    }
13951ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo                });
14051ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo            }
1418171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung        }
1425e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
143a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mPasswordEntry.requestFocus();
144966b126ea7f24ae16c6a2aa683072bfd2cae8158Jim Miller
1458ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller        // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys.
146f9a166ab8236b5824049f5103c4365e12b52b4acKonstantin Lopyrev        if (mIsAlpha) {
1478b9dda28c9850b4a68b6958b8d4f751dd64157adJim Miller            mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
1488ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
1498ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller                    | InputType.TYPE_TEXT_VARIATION_PASSWORD);
1506b05d58018c2806459c121e507c005639b74aee9Jim Miller            //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_password_code,
1516b05d58018c2806459c121e507c005639b74aee9Jim Miller                    //KeyguardStatusViewManager.LOCK_ICON);
1528b9dda28c9850b4a68b6958b8d4f751dd64157adJim Miller        } else {
1538b9dda28c9850b4a68b6958b8d4f751dd64157adJim Miller            mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
1548ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
1558ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller                    | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
1566b05d58018c2806459c121e507c005639b74aee9Jim Miller            //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_pin_code,
1576b05d58018c2806459c121e507c005639b74aee9Jim Miller                    //KeyguardStatusViewManager.LOCK_ICON);
1588b9dda28c9850b4a68b6958b8d4f751dd64157adJim Miller        }
1598b9dda28c9850b4a68b6958b8d4f751dd64157adJim Miller
1606b05d58018c2806459c121e507c005639b74aee9Jim Miller        // Poke the wakelock any time the text is selected or modified
1616b05d58018c2806459c121e507c005639b74aee9Jim Miller        mPasswordEntry.setOnClickListener(new OnClickListener() {
1626b05d58018c2806459c121e507c005639b74aee9Jim Miller            public void onClick(View v) {
1636b05d58018c2806459c121e507c005639b74aee9Jim Miller                mCallback.pokeWakelock();
1646b05d58018c2806459c121e507c005639b74aee9Jim Miller            }
1656b05d58018c2806459c121e507c005639b74aee9Jim Miller        });
1668ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller        mPasswordEntry.addTextChangedListener(new TextWatcher() {
1678ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            public void onTextChanged(CharSequence s, int start, int before, int count) {
1688ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            }
1698ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller
1708ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
1718ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            }
1728ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller
1738ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            public void afterTextChanged(Editable s) {
174dcb9376913a954266d07733e5e33bd846230cff8Jim Miller                if (!mResuming) {
175dcb9376913a954266d07733e5e33bd846230cff8Jim Miller                    mCallback.pokeWakelock();
176dcb9376913a954266d07733e5e33bd846230cff8Jim Miller                }
1778ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller            }
1788ecfac1d8c2988c3d5031e78f9edefff6e663fd1Jim Miller        });
179858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
180858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        // If there's more than one IME, enable the IME switcher button
181858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        View switchImeButton = findViewById(R.id.switch_ime_button);
182858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
183858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                Context.INPUT_METHOD_SERVICE);
184b0166bc62f781c3dd921560c0ebafd965603fb16Jim Miller        if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
185858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            switchImeButton.setVisibility(View.VISIBLE);
186d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller            imeOrDeleteButtonVisible = true;
187858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            switchImeButton.setOnClickListener(new OnClickListener() {
188858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                public void onClick(View v) {
189858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                    mCallback.pokeWakelock(); // Leave the screen on a bit longer
190858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                    imm.showInputMethodPicker();
191858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                }
192858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            });
193858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        }
194d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller
195d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller        // If no icon is visible, reset the left margin on the password field so the text is
196d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller        // still centered.
197d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller        if (!imeOrDeleteButtonVisible) {
198d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller            android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
199d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller            if (params instanceof MarginLayoutParams) {
200d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller                ((MarginLayoutParams)params).leftMargin = 0;
201d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller                mPasswordEntry.setLayoutParams(params);
202d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller            }
203d9d09451ccec7c551d5f9c2f1417c9c1de2952a6Jim Miller        }
204858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller    }
205858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
206858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller    /**
207858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller     * Method adapted from com.android.inputmethod.latin.Utils
208858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller     *
209858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller     * @param imm The input method manager
210858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller     * @param shouldIncludeAuxiliarySubtypes
211858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller     * @return true if we have multiple IMEs to choose from
212858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller     */
213858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller    private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
214858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            final boolean shouldIncludeAuxiliarySubtypes) {
215858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
216858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
217858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        // Number of the filtered IMEs
218858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        int filteredImisCount = 0;
219858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
220858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        for (InputMethodInfo imi : enabledImis) {
221858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            // We can return true immediately after we find two or more filtered IMEs.
222858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            if (filteredImisCount > 1) return true;
223858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            final List<InputMethodSubtype> subtypes =
224858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                    imm.getEnabledInputMethodSubtypeList(imi, true);
225858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            // IMEs that have no subtypes should be counted.
226858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            if (subtypes.isEmpty()) {
227858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                ++filteredImisCount;
228858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                continue;
229858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            }
230858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
231858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            int auxCount = 0;
232858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            for (InputMethodSubtype subtype : subtypes) {
233858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                if (subtype.isAuxiliary()) {
234858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                    ++auxCount;
235858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                }
236858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            }
237858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            final int nonAuxCount = subtypes.size() - auxCount;
238858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
239858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            // IMEs that have one or more non-auxiliary subtypes should be counted.
240858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
241858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            // subtypes should be counted as well.
242858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
243858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                ++filteredImisCount;
244858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                continue;
245858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller            }
246858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        }
247858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller
248858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        return filteredImisCount > 1
249858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
250858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller        // input method subtype (The current IME should be LatinIME.)
251858f8eaac75bcd1b296b41837caf3dae82d1d72aJim Miller                || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
2525e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
2535e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
254148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Miller    @Override
255148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Miller    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
256148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Miller        // send focus to the password field
257148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Miller        return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
258148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Miller    }
259148e73eaed1fc0c12cdf84f0eb20a24624397a11Jim Miller
2605e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    /** {@inheritDoc} */
2615e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    public boolean needsInput() {
262da3ae8fba865e4b02016bcb65b87a1fbfa000158Jim Miller        return mUseSystemIME && mIsAlpha;
2635e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
2645e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
2655e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    /** {@inheritDoc} */
2665e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    public void onPause() {
2676b05d58018c2806459c121e507c005639b74aee9Jim Miller        mStatusViewManager.onPause();
2685e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
2695e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
2705e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    /** {@inheritDoc} */
2715e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    public void onResume() {
272dcb9376913a954266d07733e5e33bd846230cff8Jim Miller        mResuming = true;
2738171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung        // reset status
2746b05d58018c2806459c121e507c005639b74aee9Jim Miller        mStatusViewManager.onResume();
2758171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung
2765e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        // start fresh
277a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mPasswordEntry.setText("");
278a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mPasswordEntry.requestFocus();
279f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller
280f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        // if the user is currently locked out, enforce it.
281f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
282f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        if (deadline != 0) {
283f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            handleAttemptLockout(deadline);
284f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        }
285dcb9376913a954266d07733e5e33bd846230cff8Jim Miller        mResuming = false;
2865e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
2875e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
2885e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    /** {@inheritDoc} */
2895e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    public void cleanUp() {
2905e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        mUpdateMonitor.removeCallback(this);
2915e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
2925e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
2935e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    private void verifyPasswordAndUnlock() {
294a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        String entry = mPasswordEntry.getText().toString();
2955e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        if (mLockPatternUtils.checkPassword(entry)) {
2965e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            mCallback.keyguardDone(true);
2976fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller            mCallback.reportSuccessfulUnlockAttempt();
2986b05d58018c2806459c121e507c005639b74aee9Jim Miller            mStatusViewManager.setInstructionText(null);
2995cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            KeyStore.getInstance().password(entry);
3006fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller        } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
3015e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            // to avoid accidental lockout, only count attempts that are long enough to be a
3025e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller            // real password. This may require some tweaking.
3036fe0f0e46d7863bd75f6bd23b2fa805df84b5a4dJim Miller            mCallback.reportFailedUnlockAttempt();
304f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            if (0 == (mUpdateMonitor.getFailedAttempts()
305f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                    % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
306f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
307f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                handleAttemptLockout(deadline);
308f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            }
3096b05d58018c2806459c121e507c005639b74aee9Jim Miller            mStatusViewManager.setInstructionText(
3106b05d58018c2806459c121e507c005639b74aee9Jim Miller                    mContext.getString(R.string.lockscreen_password_wrong));
311f9a166ab8236b5824049f5103c4365e12b52b4acKonstantin Lopyrev        } else if (entry.length() > 0) {
3126b05d58018c2806459c121e507c005639b74aee9Jim Miller            mStatusViewManager.setInstructionText(
3136b05d58018c2806459c121e507c005639b74aee9Jim Miller                    mContext.getString(R.string.lockscreen_password_wrong));
3145e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        }
315a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mPasswordEntry.setText("");
3165e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
3175e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
318f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller    // Prevent user from using the PIN/Password entry until scheduled deadline.
319f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
320f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        mPasswordEntry.setEnabled(false);
321f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        mKeyboardView.setEnabled(false);
322f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        long elapsedRealtime = SystemClock.elapsedRealtime();
32351ea88a86e5cf418e956b199de35658f0a5fd623Ben Komalo        new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
324f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller
325f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            @Override
326f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            public void onTick(long millisUntilFinished) {
327f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                int secondsRemaining = (int) (millisUntilFinished / 1000);
328f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                String instructions = getContext().getString(
329f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                        R.string.lockscreen_too_many_failed_attempts_countdown,
330f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                        secondsRemaining);
3316b05d58018c2806459c121e507c005639b74aee9Jim Miller                mStatusViewManager.setInstructionText(instructions);
332f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            }
333f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller
334f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            @Override
335f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            public void onFinish() {
336f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                mPasswordEntry.setEnabled(true);
337f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller                mKeyboardView.setEnabled(true);
3386b05d58018c2806459c121e507c005639b74aee9Jim Miller                mStatusViewManager.resetStatusInfo();
339f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller            }
340f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller        }.start();
341f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller    }
342f1818ffd82ad288f52e81dae8eccc44db10c6564Jim Miller
3435e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    @Override
3445e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    public boolean onKeyDown(int keyCode, KeyEvent event) {
345a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        mCallback.pokeWakelock();
3465e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        return false;
3475e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
3485e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
34975787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn    @Override
35075787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn    protected void onAttachedToWindow() {
35175787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn        super.onAttachedToWindow();
3525169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller        Configuration config = getResources().getConfiguration();
3535169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller        if (config.orientation != mCreationOrientation
3545169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller                || config.hardKeyboardHidden != mCreationHardKeyboardHidden) {
3555169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller            mCallback.recreateMe(config);
35675787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn        }
35775787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn    }
35875787398fa5db9add16f3d3bc298198ed2c6671fDianne Hackborn
3595475906f53e2d79807548932dfabbf9945143740Jim Miller    /** {@inheritDoc} */
3605475906f53e2d79807548932dfabbf9945143740Jim Miller    @Override
3615475906f53e2d79807548932dfabbf9945143740Jim Miller    protected void onConfigurationChanged(Configuration newConfig) {
3625475906f53e2d79807548932dfabbf9945143740Jim Miller        super.onConfigurationChanged(newConfig);
3635169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller        if (newConfig.orientation != mCreationOrientation
3645169fc57e38cda45d6fda4b47b727167dd937cc8Jim Miller                || newConfig.hardKeyboardHidden != mCreationHardKeyboardHidden) {
3655475906f53e2d79807548932dfabbf9945143740Jim Miller            mCallback.recreateMe(newConfig);
3665475906f53e2d79807548932dfabbf9945143740Jim Miller        }
3675e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
3685e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
3695e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    public void onKeyboardChange(boolean isKeyboardOpen) {
37042b432d84cd3bf860a03a10e9191738e05f2eaddJim Miller        // Don't show the soft keyboard when the real keyboard is open
37142b432d84cd3bf860a03a10e9191738e05f2eaddJim Miller        mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
3725e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
3735e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller
374a781d016108d64b2735740d42b5a7c57eb420406Jim Miller    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
375a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        // Check if this was the result of hitting the enter key
3761c18828d20807342d37000746b18a3c1696f3b2eJim Miller        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
3771c18828d20807342d37000746b18a3c1696f3b2eJim Miller                || actionId == EditorInfo.IME_ACTION_NEXT) {
378a781d016108d64b2735740d42b5a7c57eb420406Jim Miller            verifyPasswordAndUnlock();
379a781d016108d64b2735740d42b5a7c57eb420406Jim Miller            return true;
3805e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller        }
381a781d016108d64b2735740d42b5a7c57eb420406Jim Miller        return false;
3825e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller    }
3835e0f7ba8fa8045aab98664b5103d8620e9ac7f06Jim Miller}
384