19218687e4baaf0226ef16b58f78123d979711e5dJim Miller/*
29218687e4baaf0226ef16b58f78123d979711e5dJim Miller * Copyright (C) 2015 The Android Open Source Project
39218687e4baaf0226ef16b58f78123d979711e5dJim Miller *
49218687e4baaf0226ef16b58f78123d979711e5dJim Miller * Licensed under the Apache License, Version 2.0 (the "License");
59218687e4baaf0226ef16b58f78123d979711e5dJim Miller * you may not use this file except in compliance with the License.
69218687e4baaf0226ef16b58f78123d979711e5dJim Miller * You may obtain a copy of the License at
79218687e4baaf0226ef16b58f78123d979711e5dJim Miller *
89218687e4baaf0226ef16b58f78123d979711e5dJim Miller *      http://www.apache.org/licenses/LICENSE-2.0
99218687e4baaf0226ef16b58f78123d979711e5dJim Miller *
109218687e4baaf0226ef16b58f78123d979711e5dJim Miller * Unless required by applicable law or agreed to in writing, software
119218687e4baaf0226ef16b58f78123d979711e5dJim Miller * distributed under the License is distributed on an "AS IS" BASIS,
129218687e4baaf0226ef16b58f78123d979711e5dJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139218687e4baaf0226ef16b58f78123d979711e5dJim Miller * See the License for the specific language governing permissions and
149218687e4baaf0226ef16b58f78123d979711e5dJim Miller * limitations under the License.
159218687e4baaf0226ef16b58f78123d979711e5dJim Miller */
169218687e4baaf0226ef16b58f78123d979711e5dJim Miller
175ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggipackage com.android.settings.fingerprint;
189218687e4baaf0226ef16b58f78123d979711e5dJim Miller
199218687e4baaf0226ef16b58f78123d979711e5dJim Miller
204dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.annotation.Nullable;
219218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.app.Activity;
229218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.app.AlertDialog;
23f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinekimport android.app.Dialog;
24f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinekimport android.app.DialogFragment;
25e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Moralesimport android.app.admin.DevicePolicyManager;
264dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.content.ActivityNotFoundException;
279218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.content.Context;
289218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.content.DialogInterface;
299218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.content.Intent;
304dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.graphics.Typeface;
314f6f7c865f25f478e5198031d419b498bdeb7ffaJim Millerimport android.graphics.drawable.Drawable;
324dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.hardware.fingerprint.Fingerprint;
334dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.hardware.fingerprint.FingerprintManager;
344dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
354dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
364dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.hardware.fingerprint.FingerprintManager.RemovalCallback;
379218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.os.Bundle;
388e056115eead7040584eda8c78b069998f0a9f2bJim Millerimport android.os.CancellationSignal;
394f6f7c865f25f478e5198031d419b498bdeb7ffaJim Millerimport android.os.Handler;
409218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.preference.Preference;
419218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.preference.Preference.OnPreferenceChangeListener;
429218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.preference.PreferenceGroup;
439218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.preference.PreferenceScreen;
444dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.text.Annotation;
454dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.text.SpannableString;
464dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.text.SpannableStringBuilder;
474dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.text.TextPaint;
484dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.text.method.LinkMovementMethod;
494dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.text.style.URLSpan;
504f6f7c865f25f478e5198031d419b498bdeb7ffaJim Millerimport android.util.AttributeSet;
519218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.util.Log;
524dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.view.LayoutInflater;
534f6f7c865f25f478e5198031d419b498bdeb7ffaJim Millerimport android.view.View;
54a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Millerimport android.view.WindowManager;
559218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport android.widget.EditText;
564dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport android.widget.TextView;
57d16c9b7c3100b7ba653dcd58db036500dd220896Jim Millerimport android.widget.Toast;
589218687e4baaf0226ef16b58f78123d979711e5dJim Miller
598a963babe2e36b7a41f77b8d2598c97658196e58Chris Wrenimport com.android.internal.logging.MetricsLogger;
605ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggiimport com.android.settings.ChooseLockGeneric;
615ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggiimport com.android.settings.ChooseLockSettingsHelper;
624dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport com.android.settings.HelpUtils;
635ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggiimport com.android.settings.R;
645ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggiimport com.android.settings.SettingsPreferenceFragment;
654dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggiimport com.android.settings.SubSettings;
669218687e4baaf0226ef16b58f78123d979711e5dJim Miller
679218687e4baaf0226ef16b58f78123d979711e5dJim Millerimport java.util.List;
689218687e4baaf0226ef16b58f78123d979711e5dJim Miller
699218687e4baaf0226ef16b58f78123d979711e5dJim Miller/**
709218687e4baaf0226ef16b58f78123d979711e5dJim Miller * Settings screen for fingerprints
719218687e4baaf0226ef16b58f78123d979711e5dJim Miller */
724dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggipublic class FingerprintSettings extends SubSettings {
73457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller
74e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales    /**
75457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     * Used by the choose fingerprint wizard to indicate the wizard is
76e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     * finished, and each activity in the wizard should finish.
77e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     * <p>
78e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     * Previously, each activity in the wizard would finish itself after
79e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     * starting the next activity. However, this leads to broken 'Back'
80e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     * behavior. So, now an activity does not finish itself until it gets this
81e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     * result.
82e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales     */
83457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller    protected static final int RESULT_FINISHED = RESULT_FIRST_USER;
84457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller
85457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller    /**
86457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     * Used by the enrolling screen during setup wizard to skip over setting up fingerprint, which
87457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     * will be useful if the user accidentally entered this flow.
88457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     */
89457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller    protected static final int RESULT_SKIP = RESULT_FIRST_USER + 1;
90457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller
91457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller    /**
92457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     * Like {@link #RESULT_FINISHED} except this one indicates enrollment failed because the
93457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     * device was left idle. This is used to clear the credential token to require the user to
94457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     * re-enter their pin/pattern/password before continuing.
95457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller     */
96457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller    protected static final int RESULT_TIMEOUT = RESULT_FIRST_USER + 2;
97457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller
988e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller    private static final long LOCKOUT_DURATION = 30000; // time we have to wait for fp to reset, ms
999218687e4baaf0226ef16b58f78123d979711e5dJim Miller
1009218687e4baaf0226ef16b58f78123d979711e5dJim Miller    @Override
1019218687e4baaf0226ef16b58f78123d979711e5dJim Miller    public Intent getIntent() {
1029218687e4baaf0226ef16b58f78123d979711e5dJim Miller        Intent modIntent = new Intent(super.getIntent());
1039218687e4baaf0226ef16b58f78123d979711e5dJim Miller        modIntent.putExtra(EXTRA_SHOW_FRAGMENT, FingerprintSettingsFragment.class.getName());
1049218687e4baaf0226ef16b58f78123d979711e5dJim Miller        return modIntent;
1059218687e4baaf0226ef16b58f78123d979711e5dJim Miller    }
1069218687e4baaf0226ef16b58f78123d979711e5dJim Miller
1079218687e4baaf0226ef16b58f78123d979711e5dJim Miller    @Override
1089218687e4baaf0226ef16b58f78123d979711e5dJim Miller    protected boolean isValidFragment(String fragmentName) {
1099218687e4baaf0226ef16b58f78123d979711e5dJim Miller        if (FingerprintSettingsFragment.class.getName().equals(fragmentName)) return true;
1109218687e4baaf0226ef16b58f78123d979711e5dJim Miller        return false;
1119218687e4baaf0226ef16b58f78123d979711e5dJim Miller    }
1129218687e4baaf0226ef16b58f78123d979711e5dJim Miller
1139218687e4baaf0226ef16b58f78123d979711e5dJim Miller    @Override
1149218687e4baaf0226ef16b58f78123d979711e5dJim Miller    public void onCreate(Bundle savedInstanceState) {
1159218687e4baaf0226ef16b58f78123d979711e5dJim Miller        super.onCreate(savedInstanceState);
1169218687e4baaf0226ef16b58f78123d979711e5dJim Miller        CharSequence msg = getText(R.string.security_settings_fingerprint_preference_title);
1179218687e4baaf0226ef16b58f78123d979711e5dJim Miller        setTitle(msg);
1189218687e4baaf0226ef16b58f78123d979711e5dJim Miller    }
1199218687e4baaf0226ef16b58f78123d979711e5dJim Miller
1209218687e4baaf0226ef16b58f78123d979711e5dJim Miller    public static class FingerprintSettingsFragment extends SettingsPreferenceFragment
121f516e7dde0074416dbf51650cbfb9cc763027b27Julia Reynolds        implements OnPreferenceChangeListener {
122a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private static final int MAX_RETRY_ATTEMPTS = 20;
123a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private static final int RESET_HIGHLIGHT_DELAY_MS = 500;
124a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller
1259218687e4baaf0226ef16b58f78123d979711e5dJim Miller        private static final String TAG = "FingerprintSettings";
1268a7dea562087a58ae8eb0699f262d7114db719bcJim Miller        private static final String KEY_FINGERPRINT_ITEM_PREFIX = "key_fingerprint_item";
1279218687e4baaf0226ef16b58f78123d979711e5dJim Miller        private static final String KEY_FINGERPRINT_ADD = "key_fingerprint_add";
1289218687e4baaf0226ef16b58f78123d979711e5dJim Miller        private static final String KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE =
1299218687e4baaf0226ef16b58f78123d979711e5dJim Miller                "fingerprint_enable_keyguard_toggle";
130887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales        private static final String KEY_LAUNCHED_CONFIRM = "launched_confirm";
1319218687e4baaf0226ef16b58f78123d979711e5dJim Miller
1324f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
133a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
134a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private static final int MSG_FINGER_AUTH_FAIL = 1002;
135fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller        private static final int MSG_FINGER_AUTH_ERROR = 1003;
136fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller        private static final int MSG_FINGER_AUTH_HELP = 1004;
1374f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
138e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        private static final int CONFIRM_REQUEST = 101;
139e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        private static final int CHOOSE_LOCK_GENERIC_REQUEST = 102;
140e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
1419218687e4baaf0226ef16b58f78123d979711e5dJim Miller        private static final int ADD_FINGERPRINT_REQUEST = 10;
1429218687e4baaf0226ef16b58f78123d979711e5dJim Miller
143d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        protected static final boolean DEBUG = true;
1449218687e4baaf0226ef16b58f78123d979711e5dJim Miller
1459218687e4baaf0226ef16b58f78123d979711e5dJim Miller        private FingerprintManager mFingerprintManager;
1468e056115eead7040584eda8c78b069998f0a9f2bJim Miller        private CancellationSignal mFingerprintCancel;
1478e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        private boolean mInFingerprintLockout;
148e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        private byte[] mToken;
149887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales        private boolean mLaunchedConfirm;
150a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private Drawable mHighlightDrawable;
1518e056115eead7040584eda8c78b069998f0a9f2bJim Miller
152d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        private AuthenticationCallback mAuthCallback = new AuthenticationCallback() {
153d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            @Override
154d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            public void onAuthenticationSucceeded(AuthenticationResult result) {
155a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                int fingerId = result.getFingerprint().getFingerId();
156a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                mHandler.obtainMessage(MSG_FINGER_AUTH_SUCCESS, fingerId, 0).sendToTarget();
157d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            }
158d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller
159e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller            @Override
1608e056115eead7040584eda8c78b069998f0a9f2bJim Miller            public void onAuthenticationFailed() {
161a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                mHandler.obtainMessage(MSG_FINGER_AUTH_FAIL).sendToTarget();
1628e056115eead7040584eda8c78b069998f0a9f2bJim Miller            };
1638e056115eead7040584eda8c78b069998f0a9f2bJim Miller
164d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            @Override
165d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            public void onAuthenticationError(int errMsgId, CharSequence errString) {
166fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                mHandler.obtainMessage(MSG_FINGER_AUTH_ERROR, errMsgId, 0, errString)
167fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                        .sendToTarget();
168d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            }
169d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller
170d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            @Override
171d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
172fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                mHandler.obtainMessage(MSG_FINGER_AUTH_HELP, helpMsgId, 0, helpString)
173fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                        .sendToTarget();
174d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            }
175d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        };
176d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        private RemovalCallback mRemoveCallback = new RemovalCallback() {
177d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller
178d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            @Override
179d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            public void onRemovalSucceeded(Fingerprint fingerprint) {
180d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                mHandler.obtainMessage(MSG_REFRESH_FINGERPRINT_TEMPLATES,
181d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                        fingerprint.getFingerId(), 0).sendToTarget();
182d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            }
183d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller
184d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            @Override
185d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) {
186622142ce9d8c6359d27b44827551c665c800347cJim Miller                final Activity activity = getActivity();
187622142ce9d8c6359d27b44827551c665c800347cJim Miller                if (activity != null) {
188622142ce9d8c6359d27b44827551c665c800347cJim Miller                    Toast.makeText(activity, errString, Toast.LENGTH_SHORT);
189622142ce9d8c6359d27b44827551c665c800347cJim Miller                }
190d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            }
191d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        };
1924f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        private final Handler mHandler = new Handler() {
193e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller            @Override
1944f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            public void handleMessage(android.os.Message msg) {
1954f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                switch (msg.what) {
1964f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                    case MSG_REFRESH_FINGERPRINT_TEMPLATES:
1974f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                        removeFingerprintPreference(msg.arg1);
1985adada6083c1fb5e520e3044698b03ee29772dabJim Miller                        updateAddPreference();
1991e2433693adbe2cca0feab79c18ae5be9e43d167Jorim Jaggi                        retryFingerprint();
2004f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                    break;
201a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                    case MSG_FINGER_AUTH_SUCCESS:
202fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                        mFingerprintCancel = null;
2034f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                        highlightFingerprintItem(msg.arg1);
2048e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                        retryFingerprint();
205a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                    break;
206a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                    case MSG_FINGER_AUTH_FAIL:
2078e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                        // No action required... fingerprint will allow up to 5 of these
2084f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                    break;
2098e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    case MSG_FINGER_AUTH_ERROR:
2108e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                        handleError(msg.arg1 /* errMsgId */, (CharSequence) msg.obj /* errStr */ );
211fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                    break;
212fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                    case MSG_FINGER_AUTH_HELP: {
2138e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                        // Not used
214fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                    }
215fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                    break;
2164f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                }
2174f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            };
2184f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        };
2199218687e4baaf0226ef16b58f78123d979711e5dJim Miller
2208e056115eead7040584eda8c78b069998f0a9f2bJim Miller        private void stopFingerprint() {
2218e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            if (mFingerprintCancel != null && !mFingerprintCancel.isCanceled()) {
2228e056115eead7040584eda8c78b069998f0a9f2bJim Miller                mFingerprintCancel.cancel();
2238e056115eead7040584eda8c78b069998f0a9f2bJim Miller            }
2248e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            mFingerprintCancel = null;
2258e056115eead7040584eda8c78b069998f0a9f2bJim Miller        }
2268e056115eead7040584eda8c78b069998f0a9f2bJim Miller
2278e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        /**
2288e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller         * @param errMsgId
2298e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller         */
2308e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        protected void handleError(int errMsgId, CharSequence msg) {
2318e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            mFingerprintCancel = null;
2328e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            switch (errMsgId) {
2338e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                case FingerprintManager.FINGERPRINT_ERROR_CANCELED:
2348e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    return; // Only happens if we get preempted by another activity. Ignored.
2358e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                case FingerprintManager.FINGERPRINT_ERROR_LOCKOUT:
2368e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    mInFingerprintLockout = true;
2378e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    // We've been locked out.  Reset after 30s.
2388e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    if (!mHandler.hasCallbacks(mFingerprintLockoutReset)) {
2398e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                        mHandler.postDelayed(mFingerprintLockoutReset,
2408e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                                LOCKOUT_DURATION);
2418e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    }
2428e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    // Fall through to show message
2438e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                default:
2448e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    // Activity can be null on a screen rotation.
2458e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    final Activity activity = getActivity();
2468e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    if (activity != null) {
2478e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                        Toast.makeText(activity, msg , Toast.LENGTH_SHORT);
2488e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                    }
2498e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                break;
2508e056115eead7040584eda8c78b069998f0a9f2bJim Miller            }
2518e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            retryFingerprint(); // start again
2528e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        }
2538e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller
2548e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        private void retryFingerprint() {
2558e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            if (!mInFingerprintLockout) {
2568e056115eead7040584eda8c78b069998f0a9f2bJim Miller                mFingerprintCancel = new CancellationSignal();
257fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                mFingerprintManager.authenticate(null, mFingerprintCancel, 0 /* flags */,
258fa47bc02900d407e1a730039e94221c2efc160d0Jim Miller                        mAuthCallback, null);
2598e056115eead7040584eda8c78b069998f0a9f2bJim Miller            }
2608e056115eead7040584eda8c78b069998f0a9f2bJim Miller        }
2618e056115eead7040584eda8c78b069998f0a9f2bJim Miller
2629218687e4baaf0226ef16b58f78123d979711e5dJim Miller        @Override
2638a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren        protected int getMetricsCategory() {
2648a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren            return MetricsLogger.FINGERPRINT;
2658a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren        }
2668a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren
2678a963babe2e36b7a41f77b8d2598c97658196e58Chris Wren        @Override
2689218687e4baaf0226ef16b58f78123d979711e5dJim Miller        public void onCreate(Bundle savedInstanceState) {
2699218687e4baaf0226ef16b58f78123d979711e5dJim Miller            super.onCreate(savedInstanceState);
270e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            if (savedInstanceState != null) {
271e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                mToken = savedInstanceState.getByteArray(
272e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                        ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
273887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales                mLaunchedConfirm = savedInstanceState.getBoolean(
274887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales                        KEY_LAUNCHED_CONFIRM, false);
275e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            }
276e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
277a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            Activity activity = getActivity();
278a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            mFingerprintManager = (FingerprintManager) activity.getSystemService(
2799218687e4baaf0226ef16b58f78123d979711e5dJim Miller                    Context.FINGERPRINT_SERVICE);
280e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
281e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            // Need to authenticate a session token if none
282887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales            if (mToken == null && mLaunchedConfirm == false) {
283887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales                mLaunchedConfirm = true;
284e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                launchChooseOrConfirmLock();
285e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            }
2869218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
2879218687e4baaf0226ef16b58f78123d979711e5dJim Miller
2884dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        @Override
2894dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
2904dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            super.onViewCreated(view, savedInstanceState);
2914dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            TextView v = (TextView) LayoutInflater.from(view.getContext()).inflate(
2924dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                    R.layout.fingerprint_settings_footer, null);
2934dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            v.setText(LearnMoreSpan.linkify(getText(isFingerprintDisabled()
2944dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                            ? R.string.security_settings_fingerprint_enroll_disclaimer_lockscreen_disabled
2954dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                            : R.string.security_settings_fingerprint_enroll_disclaimer),
2964dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                    getString(getHelpResource())));
2974dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            v.setMovementMethod(new LinkMovementMethod());
2984dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            getListView().addFooterView(v);
2994dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            getListView().setFooterDividersEnabled(false);
3004dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        }
3014dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
3024dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        private boolean isFingerprintDisabled() {
3034dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            final DevicePolicyManager dpm =
3044dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                    (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
3054dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            return dpm != null && (dpm.getKeyguardDisabledFeatures(null)
3064dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                    & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
3074dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        }
3084dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
3094f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        protected void removeFingerprintPreference(int fingerprintId) {
3104f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            String name = genKey(fingerprintId);
3110dbeeda0532518665389d458155322f69e603686Jorim Jaggi            Preference prefToRemove = findPreference(name);
3124f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            if (prefToRemove != null) {
3130dbeeda0532518665389d458155322f69e603686Jorim Jaggi                if (!getPreferenceScreen().removePreference(prefToRemove)) {
3144f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                    Log.w(TAG, "Failed to remove preference with key " + name);
3154f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                }
3164f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            } else {
3174f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                Log.w(TAG, "Can't find preference to remove: " + name);
3184f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            }
3194f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
3204f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
3219218687e4baaf0226ef16b58f78123d979711e5dJim Miller        /**
3229218687e4baaf0226ef16b58f78123d979711e5dJim Miller         * Important!
3239218687e4baaf0226ef16b58f78123d979711e5dJim Miller         *
3249218687e4baaf0226ef16b58f78123d979711e5dJim Miller         * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
3259218687e4baaf0226ef16b58f78123d979711e5dJim Miller         * logic or adding/removing preferences here.
3269218687e4baaf0226ef16b58f78123d979711e5dJim Miller         */
3279218687e4baaf0226ef16b58f78123d979711e5dJim Miller        private PreferenceScreen createPreferenceHierarchy() {
3289218687e4baaf0226ef16b58f78123d979711e5dJim Miller            PreferenceScreen root = getPreferenceScreen();
3299218687e4baaf0226ef16b58f78123d979711e5dJim Miller            if (root != null) {
3309218687e4baaf0226ef16b58f78123d979711e5dJim Miller                root.removeAll();
3319218687e4baaf0226ef16b58f78123d979711e5dJim Miller            }
3329218687e4baaf0226ef16b58f78123d979711e5dJim Miller            addPreferencesFromResource(R.xml.security_settings_fingerprint);
3339218687e4baaf0226ef16b58f78123d979711e5dJim Miller            root = getPreferenceScreen();
3344dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            addFingerprintItemPreferences(root);
3359218687e4baaf0226ef16b58f78123d979711e5dJim Miller            return root;
3369218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
3379218687e4baaf0226ef16b58f78123d979711e5dJim Miller
3384dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        private void addFingerprintItemPreferences(PreferenceGroup root) {
3394dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            root.removeAll();
340d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            final List<Fingerprint> items = mFingerprintManager.getEnrolledFingerprints();
3419218687e4baaf0226ef16b58f78123d979711e5dJim Miller            final int fingerprintCount = items.size();
3429218687e4baaf0226ef16b58f78123d979711e5dJim Miller            for (int i = 0; i < fingerprintCount; i++) {
343d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                final Fingerprint item = items.get(i);
3444dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                FingerprintPreference pref = new FingerprintPreference(root.getContext());
345d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                pref.setKey(genKey(item.getFingerId()));
346d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                pref.setTitle(item.getName());
347d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                pref.setFingerprint(item);
3484f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                pref.setPersistent(false);
3494dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                root.addPreference(pref);
3509218687e4baaf0226ef16b58f78123d979711e5dJim Miller                pref.setOnPreferenceChangeListener(this);
3519218687e4baaf0226ef16b58f78123d979711e5dJim Miller            }
3524dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            Preference addPreference = new Preference(root.getContext());
3539218687e4baaf0226ef16b58f78123d979711e5dJim Miller            addPreference.setKey(KEY_FINGERPRINT_ADD);
3549218687e4baaf0226ef16b58f78123d979711e5dJim Miller            addPreference.setTitle(R.string.fingerprint_add_title);
3554dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            addPreference.setIcon(R.drawable.ic_add_24dp);
3564dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            root.addPreference(addPreference);
3579218687e4baaf0226ef16b58f78123d979711e5dJim Miller            addPreference.setOnPreferenceChangeListener(this);
3585adada6083c1fb5e520e3044698b03ee29772dabJim Miller            updateAddPreference();
3595adada6083c1fb5e520e3044698b03ee29772dabJim Miller        }
3605adada6083c1fb5e520e3044698b03ee29772dabJim Miller
3615adada6083c1fb5e520e3044698b03ee29772dabJim Miller        private void updateAddPreference() {
3625adada6083c1fb5e520e3044698b03ee29772dabJim Miller            /* Disable preference if too many fingerprints added */
3635adada6083c1fb5e520e3044698b03ee29772dabJim Miller            final int max = getContext().getResources().getInteger(
3645adada6083c1fb5e520e3044698b03ee29772dabJim Miller                    com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
3655adada6083c1fb5e520e3044698b03ee29772dabJim Miller            boolean tooMany = mFingerprintManager.getEnrolledFingerprints().size() >= max;
3665adada6083c1fb5e520e3044698b03ee29772dabJim Miller            CharSequence maxSummary = tooMany ?
3675adada6083c1fb5e520e3044698b03ee29772dabJim Miller                    getContext().getString(R.string.fingerprint_add_max, max) : "";
3685adada6083c1fb5e520e3044698b03ee29772dabJim Miller            Preference addPreference = findPreference(KEY_FINGERPRINT_ADD);
3695adada6083c1fb5e520e3044698b03ee29772dabJim Miller            addPreference.setSummary(maxSummary);
3705adada6083c1fb5e520e3044698b03ee29772dabJim Miller            addPreference.setEnabled(!tooMany);
3719218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
3729218687e4baaf0226ef16b58f78123d979711e5dJim Miller
3734f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        private static String genKey(int id) {
3748a7dea562087a58ae8eb0699f262d7114db719bcJim Miller            return KEY_FINGERPRINT_ITEM_PREFIX + "_" + id;
3754f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
3764f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
3779218687e4baaf0226ef16b58f78123d979711e5dJim Miller        @Override
3789218687e4baaf0226ef16b58f78123d979711e5dJim Miller        public void onResume() {
3799218687e4baaf0226ef16b58f78123d979711e5dJim Miller            super.onResume();
3809218687e4baaf0226ef16b58f78123d979711e5dJim Miller            // Make sure we reload the preference hierarchy since fingerprints may be added,
3819218687e4baaf0226ef16b58f78123d979711e5dJim Miller            // deleted or renamed.
382a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            updatePreferences();
383a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        }
384e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
385a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private void updatePreferences() {
386a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            createPreferenceHierarchy();
3878e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            retryFingerprint();
3888e056115eead7040584eda8c78b069998f0a9f2bJim Miller        }
3898e056115eead7040584eda8c78b069998f0a9f2bJim Miller
3908e056115eead7040584eda8c78b069998f0a9f2bJim Miller        @Override
3918e056115eead7040584eda8c78b069998f0a9f2bJim Miller        public void onPause() {
3928e056115eead7040584eda8c78b069998f0a9f2bJim Miller            super.onPause();
3938e056115eead7040584eda8c78b069998f0a9f2bJim Miller            stopFingerprint();
3949218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
3959218687e4baaf0226ef16b58f78123d979711e5dJim Miller
3969218687e4baaf0226ef16b58f78123d979711e5dJim Miller        @Override
397e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        public void onSaveInstanceState(final Bundle outState) {
398e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
399e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                    mToken);
400887c90d8af1b9cbac51e0febfa33057a64a28ee5Andres Morales            outState.putBoolean(KEY_LAUNCHED_CONFIRM, mLaunchedConfirm);
401e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        }
402e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
403e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        @Override
4049218687e4baaf0226ef16b58f78123d979711e5dJim Miller        public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference pref) {
4059218687e4baaf0226ef16b58f78123d979711e5dJim Miller            final String key = pref.getKey();
4069218687e4baaf0226ef16b58f78123d979711e5dJim Miller            if (KEY_FINGERPRINT_ADD.equals(key)) {
4079218687e4baaf0226ef16b58f78123d979711e5dJim Miller                Intent intent = new Intent();
4085ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggi                intent.setClassName("com.android.settings",
4095ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggi                        FingerprintEnrollEnrolling.class.getName());
41055af42dce53fff7b4a878dde1d1ca0f752f88f9eAndres Morales                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
4119218687e4baaf0226ef16b58f78123d979711e5dJim Miller                startActivityForResult(intent, ADD_FINGERPRINT_REQUEST);
4124f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            } else if (pref instanceof FingerprintPreference) {
4134f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                FingerprintPreference fpref = (FingerprintPreference) pref;
414d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller                final Fingerprint fp =fpref.getFingerprint();
415f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                showRenameDeleteDialog(fp);
4169218687e4baaf0226ef16b58f78123d979711e5dJim Miller                return super.onPreferenceTreeClick(preferenceScreen, pref);
4179218687e4baaf0226ef16b58f78123d979711e5dJim Miller            }
4189218687e4baaf0226ef16b58f78123d979711e5dJim Miller            return true;
4199218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
4209218687e4baaf0226ef16b58f78123d979711e5dJim Miller
421f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        private void showRenameDeleteDialog(final Fingerprint fp) {
422b83cbe202bd56cf542d898837474757dca3625f2Jorim Jaggi            RenameDeleteDialog renameDeleteDialog = new RenameDeleteDialog();
423f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            Bundle args = new Bundle();
424f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            args.putParcelable("fingerprint", fp);
425f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            renameDeleteDialog.setArguments(args);
426f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            renameDeleteDialog.setTargetFragment(this, 0);
427f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            renameDeleteDialog.show(getFragmentManager(), RenameDeleteDialog.class.getName());
4289218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
4299218687e4baaf0226ef16b58f78123d979711e5dJim Miller
4309218687e4baaf0226ef16b58f78123d979711e5dJim Miller        @Override
4319218687e4baaf0226ef16b58f78123d979711e5dJim Miller        public boolean onPreferenceChange(Preference preference, Object value) {
4329218687e4baaf0226ef16b58f78123d979711e5dJim Miller            boolean result = true;
4339218687e4baaf0226ef16b58f78123d979711e5dJim Miller            final String key = preference.getKey();
4349218687e4baaf0226ef16b58f78123d979711e5dJim Miller            if (KEY_FINGERPRINT_ENABLE_KEYGUARD_TOGGLE.equals(key)) {
4359218687e4baaf0226ef16b58f78123d979711e5dJim Miller                // TODO
4369218687e4baaf0226ef16b58f78123d979711e5dJim Miller            } else {
4379218687e4baaf0226ef16b58f78123d979711e5dJim Miller                Log.v(TAG, "Unknown key:" + key);
4389218687e4baaf0226ef16b58f78123d979711e5dJim Miller            }
4399218687e4baaf0226ef16b58f78123d979711e5dJim Miller            return result;
4409218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
4419218687e4baaf0226ef16b58f78123d979711e5dJim Miller
4429218687e4baaf0226ef16b58f78123d979711e5dJim Miller        @Override
4439218687e4baaf0226ef16b58f78123d979711e5dJim Miller        protected int getHelpResource() {
4444dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            return R.string.help_url_fingerprint;
4459218687e4baaf0226ef16b58f78123d979711e5dJim Miller        }
446e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
447e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        @Override
448e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        public void onActivityResult(int requestCode, int resultCode, Intent data) {
449e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            super.onActivityResult(requestCode, resultCode, data);
450e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST
451e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                    || requestCode == CONFIRM_REQUEST) {
452e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
453e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                    // The lock pin/pattern/password was set. Start enrolling!
454e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                    if (data != null) {
455e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                        mToken = data.getByteArrayExtra(
456e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                                ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
457e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                    }
458e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                }
459457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller            } else if (requestCode == ADD_FINGERPRINT_REQUEST) {
460457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller                if (resultCode == RESULT_TIMEOUT) {
461457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller                    Activity activity = getActivity();
462457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller                    activity.setResult(RESULT_TIMEOUT);
463457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller                    activity.finish();
464457904634cdb657f1aff2b7da8cd7be68412e299Jim Miller                }
465e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            }
466e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
467e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            if (mToken == null) {
468e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                // Didn't get an authentication, finishing
469e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                getActivity().finish();
470e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            }
471e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        }
472e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales
473e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller        @Override
474e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller        public void onDestroy() {
475e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller            super.onDestroy();
476efaa19d97d4aba1897357971af4c0991af71dbbdJim Miller            if (getActivity().isFinishing()) {
477efaa19d97d4aba1897357971af4c0991af71dbbdJim Miller                int result = mFingerprintManager.postEnroll();
478efaa19d97d4aba1897357971af4c0991af71dbbdJim Miller                if (result < 0) {
479efaa19d97d4aba1897357971af4c0991af71dbbdJim Miller                    Log.w(TAG, "postEnroll failed: result = " + result);
480efaa19d97d4aba1897357971af4c0991af71dbbdJim Miller                }
481e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller            }
482e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller        }
483e9785ac1e4b779b6119460a5cdc71bce4d6563b9Jim Miller
484a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private Drawable getHighlightDrawable() {
485a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            if (mHighlightDrawable == null) {
486622142ce9d8c6359d27b44827551c665c800347cJim Miller                final Activity activity = getActivity();
487622142ce9d8c6359d27b44827551c665c800347cJim Miller                if (activity != null) {
488622142ce9d8c6359d27b44827551c665c800347cJim Miller                    mHighlightDrawable = activity.getDrawable(R.drawable.preference_highlight);
489622142ce9d8c6359d27b44827551c665c800347cJim Miller                }
490a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            }
491a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            return mHighlightDrawable;
492a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        }
493a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller
494a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        private void highlightFingerprintItem(int fpId) {
495a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            String prefName = genKey(fpId);
496622142ce9d8c6359d27b44827551c665c800347cJim Miller            FingerprintPreference fpref = (FingerprintPreference) findPreference(prefName);
497a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller            final Drawable highlight = getHighlightDrawable();
498622142ce9d8c6359d27b44827551c665c800347cJim Miller            if (highlight != null) {
499622142ce9d8c6359d27b44827551c665c800347cJim Miller                final View view = fpref.getView();
500622142ce9d8c6359d27b44827551c665c800347cJim Miller                final int centerX = view.getWidth() / 2;
501622142ce9d8c6359d27b44827551c665c800347cJim Miller                final int centerY = view.getHeight() / 2;
502622142ce9d8c6359d27b44827551c665c800347cJim Miller                highlight.setHotspot(centerX, centerY);
503622142ce9d8c6359d27b44827551c665c800347cJim Miller                view.setBackground(highlight);
504622142ce9d8c6359d27b44827551c665c800347cJim Miller                view.setPressed(true);
5051e2433693adbe2cca0feab79c18ae5be9e43d167Jorim Jaggi                view.setPressed(false);
506622142ce9d8c6359d27b44827551c665c800347cJim Miller                mHandler.postDelayed(new Runnable() {
507622142ce9d8c6359d27b44827551c665c800347cJim Miller                    @Override
508622142ce9d8c6359d27b44827551c665c800347cJim Miller                    public void run() {
509622142ce9d8c6359d27b44827551c665c800347cJim Miller                        view.setBackground(null);
510622142ce9d8c6359d27b44827551c665c800347cJim Miller                    }
511622142ce9d8c6359d27b44827551c665c800347cJim Miller                }, RESET_HIGHLIGHT_DELAY_MS);
512622142ce9d8c6359d27b44827551c665c800347cJim Miller            }
513a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        }
514a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller
515e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        private void launchChooseOrConfirmLock() {
516e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            Intent intent = new Intent();
517e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            long challenge = mFingerprintManager.preEnroll();
518e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
5195ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggi            if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
5205ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggi                    getString(R.string.security_settings_fingerprint_preference_title),
5215ad75f07b1861b802b75c720830db260b4f93417Jorim Jaggi                    null, null, challenge)) {
522e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                intent.setClassName("com.android.settings", ChooseLockGeneric.class.getName());
523e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
524e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
525a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS,
526a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller                        true);
527e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
528e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
529e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales                startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
530e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales            }
531e29dae683e8334c18d1449fca3b0e27bc5ff7aaaAndres Morales        }
532f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek
533f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        private void deleteFingerPrint(Fingerprint fingerPrint) {
534f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            mFingerprintManager.remove(fingerPrint, mRemoveCallback);
535f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        }
536f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek
537f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        private void renameFingerPrint(int fingerId, String newName) {
538f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            mFingerprintManager.rename(fingerId, newName);
539f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            updatePreferences();
540f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        }
541f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek
5428e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        private final Runnable mFingerprintLockoutReset = new Runnable() {
5438e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            @Override
5448e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            public void run() {
5458e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                mInFingerprintLockout = false;
5468e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller                retryFingerprint();
5478e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller            }
5488e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller        };
5498e8347502404dfed7d8f322eb033fa8645b8d753Jim Miller
550f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        public static class RenameDeleteDialog extends DialogFragment {
551f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek
552f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            private Fingerprint mFp;
553f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            private EditText mDialogTextField;
554f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            private String mFingerName;
555f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            private Boolean mTextHadFocus;
556f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            private int mTextSelectionStart;
557f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            private int mTextSelectionEnd;
558f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek
559f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            @Override
560f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            public Dialog onCreateDialog(Bundle savedInstanceState) {
561f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                mFp = getArguments().getParcelable("fingerprint");
562f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                if (savedInstanceState != null) {
563f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    mFingerName = savedInstanceState.getString("fingerName");
564f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    mTextHadFocus = savedInstanceState.getBoolean("textHadFocus");
565f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    mTextSelectionStart = savedInstanceState.getInt("startSelection");
566f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    mTextSelectionEnd = savedInstanceState.getInt("endSelection");
567f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                }
568f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                final AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
569f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        .setView(R.layout.fingerprint_rename_dialog)
570f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        .setPositiveButton(R.string.security_settings_fingerprint_enroll_dialog_ok,
571f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                new DialogInterface.OnClickListener() {
572f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                    @Override
573f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                    public void onClick(DialogInterface dialog, int which) {
574f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                        final String newName =
575f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                                mDialogTextField.getText().toString();
576f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                        final CharSequence name = mFp.getName();
577f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                        if (!newName.equals(name)) {
578f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                            if (DEBUG) {
579f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                                Log.v(TAG, "rename " + name + " to " + newName);
580f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                            }
5818c543276f1dd366bd142ce44a8e3084fddb22971Jorim Jaggi                                            MetricsLogger.action(getContext(),
5821b8d5ffb47b674dd67ae6d56baa9ab3f42c8c024Chris Wren                                                    MetricsLogger.ACTION_FINGERPRINT_RENAME,
5831b8d5ffb47b674dd67ae6d56baa9ab3f42c8c024Chris Wren                                                    mFp.getFingerId());
584f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                            FingerprintSettingsFragment parent
585f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                                    = (FingerprintSettingsFragment)
586f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                                    getTargetFragment();
587f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                            parent.renameFingerPrint(mFp.getFingerId(),
588f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                                    newName);
589f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                        }
590f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                        dialog.dismiss();
591f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                    }
592f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                })
593f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        .setNegativeButton(
594f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                R.string.security_settings_fingerprint_enroll_dialog_delete,
595f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                new DialogInterface.OnClickListener() {
596f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                    @Override
597f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                    public void onClick(DialogInterface dialog, int which) {
59812ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                        onDeleteClick(dialog);
599f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                    }
600f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                })
601f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        .create();
602f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                alertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
603f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    @Override
604f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    public void onShow(DialogInterface dialog) {
605f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        mDialogTextField = (EditText) alertDialog.findViewById(
606f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                                R.id.fingerprint_rename_field);
607f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        CharSequence name = mFingerName == null ? mFp.getName() : mFingerName;
608f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        mDialogTextField.setText(name);
609f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        if (mTextHadFocus == null) {
610f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                            mDialogTextField.selectAll();
611f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        } else {
612f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                            mDialogTextField.setSelection(mTextSelectionStart, mTextSelectionEnd);
613f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                        }
614f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    }
615f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                });
616f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                if (mTextHadFocus == null || mTextHadFocus) {
617f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    // Request the IME
618f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    alertDialog.getWindow().setSoftInputMode(
619f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
620f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                }
621f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                return alertDialog;
622f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            }
623f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek
62412ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi            private void onDeleteClick(DialogInterface dialog) {
62512ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                if (DEBUG) Log.v(TAG, "Removing fpId=" + mFp.getFingerId());
6268c543276f1dd366bd142ce44a8e3084fddb22971Jorim Jaggi                MetricsLogger.action(getContext(), MetricsLogger.ACTION_FINGERPRINT_DELETE,
6271b8d5ffb47b674dd67ae6d56baa9ab3f42c8c024Chris Wren                        mFp.getFingerId());
62812ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                FingerprintSettingsFragment parent
62912ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                        = (FingerprintSettingsFragment) getTargetFragment();
63012ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                if (parent.mFingerprintManager.getEnrolledFingerprints().size() > 1) {
63112ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    parent.deleteFingerPrint(mFp);
63212ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                } else {
63312ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    ConfirmLastDeleteDialog lastDeleteDialog = new ConfirmLastDeleteDialog();
63412ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    Bundle args = new Bundle();
63512ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    args.putParcelable("fingerprint", mFp);
63612ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    lastDeleteDialog.setArguments(args);
63712ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    lastDeleteDialog.setTargetFragment(getTargetFragment(), 0);
63812ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                    lastDeleteDialog.show(getFragmentManager(),
63912ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                            ConfirmLastDeleteDialog.class.getName());
64012ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                }
64112ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                dialog.dismiss();
64212ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi            }
64312ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi
644f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            @Override
645f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            public void onSaveInstanceState(Bundle outState) {
646f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                super.onSaveInstanceState(outState);
647f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                if (mDialogTextField != null) {
648f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    outState.putString("fingerName", mDialogTextField.getText().toString());
649f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    outState.putBoolean("textHadFocus", mDialogTextField.hasFocus());
650f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    outState.putInt("startSelection", mDialogTextField.getSelectionStart());
651f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                    outState.putInt("endSelection", mDialogTextField.getSelectionEnd());
652f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek                }
653f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek            }
654f4a305ee407082bdb6e47cefbb5682e46df49794Selim Cinek        }
65512ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi
65612ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi        public static class ConfirmLastDeleteDialog extends DialogFragment {
65712ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi
65812ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi            private Fingerprint mFp;
65912ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi
66012ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi            @Override
66112ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi            public Dialog onCreateDialog(Bundle savedInstanceState) {
66212ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                mFp = getArguments().getParcelable("fingerprint");
66312ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                final AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
66412ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                        .setTitle(R.string.fingerprint_last_delete_title)
66512ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                        .setMessage(R.string.fingerprint_last_delete_message)
66612ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                        .setPositiveButton(R.string.fingerprint_last_delete_confirm,
66712ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                new DialogInterface.OnClickListener() {
66812ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                    @Override
66912ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                    public void onClick(DialogInterface dialog, int which) {
67012ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                        FingerprintSettingsFragment parent
67112ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                                = (FingerprintSettingsFragment) getTargetFragment();
67212ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                        parent.deleteFingerPrint(mFp);
67312ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                        dialog.dismiss();
67412ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                    }
67512ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                })
67612ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                        .setNegativeButton(
67712ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                R.string.cancel,
67812ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                new DialogInterface.OnClickListener() {
67912ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                    @Override
68012ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                    public void onClick(DialogInterface dialog, int which) {
68112ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                        dialog.dismiss();
68212ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                    }
68312ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                                })
68412ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                        .create();
68512ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi                return alertDialog;
68612ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi            }
68712ee807c1fbef73d9a05cff523d797748d209002Jorim Jaggi        }
6889218687e4baaf0226ef16b58f78123d979711e5dJim Miller    }
6894f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
6904f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller    public static class FingerprintPreference extends Preference {
691d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        private Fingerprint mFingerprint;
6924f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        private View mView;
6934f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
6944f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        public FingerprintPreference(Context context, AttributeSet attrs, int defStyleAttr,
6954f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller                int defStyleRes) {
6964f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            super(context, attrs, defStyleAttr, defStyleRes);
6974f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
6984f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        public FingerprintPreference(Context context, AttributeSet attrs, int defStyleAttr) {
6994f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            this(context, attrs, defStyleAttr, 0);
7004f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
7014f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
7024f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        public FingerprintPreference(Context context, AttributeSet attrs) {
7034f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            this(context, attrs, com.android.internal.R.attr.preferenceStyle);
7044f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
7054f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
7064f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        public FingerprintPreference(Context context) {
7074f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            this(context, null);
7084f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
7094f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
710a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller        public View getView() { return mView; }
711a8e22985d7866fb0528d85d9710a5bc0f482d91aJim Miller
712d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        public void setFingerprint(Fingerprint item) {
713d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            mFingerprint = item;
7144f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
7154f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
716d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller        public Fingerprint getFingerprint() {
717d16c9b7c3100b7ba653dcd58db036500dd220896Jim Miller            return mFingerprint;
7184f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
7194f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller
7204f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        @Override
7214f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        protected void onBindView(View view) {
7224f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            super.onBindView(view);
7234f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller            mView = view;
7244f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller        }
7254f6f7c865f25f478e5198031d419b498bdeb7ffaJim Miller    };
7264dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
7274dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi    private static class LearnMoreSpan extends URLSpan {
7284dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
7294dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        private static final Typeface TYPEFACE_MEDIUM =
7304dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                Typeface.create("sans-serif-medium", Typeface.NORMAL);
7314dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
7324dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        private LearnMoreSpan(String url) {
7334dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            super(url);
7344dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        }
7354dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
7364dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        @Override
7374dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        public void onClick(View widget) {
7384dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            Context ctx = widget.getContext();
73915dcebe1e79ad396a08873f940e2f33d432cf387Jason Monk            Intent intent = HelpUtils.getHelpIntent(ctx, getURL(), ctx.getClass().getName());
7404dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            try {
7416e61347242ea8d9ac0645b2669f222696c65eec6Jason Monk                ((Activity) ctx).startActivityForResult(intent, 0);
7424dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            } catch (ActivityNotFoundException e) {
7434dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                Log.w(FingerprintSettingsFragment.TAG,
7444dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                        "Actvity was not found for intent, " + intent.toString());
7454dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            }
7464dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        }
7474dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
7484dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        @Override
7494dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        public void updateDrawState(TextPaint ds) {
7504dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            super.updateDrawState(ds);
7514dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            ds.setUnderlineText(false);
7524dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            ds.setTypeface(TYPEFACE_MEDIUM);
7534dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        }
7544dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi
7554dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        public static CharSequence linkify(CharSequence rawText, String uri) {
7564dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            SpannableString msg = new SpannableString(rawText);
7574dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            Annotation[] spans = msg.getSpans(0, msg.length(), Annotation.class);
7584dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            SpannableStringBuilder builder = new SpannableStringBuilder(msg);
7594dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            for (Annotation annotation : spans) {
7604dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                int start = msg.getSpanStart(annotation);
7614dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                int end = msg.getSpanEnd(annotation);
7624dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                LearnMoreSpan link = new LearnMoreSpan(uri);
7634dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi                builder.setSpan(link, start, end, msg.getSpanFlags(link));
7644dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            }
7654dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi            return builder;
7664dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi        }
7674dfcb8208cdb49167ccf99aeaddf9e206eba87d1Jorim Jaggi    }
7689218687e4baaf0226ef16b58f78123d979711e5dJim Miller}
769