Update confirm device credentials to spec, add fingerprint

- New strings in the screen.
- New layout/style.
- Clean up internal API's around it.
- Add fingerprint support if launched from externally
- Separate theme if launched from externally
- If launched from above Keyguard, use SHOW_WHEN_LOCKED flag

Change-Id: Icdf9bf9e0506841f24e8aab5f0f1d1f4b688951f
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 479baf7..f4e3c4e 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -145,7 +145,8 @@
             } else if (!mWaitingForConfirmation) {
                 ChooseLockSettingsHelper helper =
                         new ChooseLockSettingsHelper(this.getActivity(), this);
-                if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) {
+                if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
+                        getString(R.string.unlock_set_unlock_launch_picker_title))) {
                     mPasswordConfirmed = true; // no password set, so no need to confirm
                     updatePreferencesOrFinish();
                 } else {
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 6d7b71d..8838286 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -243,7 +243,7 @@
                 updateStage(Stage.Introduction);
                 if (confirmCredentials) {
                     mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
-                            null, null);
+                            getString(R.string.unlock_set_unlock_launch_picker_title));
                 }
             } else {
                 mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 1865a6b..8892346 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -379,7 +379,8 @@
                     updateStage(Stage.NeedToConfirm);
                     boolean launchedConfirmationActivity =
                         mChooseLockSettingsHelper.launchConfirmationActivity(
-                                CONFIRM_EXISTING_REQUEST, null, null);
+                                CONFIRM_EXISTING_REQUEST,
+                                getString(R.string.unlock_set_unlock_launch_picker_title));
                     if (!launchedConfirmationActivity) {
                         updateStage(Stage.Introduction);
                     }
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index bba45ce..65697f6 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -16,13 +16,14 @@
 
 package com.android.settings;
 
-import com.android.internal.widget.LockPatternUtils;
-
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
 
+import com.android.internal.widget.LockPatternUtils;
+
 public final class ChooseLockSettingsHelper {
 
     static final String EXTRA_KEY_TYPE = "type";
@@ -48,64 +49,77 @@
 
     /**
      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
-     * @param message optional message to display about the action about to be done
-     * @param details optional detail message to display
+     *
+     * @param title title of the confirmation screen; shown in the action bar
      * @return true if one exists and we launched an activity to confirm it
-     * @see #onActivityResult(int, int, android.content.Intent)
+     * @see Activity#onActivityResult(int, int, android.content.Intent)
      */
-    boolean launchConfirmationActivity(int request, CharSequence message, CharSequence details) {
-        return launchConfirmationActivity(request, message, details, false);
+    boolean launchConfirmationActivity(int request, CharSequence title) {
+        return launchConfirmationActivity(request, title, null, null, false, false);
     }
 
     /**
      * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
-     * @param message optional message to display about the action about to be done
-     * @param details optional detail message to display
+     *
+     * @param title title of the confirmation screen; shown in the action bar
      * @param returnCredentials if true, put credentials into intent. Note that if this is true,
-                                this can only be called internally.
+     *                          this can only be called internally.
      * @return true if one exists and we launched an activity to confirm it
-     * @see #onActivityResult(int, int, android.content.Intent)
+     * @see Activity#onActivityResult(int, int, android.content.Intent)
      */
-    boolean launchConfirmationActivity(int request, CharSequence message, CharSequence details,
-                                       boolean returnCredentials) {
+    boolean launchConfirmationActivity(int request, CharSequence title, boolean returnCredentials) {
+        return launchConfirmationActivity(request, title, null, null, returnCredentials, false);
+    }
+
+    /**
+     * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
+     *
+     * @param title title of the confirmation screen; shown in the action bar
+     * @param header header of the confirmation screen; shown as large text
+     * @param description description of the confirmation screen
+     * @param returnCredentials if true, put credentials into intent. Note that if this is true,
+     *                          this can only be called internally.
+     * @param external specifies whether this activity is launched externally, meaning that it will
+     *                 get a dark theme and allow fingerprint authentication
+     * @return true if one exists and we launched an activity to confirm it
+     * @see Activity#onActivityResult(int, int, android.content.Intent)
+     */
+    boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
+            @Nullable CharSequence header, @Nullable CharSequence description,
+            boolean returnCredentials, boolean external) {
         boolean launched = false;
         switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
-                launched = confirmPattern(request, message, details, returnCredentials);
+                launched = launchConfirmationActivity(request, title, header, description,
+                        returnCredentials
+                                ? ConfirmLockPattern.InternalActivity.class
+                                : ConfirmLockPattern.class, external);
                 break;
             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
-                // TODO: update UI layout for ConfirmPassword to show message and details
-                launched = confirmPassword(request, message, returnCredentials);
+                launched = launchConfirmationActivity(request, title, header, description,
+                        returnCredentials
+                                ? ConfirmLockPassword.InternalActivity.class
+                                : ConfirmLockPassword.class, external);
                 break;
         }
         return launched;
     }
 
-    /**
-     * Launch screen to confirm the existing lock pattern.
-     * @param message shown in header of ConfirmLockPattern if not null
-     * @param details shown in footer of ConfirmLockPattern if not null
-     * @param returnCredentials if true, put credentials into intent.
-     * @see #onActivityResult(int, int, android.content.Intent)
-     * @return true if we launched an activity to confirm pattern
-     */
-    private boolean confirmPattern(int request, CharSequence message,
-                                   CharSequence details, boolean returnCredentials) {
-        if (!mLockPatternUtils.isLockPatternEnabled()) {
-            return false;
-        }
+    private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
+            CharSequence message, Class<?> activityClass, boolean external) {
         final Intent intent = new Intent();
-        // supply header and footer text in the intent
-        intent.putExtra(ConfirmLockPattern.HEADER_TEXT, message);
-        intent.putExtra(ConfirmLockPattern.FOOTER_TEXT, details);
-        intent.setClassName("com.android.settings",
-                            returnCredentials
-                            ? ConfirmLockPattern.InternalActivity.class.getName()
-                            : ConfirmLockPattern.class.getName());
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT, message);
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.ALLOW_FP_AUTHENTICATION, external);
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, external);
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_CANCEL_BUTTON, external);
+        intent.putExtra(ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, external);
+        intent.setClassName(ConfirmDeviceCredentialBaseFragment.PACKAGE, activityClass.getName());
         if (mFragment != null) {
             mFragment.startActivityForResult(intent, request);
         } else {
@@ -113,31 +127,4 @@
         }
         return true;
     }
-
-    /**
-     * Launch screen to confirm the existing lock password.
-     * @param message shown in header of ConfirmLockPassword if not null
-     * @param returnCredentials if true, put credentials into intent.
-     * @see #onActivityResult(int, int, android.content.Intent)
-     * @return true if we launched an activity to confirm password
-     */
-    private boolean confirmPassword(int request, CharSequence message,
-            boolean returnCredentials) {
-        if (!mLockPatternUtils.isLockPasswordEnabled()) return false;
-        final Intent intent = new Intent();
-        // supply header text in the intent
-        intent.putExtra(ConfirmLockPattern.HEADER_TEXT, message);
-        intent.setClassName("com.android.settings",
-                            returnCredentials
-                            ? ConfirmLockPassword.InternalActivity.class.getName()
-                            : ConfirmLockPassword.class.getName());
-        if (mFragment != null) {
-            mFragment.startActivityForResult(intent, request);
-        } else {
-            mActivity.startActivityForResult(intent, request);
-        }
-        return true;
-    }
-
-
 }
diff --git a/src/com/android/settings/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
index beb2d97..9a7f843 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
@@ -48,7 +48,8 @@
         String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
 
         ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
-        if (!helper.launchConfirmationActivity(0 /* request code */, title, details)) {
+        if (!helper.launchConfirmationActivity(0 /* request code */, null /* title */, title,
+                details, false /* returnCredentials */, true /* isExternal */)) {
             Log.d(TAG, "No pattern, password or PIN set.");
             setResult(Activity.RESULT_OK);
             finish();
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java
new file mode 100644
index 0000000..fe3de97
--- /dev/null
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings;
+
+import android.app.KeyguardManager;
+import android.os.Bundle;
+import android.view.MenuItem;
+import android.view.WindowManager;
+
+public class ConfirmDeviceCredentialBaseActivity extends SettingsActivity {
+
+    @Override
+    protected void onCreate(Bundle savedState) {
+        if (getIntent().getBooleanExtra(ConfirmDeviceCredentialBaseFragment.DARK_THEME, false)) {
+            setTheme(R.style.Theme_ConfirmDeviceCredentialsDark);
+        }
+        super.onCreate(savedState);
+        boolean deviceLocked = getSystemService(KeyguardManager.class).isKeyguardLocked();
+        if (deviceLocked && getIntent().getBooleanExtra(
+                ConfirmDeviceCredentialBaseFragment.SHOW_WHEN_LOCKED, false)) {
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+        }
+        CharSequence msg = getIntent().getStringExtra(
+                ConfirmDeviceCredentialBaseFragment.TITLE_TEXT);
+        setTitle(msg);
+        if (getActionBar() != null) {
+            getActionBar().setDisplayHomeAsUpEnabled(true);
+            getActionBar().setHomeButtonEnabled(true);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == android.R.id.home) {
+            finish();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
new file mode 100644
index 0000000..f9908b0
--- /dev/null
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings;
+
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
+ */
+public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment
+        implements FingerprintUiHelper.Callback {
+
+    public static final String PACKAGE = "com.android.settings";
+    public static final String TITLE_TEXT = PACKAGE + ".ConfirmCredentials.title";
+    public static final String HEADER_TEXT = PACKAGE + ".ConfirmCredentials.header";
+    public static final String DETAILS_TEXT = PACKAGE + ".ConfirmCredentials.details";
+    public static final String ALLOW_FP_AUTHENTICATION =
+            PACKAGE + ".ConfirmCredentials.allowFpAuthentication";
+    public static final String DARK_THEME = PACKAGE + ".ConfirmCredentials.darkTheme";
+    public static final String SHOW_CANCEL_BUTTON =
+            PACKAGE + ".ConfirmCredentials.showCancelButton";
+    public static final String SHOW_WHEN_LOCKED =
+            PACKAGE + ".ConfirmCredentials.showWhenLocked";
+
+    private FingerprintUiHelper mFingerprintHelper;
+    private boolean mAllowFpAuthentication;
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAllowFpAuthentication = getActivity().getIntent().getBooleanExtra(
+                ALLOW_FP_AUTHENTICATION, false);
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        mFingerprintHelper = new FingerprintUiHelper(
+                (ImageView) view.findViewById(R.id.fingerprintIcon),
+                (TextView) view.findViewById(R.id.errorText), this);
+        boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
+                SHOW_CANCEL_BUTTON, false);
+        Button cancelButton = (Button) view.findViewById(R.id.cancelButton);
+        cancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
+        cancelButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                getActivity().finish();
+            }
+        });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mAllowFpAuthentication) {
+            mFingerprintHelper.startListening();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (mAllowFpAuthentication) {
+            mFingerprintHelper.stopListening();
+        }
+    }
+
+    @Override
+    public void onAuthenticated() {
+        // Check whether we are still active.
+        if (getActivity() != null && getActivity().isResumed()) {
+            authenticationSucceeded(null /* password */);
+        }
+    }
+
+    protected abstract void authenticationSucceeded(@Nullable String password);
+
+    @Override
+    public void onFingerprintIconVisibilityChanged(boolean visible) {
+    }
+}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index b49dc6e..44c599b 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -16,14 +16,11 @@
 
 package com.android.settings;
 
