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);
  }