Merge "New Settings assets" into honeycomb
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c7fbfa4..f822ff6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1080,6 +1080,21 @@
             </intent-filter>
         </activity>
 
+        <!-- Pseudo-activity used to provide an intent-filter entry point to encryption settings -->
+        <activity android:name="Settings$CryptKeeperSettingsActivity"
+                android:theme="@android:style/Theme.Holo"
+                android:label="@string/crypt_keeper_encrypt_title">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <action android:name="android.app.action.START_ENCRYPTION" />
+                <category android:name="android.intent.category.DEFAULT" /> />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.CryptKeeperSettings" />
+            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
+                android:resource="@id/security_settings" />
+        </activity>
+
         <receiver android:name=".widget.SettingsAppWidgetProvider"
                 android:label="@string/gadget_title"
                 android:exported="false"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 472b391..9724e60 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -587,12 +587,12 @@
     <string name="crypt_keeper_encrypt_summary">Requires you to set a device unlock pin or password</string>
     <string name="crypt_keeper_confirm_title">Confirm encrypt</string>
     
-    <string name="crypt_keeper_desc">Device encryption will convert user data to an ecrypted state, including your accounts, system data, downloaded applications and data, photos, movies, musics, etc.\n\nEncyrption cannot be undone without performing a factory data reset, which would then erase all data.\n\nYou must set up a device lock pin or password to proceed.\n\nThis operation may take up to an hour and may not be interrupted. You must have a fully charged battery and plug in the device to initiate encryption. Running out of power during encryption will cause data loss.</string>
+    <string name="crypt_keeper_desc">You can encrypt your accounts, settings, downloaded applications and their data, media, and other files. Once you encrypt your tablet, you can\'t unencrypt it except by performing a factory data reset, erasing all the data on your tablet.\n\nEncryption takes up to an hour. You must start with a charged battery and keep your tablet plugged in until encryption is complete. If you interrupt the encryption process, you will lose some or all of your data.</string>
     
     <string name="crypt_keeper_button_text" product="tablet">Encrypt tablet</string>
     <string name="crypt_keeper_button_text" product="default">Encrypt phone</string>
     
-    <string name="crypt_keeper_final_desc">Encrypt user data? This operation is not reversible and may not be interrupted without loos of data! Encryption may take up to an hour.</string>
+    <string name="crypt_keeper_final_desc">Encrypt user data? This operation is not reversible and may not be interrupted without loss of data! Encryption may take up to an hour.</string>
     
     <string name="crypt_keeper_setup_title">Encrypting</string>
 
@@ -3054,7 +3054,7 @@
     <!-- Message shown when users select EAP in WiFi settings for SetupWizard,
          saying EAP can't be configured in SetupWizard flow.
          [CHAR LIMIT=NONE] -->
-    <string name="wifi_setup_eap_not_supported">You can\u0027t configure an EAP Wi-Fi connection during setup. After setup, you can do that in Settings, under Wireless &amp; Networks.</string>
+    <string name="wifi_setup_eap_not_supported">You can\u0027t configure an EAP Wi-Fi connection during setup. After setup, you can do that in Settings, under <b>Wireless &amp; networks</b>.</string>
     <!-- Message shown when the device is connecting a network [CHAR LIMIT=NONE] -->
     <string name="wifi_setup_description_connecting">Connecting can take a few minutes...</string>
     <!-- Message shown when the device is connected to a network [CHAR LIMIT=NONE] -->
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 88b344e..3917b76 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -30,6 +30,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.storage.IMountService;
@@ -46,7 +47,7 @@
 
 public class CryptKeeper extends Activity implements TextView.OnEditorActionListener {
     private static final String TAG = "CryptKeeper";
-    
+
     private static final String DECRYPT_STATE = "trigger_restart_framework";
 
     private static final int UPDATE_PROGRESS = 1;
@@ -60,40 +61,40 @@
     private Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            
+
             switch (msg.what) {
-            
+
             case UPDATE_PROGRESS:
                 String state = SystemProperties.get("vold.encrypt_progress");
-                
+
                 ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
                 progressBar.setProgress(0);
-                
+
                 try {
                     int progress = Integer.parseInt(state);
                     progressBar.setProgress(progress);
                 } catch (Exception e) {
                     Log.w(TAG, "Error parsing progress: " + e.toString());
                 }
-                
-                // Check the status every 1 second
-                sendEmptyMessageDelayed(0, 1000);
+
+                // Check the status every 5 second
+                sendEmptyMessageDelayed(UPDATE_PROGRESS, 5000);
                 break;
-            
+
             case COOLDOWN:
                 TextView tv = (TextView) findViewById(R.id.status);
                 if (mCooldown <= 0) {
                     // Re-enable the password entry
                     EditText passwordEntry = (EditText) findViewById(R.id.passwordEntry);
                     passwordEntry.setEnabled(true);
-                    
+
                     tv.setText(R.string.try_again);
-                    
+
                 } else {
-                    
+
                     CharSequence tempalte = getText(R.string.crypt_keeper_cooldown);
                     tv.setText(TextUtils.expandTemplate(tempalte, Integer.toString(mCooldown)));
-                    
+
                     mCooldown--;
                     mHandler.sendEmptyMessageDelayed(COOLDOWN, 1000); // Tick every second
                 }
@@ -101,44 +102,60 @@
             }
         }
     };
