CryptKeeper.java revision 00046d6e176eb05c3e3b0d13d38a8da7491bba5e
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; 2875c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parksimport android.graphics.Rect; 298fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.inputmethodservice.KeyboardView; 3006c5ff4a46686d3f599e40df0768177d3d88913cJason parksimport android.os.AsyncTask; 318fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.Bundle; 32ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.os.Handler; 338fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.IBinder; 34ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.os.Message; 3535933812b16f0b4221280bbcc3c32f6540996bf2Jason parksimport android.os.PowerManager; 368fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.ServiceManager; 378fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.SystemProperties; 388fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.storage.IMountService; 39ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.text.TextUtils; 4075c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parksimport android.util.AttributeSet; 418fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.util.Log; 428fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.view.KeyEvent; 4375c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parksimport android.view.MotionEvent; 4413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.view.View; 4513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.view.View.OnClickListener; 468fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.view.inputmethod.EditorInfo; 4775c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parksimport android.view.inputmethod.InputMethodManager; 4813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.widget.Button; 49ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.widget.EditText; 50ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.widget.ProgressBar; 518fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.widget.TextView; 528fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 538fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parkspublic class CryptKeeper extends Activity implements TextView.OnEditorActionListener { 54ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private static final String TAG = "CryptKeeper"; 5535933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 568fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks private static final String DECRYPT_STATE = "trigger_restart_framework"; 57ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks 58ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private static final int UPDATE_PROGRESS = 1; 59ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private static final int COOLDOWN = 2; 60ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks 61ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private static final int MAX_FAILED_ATTEMPTS = 30; 62ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private static final int COOL_DOWN_ATTEMPTS = 10; 63ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private static final int COOL_DOWN_INTERVAL = 30; // 30 seconds 64ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks 651499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler private int mCooldown; 661499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler PowerManager.WakeLock mWakeLock; 6706c5ff4a46686d3f599e40df0768177d3d88913cJason parks private EditText mPasswordEntry; 681499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 691499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler /** 701499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler * Used to propagate state through configuration changes (e.g. screen rotation) 711499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler */ 721499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler private static class NonConfigurationInstanceState { 731499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler final PowerManager.WakeLock wakelock; 741499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 751499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler NonConfigurationInstanceState(PowerManager.WakeLock _wakelock) { 761499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler wakelock = _wakelock; 771499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 781499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 791499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 80f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks // This activity is used to fade the screen to black after the password is entered. 81f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks public static class Blank extends Activity { 8213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler @Override 8313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler public void onCreate(Bundle savedInstanceState) { 8413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler super.onCreate(savedInstanceState); 8513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler setContentView(R.layout.crypt_keeper_blank); 8613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler } 87f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks } 88ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks 8975c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks // Use a custom EditText to prevent the input method from showing. 9075c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks public static class CryptEditText extends EditText { 9175c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks InputMethodManager imm; 9275c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 9375c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks public CryptEditText(Context context, AttributeSet attrs) { 9475c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks super(context, attrs); 9575c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks imm = ((InputMethodManager) getContext(). 9675c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks getSystemService(Context.INPUT_METHOD_SERVICE)); 9775c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 9875c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 9975c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks @Override 10075c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 10175c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks super.onFocusChanged(focused, direction, previouslyFocusedRect); 10275c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 10375c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks if (focused && imm != null && imm.isActive(this)) { 10475c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0); 10575c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 10675c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 10775c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 10875c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks @Override 10975c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks public boolean onTouchEvent(MotionEvent event) { 11075c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks boolean handled = super.onTouchEvent(event); 11175c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 11275c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks if (imm != null && imm.isActive(this)) { 11375c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0); 11475c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 11575c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 11675c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks return handled; 11775c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 11875c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 11975c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 12006c5ff4a46686d3f599e40df0768177d3d88913cJason parks private class DecryptTask extends AsyncTask<String, Void, Integer> { 12106c5ff4a46686d3f599e40df0768177d3d88913cJason parks @Override 12206c5ff4a46686d3f599e40df0768177d3d88913cJason parks protected Integer doInBackground(String... params) { 12306c5ff4a46686d3f599e40df0768177d3d88913cJason parks IMountService service = getMountService(); 12406c5ff4a46686d3f599e40df0768177d3d88913cJason parks try { 12506c5ff4a46686d3f599e40df0768177d3d88913cJason parks return service.decryptStorage(params[0]); 12606c5ff4a46686d3f599e40df0768177d3d88913cJason parks } catch (Exception e) { 12706c5ff4a46686d3f599e40df0768177d3d88913cJason parks Log.e(TAG, "Error while decrypting...", e); 12806c5ff4a46686d3f599e40df0768177d3d88913cJason parks return -1; 12906c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 13006c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 13106c5ff4a46686d3f599e40df0768177d3d88913cJason parks 13206c5ff4a46686d3f599e40df0768177d3d88913cJason parks @Override 13306c5ff4a46686d3f599e40df0768177d3d88913cJason parks protected void onPostExecute(Integer failedAttempts) { 13406c5ff4a46686d3f599e40df0768177d3d88913cJason parks if (failedAttempts == 0) { 13506c5ff4a46686d3f599e40df0768177d3d88913cJason parks // The password was entered successfully. Start the Blank activity 13606c5ff4a46686d3f599e40df0768177d3d88913cJason parks // so this activity animates to black before the devices starts. Note 13706c5ff4a46686d3f599e40df0768177d3d88913cJason parks // It has 1 second to complete the animation or it will be frozen 13806c5ff4a46686d3f599e40df0768177d3d88913cJason parks // until the boot animation comes back up. 13906c5ff4a46686d3f599e40df0768177d3d88913cJason parks Intent intent = new Intent(CryptKeeper.this, Blank.class); 14006c5ff4a46686d3f599e40df0768177d3d88913cJason parks finish(); 14106c5ff4a46686d3f599e40df0768177d3d88913cJason parks startActivity(intent); 14206c5ff4a46686d3f599e40df0768177d3d88913cJason parks } else if (failedAttempts == MAX_FAILED_ATTEMPTS) { 14306c5ff4a46686d3f599e40df0768177d3d88913cJason parks // Factory reset the device. 14406c5ff4a46686d3f599e40df0768177d3d88913cJason parks sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); 14506c5ff4a46686d3f599e40df0768177d3d88913cJason parks } else if ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) { 14606c5ff4a46686d3f599e40df0768177d3d88913cJason parks mCooldown = COOL_DOWN_INTERVAL; 14706c5ff4a46686d3f599e40df0768177d3d88913cJason parks cooldown(); 14806c5ff4a46686d3f599e40df0768177d3d88913cJason parks } else { 14906c5ff4a46686d3f599e40df0768177d3d88913cJason parks TextView tv = (TextView) findViewById(R.id.status); 15006c5ff4a46686d3f599e40df0768177d3d88913cJason parks tv.setText(R.string.try_again); 15106c5ff4a46686d3f599e40df0768177d3d88913cJason parks tv.setVisibility(View.VISIBLE); 15206c5ff4a46686d3f599e40df0768177d3d88913cJason parks 15306c5ff4a46686d3f599e40df0768177d3d88913cJason parks // Reenable the password entry 15406c5ff4a46686d3f599e40df0768177d3d88913cJason parks mPasswordEntry.setEnabled(true); 15506c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 15606c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 15706c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 15875c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks 159ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private Handler mHandler = new Handler() { 160ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks @Override 161ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks public void handleMessage(Message msg) { 162ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks switch (msg.what) { 163ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks case UPDATE_PROGRESS: 164f8217304073b5cd13823a0602568394be93bf310Jason parks updateProgress(); 165ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks break; 16635933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 167ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks case COOLDOWN: 168f8217304073b5cd13823a0602568394be93bf310Jason parks cooldown(); 169ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks break; 170ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 171ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 172ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks }; 17335933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 1748fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks @Override 1758fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks public void onCreate(Bundle savedInstanceState) { 1768fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks super.onCreate(savedInstanceState); 17735933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 1789597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler // If we are not encrypted or encrypting, get out quickly. 1798fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks String state = SystemProperties.get("vold.decrypt"); 1808fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks if ("".equals(state) || DECRYPT_STATE.equals(state)) { 18135933812b16f0b4221280bbcc3c32f6540996bf2Jason parks // Disable the crypt keeper. 1828fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks PackageManager pm = getPackageManager(); 1838fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks ComponentName name = new ComponentName(this, CryptKeeper.class); 1848fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); 1858fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks return; 1868fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 18735933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 18839f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks // Disable the status bar 18939f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE); 19013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler sbm.disable(StatusBarManager.DISABLE_EXPAND 19113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler | StatusBarManager.DISABLE_NOTIFICATION_ICONS 19239f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks | StatusBarManager.DISABLE_NOTIFICATION_ALERTS 19313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler | StatusBarManager.DISABLE_SYSTEM_INFO 19413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler | StatusBarManager.DISABLE_NAVIGATION 19513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler | StatusBarManager.DISABLE_BACK); 1961499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 1971499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler // Check for (and recover) retained instance data 1981499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler Object lastInstance = getLastNonConfigurationInstance(); 1991499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler if (lastInstance instanceof NonConfigurationInstanceState) { 2001499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler NonConfigurationInstanceState retained = (NonConfigurationInstanceState) lastInstance; 2011499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler mWakeLock = retained.wakelock; 2021499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 203ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 20435933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 2059597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler /** 2069597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler * Note, we defer the state check and screen setup to onStart() because this will be 2079597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler * re-run if the user clicks the power button (sleeping/waking the screen), and this is 2089597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler * especially important if we were to lose the wakelock for any reason. 2099597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler */ 2109597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler @Override 2119597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler public void onStart() { 2129597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler super.onStart(); 2139597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler 2149597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler // Check to see why we were started. 2159597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler String progress = SystemProperties.get("vold.encrypt_progress"); 2169597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler if (!"".equals(progress)) { 2179597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler setContentView(R.layout.crypt_keeper_progress); 2189597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler encryptionProgressInit(); 2199597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler } else { 2209597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler setContentView(R.layout.crypt_keeper_password_entry); 2219597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler passwordEntryInit(); 2229597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler } 2239597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler } 2249597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler 225f8217304073b5cd13823a0602568394be93bf310Jason parks @Override 226f8217304073b5cd13823a0602568394be93bf310Jason parks public void onStop() { 227f8217304073b5cd13823a0602568394be93bf310Jason parks super.onStop(); 228f8217304073b5cd13823a0602568394be93bf310Jason parks 229f8217304073b5cd13823a0602568394be93bf310Jason parks mHandler.removeMessages(COOLDOWN); 230f8217304073b5cd13823a0602568394be93bf310Jason parks mHandler.removeMessages(UPDATE_PROGRESS); 2311499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 2321499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 2331499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler /** 2341499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler * Reconfiguring, so propagate the wakelock to the next instance. This runs between onStop() 2351499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler * and onDestroy() and only if we are changing configuration (e.g. rotation). Also clears 2361499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler * mWakeLock so the subsequent call to onDestroy does not release it. 2371499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler */ 2381499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler @Override 2391499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler public Object onRetainNonConfigurationInstance() { 2401499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler NonConfigurationInstanceState state = new NonConfigurationInstanceState(mWakeLock); 2411499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler mWakeLock = null; 2421499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler return state; 2431499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 2441499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 2451499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler @Override 2461499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler public void onDestroy() { 2471499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler super.onDestroy(); 248f8217304073b5cd13823a0602568394be93bf310Jason parks 249f8217304073b5cd13823a0602568394be93bf310Jason parks if (mWakeLock != null) { 250f8217304073b5cd13823a0602568394be93bf310Jason parks mWakeLock.release(); 251f8217304073b5cd13823a0602568394be93bf310Jason parks mWakeLock = null; 252f8217304073b5cd13823a0602568394be93bf310Jason parks } 253f8217304073b5cd13823a0602568394be93bf310Jason parks } 254f8217304073b5cd13823a0602568394be93bf310Jason parks 255ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private void encryptionProgressInit() { 25635933812b16f0b4221280bbcc3c32f6540996bf2Jason parks // Accquire a partial wakelock to prevent the device from sleeping. Note 25735933812b16f0b4221280bbcc3c32f6540996bf2Jason parks // we never release this wakelock as we will be restarted after the device 25835933812b16f0b4221280bbcc3c32f6540996bf2Jason parks // is encrypted. 25935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 26035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 261f8217304073b5cd13823a0602568394be93bf310Jason parks mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); 262f8217304073b5cd13823a0602568394be93bf310Jason parks 263f8217304073b5cd13823a0602568394be93bf310Jason parks mWakeLock.acquire(); 264f8217304073b5cd13823a0602568394be93bf310Jason parks 265f8217304073b5cd13823a0602568394be93bf310Jason parks ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); 266f8217304073b5cd13823a0602568394be93bf310Jason parks progressBar.setIndeterminate(true); 26735933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 268f8217304073b5cd13823a0602568394be93bf310Jason parks updateProgress(); 269f8217304073b5cd13823a0602568394be93bf310Jason parks } 270f8217304073b5cd13823a0602568394be93bf310Jason parks 27113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler private void showFactoryReset() { 27213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler // Hide the encryption-bot to make room for the "factory reset" button 27313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler findViewById(R.id.encroid).setVisibility(View.GONE); 27413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 27513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler // Show the reset button, failure text, and a divider 27613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler Button button = (Button) findViewById(R.id.factory_reset); 27713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler button.setVisibility(View.VISIBLE); 27813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler button.setOnClickListener(new OnClickListener() { 27913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler public void onClick(View v) { 28013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler // Factory reset the device. 28113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); 28213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler } 28313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler }); 28413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 28513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler TextView tv = (TextView) findViewById(R.id.title); 28613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler tv.setText(R.string.crypt_keeper_failed_title); 28713d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 28813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler tv = (TextView) findViewById(R.id.status); 28913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler tv.setText(R.string.crypt_keeper_failed_summary); 29013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 29113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler View view = findViewById(R.id.bottom_divider); 29213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler view.setVisibility(View.VISIBLE); 29313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler } 29413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 295f8217304073b5cd13823a0602568394be93bf310Jason parks private void updateProgress() { 296f8217304073b5cd13823a0602568394be93bf310Jason parks String state = SystemProperties.get("vold.encrypt_progress"); 297f8217304073b5cd13823a0602568394be93bf310Jason parks 29813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler if ("error_partially_encrypted".equals(state)) { 29913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler showFactoryReset(); 30013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler return; 30113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler } 30213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 303f8217304073b5cd13823a0602568394be93bf310Jason parks int progress = 0; 304f8217304073b5cd13823a0602568394be93bf310Jason parks try { 305f8217304073b5cd13823a0602568394be93bf310Jason parks progress = Integer.parseInt(state); 306f8217304073b5cd13823a0602568394be93bf310Jason parks } catch (Exception e) { 307f8217304073b5cd13823a0602568394be93bf310Jason parks Log.w(TAG, "Error parsing progress: " + e.toString()); 308f8217304073b5cd13823a0602568394be93bf310Jason parks } 30935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 310f8217304073b5cd13823a0602568394be93bf310Jason parks CharSequence status = getText(R.string.crypt_keeper_setup_description); 311f8217304073b5cd13823a0602568394be93bf310Jason parks TextView tv = (TextView) findViewById(R.id.status); 312f8217304073b5cd13823a0602568394be93bf310Jason parks tv.setText(TextUtils.expandTemplate(status, Integer.toString(progress))); 313f8217304073b5cd13823a0602568394be93bf310Jason parks 314f8217304073b5cd13823a0602568394be93bf310Jason parks // Check the progress every 5 seconds 315f8217304073b5cd13823a0602568394be93bf310Jason parks mHandler.removeMessages(UPDATE_PROGRESS); 316f8217304073b5cd13823a0602568394be93bf310Jason parks mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 5000); 317f8217304073b5cd13823a0602568394be93bf310Jason parks } 318f8217304073b5cd13823a0602568394be93bf310Jason parks 319f8217304073b5cd13823a0602568394be93bf310Jason parks private void cooldown() { 320f8217304073b5cd13823a0602568394be93bf310Jason parks TextView tv = (TextView) findViewById(R.id.status); 32113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 322f8217304073b5cd13823a0602568394be93bf310Jason parks if (mCooldown <= 0) { 323f8217304073b5cd13823a0602568394be93bf310Jason parks // Re-enable the password entry 32406c5ff4a46686d3f599e40df0768177d3d88913cJason parks mPasswordEntry.setEnabled(true); 325f8217304073b5cd13823a0602568394be93bf310Jason parks 32613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler tv.setVisibility(View.GONE); 327f8217304073b5cd13823a0602568394be93bf310Jason parks } else { 32813d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler CharSequence template = getText(R.string.crypt_keeper_cooldown); 32913d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler tv.setText(TextUtils.expandTemplate(template, Integer.toString(mCooldown))); 33013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 33113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler tv.setVisibility(View.VISIBLE); 332f8217304073b5cd13823a0602568394be93bf310Jason parks 333f8217304073b5cd13823a0602568394be93bf310Jason parks mCooldown--; 334f8217304073b5cd13823a0602568394be93bf310Jason parks mHandler.removeMessages(COOLDOWN); 335f8217304073b5cd13823a0602568394be93bf310Jason parks mHandler.sendEmptyMessageDelayed(COOLDOWN, 1000); // Tick every second 336f8217304073b5cd13823a0602568394be93bf310Jason parks } 337ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 33835933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 339ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks private void passwordEntryInit() { 34006c5ff4a46686d3f599e40df0768177d3d88913cJason parks mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); 34106c5ff4a46686d3f599e40df0768177d3d88913cJason parks mPasswordEntry.setOnEditorActionListener(this); 34235933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 3438fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks KeyboardView keyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); 34435933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 34500046d6e176eb05c3e3b0d13d38a8da7491bba5eJason parks if (keyboardView != null) { 34600046d6e176eb05c3e3b0d13d38a8da7491bba5eJason parks PasswordEntryKeyboardHelper keyboardHelper = new PasswordEntryKeyboardHelper(this, 34700046d6e176eb05c3e3b0d13d38a8da7491bba5eJason parks keyboardView, mPasswordEntry, false); 34800046d6e176eb05c3e3b0d13d38a8da7491bba5eJason parks keyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA); 34900046d6e176eb05c3e3b0d13d38a8da7491bba5eJason parks } 3508fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 3518fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 3528fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks private IMountService getMountService() { 3538fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks IBinder service = ServiceManager.getService("mount"); 3548fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks if (service != null) { 3558fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks return IMountService.Stub.asInterface(service); 3568fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 3578fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks return null; 3588fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 3598fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 3608fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks @Override 3618fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 36200046d6e176eb05c3e3b0d13d38a8da7491bba5eJason parks if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE) { 3638fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks // Get the password 3648fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks String password = v.getText().toString(); 3658fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 366ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks if (TextUtils.isEmpty(password)) { 367ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks return true; 368ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 36935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 3708fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks // Now that we have the password clear the password field. 3718fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks v.setText(null); 3728fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 37306c5ff4a46686d3f599e40df0768177d3d88913cJason parks // Disable the password entry while checking the password. This 37406c5ff4a46686d3f599e40df0768177d3d88913cJason parks // we either be reenabled if the password was wrong or after the 37506c5ff4a46686d3f599e40df0768177d3d88913cJason parks // cooldown period. 37606c5ff4a46686d3f599e40df0768177d3d88913cJason parks mPasswordEntry.setEnabled(false); 37706c5ff4a46686d3f599e40df0768177d3d88913cJason parks 37806c5ff4a46686d3f599e40df0768177d3d88913cJason parks new DecryptTask().execute(password); 37935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 3808fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks return true; 3818fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 3828fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks return false; 3838fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 3848fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks}