Ask password when user adds a new fingerprint including a checkbox to ask that
if they want to use fingerprints in the future and stores it as shared prefernces.

Including some refactoring.
- Keep the purchase button visible after a successful purchase so that users of
the app can test a flow after registering a new fingerprint.
- Fixed broken tests.
- Use end/start instead of left/right for RTL languages.

Bug: 21655960

Change-Id: I9b0015fa5f61048c611ab798afbf96edbc3239eb
diff --git a/security/FingerprintDialog/Application/src/main/AndroidManifest.xml b/security/FingerprintDialog/Application/src/main/AndroidManifest.xml
index 5f754ad..3b19fbe 100644
--- a/security/FingerprintDialog/Application/src/main/AndroidManifest.xml
+++ b/security/FingerprintDialog/Application/src/main/AndroidManifest.xml
@@ -35,7 +35,9 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+
+        <activity
+            android:name=".SettingsActivity"
+            android:label="@string/action_settings" />
     </application>
-
-
 </manifest>
diff --git a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintAuthenticationDialogFragment.java b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintAuthenticationDialogFragment.java
index 57c00de..8909f75 100644
--- a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintAuthenticationDialogFragment.java
+++ b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintAuthenticationDialogFragment.java
@@ -17,6 +17,7 @@
 package com.example.android.fingerprintdialog;
 
 import android.app.DialogFragment;
+import android.content.SharedPreferences;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.view.KeyEvent;
@@ -26,6 +27,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
+import android.widget.CheckBox;
 import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -44,6 +46,9 @@
     private View mFingerprintContent;
     private View mBackupContent;
     private EditText mPassword;
+    private CheckBox mUseFingerprintFutureCheckBox;
+    private TextView mPasswordDescriptionTextView;
+    private TextView mNewFingerprintEnrolledTextView;
 
     private Stage mStage = Stage.FINGERPRINT;
 
@@ -52,6 +57,7 @@
 
     @Inject FingerprintUiHelper.FingerprintUiHelperBuilder mFingerprintUiHelperBuilder;
     @Inject InputMethodManager mInputMethodManager;
+    @Inject SharedPreferences mSharedPreferences;
 
     @Inject
     public FingerprintAuthenticationDialogFragment() {}
@@ -93,6 +99,11 @@
         mBackupContent = v.findViewById(R.id.backup_container);
         mPassword = (EditText) v.findViewById(R.id.password);
         mPassword.setOnEditorActionListener(this);
+        mPasswordDescriptionTextView = (TextView) v.findViewById(R.id.password_description);
+        mUseFingerprintFutureCheckBox = (CheckBox)
+                v.findViewById(R.id.use_fingerprint_in_future_check);
+        mNewFingerprintEnrolledTextView = (TextView)
+                v.findViewById(R.id.new_fingerprint_enrolled_description);
         mFingerprintUiHelper = mFingerprintUiHelperBuilder.build(
                 (ImageView) v.findViewById(R.id.fingerprint_icon),
                 (TextView) v.findViewById(R.id.fingerprint_status), this);
@@ -114,6 +125,10 @@
         }
     }
 
+    public void setStage(Stage stage) {
+        mStage = stage;
+    }
+
     @Override
     public void onPause() {
         super.onPause();
@@ -149,12 +164,25 @@
      * let's the activity know about the result.
      */
     private void verifyPassword() {
-        if (checkPassword(mPassword.getText().toString())) {
-            ((MainActivity) getActivity()).onPurchased(false /* without Fingerprint */);
-            dismiss();
-        } else {
-            // assume the password is always correct.
+        if (!checkPassword(mPassword.getText().toString())) {
+            return;
         }
+        MainActivity activity = ((MainActivity) getActivity());
+        if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) {
+            SharedPreferences.Editor editor = mSharedPreferences.edit();
+            editor.putBoolean(getString(R.string.use_fingerprint_to_authenticate_key),
+                    mUseFingerprintFutureCheckBox.isChecked());
+            editor.apply();
+
+            if (mUseFingerprintFutureCheckBox.isChecked()) {
+                // Re-create the key so that fingerprints including new ones are validated.
+                activity.createKey();
+                mStage = Stage.FINGERPRINT;
+            }
+        }
+        mPassword.setText("");
+        ((MainActivity) getActivity()).onPurchased(false /* without Fingerprint */);
+        dismiss();
     }
 
     /**
@@ -181,11 +209,18 @@
                 mFingerprintContent.setVisibility(View.VISIBLE);
                 mBackupContent.setVisibility(View.GONE);
                 break;
+            case NEW_FINGERPRINT_ENROLLED:
+                // Intentional fall through
             case PASSWORD:
                 mCancelButton.setText(R.string.cancel);
                 mSecondDialogButton.setText(R.string.ok);
                 mFingerprintContent.setVisibility(View.GONE);
                 mBackupContent.setVisibility(View.VISIBLE);
+                if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) {
+                    mPasswordDescriptionTextView.setVisibility(View.GONE);
+                    mNewFingerprintEnrolledTextView.setVisibility(View.VISIBLE);
+                    mUseFingerprintFutureCheckBox.setVisibility(View.VISIBLE);
+                }
                 break;
         }
     }
@@ -215,8 +250,9 @@
     /**
      * Enumeration to indicate which authentication method the user is trying to authenticate with.
      */
-    private enum Stage {
+    public enum Stage {
         FINGERPRINT,
+        NEW_FINGERPRINT_ENROLLED,
         PASSWORD
     }
 }
diff --git a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintModule.java b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintModule.java
index 16d5067..964e1f6 100644
--- a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintModule.java
+++ b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintModule.java
@@ -18,7 +18,10 @@
 
 import android.app.KeyguardManager;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.hardware.fingerprint.FingerprintManager;
+import android.preference.PreferenceManager;
+import android.security.keystore.KeyProperties;
 import android.view.inputmethod.InputMethodManager;
 
 import java.security.KeyStore;
@@ -75,7 +78,7 @@
     @Provides
     public KeyGenerator providesKeyGenerator() {
         try {
-            return KeyGenerator.getInstance("AES", "AndroidKeyStore");
+            return KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
         } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
             throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
         }
@@ -84,7 +87,9 @@
     @Provides
     public Cipher providesCipher(KeyStore keyStore) {
         try {
-            return Cipher.getInstance("AES/CBC/PKCS7Padding");
+            return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+                    + KeyProperties.BLOCK_MODE_CBC + "/"
+                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
         } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
             throw new RuntimeException("Failed to get an instance of Cipher", e);
         }
@@ -94,4 +99,9 @@
     public InputMethodManager providesInputMethodManager(Context context) {
         return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
     }
+
+    @Provides
+    public SharedPreferences providesSharedPreferences(Context context) {
+        return PreferenceManager.getDefaultSharedPreferences(context);
+    }
 }
diff --git a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.java b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.java
index 6d31ddc..92fcdb1 100644
--- a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.java
+++ b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.java
@@ -82,7 +82,8 @@
         }
         mCancellationSignal = new CancellationSignal();
         mSelfCancelled = false;
-        mFingerprintManager.authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
+        mFingerprintManager
+                .authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
         mIcon.setImageResource(R.drawable.ic_fp_40px);
     }
 
diff --git a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/MainActivity.java b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/MainActivity.java
index 9d09765..208fd17 100644
--- a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/MainActivity.java
+++ b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/MainActivity.java
@@ -19,6 +19,8 @@
 import android.Manifest;
 import android.app.Activity;
 import android.app.KeyguardManager;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
@@ -27,6 +29,8 @@
 import android.security.keystore.KeyProperties;
 import android.util.Base64;
 import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.widget.Button;
 import android.widget.TextView;
@@ -60,23 +64,28 @@
     /** Alias for our key in the Android Key Store */
     private static final String KEY_NAME = "my_key";
 
+    private static final int FINGERPRINT_PERMISSION_REQUEST_CODE = 0;
+
     @Inject KeyguardManager mKeyguardManager;
     @Inject FingerprintAuthenticationDialogFragment mFragment;
     @Inject KeyStore mKeyStore;
     @Inject KeyGenerator mKeyGenerator;
     @Inject Cipher mCipher;
+    @Inject SharedPreferences mSharedPreferences;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         ((InjectedApplication) getApplication()).inject(this);
 
-        requestPermissions(new String[]{Manifest.permission.USE_FINGERPRINT}, 0);
+        requestPermissions(new String[]{Manifest.permission.USE_FINGERPRINT},
+                FINGERPRINT_PERMISSION_REQUEST_CODE);
     }
 
     @Override
     public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] state) {
-        if (requestCode == 0 && state[0] == PackageManager.PERMISSION_GRANTED) {
+        if (requestCode == FINGERPRINT_PERMISSION_REQUEST_CODE
+                && state[0] == PackageManager.PERMISSION_GRANTED) {
             setContentView(R.layout.activity_main);
             Button purchaseButton = (Button) findViewById(R.id.purchase_button);
             if (!mKeyguardManager.isKeyguardSecure()) {
@@ -86,37 +95,63 @@
                                 + "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint",
                         Toast.LENGTH_LONG).show();
                 purchaseButton.setEnabled(false);
-                return;
             }
             createKey();
             purchaseButton.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
+                    findViewById(R.id.confirmation_message).setVisibility(View.GONE);
+                    findViewById(R.id.encrypted_message).setVisibility(View.GONE);
 
-                    // Show the fingerprint dialog. The user has the option to use the fingerprint with
-                    // crypto, or you can fall back to using a server-side verified password.
-                    mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
-                    mFragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+                    // Set up the crypto object for later. The object will be authenticated by use
+                    // of the fingerprint.
+                    if (initCipher()) {
+
+                        // Show the fingerprint dialog. The user has the option to use the fingerprint with
+                        // crypto, or you can fall back to using a server-side verified password.
+                        mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
+                        boolean useFingerprintPreference = mSharedPreferences
+                                .getBoolean(getString(R.string.use_fingerprint_to_authenticate_key),
+                                        true);
+                        if (useFingerprintPreference) {
+                            mFragment.setStage(
+                                    FingerprintAuthenticationDialogFragment.Stage.FINGERPRINT);
+                        } else {
+                            mFragment.setStage(
+                                    FingerprintAuthenticationDialogFragment.Stage.PASSWORD);
+                        }
+                        mFragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+                    } else {
+                        // This happens if the lock screen has been disabled or or a fingerprint got
+                        // enrolled. Thus show the dialog to authenticate with their password first
+                        // and ask the user if they want to authenticate with fingerprints in the
+                        // future
+                        mFragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
+                        mFragment.setStage(
+                                FingerprintAuthenticationDialogFragment.Stage.NEW_FINGERPRINT_ENROLLED);
+                        mFragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
+                    }
                 }
             });
-
-            // Set up the crypto object for later. The object will be authenticated by use
-            // of the fingerprint.
-            initCipher();
         }
     }
 
-    private void initCipher() {
+    /**
+     * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()}
+     * method.
+     *
+     * @return {@code true} if initialization is successful, {@code false} if the lock screen has
+     * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
+     * the key was generated.
+     */
+    private boolean initCipher() {
         try {
             mKeyStore.load(null);
             SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null);
             mCipher.init(Cipher.ENCRYPT_MODE, key);
+            return true;
         } catch (KeyPermanentlyInvalidatedException e) {
-            // This happens if the lock screen has been disabled or reset after the key was
-            // generated, or if a fingerprint got enrolled after the key was generated.
-            Toast.makeText(this, "Keys are invalidated after created. Retry the purchase\n"
-                            + e.getMessage(),
-                    Toast.LENGTH_LONG).show();
+            return false;
         } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
                 | NoSuchAlgorithmException | InvalidKeyException e) {
             throw new RuntimeException("Failed to init Cipher", e);
@@ -124,7 +159,6 @@
     }
 
     public void onPurchased(boolean withFingerprint) {
-        findViewById(R.id.purchase_button).setVisibility(View.GONE);
         if (withFingerprint) {
             // If the user has authenticated with fingerprint, verify that using cryptography and
             // then show the confirmation message.
@@ -164,7 +198,7 @@
      * Creates a symmetric key in the Android Key Store which can only be used after the user has
      * authenticated with fingerprint.
      */
-    private void createKey() {
+    public void createKey() {
         // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
         // for your flow. Use of keys is necessary if you need to know if the set of
         // enrolled fingerprints has changed.
@@ -187,4 +221,22 @@
             throw new RuntimeException(e);
         }
     }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.menu_main, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        int id = item.getItemId();
+
+        if (id == R.id.action_settings) {
+            Intent intent = new Intent(this, SettingsActivity.class);
+            startActivity(intent);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
 }
diff --git a/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/SettingsActivity.java b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/SettingsActivity.java
new file mode 100644
index 0000000..08b3911
--- /dev/null
+++ b/security/FingerprintDialog/Application/src/main/java/com/example/android/fingerprintdialog/SettingsActivity.java
@@ -0,0 +1,47 @@
+/*
+ * 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.example.android.fingerprintdialog;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class SettingsActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Display the fragment as the main content.
+        getFragmentManager().beginTransaction().replace(android.R.id.content,
+                new SettingsFragment()).commit();
+    }
+
+    /**
+     * Fragment for settings.
+     */
+    public static class SettingsFragment extends PreferenceFragment {
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            addPreferencesFromResource(R.xml.preferences);
+        }
+    }
+}
+
+
diff --git a/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_backup.xml b/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_backup.xml
index 0b88e33..2be05b1 100644
--- a/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_backup.xml
+++ b/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_backup.xml
@@ -16,21 +16,37 @@
   -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/backup_container"
-    android:layout_width="match_parent" android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:paddingTop="16dp"
     android:paddingBottom="8dp">
 
-    <TextView
+    <FrameLayout
+        android:id="@+id/description"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-        android:text="@string/password_description"
-        android:id="@+id/description"
         android:layout_alignParentTop="true"
         android:layout_alignParentStart="true"
         android:layout_marginStart="24dp"
         android:layout_marginEnd="24dp"
-        android:textColor="?android:attr/textColorSecondary"/>
+        >
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+            android:text="@string/password_description"
+            android:id="@+id/password_description"
+            android:textColor="?android:attr/textColorSecondary" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+            android:text="@string/new_fingerprint_enrolled_description"
+            android:id="@+id/new_fingerprint_enrolled_description"
+            android:visibility="gone"
+            android:textColor="?android:attr/textColorSecondary" />
+    </FrameLayout>
 
     <EditText
         android:layout_width="wrap_content"
@@ -46,4 +62,17 @@
         android:layout_marginEnd="20dp"
         android:layout_alignParentStart="true" />
 
+    <CheckBox
+        android:id="@+id/use_fingerprint_in_future_check"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@+id/password"
+        android:layout_alignParentStart="true"
+        android:layout_marginTop="16dp"
+        android:layout_marginStart="20dp"
+        android:layout_marginEnd="20dp"
+        android:checked="true"
+        android:visibility="gone"
+        android:text="@string/use_fingerprint_in_future" />
+
 </RelativeLayout>
\ No newline at end of file
diff --git a/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_content.xml b/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_content.xml
index b56ccbb..3929eba 100644
--- a/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_content.xml
+++ b/security/FingerprintDialog/Application/src/main/res/layout/fingerprint_dialog_content.xml
@@ -19,8 +19,8 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingBottom="8dp"
-    android:paddingLeft="24dp"
-    android:paddingRight="24dp"
+    android:paddingStart="24dp"
+    android:paddingEnd="24dp"
     android:paddingTop="16dp">
 
     <TextView
@@ -50,7 +50,7 @@
         android:layout_height="wrap_content"
         android:layout_alignBottom="@+id/fingerprint_icon"
         android:layout_alignTop="@+id/fingerprint_icon"
-        android:layout_marginLeft="16dp"
+        android:layout_marginStart="16dp"
         android:layout_toEndOf="@+id/fingerprint_icon"
         android:gravity="center_vertical"
         android:text="@string/fingerprint_hint"
diff --git a/security/FingerprintDialog/Application/src/main/res/menu/menu_main.xml b/security/FingerprintDialog/Application/src/main/res/menu/menu_main.xml
new file mode 100644
index 0000000..73f5e89
--- /dev/null
+++ b/security/FingerprintDialog/Application/src/main/res/menu/menu_main.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
+    <item android:id="@+id/action_settings" android:title="@string/action_settings"
+        android:orderInCategory="100" android:showAsAction="never" />
+</menu>
diff --git a/security/FingerprintDialog/Application/src/main/res/values/strings.xml b/security/FingerprintDialog/Application/src/main/res/values/strings.xml
index 8a6ecde..9f5a6fd 100644
--- a/security/FingerprintDialog/Application/src/main/res/values/strings.xml
+++ b/security/FingerprintDialog/Application/src/main/res/values/strings.xml
@@ -31,4 +31,8 @@
     <string name="item_price">$62.68</string>
     <string name="item_description">Mesh backpack in white. Black textile trim throughout.</string>
     <string name="purchase_done">Purchase successful</string>
+    <string name="new_fingerprint_enrolled_description">A new fingerprint was added to this device, so your password is required.</string>
+    <string name="use_fingerprint_in_future">Use fingerprint in the future</string>
+    <string name="use_fingerprint_to_authenticate_title">Use fingerprint to authenticate</string>
+    <string name="use_fingerprint_to_authenticate_key" >use_fingerprint_to_authenticate_key</string>
 </resources>
diff --git a/security/FingerprintDialog/Application/src/main/res/xml/preferences.xml b/security/FingerprintDialog/Application/src/main/res/xml/preferences.xml
new file mode 100644
index 0000000..761391d
--- /dev/null
+++ b/security/FingerprintDialog/Application/src/main/res/xml/preferences.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
+    <CheckBoxPreference
+        android:key="@string/use_fingerprint_to_authenticate_key"
+        android:title="@string/use_fingerprint_to_authenticate_title"
+        android:persistent="true"
+        android:defaultValue="true" />
+</PreferenceScreen>
\ No newline at end of file
diff --git a/security/FingerprintDialog/Application/src/test/java/com/example/android/fingerprintdialog/FingerprintUiHelperTest.java b/security/FingerprintDialog/Application/src/test/java/com/example/android/fingerprintdialog/FingerprintUiHelperTest.java
index 9a68ee7..da9b2a3 100644
--- a/security/FingerprintDialog/Application/src/test/java/com/example/android/fingerprintdialog/FingerprintUiHelperTest.java
+++ b/security/FingerprintDialog/Application/src/test/java/com/example/android/fingerprintdialog/FingerprintUiHelperTest.java
@@ -12,6 +12,7 @@
 import android.content.res.Resources;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.CancellationSignal;
+import android.os.Handler;
 import android.widget.ImageView;
 import android.widget.TextView;
 
@@ -59,8 +60,9 @@
     public void testStartListening_fingerprintAuthAvailable() {
         mFingerprintUiHelper.startListening(mockCryptoObject);
 
-        verify(mockFingerprintManager).authenticate(eq(mockCryptoObject), eq(0),
-                isA(CancellationSignal.class), eq(mFingerprintUiHelper), any(Handler.class));
+        verify(mockFingerprintManager).authenticate(eq(mockCryptoObject),
+                isA(CancellationSignal.class), eq(0), eq(mFingerprintUiHelper),
+                any(Handler.class));
         verify(mockIcon).setImageResource(R.drawable.ic_fp_40px);
     }
 
@@ -71,8 +73,8 @@
         mFingerprintUiHelper.startListening(mockCryptoObject);
 
         verify(mockFingerprintManager, never()).authenticate(
-                any(FingerprintManager.CryptoObject.class), eq(0),
-                any(CancellationSignal.class), any(FingerprintUiHelper.class), any(Handler.class));
+                any(FingerprintManager.CryptoObject.class), any(CancellationSignal.class), eq(0),
+                any(FingerprintUiHelper.class), any(Handler.class));
     }
 
     @Test
diff --git a/security/FingerprintDialog/screenshots/4-new-fingerprint-enrolled.png b/security/FingerprintDialog/screenshots/4-new-fingerprint-enrolled.png
new file mode 100644
index 0000000..7dcf080
--- /dev/null
+++ b/security/FingerprintDialog/screenshots/4-new-fingerprint-enrolled.png
Binary files differ
diff --git a/security/FingerprintDialog/template-params.xml b/security/FingerprintDialog/template-params.xml
index 3916c57..ab392ea 100644
--- a/security/FingerprintDialog/template-params.xml
+++ b/security/FingerprintDialog/template-params.xml
@@ -61,6 +61,7 @@
             <img>screenshots/1-purchase-screen.png</img>
             <img>screenshots/2-fingerprint-dialog.png</img>
             <img>screenshots/3-fingerprint-authenticated.png</img>
+            <img>screenshots/4-new-fingerprint-enrolled.png</img>
         </screenshots>
 
         <api_refs>