blob: 222e954f140afce2df3bb8d9c3b4a8421b8ee01b [file] [log] [blame]
Jason parks8fd5bc92011-01-12 16:03:31 -06001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
19import com.android.internal.widget.PasswordEntryKeyboardHelper;
20import com.android.internal.widget.PasswordEntryKeyboardView;
21
22import android.app.Activity;
23import android.app.StatusBarManager;
24import android.content.ComponentName;
25import android.content.Context;
Jason parksec5a45e2011-01-18 15:28:36 -060026import android.content.Intent;
Jason parks8fd5bc92011-01-12 16:03:31 -060027import android.content.pm.PackageManager;
28import android.inputmethodservice.KeyboardView;
29import android.os.Bundle;
Jason parksec5a45e2011-01-18 15:28:36 -060030import android.os.Handler;
Jason parks8fd5bc92011-01-12 16:03:31 -060031import android.os.IBinder;
Jason parksec5a45e2011-01-18 15:28:36 -060032import android.os.Message;
Jason parks8fd5bc92011-01-12 16:03:31 -060033import android.os.ServiceManager;
34import android.os.SystemProperties;
35import android.os.storage.IMountService;
Jason parksec5a45e2011-01-18 15:28:36 -060036import android.text.TextUtils;
Jason parks8fd5bc92011-01-12 16:03:31 -060037import android.text.format.DateFormat;
38import android.util.Log;
39import android.view.KeyEvent;
40import android.view.inputmethod.EditorInfo;
Jason parksec5a45e2011-01-18 15:28:36 -060041import android.widget.EditText;
42import android.widget.ProgressBar;
Jason parks8fd5bc92011-01-12 16:03:31 -060043import android.widget.TextView;
44
45import java.util.Date;
46
47public class CryptKeeper extends Activity implements TextView.OnEditorActionListener {
Jason parksec5a45e2011-01-18 15:28:36 -060048 private static final String TAG = "CryptKeeper";
49
Jason parks8fd5bc92011-01-12 16:03:31 -060050 private static final String DECRYPT_STATE = "trigger_restart_framework";
Jason parksec5a45e2011-01-18 15:28:36 -060051
52 private static final int UPDATE_PROGRESS = 1;
53 private static final int COOLDOWN = 2;
54
55 private static final int MAX_FAILED_ATTEMPTS = 30;
56 private static final int COOL_DOWN_ATTEMPTS = 10;
57 private static final int COOL_DOWN_INTERVAL = 30; // 30 seconds
58
59
60 private Handler mHandler = new Handler() {
61 @Override
62 public void handleMessage(Message msg) {
63
64 switch (msg.what) {
65
66 case UPDATE_PROGRESS:
67 String state = SystemProperties.get("vold.encrypt_progress");
68
69 ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
70 progressBar.setProgress(0);
71
72 try {
73 int progress = Integer.parseInt(state);
74 progressBar.setProgress(progress);
75 } catch (Exception e) {
76 Log.w(TAG, "Error parsing progress: " + e.toString());
77 }
Jason parks39f1e042011-01-20 23:29:28 -060078
79 // Check the status every 5 second
80 sendEmptyMessageDelayed(UPDATE_PROGRESS, 5000);
Jason parksec5a45e2011-01-18 15:28:36 -060081 break;
82
83 case COOLDOWN:
84 TextView tv = (TextView) findViewById(R.id.status);
85 if (mCooldown <= 0) {
86 // Re-enable the password entry
87 EditText passwordEntry = (EditText) findViewById(R.id.passwordEntry);
88 passwordEntry.setEnabled(true);
89
90 tv.setText(R.string.try_again);
91
92 } else {
93
94 CharSequence tempalte = getText(R.string.crypt_keeper_cooldown);
95 tv.setText(TextUtils.expandTemplate(tempalte, Integer.toString(mCooldown)));
96
97 mCooldown--;
98 mHandler.sendEmptyMessageDelayed(COOLDOWN, 1000); // Tick every second
99 }
100 break;
101 }
102 }
103 };
104
105 private int mFailedAttempts = 0;
106 private int mCooldown;
Jason parks8fd5bc92011-01-12 16:03:31 -0600107
108 @Override
109 public void onCreate(Bundle savedInstanceState) {
110 super.onCreate(savedInstanceState);
Jason parks8fd5bc92011-01-12 16:03:31 -0600111
112 String state = SystemProperties.get("vold.decrypt");
113 if ("".equals(state) || DECRYPT_STATE.equals(state)) {
Jason parksec5a45e2011-01-18 15:28:36 -0600114 // Disable the crypt keeper.
Jason parks8fd5bc92011-01-12 16:03:31 -0600115 PackageManager pm = getPackageManager();
116 ComponentName name = new ComponentName(this, CryptKeeper.class);
117 pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
118 return;
119 }
120
Jason parksec5a45e2011-01-18 15:28:36 -0600121 // Check to see why we were started.
122 String progress = SystemProperties.get("vold.encrypt_progress");
Jason parksdbf43222011-01-20 18:49:58 -0600123
124 if (!"".equals(progress)) {
Jason parksec5a45e2011-01-18 15:28:36 -0600125 setContentView(R.layout.crypt_keeper_progress);
126 encryptionProgressInit();
127 } else {
128 setContentView(R.layout.crypt_keeper_password_entry);
129 passwordEntryInit();
130 }
Jason parks39f1e042011-01-20 23:29:28 -0600131
132 // Disable the status bar
133 StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
134 sbm.disable(StatusBarManager.DISABLE_EXPAND | StatusBarManager.DISABLE_NOTIFICATION_ICONS
135 | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
136 | StatusBarManager.DISABLE_SYSTEM_INFO | StatusBarManager.DISABLE_NAVIGATION);
Jason parksec5a45e2011-01-18 15:28:36 -0600137 }
138
139 private void encryptionProgressInit() {
140 mHandler.sendEmptyMessage(UPDATE_PROGRESS);
141 }
142
143 private void passwordEntryInit() {
Jason parks8fd5bc92011-01-12 16:03:31 -0600144 TextView passwordEntry = (TextView) findViewById(R.id.passwordEntry);
145 passwordEntry.setOnEditorActionListener(this);
146
147 KeyboardView keyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
148
149 PasswordEntryKeyboardHelper keyboardHelper = new PasswordEntryKeyboardHelper(this,
150 keyboardView, passwordEntry, false);
151 keyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
152
153
154 passwordEntry.setCompoundDrawablesWithIntrinsicBounds(android.R.drawable.ic_lock_idle_lock,
155 0, 0, 0);
156
157 String dateFormatString = getString(com.android.internal.R.string.full_wday_month_day_no_year);
158 TextView date = (TextView) findViewById(R.id.date);
159 date.setText(DateFormat.format(dateFormatString, new Date()));
Jason parks8fd5bc92011-01-12 16:03:31 -0600160 }
161
162 private IMountService getMountService() {
163 IBinder service = ServiceManager.getService("mount");
164 if (service != null) {
165 return IMountService.Stub.asInterface(service);
166 }
167 return null;
168 }
169
170 @Override
171 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
172 if (actionId == EditorInfo.IME_NULL) {
173 // Get the password
174 String password = v.getText().toString();
175
Jason parksec5a45e2011-01-18 15:28:36 -0600176 if (TextUtils.isEmpty(password)) {
177 return true;
178 }
179
Jason parks8fd5bc92011-01-12 16:03:31 -0600180 // Now that we have the password clear the password field.
181 v.setText(null);
182
183 IMountService service = getMountService();
184 try {
185 service.decryptStorage(password);
186
Jason parks39f1e042011-01-20 23:29:28 -0600187 if (mFailedAttempts == 0) {
188 // Success. Do something here within 2 seconds
Jason parks8fd5bc92011-01-12 16:03:31 -0600189
Jason parks39f1e042011-01-20 23:29:28 -0600190 } else if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
Jason parksec5a45e2011-01-18 15:28:36 -0600191 // Factory reset the device.
192 sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
193 } else if ((mFailedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
194 mCooldown = COOL_DOWN_INTERVAL;
195 EditText passwordEntry = (EditText) findViewById(R.id.passwordEntry);
196 passwordEntry.setEnabled(false);
197 mHandler.sendEmptyMessage(COOLDOWN);
198 } else {
199 TextView tv = (TextView) findViewById(R.id.status);
200 tv.setText(R.string.try_again);
201 }
Jason parks8fd5bc92011-01-12 16:03:31 -0600202 } catch (Exception e) {
Jason parksec5a45e2011-01-18 15:28:36 -0600203 Log.e(TAG, "Error while decrypting...", e);
Jason parks8fd5bc92011-01-12 16:03:31 -0600204 }
205
206 return true;
207 }
208 return false;
209 }
210}