CredentialStorage.java revision 9815429821832c204eaf8edebb37f4e2ff7636f0
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;
219815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.content.ComponentName;
229815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.content.Context;
2391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.content.DialogInterface;
2491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.content.Intent;
259815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.content.ServiceConnection;
269815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.AsyncTask;
2791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.os.Bundle;
289815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.IBinder;
299815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.RemoteException;
309815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.security.IKeyChainService;
3191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.security.KeyStore;
3291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.Editable;
3391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.TextWatcher;
3491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.util.Log;
3591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.view.View;
3691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Button;
3791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.TextView;
3891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Toast;
3991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
409815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport java.util.concurrent.BlockingQueue;
419815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport java.util.concurrent.LinkedBlockingQueue;
4291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport java.io.UnsupportedEncodingException;
4391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
4491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehpublic class CredentialStorage extends Activity implements TextWatcher,
4591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
4691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
4791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK";
4891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_SET_PASSWORD = "com.android.credentials.SET_PASSWORD";
4991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_INSTALL = "com.android.credentials.INSTALL";
5091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_RESET = "com.android.credentials.RESET";
5191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
5291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final String TAG = "CredentialStorage";
5391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
5491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private KeyStore mKeyStore = KeyStore.getInstance();
559815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    private boolean mPositive = false;
569815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    private boolean mNeutral = false;
5791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private Bundle mBundle;
5891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
5991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private TextView mOldPassword;
6091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private TextView mNewPassword;
6191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private TextView mConfirmPassword;
6291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private TextView mError;
6391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private Button mButton;
6491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
6591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    @Override
6691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    protected void onCreate(Bundle savedInstanceState) {
6791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        super.onCreate(savedInstanceState);
6891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
6991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        Intent intent = getIntent();
7091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        String action = intent.getAction();
7191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        int state = mKeyStore.test();
7291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
7391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if (ACTION_RESET.equals(action)) {
7491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            showResetDialog();
7591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        } else if (ACTION_SET_PASSWORD.equals(action)) {
7691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            showPasswordDialog(state == KeyStore.UNINITIALIZED);
7791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        } else {
7891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            if (ACTION_INSTALL.equals(action) &&
7991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    "com.android.certinstaller".equals(getCallingPackage())) {
8091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                mBundle = intent.getExtras();
8191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
8291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            if (state == KeyStore.UNINITIALIZED) {
8391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                showPasswordDialog(true);
8491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            } else if (state == KeyStore.LOCKED) {
8591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                showUnlockDialog();
8691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            } else {
8791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                install();
8891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                finish();
8991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
9091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
9191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
9291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
9391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private void install() {
9491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if (mBundle != null && !mBundle.isEmpty()) {
9591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            try {
9691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                for (String key : mBundle.keySet()) {
9791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    byte[] value = mBundle.getByteArray(key);
9891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    if (value != null && !mKeyStore.put(key.getBytes("UTF-8"), value)) {
9991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                        Log.e(TAG, "Failed to install " + key);
10091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                        return;
10191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    }
10291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                }
10391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                setResult(RESULT_OK);
10491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            } catch (UnsupportedEncodingException e) {
10591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                // Should never happen.
10691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                throw new RuntimeException(e);
10791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
10891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
10991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
11091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
11191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private void showResetDialog() {
11291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        AlertDialog dialog = new AlertDialog.Builder(this)
11391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setTitle(android.R.string.dialog_alert_title)
11491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setIcon(android.R.drawable.ic_dialog_alert)
11591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setMessage(R.string.credentials_reset_hint)
11691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setNeutralButton(android.R.string.ok, this)
11791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setNegativeButton(android.R.string.cancel, this)
11891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .create();
11991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        dialog.setOnDismissListener(this);
12091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        dialog.show();
12191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
12291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
12391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private void showPasswordDialog(boolean firstTime) {
12491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        View view = View.inflate(this, R.layout.credentials_dialog, null);
12591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
12691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        ((TextView) view.findViewById(R.id.hint)).setText(R.string.credentials_password_hint);
12791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if (!firstTime) {
12891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            view.findViewById(R.id.old_password_prompt).setVisibility(View.VISIBLE);
12991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mOldPassword = (TextView) view.findViewById(R.id.old_password);
13091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mOldPassword.setVisibility(View.VISIBLE);
13191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mOldPassword.addTextChangedListener(this);
13291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
13391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        view.findViewById(R.id.new_passwords).setVisibility(View.VISIBLE);
13491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mNewPassword = (TextView) view.findViewById(R.id.new_password);
13591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mNewPassword.addTextChangedListener(this);
13691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mConfirmPassword = (TextView) view.findViewById(R.id.confirm_password);
13791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mConfirmPassword.addTextChangedListener(this);
13891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mError = (TextView) view.findViewById(R.id.error);
13991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
14091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        AlertDialog dialog = new AlertDialog.Builder(this)
14191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setView(view)
14291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setTitle(R.string.credentials_set_password)
14391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setPositiveButton(android.R.string.ok, this)
14491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setNegativeButton(android.R.string.cancel, this)
14591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .create();
14691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        dialog.setOnDismissListener(this);
14791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        dialog.show();
14891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
14991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mButton.setEnabled(false);
15091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
15191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
15291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private void showUnlockDialog() {
15391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        View view = View.inflate(this, R.layout.credentials_dialog, null);
15491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
15591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        ((TextView) view.findViewById(R.id.hint)).setText(R.string.credentials_unlock_hint);
15691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mOldPassword = (TextView) view.findViewById(R.id.old_password);
15791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mOldPassword.setVisibility(View.VISIBLE);
15891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mOldPassword.addTextChangedListener(this);
15991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mError = (TextView) view.findViewById(R.id.error);
16091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
16191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        AlertDialog dialog = new AlertDialog.Builder(this)
16291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setView(view)
16391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setTitle(R.string.credentials_unlock)
16491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setPositiveButton(android.R.string.ok, this)
16591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .setNegativeButton(android.R.string.cancel, this)
16691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                .create();
16791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        dialog.setOnDismissListener(this);
16891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        dialog.show();
16991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
17091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mButton.setEnabled(false);
17191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
17291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
17391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public void afterTextChanged(Editable editable) {
17491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if ((mOldPassword == null || mOldPassword.getText().length() > 0) &&
17591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            (mNewPassword == null || mNewPassword.getText().length() >= 8) &&
17691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            (mConfirmPassword == null || mConfirmPassword.getText().length() >= 8)) {
17791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mButton.setEnabled(true);
17891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        } else {
17991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mButton.setEnabled(false);
18091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
18191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
18291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
18391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
18491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
18591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
18691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public void onTextChanged(CharSequence s,int start, int before, int count) {
18791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
18891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
18991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public void onClick(DialogInterface dialog, int button) {
1909815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        mPositive = (button == DialogInterface.BUTTON_POSITIVE);
1919815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        mNeutral = (button == DialogInterface.BUTTON_NEUTRAL);
19291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
19391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
19491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public void onDismiss(DialogInterface dialog) {
1959815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        if (mPositive) {
1969815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            mPositive = false;
19791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mError.setVisibility(View.VISIBLE);
19891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
19991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            if (mNewPassword == null) {
20091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                mKeyStore.unlock(mOldPassword.getText().toString());
20191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            } else {
20291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                String newPassword = mNewPassword.getText().toString();
20391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                String confirmPassword = mConfirmPassword.getText().toString();
20491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
20591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                if (!newPassword.equals(confirmPassword)) {
20691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    mError.setText(R.string.credentials_passwords_mismatch);
20791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    ((AlertDialog) dialog).show();
20891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    return;
20991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                } else if (mOldPassword == null) {
21091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    mKeyStore.password(newPassword);
21191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                } else {
21291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    mKeyStore.password(mOldPassword.getText().toString(), newPassword);
21391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                }
21491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
21591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
21691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            int error = mKeyStore.getLastError();
21791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            if (error == KeyStore.NO_ERROR) {
21891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                Toast.makeText(this, R.string.credentials_enabled, Toast.LENGTH_SHORT).show();
21991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                install();
22091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            } else if (error == KeyStore.UNINITIALIZED) {
22191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                Toast.makeText(this, R.string.credentials_erased,  Toast.LENGTH_SHORT).show();
22291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            } else if (error >= KeyStore.WRONG_PASSWORD) {
22391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                int count = error - KeyStore.WRONG_PASSWORD + 1;
22491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                if (count > 3) {
22591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    mError.setText(R.string.credentials_wrong_password);
22691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                } else if (count == 1) {
22791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    mError.setText(R.string.credentials_reset_warning);
22891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                } else {
22991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                    mError.setText(getString(R.string.credentials_reset_warning_plural, count));
23091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                }
23191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                ((AlertDialog) dialog).show();
23291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                return;
23391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
23491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
2359815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        if (mNeutral) {
2369815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            mNeutral = false;
2379815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            new ResetKeyStoreAndKeyChain().execute();
2389815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            return;
2399815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
24091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        finish();
24191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
2429815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2439815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> {
2449815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2459815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        @Override protected Boolean doInBackground(Void... unused) {
2469815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2479815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            mKeyStore.reset();
2489815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2499815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            final BlockingQueue<IKeyChainService> q = new LinkedBlockingQueue<IKeyChainService>(1);
2509815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            ServiceConnection keyChainServiceConnection = new ServiceConnection() {
2519815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                @Override public void onServiceConnected(ComponentName name, IBinder service) {
2529815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                    try {
2539815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                        q.put(IKeyChainService.Stub.asInterface(service));
2549815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                    } catch (InterruptedException e) {
2559815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                        throw new AssertionError(e);
2569815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                    }
2579815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                }
2589815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                @Override public void onServiceDisconnected(ComponentName name) {}
2599815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            };
2609815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            boolean isBound = bindService(new Intent(IKeyChainService.class.getName()),
2619815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                                          keyChainServiceConnection,
2629815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                                          Context.BIND_AUTO_CREATE);
2639815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            if (!isBound) {
2649815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Log.w(TAG, "could not bind to KeyChainService");
2659815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                return false;
2669815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
2679815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            IKeyChainService keyChainService;
2689815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            try {
2699815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                keyChainService = q.take();
2709815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                return keyChainService.reset();
2719815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } catch (InterruptedException e) {
2729815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Thread.currentThread().interrupt();
2739815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                return false;
2749815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } catch (RemoteException e) {
2759815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                return false;
2769815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } finally {
2779815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                unbindService(keyChainServiceConnection);
2789815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
2799815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
2809815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
2819815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        @Override protected void onPostExecute(Boolean success) {
2829815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            if (success) {
2839815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Toast.makeText(CredentialStorage.this,
2849815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                               R.string.credentials_erased, Toast.LENGTH_SHORT).show();
2859815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } else {
2869815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Toast.makeText(CredentialStorage.this,
2879815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                               R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
2889815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
2899815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            finish();
2909815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
2919815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    }
29291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh}
293