CryptKeeper.java revision 9597406aa1b83867b03a47d1a5162969b924f2fc
18fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks/*
28fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * Copyright (C) 2011 The Android Open Source Project
38fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks *
48fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * Licensed under the Apache License, Version 2.0 (the "License");
58fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * you may not use this file except in compliance with the License.
68fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * You may obtain a copy of the License at
78fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks *
88fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks *      http://www.apache.org/licenses/LICENSE-2.0
98fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks *
108fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * Unless required by applicable law or agreed to in writing, software
118fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * distributed under the License is distributed on an "AS IS" BASIS,
128fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * See the License for the specific language governing permissions and
148fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks * limitations under the License.
158fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks */
168fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
178fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parkspackage com.android.settings;
188fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
198fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport com.android.internal.widget.PasswordEntryKeyboardHelper;
208fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport com.android.internal.widget.PasswordEntryKeyboardView;
218fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
228fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.app.Activity;
238fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.app.StatusBarManager;
248fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.content.ComponentName;
258fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.content.Context;
26ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.content.Intent;
278fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.content.pm.PackageManager;
288fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.inputmethodservice.KeyboardView;
298fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.Bundle;
30ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.os.Handler;
318fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.IBinder;
32ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.os.Message;
3335933812b16f0b4221280bbcc3c32f6540996bf2Jason parksimport android.os.PowerManager;
348fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.ServiceManager;
358fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.SystemProperties;
368fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.storage.IMountService;
37ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.text.TextUtils;
388fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.util.Log;
398fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.view.KeyEvent;
4013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.view.View;
4113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.view.View.OnClickListener;
428fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.view.inputmethod.EditorInfo;
4313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.widget.Button;
44ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.widget.EditText;
45ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.widget.ProgressBar;
468fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.widget.TextView;
478fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
488fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parkspublic class CryptKeeper extends Activity implements TextView.OnEditorActionListener {
49ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private static final String TAG = "CryptKeeper";
5035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
518fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    private static final String DECRYPT_STATE = "trigger_restart_framework";
52ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks
53ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private static final int UPDATE_PROGRESS = 1;
54ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private static final int COOLDOWN = 2;
55ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks
56ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private static final int MAX_FAILED_ATTEMPTS = 30;
57ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private static final int COOL_DOWN_ATTEMPTS = 10;
58ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private static final int COOL_DOWN_INTERVAL = 30; // 30 seconds
59ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks
601499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    private int mCooldown;
611499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    PowerManager.WakeLock mWakeLock;
621499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler
631499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    /**
641499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler     * Used to propagate state through configuration changes (e.g. screen rotation)
651499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler     */
661499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    private static class NonConfigurationInstanceState {
671499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        final PowerManager.WakeLock wakelock;
681499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler
691499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        NonConfigurationInstanceState(PowerManager.WakeLock _wakelock) {
701499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler            wakelock = _wakelock;
711499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        }
721499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    }
731499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler
74f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks    // This activity is used to fade the screen to black after the password is entered.
75f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks    public static class Blank extends Activity {
7613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        @Override
7713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        public void onCreate(Bundle savedInstanceState) {
7813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            super.onCreate(savedInstanceState);
7913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            setContentView(R.layout.crypt_keeper_blank);
8013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        }
81f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks    }
82ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks
83ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private Handler mHandler = new Handler() {
84ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks        @Override
85ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks        public void handleMessage(Message msg) {
86ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks            switch (msg.what) {
87ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks            case UPDATE_PROGRESS:
88f8217304073b5cd13823a0602568394be93bf310Jason parks                updateProgress();
89ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                break;
9035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
91ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks            case COOLDOWN:
92f8217304073b5cd13823a0602568394be93bf310Jason parks                cooldown();
93ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                break;
94ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks            }
95ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks        }
96ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    };
9735933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
988fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    @Override
998fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    public void onCreate(Bundle savedInstanceState) {
1008fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        super.onCreate(savedInstanceState);
10135933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
1029597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        // If we are not encrypted or encrypting, get out quickly.
1038fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        String state = SystemProperties.get("vold.decrypt");
1048fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        if ("".equals(state) || DECRYPT_STATE.equals(state)) {
10535933812b16f0b4221280bbcc3c32f6540996bf2Jason parks            // Disable the crypt keeper.
1068fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            PackageManager pm = getPackageManager();
1078fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            ComponentName name = new ComponentName(this, CryptKeeper.class);
1088fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
1098fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            return;
1108fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        }
11135933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
11239f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks        // Disable the status bar
11339f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks        StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
11413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        sbm.disable(StatusBarManager.DISABLE_EXPAND
11513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                | StatusBarManager.DISABLE_NOTIFICATION_ICONS
11639f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks                | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
11713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                | StatusBarManager.DISABLE_SYSTEM_INFO
11813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                | StatusBarManager.DISABLE_NAVIGATION
11913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                | StatusBarManager.DISABLE_BACK);
1201499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler
1211499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        // Check for (and recover) retained instance data
1221499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        Object lastInstance = getLastNonConfigurationInstance();
1231499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        if (lastInstance instanceof NonConfigurationInstanceState) {
1241499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler            NonConfigurationInstanceState retained = (NonConfigurationInstanceState) lastInstance;
1251499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler            mWakeLock = retained.wakelock;
1261499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        }
127ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    }
12835933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
1299597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler    /**
1309597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler     * Note, we defer the state check and screen setup to onStart() because this will be
1319597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler     * re-run if the user clicks the power button (sleeping/waking the screen), and this is
1329597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler     * especially important if we were to lose the wakelock for any reason.
1339597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler     */
1349597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler    @Override
1359597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler    public void onStart() {
1369597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        super.onStart();
1379597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler
1389597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        // Check to see why we were started.
1399597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        String progress = SystemProperties.get("vold.encrypt_progress");
1409597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        if (!"".equals(progress)) {
1419597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler            setContentView(R.layout.crypt_keeper_progress);
1429597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler            encryptionProgressInit();
1439597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        } else {
1449597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler            setContentView(R.layout.crypt_keeper_password_entry);
1459597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler            passwordEntryInit();
1469597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler        }
1479597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler    }
1489597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler
149f8217304073b5cd13823a0602568394be93bf310Jason parks    @Override
150f8217304073b5cd13823a0602568394be93bf310Jason parks    public void onStop() {
151f8217304073b5cd13823a0602568394be93bf310Jason parks        super.onStop();
152f8217304073b5cd13823a0602568394be93bf310Jason parks
153f8217304073b5cd13823a0602568394be93bf310Jason parks        mHandler.removeMessages(COOLDOWN);
154f8217304073b5cd13823a0602568394be93bf310Jason parks        mHandler.removeMessages(UPDATE_PROGRESS);
1551499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    }
1561499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler
1571499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    /**
1581499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler     * Reconfiguring, so propagate the wakelock to the next instance.  This runs between onStop()
1591499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler     * and onDestroy() and only if we are changing configuration (e.g. rotation).  Also clears
1601499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler     * mWakeLock so the subsequent call to onDestroy does not release it.
1611499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler     */
1621499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    @Override
1631499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    public Object onRetainNonConfigurationInstance() {
1641499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        NonConfigurationInstanceState state = new NonConfigurationInstanceState(mWakeLock);
1651499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        mWakeLock = null;
1661499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        return state;
1671499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    }
1681499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler
1691499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    @Override
1701499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler    public void onDestroy() {
1711499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler        super.onDestroy();
172f8217304073b5cd13823a0602568394be93bf310Jason parks
173f8217304073b5cd13823a0602568394be93bf310Jason parks        if (mWakeLock != null) {
174f8217304073b5cd13823a0602568394be93bf310Jason parks            mWakeLock.release();
175f8217304073b5cd13823a0602568394be93bf310Jason parks            mWakeLock = null;
176f8217304073b5cd13823a0602568394be93bf310Jason parks        }
177f8217304073b5cd13823a0602568394be93bf310Jason parks    }
178f8217304073b5cd13823a0602568394be93bf310Jason parks
179ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private void encryptionProgressInit() {
18035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks        // Accquire a partial wakelock to prevent the device from sleeping. Note
18135933812b16f0b4221280bbcc3c32f6540996bf2Jason parks        // we never release this wakelock as we will be restarted after the device
18235933812b16f0b4221280bbcc3c32f6540996bf2Jason parks        // is encrypted.
18335933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
18435933812b16f0b4221280bbcc3c32f6540996bf2Jason parks        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
185f8217304073b5cd13823a0602568394be93bf310Jason parks        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
186f8217304073b5cd13823a0602568394be93bf310Jason parks
187f8217304073b5cd13823a0602568394be93bf310Jason parks        mWakeLock.acquire();
188f8217304073b5cd13823a0602568394be93bf310Jason parks
189f8217304073b5cd13823a0602568394be93bf310Jason parks        ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
190f8217304073b5cd13823a0602568394be93bf310Jason parks        progressBar.setIndeterminate(true);
19135933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
192f8217304073b5cd13823a0602568394be93bf310Jason parks        updateProgress();
193f8217304073b5cd13823a0602568394be93bf310Jason parks    }
194f8217304073b5cd13823a0602568394be93bf310Jason parks
19513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler    private void showFactoryReset() {
19613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        // Hide the encryption-bot to make room for the "factory reset" button
19713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        findViewById(R.id.encroid).setVisibility(View.GONE);
19813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
19913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        // Show the reset button, failure text, and a divider
20013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        Button button = (Button) findViewById(R.id.factory_reset);
20113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        button.setVisibility(View.VISIBLE);
20213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        button.setOnClickListener(new OnClickListener() {
20313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            public void onClick(View v) {
20413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                // Factory reset the device.
20513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
20613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            }
20713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        });
20813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
20913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        TextView tv = (TextView) findViewById(R.id.title);
21013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        tv.setText(R.string.crypt_keeper_failed_title);
21113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
21213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        tv = (TextView) findViewById(R.id.status);
21313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        tv.setText(R.string.crypt_keeper_failed_summary);
21413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
21513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        View view = findViewById(R.id.bottom_divider);
21613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        view.setVisibility(View.VISIBLE);
21713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler    }
21813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
219f8217304073b5cd13823a0602568394be93bf310Jason parks    private void updateProgress() {
220f8217304073b5cd13823a0602568394be93bf310Jason parks        String state = SystemProperties.get("vold.encrypt_progress");
221f8217304073b5cd13823a0602568394be93bf310Jason parks
22213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        if ("error_partially_encrypted".equals(state)) {
22313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            showFactoryReset();
22413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            return;
22513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler        }
22613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
227f8217304073b5cd13823a0602568394be93bf310Jason parks        int progress = 0;
228f8217304073b5cd13823a0602568394be93bf310Jason parks        try {
229f8217304073b5cd13823a0602568394be93bf310Jason parks            progress = Integer.parseInt(state);
230f8217304073b5cd13823a0602568394be93bf310Jason parks        } catch (Exception e) {
231f8217304073b5cd13823a0602568394be93bf310Jason parks            Log.w(TAG, "Error parsing progress: " + e.toString());
232f8217304073b5cd13823a0602568394be93bf310Jason parks        }
23335933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
234f8217304073b5cd13823a0602568394be93bf310Jason parks        CharSequence status = getText(R.string.crypt_keeper_setup_description);
235f8217304073b5cd13823a0602568394be93bf310Jason parks        TextView tv = (TextView) findViewById(R.id.status);
236f8217304073b5cd13823a0602568394be93bf310Jason parks        tv.setText(TextUtils.expandTemplate(status, Integer.toString(progress)));
237f8217304073b5cd13823a0602568394be93bf310Jason parks
238f8217304073b5cd13823a0602568394be93bf310Jason parks        // Check the progress every 5 seconds
239f8217304073b5cd13823a0602568394be93bf310Jason parks        mHandler.removeMessages(UPDATE_PROGRESS);
240f8217304073b5cd13823a0602568394be93bf310Jason parks        mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 5000);
241f8217304073b5cd13823a0602568394be93bf310Jason parks    }
242f8217304073b5cd13823a0602568394be93bf310Jason parks
243f8217304073b5cd13823a0602568394be93bf310Jason parks    private void cooldown() {
244f8217304073b5cd13823a0602568394be93bf310Jason parks        TextView tv = (TextView) findViewById(R.id.status);
24513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
246f8217304073b5cd13823a0602568394be93bf310Jason parks        if (mCooldown <= 0) {
247f8217304073b5cd13823a0602568394be93bf310Jason parks            // Re-enable the password entry
248f8217304073b5cd13823a0602568394be93bf310Jason parks            EditText passwordEntry = (EditText) findViewById(R.id.passwordEntry);
249f8217304073b5cd13823a0602568394be93bf310Jason parks            passwordEntry.setEnabled(true);
250f8217304073b5cd13823a0602568394be93bf310Jason parks
25113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            tv.setVisibility(View.GONE);
252f8217304073b5cd13823a0602568394be93bf310Jason parks        } else {
25313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            CharSequence template = getText(R.string.crypt_keeper_cooldown);
25413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            tv.setText(TextUtils.expandTemplate(template, Integer.toString(mCooldown)));
25513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler
25613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler            tv.setVisibility(View.VISIBLE);
257f8217304073b5cd13823a0602568394be93bf310Jason parks
258f8217304073b5cd13823a0602568394be93bf310Jason parks            mCooldown--;
259f8217304073b5cd13823a0602568394be93bf310Jason parks            mHandler.removeMessages(COOLDOWN);
260f8217304073b5cd13823a0602568394be93bf310Jason parks            mHandler.sendEmptyMessageDelayed(COOLDOWN, 1000); // Tick every second
261f8217304073b5cd13823a0602568394be93bf310Jason parks        }
262ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    }
26335933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
264ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks    private void passwordEntryInit() {
2658fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        TextView passwordEntry = (TextView) findViewById(R.id.passwordEntry);
2668fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        passwordEntry.setOnEditorActionListener(this);
26735933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
2688fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        KeyboardView keyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
26935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
2708fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        PasswordEntryKeyboardHelper keyboardHelper = new PasswordEntryKeyboardHelper(this,
2718fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks                keyboardView, passwordEntry, false);
2728fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        keyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
2738fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    }
2748fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
2758fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    private IMountService getMountService() {
2768fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        IBinder service = ServiceManager.getService("mount");
2778fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        if (service != null) {
2788fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            return IMountService.Stub.asInterface(service);
2798fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        }
2808fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        return null;
2818fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    }
2828fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
2838fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    @Override
2848fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
2858fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        if (actionId == EditorInfo.IME_NULL) {
2868fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            // Get the password
2878fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            String password = v.getText().toString();
2888fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
289ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks            if (TextUtils.isEmpty(password)) {
290ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                return true;
291ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks            }
29235933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
2938fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            // Now that we have the password clear the password field.
2948fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            v.setText(null);
2958fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks
2968fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            IMountService service = getMountService();
2978fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            try {
298f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                int failedAttempts = service.decryptStorage(password);
299f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks
300f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                if (failedAttempts == 0) {
301f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    // The password was entered successfully. Start the Blank activity
302f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    // so this activity animates to black before the devices starts. Note
303f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    // It has 1 second to complete the animation or it will be frozen
304f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    // until the boot animation comes back up.
305f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    Intent intent = new Intent(this, Blank.class);
306f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    finish();
307f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                    startActivity(intent);
308f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                } else if (failedAttempts == MAX_FAILED_ATTEMPTS) {
309ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    // Factory reset the device.
310ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
311f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks                } else if ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
312ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    mCooldown = COOL_DOWN_INTERVAL;
313ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    EditText passwordEntry = (EditText) findViewById(R.id.passwordEntry);
314ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    passwordEntry.setEnabled(false);
315f8217304073b5cd13823a0602568394be93bf310Jason parks                    cooldown();
316ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                } else {
317ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    TextView tv = (TextView) findViewById(R.id.status);
318ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                    tv.setText(R.string.try_again);
31913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler                    tv.setVisibility(View.VISIBLE);
320ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                }
3218fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            } catch (Exception e) {
322ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks                Log.e(TAG, "Error while decrypting...", e);
3238fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            }
32435933812b16f0b4221280bbcc3c32f6540996bf2Jason parks
3258fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks            return true;
3268fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        }
3278fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks        return false;
3288fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks    }
3298fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks}