CredentialStorage.java revision 7422474c72b05517287fb0c226d1170cb11a064d
191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh/*
291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * Copyright (C) 2011 The Android Open Source Project
391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *
491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * you may not use this file except in compliance with the License.
691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * You may obtain a copy of the License at
791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *
891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *
1091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * See the License for the specific language governing permissions and
1491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * limitations under the License.
1591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh */
1691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
1791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehpackage com.android.settings;
1891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
1991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.app.Activity;
2091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.app.AlertDialog;
21d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstromimport android.app.admin.DevicePolicyManager;
2291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.content.DialogInterface;
2391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.content.Intent;
240e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstromimport android.content.res.Resources;
259815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.AsyncTask;
2691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.os.Bundle;
279815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.RemoteException;
28cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Rootimport android.os.UserHandle;
29b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Rootimport android.security.Credentials;
30435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstromimport android.security.KeyChain.KeyChainConnection;
31d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstromimport android.security.KeyChain;
3291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.security.KeyStore;
3391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.Editable;
340e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstromimport android.text.TextUtils;
3591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.TextWatcher;
3691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.util.Log;
3791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.view.View;
3891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Button;
3991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.TextView;
4091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Toast;
41d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstromimport com.android.internal.widget.LockPatternUtils;
4291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
430e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom/**
440e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * CredentialStorage handles KeyStore reset, unlock, and install.
450e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
460e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * CredentialStorage has a pretty convoluted state machine to migrate
470e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * from the old style separate keystore password to a new key guard
480e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * based password, as well as to deal with setting up the key guard if
490e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * necessary.
500e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
510e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNINITALIZED
520e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF
530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   set up key guard
540e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    factory state
550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNINITALIZED
570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: ON
580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   confirm key guard
590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    user had key guard but no keystore and upgraded from pre-ICS
600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *           OR user had key guard and pre-ICS keystore password which was then reset
610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: LOCKED
630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF/ON
640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   old unlock dialog
650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    assume old password, need to use it to unlock.
660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *           if unlock, ensure key guard before install.
670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *           if reset, treat as UNINITALIZED/OFF
680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNLOCKED
700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF
710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   set up key guard
720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    ensure key guard, then proceed
730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNLOCKED
750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * keyguard: ON
760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   normal unlock/install
770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    this is the common case
780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */
790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrompublic final class CredentialStorage extends Activity {
8091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
81d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private static final String TAG = "CredentialStorage";
8291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
8391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK";
8491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_INSTALL = "com.android.credentials.INSTALL";
8591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_RESET = "com.android.credentials.RESET";
8691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
87d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    // This is the minimum acceptable password quality.  If the current password quality is
88d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    // lower than this, keystore should not be activated.
89d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
9091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
910e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private static final int CONFIRM_KEY_GUARD_REQUEST = 1;
920e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
93d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private final KeyStore mKeyStore = KeyStore.getInstance();
940e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
950e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
960e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * When non-null, the bundle containing credentials to install.
970e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
980e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private Bundle mInstallBundle;
990e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1000e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1010e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * After unsuccessful KeyStore.unlock, the number of unlock
1020e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * attempts remaining before the KeyStore will reset itself.
1030e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     *
1040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Reset to -1 on successful unlock or reset.
1050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private int mRetriesRemaining = -1;
10791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
108cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root    @Override
109cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root    protected void onResume() {
110d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        super.onResume();
11191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
112cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root        if (UserHandle.myUserId() != UserHandle.USER_OWNER) {
113cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root            Log.i(TAG, "Cannot install to CredentialStorage as non-primary user");
114cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root            finish();
115cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root            return;
116cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root        }
117cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root
11891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        Intent intent = getIntent();
11991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        String action = intent.getAction();
12091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
12191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if (ACTION_RESET.equals(action)) {
122d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            new ResetDialog();
12391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        } else {
124cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root            if (ACTION_INSTALL.equals(action)
125cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root                    && "com.android.certinstaller".equals(getCallingPackage())) {
1260e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                mInstallBundle = intent.getExtras();
1270e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
1280e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // ACTION_UNLOCK also handled here in addition to ACTION_INSTALL
1290e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            handleUnlockOrInstall();
1300e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1310e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
1320e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1330e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1340e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Based on the current state of the KeyStore and key guard, try to
1350e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * make progress on unlocking or installing to the keystore.
1360e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1370e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private void handleUnlockOrInstall() {
1380e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        // something already decided we are done, do not proceed
1390e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (isFinishing()) {
1400e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            return;
1410e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1420e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        switch (mKeyStore.state()) {
1430e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            case UNINITIALIZED: {
1440e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                ensureKeyGuard();
1450e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
14691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
1470e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            case LOCKED: {
1480e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                new UnlockDialog();
1490e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
15091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
1510e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            case UNLOCKED: {
1520e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                if (!checkKeyGuardQuality()) {
1530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    new ConfigureKeyGuardDialog();
1540e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    return;
1550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                }
1560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                installIfAvailable();
1570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                finish();
1580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
1590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
1600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
1620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Make sure the user enters the key guard to set or change the
1650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * keystore password. This can be used in UNINITIALIZED to set the
1660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * keystore password or UNLOCKED to change the password (as is the
1670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * case after unlocking with an old-style password).
1680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private void ensureKeyGuard() {
1700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (!checkKeyGuardQuality()) {
1710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // key guard not setup, doing so will initialize keystore
1720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            new ConfigureKeyGuardDialog();
1730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // will return to onResume after Activity
1740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            return;
17591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
1760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        // force key guard confirmation
1770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (confirmKeyGuard()) {
1780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // will return password value via onActivityResult
1790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            return;
1800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        finish();
18291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
18391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
1840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Returns true if the currently set key guard matches our minimum quality requirements.
1860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private boolean checkKeyGuardQuality() {
188d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        int quality = new LockPatternUtils(this).getActivePasswordQuality();
189d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        return (quality >= MIN_PASSWORD_QUALITY);
190d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    }
191d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
1920e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1930e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Install credentials if available, otherwise do nothing.
1940e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1950e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private void installIfAvailable() {
1960e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (mInstallBundle != null && !mInstallBundle.isEmpty()) {
1970e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            Bundle bundle = mInstallBundle;
1980e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            mInstallBundle = null;
199b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2007422474c72b05517287fb0c226d1170cb11a064dKenny Root            final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
2017422474c72b05517287fb0c226d1170cb11a064dKenny Root
202b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) {
203b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
204b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
205b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2067422474c72b05517287fb0c226d1170cb11a064dKenny Root                if (!mKeyStore.importKey(key, value, uid)) {
2077422474c72b05517287fb0c226d1170cb11a064dKenny Root                    Log.e(TAG, "Failed to install " + key + " as user " + uid);
208d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    return;
20991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                }
21091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
211b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
212b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
213b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
214b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
215b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2167422474c72b05517287fb0c226d1170cb11a064dKenny Root                if (!mKeyStore.put(certName, certData, uid)) {
2177422474c72b05517287fb0c226d1170cb11a064dKenny Root                    Log.e(TAG, "Failed to install " + certName + " as user " + uid);
218b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                    return;
219b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                }
220b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            }
221b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
222b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            if (bundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) {
223b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
224b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);
225b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2267422474c72b05517287fb0c226d1170cb11a064dKenny Root                if (!mKeyStore.put(caListName, caListData, uid)) {
2277422474c72b05517287fb0c226d1170cb11a064dKenny Root                    Log.e(TAG, "Failed to install " + caListName + " as user " + uid);
228b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                    return;
229b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root                }
230b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            }
231b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
232d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            setResult(RESULT_OK);
23391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
23491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
23591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
2360e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
2370e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Prompt for reset confirmation, resetting on confirmation, finishing otherwise.
2380e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
239d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private class ResetDialog
240d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
241d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    {
242d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private boolean mResetConfirmed;
243d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
244d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private ResetDialog() {
245d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
246d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setTitle(android.R.string.dialog_alert_title)
247e7c53b1c9e48c6f997c47a0ca9a2f190ecbbf586Björn Lundén                    .setIconAttribute(android.R.attr.alertDialogIcon)
248d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setMessage(R.string.credentials_reset_hint)
249d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setPositiveButton(android.R.string.ok, this)
250d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setNegativeButton(android.R.string.cancel, this)
251d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .create();
252d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.setOnDismissListener(this);
253d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.show();
25491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
25591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
256d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onClick(DialogInterface dialog, int button) {
257d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
25891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
25991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
260d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onDismiss(DialogInterface dialog) {
261d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            if (mResetConfirmed) {
262d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mResetConfirmed = false;
263d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                new ResetKeyStoreAndKeyChain().execute();
26491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                return;
26591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
266d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            finish();
26791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
26891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
2699815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
2710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Background task to handle reset of both keystore and user installed CAs.
2720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
2739815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> {
2749815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2759815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        @Override protected Boolean doInBackground(Void... unused) {
2769815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2779815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            mKeyStore.reset();
2789815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2799815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            try {
280435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this);
281435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                try {
282435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                    return keyChainConnection.getService().reset();
283435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                } catch (RemoteException e) {
284435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                    return false;
285435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                } finally {
286435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                    keyChainConnection.close();
287435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                }
2889815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } catch (InterruptedException e) {
2899815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Thread.currentThread().interrupt();
2909815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                return false;
2919815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
2929815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
2939815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2949815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        @Override protected void onPostExecute(Boolean success) {
2959815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            if (success) {
2969815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Toast.makeText(CredentialStorage.this,
2979815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                               R.string.credentials_erased, Toast.LENGTH_SHORT).show();
2989815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } else {
2999815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Toast.makeText(CredentialStorage.this,
3009815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                               R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
3019815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
3029815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            finish();
3039815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
3049815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    }
305d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
3060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
3070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Prompt for key guard configuration confirmation.
3080e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
3090e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private class ConfigureKeyGuardDialog
310d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
311d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    {
312d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private boolean mConfigureConfirmed;
313d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
3140e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        private ConfigureKeyGuardDialog() {
315d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
316d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setTitle(android.R.string.dialog_alert_title)
317e7c53b1c9e48c6f997c47a0ca9a2f190ecbbf586Björn Lundén                    .setIconAttribute(android.R.attr.alertDialogIcon)
318d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setMessage(R.string.credentials_configure_lock_screen_hint)
319d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setPositiveButton(android.R.string.ok, this)
320d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setNegativeButton(android.R.string.cancel, this)
321d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .create();
322d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.setOnDismissListener(this);
323d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.show();
324d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
325d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
326d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onClick(DialogInterface dialog, int button) {
327d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
328d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
329d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
330d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onDismiss(DialogInterface dialog) {
331d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            if (mConfigureConfirmed) {
332d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mConfigureConfirmed = false;
333d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
334d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
335d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                MIN_PASSWORD_QUALITY);
336d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                startActivity(intent);
337d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                return;
338d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            }
339d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            finish();
340d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
341d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    }
342d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
3430e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
3440e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Confirm existing key guard, returning password via onActivityResult.
3450e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
3460e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private boolean confirmKeyGuard() {
3470e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        Resources res = getResources();
3480e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        boolean launched = new ChooseLockSettingsHelper(this)
3490e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST,
35081d7a806a6403cd98a0c6dd0ba7288d728382144Brian Carlstrom                                            res.getText(R.string.credentials_install_gesture_prompt),
35181d7a806a6403cd98a0c6dd0ba7288d728382144Brian Carlstrom                                            res.getText(R.string.credentials_install_gesture_explanation));
3520e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        return launched;
3530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
3540e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
3550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    @Override
3560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    public void onActivityResult(int requestCode, int resultCode, Intent data) {
3570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        super.onActivityResult(requestCode, resultCode, data);
3580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
3590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        /**
3600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom         * Receive key guard password initiated by confirmKeyGuard.
3610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom         */
3620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (requestCode == CONFIRM_KEY_GUARD_REQUEST) {
3630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            if (resultCode == Activity.RESULT_OK) {
3640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
3650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                if (!TextUtils.isEmpty(password)) {
3660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // success
3670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mKeyStore.password(password);
3680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // return to onResume
3690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    return;
3700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                }
3710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
3720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // failed confirmation, bail
3730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            finish();
3740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
3750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
3760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
3770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
3780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Prompt for unlock with old-style password.
3790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     *
3800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * On successful unlock, ensure migration to key guard before continuing.
3810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * On unsuccessful unlock, retry by calling handleUnlockOrInstall.
3820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
383d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private class UnlockDialog implements TextWatcher,
384d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            DialogInterface.OnClickListener, DialogInterface.OnDismissListener
385d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    {
386d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private boolean mUnlockConfirmed;
387d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
388d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private final Button mButton;
389d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private final TextView mOldPassword;
390d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private final TextView mError;
391d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
392d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private UnlockDialog() {
393d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            View view = View.inflate(CredentialStorage.this, R.layout.credentials_dialog, null);
394d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
3950e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            CharSequence text;
3960e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            if (mRetriesRemaining == -1) {
3970e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getResources().getText(R.string.credentials_unlock_hint);
3980e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            } else if (mRetriesRemaining > 3) {
3990e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getResources().getText(R.string.credentials_wrong_password);
4000e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            } else if (mRetriesRemaining == 1) {
4010e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getResources().getText(R.string.credentials_reset_warning);
4020e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            } else {
4030e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getString(R.string.credentials_reset_warning_plural, mRetriesRemaining);
4040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
4050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
4060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            ((TextView) view.findViewById(R.id.hint)).setText(text);
407d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mOldPassword = (TextView) view.findViewById(R.id.old_password);
408d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mOldPassword.setVisibility(View.VISIBLE);
409d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mOldPassword.addTextChangedListener(this);
410d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mError = (TextView) view.findViewById(R.id.error);
411d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
412d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
413d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setView(view)
414d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setTitle(R.string.credentials_unlock)
415d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setPositiveButton(android.R.string.ok, this)
416d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setNegativeButton(android.R.string.cancel, this)
417d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .create();
418d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.setOnDismissListener(this);
419d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.show();
420d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
421d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mButton.setEnabled(false);
422d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
423d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
424d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void afterTextChanged(Editable editable) {
425d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0);
426d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
427d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
428d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
429d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
430d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
431d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onTextChanged(CharSequence s,int start, int before, int count) {
432d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
433d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
434d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onClick(DialogInterface dialog, int button) {
435d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
436d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
437d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
438d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onDismiss(DialogInterface dialog) {
439d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            if (mUnlockConfirmed) {
440d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mUnlockConfirmed = false;
441d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mError.setVisibility(View.VISIBLE);
442d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mKeyStore.unlock(mOldPassword.getText().toString());
443d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                int error = mKeyStore.getLastError();
444d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                if (error == KeyStore.NO_ERROR) {
4450e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mRetriesRemaining = -1;
446d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    Toast.makeText(CredentialStorage.this,
447d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   R.string.credentials_enabled,
448d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   Toast.LENGTH_SHORT).show();
4490e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // aha, now we are unlocked, switch to key guard.
4500e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // we'll end up back in onResume to install
4510e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    ensureKeyGuard();
452d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                } else if (error == KeyStore.UNINITIALIZED) {
4530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mRetriesRemaining = -1;
454d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    Toast.makeText(CredentialStorage.this,
455d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   R.string.credentials_erased,
456d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   Toast.LENGTH_SHORT).show();
4570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // we are reset, we can now set new password with key guard
4580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    handleUnlockOrInstall();
459d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                } else if (error >= KeyStore.WRONG_PASSWORD) {
4600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // we need to try again
4610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mRetriesRemaining = error - KeyStore.WRONG_PASSWORD + 1;
4620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    handleUnlockOrInstall();
463d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                }
4640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
465d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            }
466d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            finish();
467d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
468d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    }
46991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh}
470