+import android.annotation.Nullable;
 import android.text.TextUtils;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.PasswordEntryKeyboardHelper;
-import com.android.internal.widget.PasswordEntryKeyboardView;
 
-import android.app.Activity;
-import android.app.Fragment;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
 import android.os.Bundle;
@@ -31,23 +28,18 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.os.storage.StorageManager;
-import android.text.Editable;
 import android.text.InputType;
-import android.text.TextWatcher;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
-import android.widget.Button;
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
-public class ConfirmLockPassword extends SettingsActivity {
-
-    public static final String PACKAGE = "com.android.settings";
-    public static final String HEADER_TEXT = PACKAGE + ".ConfirmLockPattern.header";
+public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
 
     public static class InternalActivity extends ConfirmLockPassword {
     }
@@ -65,28 +57,17 @@
         return false;
     }
 
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        // Disable IME on our window since we provide our own keyboard
-        //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
-                //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
-        super.onCreate(savedInstanceState);
-        CharSequence msg = getText(R.string.lockpassword_confirm_your_password_header);
-        setTitle(msg);
-    }
-
-    public static class ConfirmLockPasswordFragment extends InstrumentedFragment
-            implements OnClickListener, OnEditorActionListener, TextWatcher {
+    public static class ConfirmLockPasswordFragment extends ConfirmDeviceCredentialBaseFragment
+            implements OnClickListener, OnEditorActionListener {
         private static final String KEY_NUM_WRONG_CONFIRM_ATTEMPTS
                 = "confirm_lock_password_fragment.key_num_wrong_confirm_attempts";
         private static final long ERROR_MESSAGE_TIMEOUT = 3000;
         private TextView mPasswordEntry;
         private LockPatternUtils mLockPatternUtils;
-        private TextView mHeaderText;
+        private TextView mHeaderTextView;
+        private TextView mDetailsTextView;
+        private TextView mErrorTextView;
         private Handler mHandler = new Handler();
-        private PasswordEntryKeyboardHelper mKeyboardHelper;
-        private PasswordEntryKeyboardView mKeyboardView;
-        private Button mContinueButton;
         private int mNumWrongConfirmAttempts;
         private CountDownTimer mCountdownTimer;
         private boolean mIsAlpha;
@@ -111,51 +92,35 @@
                 Bundle savedInstanceState) {
             final int storedQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
             View view = inflater.inflate(R.layout.confirm_lock_password, null);
-            // Disable IME on our window since we provide our own keyboard
-
-            view.findViewById(R.id.cancel_button).setOnClickListener(this);
-            mContinueButton = (Button) view.findViewById(R.id.next_button);
-            mContinueButton.setOnClickListener(this);
-            mContinueButton.setEnabled(false); // disable until the user enters at least one char
 
             mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
             mPasswordEntry.setOnEditorActionListener(this);
-            mPasswordEntry.addTextChangedListener(this);
 
-            mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
-            mHeaderText = (TextView) view.findViewById(R.id.headerText);
+            mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
+            mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
+            mErrorTextView = (TextView) view.findViewById(R.id.errorText);
             mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
                     || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
                     || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
 
             Intent intent = getActivity().getIntent();
             if (intent != null) {
-                CharSequence headerMessage = intent.getCharSequenceExtra(HEADER_TEXT);
+                CharSequence headerMessage = intent.getCharSequenceExtra(
+                        ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
+                CharSequence detailsMessage = intent.getCharSequenceExtra(
+                        ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
                 if (TextUtils.isEmpty(headerMessage)) {
                     headerMessage = getString(getDefaultHeader());
                 }
-                mHeaderText.setText(headerMessage);
+                if (TextUtils.isEmpty(detailsMessage)) {
+                    detailsMessage = getString(getDefaultDetails());
+                }
+                mHeaderTextView.setText(headerMessage);
+                mDetailsTextView.setText(detailsMessage);
             }
-
-            final Activity activity = getActivity();
-            mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
-                    mKeyboardView, mPasswordEntry);
-            mKeyboardHelper.setKeyboardMode(mIsAlpha ?
-                    PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
-                    : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
-            mKeyboardView.requestFocus();
-
             int currentType = mPasswordEntry.getInputType();
             mPasswordEntry.setInputType(mIsAlpha ? currentType
                     : (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
-
-            if (activity instanceof SettingsActivity) {
-                final SettingsActivity sa = (SettingsActivity) activity;
-                int id = getDefaultHeader();
-                CharSequence title = getText(id);
-                sa.setTitle(title);
-            }
-
             return view;
         }
 
@@ -164,10 +129,19 @@
                     : R.string.lockpassword_confirm_your_pin_header;
         }
 
+        private int getDefaultDetails() {
+            return mIsAlpha ? R.string.lockpassword_confirm_your_password_generic
+                    : R.string.lockpassword_confirm_your_pin_generic;
+        }
+
+        private int getErrorMessage() {
+            return mIsAlpha ? R.string.lockpassword_invalid_password
+                    : R.string.lockpassword_invalid_pin;
+        }
+
         @Override
         public void onPause() {
             super.onPause();
-            mKeyboardView.requestFocus();
             if (mCountdownTimer != null) {
                 mCountdownTimer.cancel();
                 mCountdownTimer = null;
@@ -181,9 +155,7 @@
 
         @Override
         public void onResume() {
-            // TODO Auto-generated method stub
             super.onResume();
-            mKeyboardView.requestFocus();
             long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
             if (deadline != 0) {
                 handleAttemptLockout(deadline);
@@ -196,33 +168,35 @@
             outState.putInt(KEY_NUM_WRONG_CONFIRM_ATTEMPTS, mNumWrongConfirmAttempts);
         }
 
+        @Override
+        protected void authenticationSucceeded(@Nullable String password) {
+            Intent intent = new Intent();
+            if (getActivity() instanceof ConfirmLockPassword.InternalActivity) {
+                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
+                        mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
+                                : StorageManager.CRYPT_TYPE_PIN);
+                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
+            }
+            getActivity().setResult(RESULT_OK, intent);
+            getActivity().finish();
+        }
+
         private void handleNext() {
             final String pin = mPasswordEntry.getText().toString();
             if (mLockPatternUtils.checkPassword(pin)) {
-
-                Intent intent = new Intent();
-                if (getActivity() instanceof ConfirmLockPassword.InternalActivity) {
-                    intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
-                                    mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
-                                             : StorageManager.CRYPT_TYPE_PIN);
-                    intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin);
-                }
-
-                getActivity().setResult(RESULT_OK, intent);
-                getActivity().finish();
+                authenticationSucceeded(pin);
             } else {
                 if (++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
                     long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
                     handleAttemptLockout(deadline);
                 } else {
-                    showError(R.string.lockpattern_need_to_unlock_wrong);
+                    showError(getErrorMessage());
                 }
             }
         }
 
         private void handleAttemptLockout(long elapsedRealtimeDeadline) {
             long elapsedRealtime = SystemClock.elapsedRealtime();
-            showError(R.string.lockpattern_too_many_failed_confirmation_attempts_header, 0);
             mPasswordEntry.setEnabled(false);
             mCountdownTimer = new CountDownTimer(
                     elapsedRealtimeDeadline - elapsedRealtime,
@@ -231,15 +205,15 @@
                 @Override
                 public void onTick(long millisUntilFinished) {
                     final int secondsCountdown = (int) (millisUntilFinished / 1000);
-                    mHeaderText.setText(getString(
-                            R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
-                            secondsCountdown));
+                    showError(getString(
+                            R.string.lockpattern_too_many_failed_confirmation_attempts,
+                            secondsCountdown), 0);
                 }
 
                 @Override
                 public void onFinish() {
                     mPasswordEntry.setEnabled(true);
-                    mHeaderText.setText(getDefaultHeader());
+                    mErrorTextView.setText("");
                     mNumWrongConfirmAttempts = 0;
                 }
             }.start();
@@ -264,13 +238,13 @@
 
         private final Runnable mResetErrorRunnable = new Runnable() {
             public void run() {
-                mHeaderText.setText(getDefaultHeader());
+                mErrorTextView.setText("");
             }
         };
 
-        private void showError(int msg, long timeout) {
-            mHeaderText.setText(msg);
-            mHeaderText.announceForAccessibility(mHeaderText.getText());
+        private void showError(CharSequence msg, long timeout) {
+            mErrorTextView.setText(msg);
+            mErrorTextView.announceForAccessibility(mErrorTextView.getText());
             mPasswordEntry.setText(null);
             mHandler.removeCallbacks(mResetErrorRunnable);
             if (timeout != 0) {
@@ -278,6 +252,10 @@
             }
         }
 
+        private void showError(int msg, long timeout) {
+            showError(getText(msg), timeout);
+        }
+
         // {@link OnEditorActionListener} methods.
         public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
             // Check if this was the result of hitting the enter or "done" key
@@ -289,16 +267,5 @@
             }
             return false;
         }
-
-        // {@link TextWatcher} methods.
-        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-        }
-
-        public void onTextChanged(CharSequence s, int start, int before, int count) {
-        }
-
-        public void afterTextChanged(Editable s) {
-            mContinueButton.setEnabled(mPasswordEntry.getText().length() > 0);
-        }
     }
 }
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index b5d444b..8c4fabc 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -22,13 +22,14 @@
 import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
 import com.android.internal.widget.LockPatternView.Cell;
 
+import android.annotation.Nullable;
 import android.app.Activity;
-import android.app.Fragment;
 import android.content.Intent;
 import android.os.CountDownTimer;
 import android.os.SystemClock;
 import android.os.Bundle;
 import android.os.storage.StorageManager;
+import android.view.MenuItem;
 import android.widget.TextView;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -42,23 +43,11 @@
  * Sets an activity result of {@link Activity#RESULT_OK} when the user
  * successfully confirmed their pattern.
  */
-public class ConfirmLockPattern extends SettingsActivity {
+public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
 
     public static class InternalActivity extends ConfirmLockPattern {
     }
 
-    /**
-     * Names of {@link CharSequence} fields within the originating {@link Intent}
-     * that are used to configure the keyguard confirmation view's labeling.
-     * The view will use the system-defined resource strings for any labels that
-     * the caller does not supply.
-     */
-    public static final String PACKAGE = "com.android.settings";
-    public static final String HEADER_TEXT = PACKAGE + ".ConfirmLockPattern.header";
-    public static final String FOOTER_TEXT = PACKAGE + ".ConfirmLockPattern.footer";
-    public static final String HEADER_WRONG_TEXT = PACKAGE + ".ConfirmLockPattern.header_wrong";
-    public static final String FOOTER_WRONG_TEXT = PACKAGE + ".ConfirmLockPattern.footer_wrong";
-
     private enum Stage {
         NeedToUnlock,
         NeedToUnlockWrong,
@@ -66,13 +55,6 @@
     }
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        CharSequence msg = getText(R.string.lockpassword_confirm_your_pattern_header);
-        setTitle(msg);
-    }
-
-    @Override
     public Intent getIntent() {
         Intent modIntent = new Intent(super.getIntent());
         modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ConfirmLockPatternFragment.class.getName());
@@ -85,7 +67,7 @@
         return false;
     }
 
-    public static class ConfirmLockPatternFragment extends InstrumentedFragment {
+    public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment {
 
         // how long we wait to clear a wrong pattern
         private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
@@ -98,13 +80,14 @@
         private CountDownTimer mCountdownTimer;
 
         private TextView mHeaderTextView;
-        private TextView mFooterTextView;
+        private TextView mDetailsTextView;
+        private TextView mErrorTextView;
+        private View mLeftSpacerLandscape;
+        private View mRightSpacerLandscape;
 
         // caller-supplied text for various prompts
         private CharSequence mHeaderText;
-        private CharSequence mFooterText;
-        private CharSequence mHeaderWrongText;
-        private CharSequence mFooterWrongText;
+        private CharSequence mDetailsText;
 
         // required constructor for fragments
         public ConfirmLockPatternFragment() {
@@ -123,7 +106,10 @@
             View view = inflater.inflate(R.layout.confirm_lock_pattern, null);
             mHeaderTextView = (TextView) view.findViewById(R.id.headerText);
             mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern);
-            mFooterTextView = (TextView) view.findViewById(R.id.footerText);
+            mDetailsTextView = (TextView) view.findViewById(R.id.detailsText);
+            mErrorTextView = (TextView) view.findViewById(R.id.errorText);
+            mLeftSpacerLandscape = view.findViewById(R.id.leftSpacer);
+            mRightSpacerLandscape = view.findViewById(R.id.rightSpacer);
 
             // make it so unhandled touch events within the unlock screen go to the
             // lock pattern view.
@@ -133,10 +119,10 @@
 
             Intent intent = getActivity().getIntent();
             if (intent != null) {
-                mHeaderText = intent.getCharSequenceExtra(HEADER_TEXT);
-                mFooterText = intent.getCharSequenceExtra(FOOTER_TEXT);
-                mHeaderWrongText = intent.getCharSequenceExtra(HEADER_WRONG_TEXT);
-                mFooterWrongText = intent.getCharSequenceExtra(FOOTER_WRONG_TEXT);
+                mHeaderText = intent.getCharSequenceExtra(
+                        ConfirmDeviceCredentialBaseFragment.HEADER_TEXT);
+                mDetailsText = intent.getCharSequenceExtra(
+                        ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT);
             }
 
             mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
@@ -199,28 +185,21 @@
                     if (mHeaderText != null) {
                         mHeaderTextView.setText(mHeaderText);
                     } else {
-                        mHeaderTextView.setText(R.string.lockpattern_need_to_unlock);
+                        mHeaderTextView.setText(R.string.lockpassword_confirm_your_pattern_header);
                     }
-                    if (mFooterText != null) {
-                        mFooterTextView.setText(mFooterText);
+                    if (mDetailsText != null) {
+                        mDetailsTextView.setText(mDetailsText);
                     } else {
-                        mFooterTextView.setText(R.string.lockpattern_need_to_unlock_footer);
+                        mDetailsTextView.setText(
+                                R.string.lockpassword_confirm_your_pattern_generic);
                     }
+                    mErrorTextView.setText("");
 
                     mLockPatternView.setEnabled(true);
                     mLockPatternView.enableInput();
                     break;
                 case NeedToUnlockWrong:
-                    if (mHeaderWrongText != null) {
-                        mHeaderTextView.setText(mHeaderWrongText);
-                    } else {
-                        mHeaderTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
-                    }
-                    if (mFooterWrongText != null) {
-                        mFooterTextView.setText(mFooterWrongText);
-                    } else {
-                        mFooterTextView.setText(R.string.lockpattern_need_to_unlock_wrong_footer);
-                    }
+                    mErrorTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
 
                     mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
                     mLockPatternView.setEnabled(true);
@@ -252,6 +231,28 @@
             mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
         }
 
+        @Override
+        protected void authenticationSucceeded(@Nullable String password) {
+            Intent intent = new Intent();
+            if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
+                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
+                        StorageManager.CRYPT_TYPE_PATTERN);
+                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
+            }
+            getActivity().setResult(Activity.RESULT_OK, intent);
+            getActivity().finish();
+        }
+
+        @Override
+        public void onFingerprintIconVisibilityChanged(boolean visible) {
+            if (mLeftSpacerLandscape != null && mRightSpacerLandscape != null) {
+
+                // In landscape, adjust spacing depending on fingerprint icon visibility.
+                mLeftSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
+                mRightSpacerLandscape.setVisibility(visible ? View.GONE : View.VISIBLE);
+            }
+        }
+
         /**
          * The pattern listener that responds according to a user confirming
          * an existing lock pattern.
@@ -273,17 +274,7 @@
 
             public void onPatternDetected(List<LockPatternView.Cell> pattern) {
                 if (mLockPatternUtils.checkPattern(pattern)) {
-
-                    Intent intent = new Intent();
-                    if (getActivity() instanceof ConfirmLockPattern.InternalActivity) {
-                        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
-                                        StorageManager.CRYPT_TYPE_PATTERN);
-                        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
-                                        LockPatternUtils.patternToString(pattern));
-                    }
-
-                    getActivity().setResult(Activity.RESULT_OK, intent);
-                    getActivity().finish();
+                    authenticationSucceeded(LockPatternUtils.patternToString(pattern));
                 } else {
                     if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL &&
                             ++mNumWrongConfirmAttempts
@@ -308,10 +299,9 @@
 
                 @Override
                 public void onTick(long millisUntilFinished) {
-                    mHeaderTextView.setText(R.string.lockpattern_too_many_failed_confirmation_attempts_header);
                     final int secondsCountdown = (int) (millisUntilFinished / 1000);
-                    mFooterTextView.setText(getString(
-                            R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
+                    mErrorTextView.setText(getString(
+                            R.string.lockpattern_too_many_failed_confirmation_attempts,
                             secondsCountdown));
                 }
 
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
index 45d3d11..8506964 100644
--- a/src/com/android/settings/CredentialStorage.java
+++ b/src/com/android/settings/CredentialStorage.java
@@ -439,9 +439,8 @@
     private boolean confirmKeyGuard() {
         Resources res = getResources();
         boolean launched = new ChooseLockSettingsHelper(this)
-                .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST, null,
-                                            res.getText(R.string.credentials_install_gesture_explanation),
-                                            true);
+                .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST,
+                        res.getText(R.string.credentials_title), true);
         return launched;
     }
 
diff --git a/src/com/android/settings/CryptKeeperSettings.java b/src/com/android/settings/CryptKeeperSettings.java
index 3fb60e3..2e4aeb8 100644
--- a/src/com/android/settings/CryptKeeperSettings.java
+++ b/src/com/android/settings/CryptKeeperSettings.java
@@ -166,9 +166,8 @@
             return true;
         }
 
-        return helper.launchConfirmationActivity(request, null,
-                res.getText(R.string.crypt_keeper_confirm_encrypt),
-                true);
+        return helper.launchConfirmationActivity(request,
+                res.getText(R.string.crypt_keeper_encrypt_title), true);
     }
 
     @Override
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 5fafc92..5c7e0e9 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -1610,10 +1610,8 @@
     }
 
     private boolean showKeyguardConfirmation(Resources resources, int requestCode) {
-        return new ChooseLockSettingsHelper(getActivity(), this)
-                .launchConfirmationActivity(requestCode,
-                        resources.getString(R.string.oem_unlock_enable_pin_prompt),
-                        resources.getString(R.string.oem_unlock_enable_pin_description));
+        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+                requestCode, resources.getString(R.string.oem_unlock_enable));
     }
 
     @Override
diff --git a/src/com/android/settings/FingerprintUiHelper.java b/src/com/android/settings/FingerprintUiHelper.java
new file mode 100644
index 0000000..20ad7fc
--- /dev/null
+++ b/src/com/android/settings/FingerprintUiHelper.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings;
+
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.CancellationSignal;
+import android.os.Vibrator;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Small helper class to manage text/icon around fingerprint authentication UI.
+ */
+public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
+
+    private static final long ERROR_TIMEOUT = 1300;
+    private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
+    private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
+
+    private ImageView mIcon;
+    private TextView mErrorTextView;
+    private CancellationSignal mCancellationSignal;
+
+    private Callback mCallback;
+    private FingerprintManager mFingerprintManager;
+
+    public FingerprintUiHelper(ImageView icon, TextView errorTextView, Callback callback) {
+        mFingerprintManager = icon.getContext().getSystemService(FingerprintManager.class);
+        mIcon = icon;
+        mErrorTextView = errorTextView;
+        mCallback = callback;
+    }
+
+    public void startListening() {
+        if (mFingerprintManager.getEnrolledFingerprints().size() > 0) {
+            mCancellationSignal = new CancellationSignal();
+            mFingerprintManager.authenticate(null, mCancellationSignal, this, 0 /* flags */);
+            setFingerprintIconVisibility(true);
+            mIcon.setImageResource(R.drawable.ic_fingerprint);
+        }
+    }
+
+    public void stopListening() {
+        mCancellationSignal.cancel();
+        mCancellationSignal = null;
+    }
+
+    private void setFingerprintIconVisibility(boolean visible) {
+        mIcon.setVisibility(visible ? View.VISIBLE : View.GONE);
+        mCallback.onFingerprintIconVisibilityChanged(visible);
+    }
+
+    @Override
+    public void onAuthenticationError(int errMsgId, CharSequence errString) {
+        showError(errString);
+        setFingerprintIconVisibility(false);
+    }
+
+    @Override
+    public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
+        showError(helpString);
+    }
+
+    @Override
+    public void onAuthenticationFailed() {
+        showError(mIcon.getResources().getString(
+                R.string.fingerprint_not_recognized));
+    }
+
+    @Override
+    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
+        vibrateFingerprintSuccess();
+        mCallback.onAuthenticated();
+    }
+
+    private void showError(CharSequence error) {
+        vibrateFingerprintError();
+        mIcon.setImageResource(R.drawable.ic_fingerprint_error);
+        mErrorTextView.setText(error);
+        mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
+        mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT);
+    }
+
+    private void vibrateFingerprintError() {
+        mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
+    }
+
+    private void vibrateFingerprintSuccess() {
+        mIcon.getContext().getSystemService(Vibrator.class).vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
+    }
+
+    private Runnable mResetErrorTextRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mErrorTextView.setText("");
+            mIcon.setImageResource(R.drawable.ic_fingerprint);
+        }
+    };
+
+    public interface Callback {
+        void onAuthenticated();
+        void onFingerprintIconVisibilityChanged(boolean visible);
+    }
+}
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 1b6468f..23f6812 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -75,8 +75,8 @@
      */
     private boolean runKeyguardConfirmation(int request) {
         Resources res = getActivity().getResources();
-        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(request,
-                null, res.getText(R.string.master_clear_gesture_explanation));
+        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+                request, res.getText(R.string.master_clear_title));
     }
 
     @Override
diff --git a/src/com/android/settings/MediaFormat.java b/src/com/android/settings/MediaFormat.java
index 20dac8e..517ec2d 100644
--- a/src/com/android/settings/MediaFormat.java
+++ b/src/com/android/settings/MediaFormat.java
@@ -72,9 +72,8 @@
      * component as a subactivity
      */
     private boolean runKeyguardConfirmation(int request) {
-        return new ChooseLockSettingsHelper(this)
-                .launchConfirmationActivity(request, null,
-                        getText(R.string.media_format_gesture_explanation));
+        return new ChooseLockSettingsHelper(this).launchConfirmationActivity(request,
+                getText(R.string.media_format_title));
     }
 
     @Override
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index a3376d3..587b8e8 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -78,8 +78,8 @@
      */
     private boolean runKeyguardConfirmation(int request) {
         Resources res = getActivity().getResources();
-        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(request,
-                null, res.getText(R.string.reset_network_gesture_explanation));
+        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+                request, res.getText(R.string.reset_network_title));
     }
 
     @Override
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index c74c90a..fd99536 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -603,8 +603,9 @@
             ChooseLockSettingsHelper helper =
                     new ChooseLockSettingsHelper(this.getActivity(), this);
             mTrustAgentClickIntent = preference.getIntent();
-            if (!helper.launchConfirmationActivity(CHANGE_TRUST_AGENT_SETTINGS, null, null) &&
-                    mTrustAgentClickIntent != null) {
+            boolean confirmationLaunched = helper.launchConfirmationActivity(
+                    CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
+            if (!confirmationLaunched&&  mTrustAgentClickIntent != null) {
                 // If this returns false, it means no password confirmation is required.
                 startActivity(mTrustAgentClickIntent);
                 mTrustAgentClickIntent = null;