-    
+
     private int mFailedAttempts = 0;
     private int mCooldown;
-    
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        
+
         String state = SystemProperties.get("vold.decrypt");
         if ("".equals(state) || DECRYPT_STATE.equals(state)) {
-            // Disable the crypt keeper. 
+            // Disable the crypt keeper.
             PackageManager pm = getPackageManager();
             ComponentName name = new ComponentName(this, CryptKeeper.class);
             pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
             return;
         }
-        
+
         // Check to see why we were started.
         String progress = SystemProperties.get("vold.encrypt_progress");
-        if ("startup".equals(progress)) {
+
+        if (!"".equals(progress)) {
             setContentView(R.layout.crypt_keeper_progress);
             encryptionProgressInit();
         } else {
             setContentView(R.layout.crypt_keeper_password_entry);
             passwordEntryInit();
         }
+
+        // Disable the status bar
+        StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
+        sbm.disable(StatusBarManager.DISABLE_EXPAND | StatusBarManager.DISABLE_NOTIFICATION_ICONS
+                | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
+                | StatusBarManager.DISABLE_SYSTEM_INFO | StatusBarManager.DISABLE_NAVIGATION);
     }
-    
+
     private void encryptionProgressInit() {
+        // Accquire a partial wakelock to prevent the device from sleeping. Note
+        // we never release this wakelock as we will be restarted after the device
+        // is encrypted.
+
+        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+        PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+        wakeLock.acquire();
+
         mHandler.sendEmptyMessage(UPDATE_PROGRESS);
     }
