public PasswordUnlockScreen( Context context, Configuration configuration, LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback) { super(context); mCreationHardKeyboardHidden = configuration.hardKeyboardHidden; mCreationOrientation = configuration.orientation; mUpdateMonitor = updateMonitor; mCallback = callback; mLockPatternUtils = lockPatternUtils; LayoutInflater layoutInflater = LayoutInflater.from(context); if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) { layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true); } else { layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true); } LockScreen.setBackground(context, (ViewGroup) findViewById(R.id.root)); mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils, mCallback, true); final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality(); mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality; mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); mPasswordEntry.setOnEditorActionListener(this); mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false); mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled()); boolean imeOrDeleteButtonVisible = false; if (mIsAlpha) { // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA); mKeyboardView.setVisibility(View.GONE); } else { // Use lockscreen's numeric keyboard if the physical keyboard isn't showing mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); mKeyboardView.setVisibility( mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE); // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts, // not a separate view View pinDelete = findViewById(R.id.pinDel); if (pinDelete != null) { pinDelete.setVisibility(View.VISIBLE); imeOrDeleteButtonVisible = true; pinDelete.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { mKeyboardHelper.handleBackspace(); } }); } } mPasswordEntry.requestFocus(); // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys. if (mIsAlpha) { mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); mPasswordEntry.setInputType( InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); // mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_password_code, // KeyguardStatusViewManager.LOCK_ICON); } else { mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); mPasswordEntry.setInputType( InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD); // mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_pin_code, // KeyguardStatusViewManager.LOCK_ICON); } // Poke the wakelock any time the text is selected or modified mPasswordEntry.setOnClickListener( new OnClickListener() { public void onClick(View v) { mCallback.pokeWakelock(); } }); mQuickUnlock = (Settings.System.getInt( mContext.getContentResolver(), Settings.System.LOCKSCREEN_QUICK_UNLOCK_CONTROL, 0) == 1); mPasswordEntry.addTextChangedListener( new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) {} public void afterTextChanged(Editable s) { if (!mResuming) { mCallback.pokeWakelock(); } if (mQuickUnlock) { String entry = mPasswordEntry.getText().toString(); if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT && mLockPatternUtils.checkPassword(entry)) { mCallback.keyguardDone(true); mCallback.reportSuccessfulUnlockAttempt(); KeyStore.getInstance().password(entry); } } } }); // If there's more than one IME, enable the IME switcher button View switchImeButton = findViewById(R.id.switch_ime_button); final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) { switchImeButton.setVisibility(View.VISIBLE); imeOrDeleteButtonVisible = true; switchImeButton.setOnClickListener( new OnClickListener() { public void onClick(View v) { mCallback.pokeWakelock(); // Leave the screen on a bit longer imm.showInputMethodPicker(); } }); } // If no icon is visible, reset the left margin on the password field so the text is // still centered. if (!imeOrDeleteButtonVisible) { android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); if (params instanceof MarginLayoutParams) { ((MarginLayoutParams) params).leftMargin = 0; mPasswordEntry.setLayoutParams(params); } } }
/** * @param context The context. * @param configuration * @param lockPatternUtils Used to lookup lock pattern settings. * @param updateMonitor Used to lookup state affecting keyguard. * @param callback Used to notify the manager when we're done, etc. * @param totalFailedAttempts The current number of failed attempts. * @param enableFallback True if a backup unlock option is available when the user has forgotten * their pattern (e.g they have a google account so we can show them the account based backup * option). */ PatternUnlockScreen( Context context, Configuration configuration, LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback, int totalFailedAttempts) { super(context); mLockPatternUtils = lockPatternUtils; mUpdateMonitor = updateMonitor; mCallback = callback; mTotalFailedPatternAttempts = totalFailedAttempts; mFailedPatternAttemptsSinceLastTimeout = totalFailedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; if (DEBUG) Log.d( TAG, "UnlockScreen() ctor: totalFailedAttempts=" + totalFailedAttempts + ", mFailedPat...=" + mFailedPatternAttemptsSinceLastTimeout); mCreationOrientation = configuration.orientation; LayoutInflater inflater = LayoutInflater.from(context); if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) { Log.d(TAG, "portrait mode"); inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true); } else { Log.d(TAG, "landscape mode"); inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true); } LockScreen.setBackground(context, (ViewGroup) findViewById(R.id.root)); mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils, mCallback, true); mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern); mForgotPatternButton = (Button) findViewById(R.id.forgotPatternButton); mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text); mForgotPatternButton.setOnClickListener(mForgotPatternClick); // make it so unhandled touch events within the unlock screen go to the // lock pattern view. setDefaultTouchRecepient(mLockPatternView); mLockPatternView.setSaveEnabled(false); mLockPatternView.setFocusable(false); mLockPatternView.setOnPatternListener(new UnlockPatternListener()); // stealth mode will be the same for the life of this screen mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled()); // vibrate mode will be the same for the life of this screen mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled()); // assume normal footer mode for now updateFooter(FooterMode.Normal); setFocusableInTouchMode(true); }