CryptKeeper.java revision 06c5ff4a46686d3f599e40df0768177d3d88913c
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; 23ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.app.StatusBarManager; 248fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.content.ComponentName; 25de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwalimport android.content.Context; 2606c5ff4a46686d3f599e40df0768177d3d88913cJason parksimport android.content.Intent; 278fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.content.pm.PackageManager; 28ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.graphics.Rect; 298fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.inputmethodservice.KeyboardView; 30ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.os.AsyncTask; 3135933812b16f0b4221280bbcc3c32f6540996bf2Jason parksimport android.os.Bundle; 328373b451692a39abdfd12444241c016831e1a4a4David Brownimport android.os.Handler; 338fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.IBinder; 348fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.Message; 358fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.PowerManager; 368373b451692a39abdfd12444241c016831e1a4a4David Brownimport android.os.ServiceManager; 37ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.os.SystemProperties; 388fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.os.storage.IMountService; 398fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.text.TextUtils; 4013d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.util.AttributeSet; 4113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.util.Log; 428fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.view.KeyEvent; 439fcb6a7fac02aef85085c2db616556257e1642f5Ben Komaloimport android.view.MotionEvent; 4475c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parksimport android.view.View; 459fcb6a7fac02aef85085c2db616556257e1642f5Ben Komaloimport android.view.View.OnClickListener; 4613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadlerimport android.view.inputmethod.EditorInfo; 47ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.view.inputmethod.InputMethodManager; 48ec5a45e79cb7161adfabf475342c1e1b25994276Jason parksimport android.widget.Button; 498fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.widget.EditText; 508fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parksimport android.widget.ProgressBar; 5191a2f0566afb91549cbda9289b516154a6467624Ben Komaloimport android.widget.TextView; 529fcb6a7fac02aef85085c2db616556257e1642f5Ben Komalo 539fcb6a7fac02aef85085c2db616556257e1642f5Ben Komalopublic class CryptKeeper extends Activity implements TextView.OnEditorActionListener { 5491a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final String TAG = "CryptKeeper"; 5591a2f0566afb91549cbda9289b516154a6467624Ben Komalo 5691a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final String DECRYPT_STATE = "trigger_restart_framework"; 5791a2f0566afb91549cbda9289b516154a6467624Ben Komalo 5891a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final int UPDATE_PROGRESS = 1; 5991a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final int COOLDOWN = 2; 6091a2f0566afb91549cbda9289b516154a6467624Ben Komalo 6191a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final int MAX_FAILED_ATTEMPTS = 30; 6291a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final int COOL_DOWN_ATTEMPTS = 10; 6391a2f0566afb91549cbda9289b516154a6467624Ben Komalo private static final int COOL_DOWN_INTERVAL = 30; // 30 seconds 6491a2f0566afb91549cbda9289b516154a6467624Ben Komalo 6591a2f0566afb91549cbda9289b516154a6467624Ben Komalo private int mCooldown; 6691a2f0566afb91549cbda9289b516154a6467624Ben Komalo PowerManager.WakeLock mWakeLock; 6791a2f0566afb91549cbda9289b516154a6467624Ben Komalo private EditText mPasswordEntry; 688fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 69ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks /** 7035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks * Used to propagate state through configuration changes (e.g. screen rotation) 718fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks */ 72de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal private static class NonConfigurationInstanceState { 73de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal final PowerManager.WakeLock wakelock; 74de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 75de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal NonConfigurationInstanceState(PowerManager.WakeLock _wakelock) { 76de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal wakelock = _wakelock; 77de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 78de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 79de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 80ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks // This activity is used to fade the screen to black after the password is entered. 81ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks public static class Blank extends Activity { 82ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks @Override 83ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks public void onCreate(Bundle savedInstanceState) { 848373b451692a39abdfd12444241c016831e1a4a4David Brown super.onCreate(savedInstanceState); 858373b451692a39abdfd12444241c016831e1a4a4David Brown setContentView(R.layout.crypt_keeper_blank); 868373b451692a39abdfd12444241c016831e1a4a4David Brown } 8791a2f0566afb91549cbda9289b516154a6467624Ben Komalo } 8891a2f0566afb91549cbda9289b516154a6467624Ben Komalo 8991a2f0566afb91549cbda9289b516154a6467624Ben Komalo // Use a custom EditText to prevent the input method from showing. 9091a2f0566afb91549cbda9289b516154a6467624Ben Komalo public static class CryptEditText extends EditText { 9191a2f0566afb91549cbda9289b516154a6467624Ben Komalo InputMethodManager imm; 92de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 9391a2f0566afb91549cbda9289b516154a6467624Ben Komalo public CryptEditText(Context context, AttributeSet attrs) { 94bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal super(context, attrs); 950e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo imm = ((InputMethodManager) getContext(). 96d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo getSystemService(Context.INPUT_METHOD_SERVICE)); 970e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo } 980e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo 99de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal @Override 100de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 1010e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo super.onFocusChanged(focused, direction, previouslyFocusedRect); 1021499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 1031499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler if (focused && imm != null && imm.isActive(this)) { 10406c5ff4a46686d3f599e40df0768177d3d88913cJason parks imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0); 1051499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 1061499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 1071499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 1081499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler @Override 1091499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler public boolean onTouchEvent(MotionEvent event) { 1101499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler boolean handled = super.onTouchEvent(event); 1111499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 1121499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler if (imm != null && imm.isActive(this)) { 1131499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0); 1141499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 1151499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 1161499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler return handled; 117bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal } 118bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal } 119bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal 1209f55ae28789754dafeed5c68468d45135d46199eVikram Aggarwal private class DecryptTask extends AsyncTask<String, Void, Integer> { 12113d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler @Override 12213d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler protected Integer doInBackground(String... params) { 12313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler IMountService service = getMountService(); 12413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler try { 12513d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler return service.decryptStorage(params[0]); 126de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } catch (Exception e) { 127de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal Log.e(TAG, "Error while decrypting...", e); 128de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal return -1; 129de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 130de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 131f1dbf55819e01f6cf1a99d38a292b15de1262a29Jason parks 132ec5a45e79cb7161adfabf475342c1e1b25994276Jason 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 136de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal // 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); 152bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal 15306c5ff4a46686d3f599e40df0768177d3d88913cJason parks // Reenable the password entry 15406c5ff4a46686d3f599e40df0768177d3d88913cJason parks mPasswordEntry.setEnabled(true); 15506c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 15606c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 15706c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 15806c5ff4a46686d3f599e40df0768177d3d88913cJason parks 15906c5ff4a46686d3f599e40df0768177d3d88913cJason parks private Handler mHandler = new Handler() { 16006c5ff4a46686d3f599e40df0768177d3d88913cJason parks @Override 16106c5ff4a46686d3f599e40df0768177d3d88913cJason parks public void handleMessage(Message msg) { 162bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal switch (msg.what) { 163bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal case UPDATE_PROGRESS: 164bfa3a64310162c8f29eae208220988380ffeea6eVikram Aggarwal updateProgress(); 16506c5ff4a46686d3f599e40df0768177d3d88913cJason parks break; 16606c5ff4a46686d3f599e40df0768177d3d88913cJason parks 16706c5ff4a46686d3f599e40df0768177d3d88913cJason parks case COOLDOWN: 16806c5ff4a46686d3f599e40df0768177d3d88913cJason parks cooldown(); 16906c5ff4a46686d3f599e40df0768177d3d88913cJason parks break; 17006c5ff4a46686d3f599e40df0768177d3d88913cJason parks } 17175c085ee890744cdd4b90c72f8b50e6aeeb31e88Jason parks } 1720e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo }; 1730e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo 1740e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo @Override 175de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal public void onCreate(Bundle savedInstanceState) { 1760e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo super.onCreate(savedInstanceState); 177d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo 1780e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo // If we are not encrypted or encrypting, get out quickly. 1790e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo String state = SystemProperties.get("vold.decrypt"); 1800e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo if ("".equals(state) || DECRYPT_STATE.equals(state)) { 1810e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo // Disable the crypt keeper. 1820e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo PackageManager pm = getPackageManager(); 1830e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo ComponentName name = new ComponentName(this, CryptKeeper.class); 1840e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); 1850e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo return; 1860e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo } 1870e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo 1880e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo // Disable the status bar 1890e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE); 1900e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo sbm.disable(StatusBarManager.DISABLE_EXPAND 1910e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo | StatusBarManager.DISABLE_NOTIFICATION_ICONS 1920e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo | StatusBarManager.DISABLE_NOTIFICATION_ALERTS 1930e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo | StatusBarManager.DISABLE_SYSTEM_INFO 1940e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo | StatusBarManager.DISABLE_NAVIGATION 1950e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo | StatusBarManager.DISABLE_BACK); 196d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo 197d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo // Check for (and recover) retained instance data 1980e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo Object lastInstance = getLastNonConfigurationInstance(); 1990e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo if (lastInstance instanceof NonConfigurationInstanceState) { 2000e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo NonConfigurationInstanceState retained = (NonConfigurationInstanceState) lastInstance; 2010e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo mWakeLock = retained.wakelock; 2020e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo } 20391a2f0566afb91549cbda9289b516154a6467624Ben Komalo } 204ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks 205ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks /** 206ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks * Note, we defer the state check and screen setup to onStart() because this will be 207de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal * re-run if the user clicks the power button (sleeping/waking the screen), and this is 208f8217304073b5cd13823a0602568394be93bf310Jason parks * especially important if we were to lose the wakelock for any reason. 209ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks */ 21035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks @Override 211de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal public void onStart() { 212f8217304073b5cd13823a0602568394be93bf310Jason parks super.onStart(); 213ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks 214de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal // Check to see why we were started. 215de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal String progress = SystemProperties.get("vold.encrypt_progress"); 216de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal if (!"".equals(progress)) { 217de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal setContentView(R.layout.crypt_keeper_progress); 218ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks encryptionProgressInit(); 219ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } else { 220ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks setContentView(R.layout.crypt_keeper_password_entry); 22135933812b16f0b4221280bbcc3c32f6540996bf2Jason parks passwordEntryInit(); 222de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 223de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 22491a2f0566afb91549cbda9289b516154a6467624Ben Komalo 22591a2f0566afb91549cbda9289b516154a6467624Ben Komalo @Override 22691a2f0566afb91549cbda9289b516154a6467624Ben Komalo public void onStop() { 22791a2f0566afb91549cbda9289b516154a6467624Ben Komalo super.onStop(); 22891a2f0566afb91549cbda9289b516154a6467624Ben Komalo 22991a2f0566afb91549cbda9289b516154a6467624Ben Komalo mHandler.removeMessages(COOLDOWN); 23091a2f0566afb91549cbda9289b516154a6467624Ben Komalo mHandler.removeMessages(UPDATE_PROGRESS); 23191a2f0566afb91549cbda9289b516154a6467624Ben Komalo } 23291a2f0566afb91549cbda9289b516154a6467624Ben Komalo 23391a2f0566afb91549cbda9289b516154a6467624Ben Komalo /** 234de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal * Reconfiguring, so propagate the wakelock to the next instance. This runs between onStop() 235de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal * and onDestroy() and only if we are changing configuration (e.g. rotation). Also clears 236de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal * mWakeLock so the subsequent call to onDestroy does not release it. 237de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal */ 238de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal @Override 239de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal public Object onRetainNonConfigurationInstance() { 240de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal NonConfigurationInstanceState state = new NonConfigurationInstanceState(mWakeLock); 241de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal mWakeLock = null; 242de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal return state; 243de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 244de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 245de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal @Override 246de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal public void onDestroy() { 247de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal super.onDestroy(); 248de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 249de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal if (mWakeLock != null) { 250de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal mWakeLock.release(); 251de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal mWakeLock = null; 252de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 253de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 254de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 255de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal private void encryptionProgressInit() { 256de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal // Accquire a partial wakelock to prevent the device from sleeping. Note 257de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal // we never release this wakelock as we will be restarted after the device 258de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal // is encrypted. 259de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 260de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 261de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG); 262de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 263de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal mWakeLock.acquire(); 264de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 265de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); 266de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal progressBar.setIndeterminate(true); 2678fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 2688fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks updateProgress(); 2698fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks } 27035933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 2719597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler private void showFactoryReset() { 272de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal // Hide the encryption-bot to make room for the "factory reset" button 27391a2f0566afb91549cbda9289b516154a6467624Ben Komalo findViewById(R.id.encroid).setVisibility(View.GONE); 27435933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 2758fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks // Show the reset button, failure text, and a divider 2768fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks Button button = (Button) findViewById(R.id.factory_reset); 277140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn button.setVisibility(View.VISIBLE); 278140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn button.setOnClickListener(new OnClickListener() { 279140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn public void onClick(View v) { 280644fa4243b4c288c85845b3f86aab25135635729Dianne Hackborn // Factory reset the device. 281644fa4243b4c288c85845b3f86aab25135635729Dianne Hackborn sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR")); 282644fa4243b4c288c85845b3f86aab25135635729Dianne Hackborn } 283140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn }); 284140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn 285140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn TextView tv = (TextView) findViewById(R.id.title); 286140f6c6cf705f020c0ee6a2843cf1691cc68e729Dianne Hackborn tv.setText(R.string.crypt_keeper_failed_title); 2878fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks 2888fd5bc9e6ff0d02012df670a6bf4bcdaf903c09dJason parks tv = (TextView) findViewById(R.id.status); 28935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks tv.setText(R.string.crypt_keeper_failed_summary); 290b96b35a62b1f092b6322643c3568f3e712543e53Vikram Aggarwal 291b96b35a62b1f092b6322643c3568f3e712543e53Vikram Aggarwal View view = findViewById(R.id.bottom_divider); 29239f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks view.setVisibility(View.VISIBLE); 29313d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler } 29413d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler 29539f1e04079976d3d10fdd8e5dd36c833bab8a371Jason parks private void updateProgress() { 29613d62049f7c96c47356f23eaee7f0997612fdf9fAndy Stadler String state = SystemProperties.get("vold.encrypt_progress"); 2974d2bfd149118c8b82827d76d1d110fd5c65294c8Daniel Sandler 298b96b35a62b1f092b6322643c3568f3e712543e53Vikram Aggarwal if ("error_partially_encrypted".equals(state)) { 2991499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler showFactoryReset(); 300de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal return; 3011499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 302de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 3031499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler int progress = 0; 3041499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler try { 3051499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler progress = Integer.parseInt(state); 3060460675b7c0d5a9b02dae01578c64ff0453e4fb7Ben Komalo } catch (Exception e) { 3071499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler Log.w(TAG, "Error parsing progress: " + e.toString()); 308ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 30935933812b16f0b4221280bbcc3c32f6540996bf2Jason parks 3109597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler CharSequence status = getText(R.string.crypt_keeper_setup_description); 3119597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler TextView tv = (TextView) findViewById(R.id.status); 3129597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler tv.setText(TextUtils.expandTemplate(status, Integer.toString(progress))); 3139597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler 3149597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler // Check the progress every 5 seconds 3159597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler mHandler.removeMessages(UPDATE_PROGRESS); 3169597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 5000); 3179597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler } 318d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo 3190e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo private void cooldown() { 3200e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo TextView tv = (TextView) findViewById(R.id.status); 3210e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo 3220e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo if (mCooldown <= 0) { 3230e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo // Re-enable the password entry 3240e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo mPasswordEntry.setEnabled(true); 3250e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo 3260e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo tv.setVisibility(View.GONE); 3270e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo } else { 3280e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo CharSequence template = getText(R.string.crypt_keeper_cooldown); 3290e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo tv.setText(TextUtils.expandTemplate(template, Integer.toString(mCooldown))); 3300e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo 3310e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo tv.setVisibility(View.VISIBLE); 332de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 3330e66609c95047ba7e5c0408bdc88af4315fd35b1Ben Komalo mCooldown--; 3349597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler mHandler.removeMessages(COOLDOWN); 3359597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler mHandler.sendEmptyMessageDelayed(COOLDOWN, 1000); // Tick every second 336de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 3379597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler } 3389597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler 339d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo private void passwordEntryInit() { 340d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); 341d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo mPasswordEntry.setOnEditorActionListener(this); 342d4758efef6d6564d7b4b0b747d0a9ae9b44a38c7Ben Komalo 3439597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler KeyboardView keyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); 3449597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler 3459597406aa1b83867b03a47d1a5162969b924f2fcAndy Stadler PasswordEntryKeyboardHelper keyboardHelper = new PasswordEntryKeyboardHelper(this, 346f8217304073b5cd13823a0602568394be93bf310Jason parks keyboardView, mPasswordEntry, false); 347f8217304073b5cd13823a0602568394be93bf310Jason parks keyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA); 348f8217304073b5cd13823a0602568394be93bf310Jason parks } 349de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal 350de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal private IMountService getMountService() { 351de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal IBinder service = ServiceManager.getService("mount"); 3521499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler if (service != null) { 3531499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler return IMountService.Stub.asInterface(service); 3541499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 3551499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler return null; 3561499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 3571499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 3581499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler @Override 3591499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 3601499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler if (actionId == EditorInfo.IME_NULL) { 3611499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler // Get the password 3620460675b7c0d5a9b02dae01578c64ff0453e4fb7Ben Komalo String password = v.getText().toString(); 3631499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 3641499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler if (TextUtils.isEmpty(password)) { 3651499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler return true; 3661499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler } 3671499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler 3681499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler // Now that we have the password clear the password field. 3691499740c13af5fbd5766a87825c3e789b37bab24Andy Stadler v.setText(null); 370f8217304073b5cd13823a0602568394be93bf310Jason parks 371f8217304073b5cd13823a0602568394be93bf310Jason parks // Disable the password entry while checking the password. This 3720460675b7c0d5a9b02dae01578c64ff0453e4fb7Ben Komalo // we either be reenabled if the password was wrong or after the 373f8217304073b5cd13823a0602568394be93bf310Jason parks // cooldown period. 374f8217304073b5cd13823a0602568394be93bf310Jason parks mPasswordEntry.setEnabled(false); 375f8217304073b5cd13823a0602568394be93bf310Jason parks 376f8217304073b5cd13823a0602568394be93bf310Jason parks new DecryptTask().execute(password); 377f8217304073b5cd13823a0602568394be93bf310Jason parks 378de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal return true; 379de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal } 380de3c9cb412688eb841993ad971d06039d8a952c3Vikram Aggarwal return false; 381ec5a45e79cb7161adfabf475342c1e1b25994276Jason parks } 38235933812b16f0b4221280bbcc3c32f6540996bf2Jason parks}