-    
+
     private void passwordEntryInit() {
         TextView passwordEntry = (TextView) findViewById(R.id.passwordEntry);
         passwordEntry.setOnEditorActionListener(this);
-        
+
         KeyboardView keyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
-        
+
         PasswordEntryKeyboardHelper keyboardHelper = new PasswordEntryKeyboardHelper(this,
                 keyboardView, passwordEntry, false);
         keyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
@@ -150,12 +167,6 @@
         String dateFormatString = getString(com.android.internal.R.string.full_wday_month_day_no_year);
         TextView date = (TextView) findViewById(R.id.date);
         date.setText(DateFormat.format(dateFormatString, new Date()));
-
-        // Disable the status bar
-        StatusBarManager sbm = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
-        sbm.disable(StatusBarManager.DISABLE_EXPAND | StatusBarManager.DISABLE_NOTIFICATION_ICONS
-                | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
-                | StatusBarManager.DISABLE_SYSTEM_INFO | StatusBarManager.DISABLE_NAVIGATION);
     }
 
     private IMountService getMountService() {
@@ -175,7 +186,7 @@
             if (TextUtils.isEmpty(password)) {
                 return true;
             }
-            
+
             // Now that we have the password clear the password field.
             v.setText(null);
 
@@ -183,12 +194,10 @@
             try {
                 service.decryptStorage(password);
 
-                // For now the only way to get here is for the password to be
-                // wrong.
+                if (mFailedAttempts == 0) {
+                    // Success. Do something here within 2 seconds
 
-                mFailedAttempts++;
-                
-                if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
+                } else if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
                     // Factory reset the device.
                     sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
                 } else if ((mFailedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
@@ -203,7 +212,7 @@
             } catch (Exception e) {
                 Log.e(TAG, "Error while decrypting...", e);
             }
-            
+
             return true;
         }
         return false;
diff --git a/src/com/android/settings/CryptKeeperSettings.java b/src/com/android/settings/CryptKeeperSettings.java
index 8b60ca7..d26e5ff 100644
--- a/src/com/android/settings/CryptKeeperSettings.java
+++ b/src/com/android/settings/CryptKeeperSettings.java
@@ -17,9 +17,15 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.Resources;
+import android.os.BatteryManager;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
@@ -45,6 +51,93 @@
 
     private View mContentView;
     private Button mInitiateButton;
+    private IntentFilter mIntentFilter;
+
+    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+                int level = intent.getIntExtra("level", 0);
+                int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
+
+                if (status == BatteryManager.BATTERY_STATUS_CHARGING && level >= 80) {
+                    mInitiateButton.setEnabled(true);
+                } else {
+                    mInitiateButton.setEnabled(false);
+                }
+            }
+        }
+    };
+
+    /**
+     * If the user clicks to begin the reset sequence, we next require a
+     * keyguard confirmation if the user has currently enabled one.  If there
+     * is no keyguard available, we prompt the user to set a password.
+     */
+    private Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
+
+        public void onClick(View v) {
+            if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
+                // TODO remove with proper flow
+                new AlertDialog.Builder(getActivity())
+                    .setTitle("No password set")
+                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .setMessage("Before you enable encryption you must set a device password.")
+                    .setPositiveButton(android.R.string.ok, null)
+                    .create()
+                    .show();
+            }
+        }
+    };
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+        mContentView = inflater.inflate(R.layout.crypt_keeper_settings, null);
+
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+
+        mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_encrypt);
+        mInitiateButton.setOnClickListener(mInitiateListener);
+        mInitiateButton.setEnabled(false);
+
+        return mContentView;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        getActivity().registerReceiver(mIntentReceiver, mIntentFilter);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        getActivity().unregisterReceiver(mIntentReceiver);
+    }
+
+    /**
+     * If encryption is already started, and this launched via a "start encryption" intent,
+     * then exit immediately - it's already up and running, so there's no point in "starting" it.
+     */
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        Activity activity = getActivity();
+        Intent intent = activity.getIntent();
+        if (DevicePolicyManager.ACTION_START_ENCRYPTION.equals(intent.getAction())) {
+            DevicePolicyManager dpm = (DevicePolicyManager)
+                    activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
+            if (dpm != null) {
+                int status = dpm.getStorageEncryptionStatus();
+                if (status != DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE) {
+                    // There is nothing to do here, so simply finish() (which returns to caller)
+                    activity.finish();
+                }
+            }
+        }
+    }
 
     /**
      * Keyguard validation is run using the standard {@link ConfirmLockPattern}
@@ -67,14 +160,12 @@
         if (requestCode != KEYGUARD_REQUEST) {
             return;
         }
-        
+
         // If the user entered a valid keyguard trace, present the final
         // confirmation prompt; otherwise, go back to the initial state.
         if (resultCode == Activity.RESULT_OK) {
             String password = data.getStringExtra("password");
             showFinalConfirmation(password);
-        } else {
-            establishInitialState();
         }
     }
 
@@ -85,45 +176,5 @@
         preference.getExtras().putString("password", password);
         ((PreferenceActivity) getActivity()).onPreferenceStartFragment(null, preference);
     }
-
-    /**
-     * If the user clicks to begin the reset sequence, we next require a
-     * keyguard confirmation if the user has currently enabled one.  If there
-     * is no keyguard available, we simply go to the final confirmation prompt.
-     */
-    private Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
-
-        public void onClick(View v) {
-            if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
-                // TODO: Need to request a password
-               // showFinalConfirmation();
-            }
-        }
-    };
-
-    /**
-     * In its initial state, the activity presents a button for the user to
-     * click in order to initiate a confirmation sequence.  This method is
-     * called from various other points in the code to reset the activity to
-     * this base state.
-     *
-     * <p>Reinflating views from resources is expensive and prevents us from
-     * caching widget pointers, so we use a single-inflate pattern:  we lazy-
-     * inflate each view, caching all of the widget pointers we'll need at the
-     * time, then simply reuse the inflated views directly whenever we need
-     * to change contents.
-     */
-    private void establishInitialState() {
-        mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_encrypt);
-        mInitiateButton.setOnClickListener(mInitiateListener);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        mContentView = inflater.inflate(R.layout.crypt_keeper_settings, null);
-
-        establishInitialState();
-        return mContentView;
-    }
 }
 
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 5bb169e..aaaf265 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -21,38 +21,25 @@
 
 import com.android.internal.widget.LockPatternUtils;
 
-import android.app.AlertDialog;
-import android.app.Dialog;
 import android.app.admin.DevicePolicyManager;
 import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.database.Cursor;
 import android.location.LocationManager;
 import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.Vibrator;
-import android.os.storage.IMountService;
 import android.preference.CheckBoxPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.PreferenceCategory;
 import android.preference.PreferenceGroup;
-import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
-import android.security.Credentials;
 import android.security.KeyStore;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-import android.widget.Toast;
 
 import java.util.ArrayList;
 import java.util.Observable;
@@ -410,90 +397,6 @@
         createPreferenceHierarchy();
     }
 
-    private class Encryption implements DialogInterface.OnClickListener,
-            DialogInterface.OnDismissListener {
-
-        private boolean mSubmit;
-
-        public void showPasswordDialog() {
-            View view = View.inflate(SecuritySettings.this.getActivity(),
-                    R.layout.credentials_dialog, null);
-            view.findViewById(R.id.new_passwords).setVisibility(View.VISIBLE);
-
-            Dialog dialog = new AlertDialog.Builder(SecuritySettings.this.getActivity())
-                    .setView(view).setTitle(R.string.credentials_set_password)
-                    .setPositiveButton(android.R.string.ok, this)
-                    .setNegativeButton(android.R.string.cancel, this).create();
-            dialog.setOnDismissListener(this);
-            dialog.show();
-        }
-
-        public void onClick(DialogInterface dialog, int button) {
-            if (button == DialogInterface.BUTTON_POSITIVE) {
-                mSubmit = true;
-            }
-        }
-
-        public void onDismiss(DialogInterface dialog) {
-            if (mSubmit) {
-                mSubmit = false;
-                if (!checkPassword((Dialog) dialog)) {
-                    ((Dialog) dialog).show();
-                    return;
-                }
-            }
-        }
-
-        // Return true if there is no error.
-        private boolean checkPassword(Dialog dialog) {
-            String newPassword = getText(dialog, R.id.new_password);
-            String confirmPassword = getText(dialog, R.id.confirm_password);
-
-            if (newPassword == null || confirmPassword == null || newPassword.length() == 0
-                    || confirmPassword.length() == 0) {
-                showError(dialog, R.string.credentials_passwords_empty);
-            } else if (!newPassword.equals(confirmPassword)) {
-                showError(dialog, R.string.credentials_passwords_mismatch);
-            } else {
-
-                IBinder service = ServiceManager.getService("mount");
-                if (service == null) {
-                    return false;
-                }
-
-                IMountService mountService = IMountService.Stub.asInterface(service);
-                try {
-                    mountService.encryptStorage(newPassword);
-                } catch (Exception e) {
-                    Log.e(TAG, "Error while encrypting...", e);
-                }
-
-                return true;
-            }
-
-            return false;
-        }
-
-        private String getText(Dialog dialog, int viewId) {
-            TextView view = (TextView) dialog.findViewById(viewId);
-            return (view == null || view.getVisibility() == View.GONE) ? null : view.getText()
-                    .toString();
-        }
-
-        private void showError(Dialog dialog, int stringId, Object... formatArgs) {
-            TextView view = (TextView) dialog.findViewById(R.id.error);
-            if (view != null) {
-                if (formatArgs == null || formatArgs.length == 0) {
-                    view.setText(stringId);
-                } else {
-                    view.setText(getString(stringId, formatArgs));
-                }
-                view.setVisibility(View.VISIBLE);
-            }
-        }
-
-    }
-
     public boolean onPreferenceChange(Preference preference, Object value) {
         if (preference == mLockAfter) {
             int timeout = Integer.parseInt((String) value);
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 11d8c57..1e54504 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -332,4 +332,5 @@
     public static class PowerUsageSummaryActivity extends Settings { }
     public static class AccountSyncSettingsActivity extends Settings { }
     public static class AccountSyncSettingsInAddAccountActivity extends Settings { }
+    public static class CryptKeeperSettingsActivity extends Settings { }
 }