am 7dc2e9c5: Merge "Improve the reboot-to-recovery dialogs" into mnc-dev

* commit '7dc2e9c59cab0ffc9ecbce84092c5cc7bc48a251':
  Improve the reboot-to-recovery dialogs
This commit is contained in:
Tao Bao
2015-06-09 17:45:57 +00:00
committed by Android Git Automerger
3 changed files with 113 additions and 55 deletions

View File

@@ -414,8 +414,14 @@
<string name="silent_mode_ring">Ringer on</string>
<!-- Reboot to Recovery Progress Dialog. This is shown before it reboots to recovery. -->
<string name="reboot_to_recovery_title">Prepare for update</string>
<string name="reboot_to_recovery_progress">Processing the update package\u2026</string>
<string name="reboot_to_update_title">Android system update</string>
<string name="reboot_to_update_prepare">Preparing to update\u2026</string>
<string name="reboot_to_update_package">Processing the update package\u2026</string>
<string name="reboot_to_update_reboot">Restarting\u2026</string>
<!-- Reboot to Recovery for factory reset. -->
<string name="reboot_to_reset_title">Factory data reset</string>
<string name="reboot_to_reset_message">Restarting\u2026</string>
<!-- Shutdown Progress Dialog. This is shown if the user chooses to power off the phone. -->
<string name="shutdown_progress">Shutting down\u2026</string>

View File

@@ -820,8 +820,12 @@
<java-symbol type="string" name="mobile_provisioning_url" />
<java-symbol type="string" name="mobile_redirected_provisioning_url" />
<java-symbol type="string" name="quick_contacts_not_available" />
<java-symbol type="string" name="reboot_to_recovery_progress" />
<java-symbol type="string" name="reboot_to_recovery_title" />
<java-symbol type="string" name="reboot_to_update_package" />
<java-symbol type="string" name="reboot_to_update_prepare" />
<java-symbol type="string" name="reboot_to_update_title" />
<java-symbol type="string" name="reboot_to_update_reboot" />
<java-symbol type="string" name="reboot_to_reset_title" />
<java-symbol type="string" name="reboot_to_reset_message" />
<java-symbol type="string" name="reboot_safemode_confirm" />
<java-symbol type="string" name="reboot_safemode_title" />
<java-symbol type="string" name="relationTypeAssistant" />

View File

@@ -67,6 +67,12 @@ public final class ShutdownThread extends Thread {
private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
private static final int MAX_RADIO_WAIT_TIME = 12*1000;
private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*1000;
// constants for progress bar. the values are roughly estimated based on timeout.
private static final int BROADCAST_STOP_PERCENT = 2;
private static final int ACTIVITY_MANAGER_STOP_PERCENT = 4;
private static final int PACKAGE_MANAGER_STOP_PERCENT = 6;
private static final int RADIO_STOP_PERCENT = 18;
private static final int MOUNT_SERVICE_STOP_PERCENT = 20;
// length of vibration before shutting down
private static final int SHUTDOWN_VIBRATE_MS = 500;
@@ -75,11 +81,13 @@ public final class ShutdownThread extends Thread {
private static Object sIsStartedGuard = new Object();
private static boolean sIsStarted = false;
// uncrypt status file
// uncrypt status files
private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status";
private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
private static boolean mReboot;
private static boolean mRebootSafeMode;
private static boolean mRebootUpdate;
private static String mRebootReason;
// Provides shutdown assurance in case the system_server is killed
@@ -203,6 +211,7 @@ public final class ShutdownThread extends Thread {
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;
mRebootSafeMode = false;
mRebootUpdate = false;
mRebootReason = reason;
shutdownInner(context, confirm);
}
@@ -222,6 +231,7 @@ public final class ShutdownThread extends Thread {
mReboot = true;
mRebootSafeMode = true;
mRebootUpdate = false;
mRebootReason = null;
shutdownInner(context, confirm);
}
@@ -235,16 +245,44 @@ public final class ShutdownThread extends Thread {
sIsStarted = true;
}
// throw up an indeterminate system dialog to indicate radio is
// shutting down.
// Throw up a system dialog to indicate the device is rebooting / shutting down.
ProgressDialog pd = new ProgressDialog(context);
// Path 1: Reboot to recovery and install the update
// Condition: mRebootReason == REBOOT_RECOVERY and mRebootUpdate == True
// (mRebootUpdate is set by checking if /cache/recovery/uncrypt_file exists.)
// UI: progress bar
//
// Path 2: Reboot to recovery for factory reset
// Condition: mRebootReason == REBOOT_RECOVERY
// UI: spinning circle only (no progress bar)
//
// Path 3: Regular reboot / shutdown
// Condition: Otherwise
// UI: spinning circle only (no progress bar)
if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_recovery_title));
mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists();
if (mRebootUpdate) {
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_update_prepare));
pd.setMax(100);
pd.setProgressNumberFormat(null);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setProgress(0);
pd.setIndeterminate(false);
} else {
// Factory reset path. Set the dialog message accordingly.
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_reset_message));
pd.setIndeterminate(true);
}
} else {
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
}
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
@@ -339,13 +377,20 @@ public final class ShutdownThread extends Thread {
if (delay <= 0) {
Log.w(TAG, "Shutdown broadcast timed out");
break;
} else if (mRebootUpdate) {
int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
sInstance.setRebootProgress(status, null);
}
try {
mActionDoneSync.wait(delay);
mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
} catch (InterruptedException e) {
}
}
}
if (mRebootUpdate) {
sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
}
Log.i(TAG, "Shutting down activity manager...");
@@ -357,6 +402,9 @@ public final class ShutdownThread extends Thread {
} catch (RemoteException e) {
}
}
if (mRebootUpdate) {
sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
}
Log.i(TAG, "Shutting down package manager...");
@@ -365,9 +413,15 @@ public final class ShutdownThread extends Thread {
if (pm != null) {
pm.shutdown();
}
if (mRebootUpdate) {
sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
}
// Shutdown radios.
shutdownRadios(MAX_RADIO_WAIT_TIME);
if (mRebootUpdate) {
sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
}
// Shutdown MountService to ensure media is in a safe state
IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
@@ -399,64 +453,44 @@ public final class ShutdownThread extends Thread {
if (delay <= 0) {
Log.w(TAG, "Shutdown wait timed out");
break;
} else if (mRebootUpdate) {
int status = (int)((MAX_SHUTDOWN_WAIT_TIME - delay) * 1.0 *
(MOUNT_SERVICE_STOP_PERCENT - RADIO_STOP_PERCENT) /
MAX_SHUTDOWN_WAIT_TIME);
status += RADIO_STOP_PERCENT;
sInstance.setRebootProgress(status, null);
}
try {
mActionDoneSync.wait(delay);
mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
} catch (InterruptedException e) {
}
}
}
if (mRebootUpdate) {
sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);
// If it's to reboot into recovery, invoke uncrypt via init service.
if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
// If it's to reboot to install update, invoke uncrypt via init service.
uncrypt();
}
rebootOrShutdown(mContext, mReboot, mRebootReason);
}
private void prepareUncryptProgress() {
// Reset the dialog message to show the decrypt process.
mHandler.post(new Runnable() {
@Override
public void run() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
// It doesn't work to change the style of the existing
// one. Have to create a new one.
ProgressDialog pd = new ProgressDialog(mContext);
pd.setTitle(mContext.getText(
com.android.internal.R.string.reboot_to_recovery_title));
pd.setMessage(mContext.getText(
com.android.internal.R.string.reboot_to_recovery_progress));
pd.setIndeterminate(false);
pd.setMax(100);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setProgressNumberFormat(null);
pd.setProgress(0);
mProgressDialog = pd;
mProgressDialog.show();
}
});
}
private void setUncryptProgress(final int progress) {
private void setRebootProgress(final int progress, final CharSequence message) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mProgressDialog != null) {
mProgressDialog.setProgress(progress);
if (message != null) {
mProgressDialog.setMessage(message);
}
}
}
});
}
private void shutdownRadios(int timeout) {
private void shutdownRadios(final int timeout) {
// If a radio is wedged, disabling it may hang so we do this work in another thread,
// just in case.
final long endTime = SystemClock.elapsedRealtime() + timeout;
@@ -511,7 +545,15 @@ public final class ShutdownThread extends Thread {
Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
while (SystemClock.elapsedRealtime() < endTime) {
long delay = endTime - SystemClock.elapsedRealtime();
while (delay > 0) {
if (mRebootUpdate) {
int status = (int)((timeout - delay) * 1.0 *
(RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout);
status += PACKAGE_MANAGER_STOP_PERCENT;
sInstance.setRebootProgress(status, null);
}
if (!bluetoothOff) {
try {
bluetoothOff = !bluetooth.isEnabled();
@@ -552,6 +594,8 @@ public final class ShutdownThread extends Thread {
break;
}
SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
delay = endTime - SystemClock.elapsedRealtime();
}
}
};
@@ -604,9 +648,6 @@ public final class ShutdownThread extends Thread {
private void uncrypt() {
Log.i(TAG, "Calling uncrypt and monitoring the progress...");
// Update the ProcessDialog message and style.
sInstance.prepareUncryptProgress();
final boolean[] done = new boolean[1];
done[0] = false;
Thread t = new Thread() {
@@ -627,25 +668,32 @@ public final class ShutdownThread extends Thread {
try (BufferedReader reader = new BufferedReader(
new FileReader(UNCRYPT_STATUS_FILE))) {
int last_status = Integer.MIN_VALUE;
int lastStatus = Integer.MIN_VALUE;
while (true) {
String str = reader.readLine();
try {
int status = Integer.parseInt(str);
// Avoid flooding the log with the same message.
if (status == last_status && last_status != Integer.MIN_VALUE) {
if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
continue;
}
last_status = status;
lastStatus = status;
if (status >= 0 && status < 100) {
// Update status
Log.d(TAG, "uncrypt read status: " + status);
sInstance.setUncryptProgress(status);
// Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100).
status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100);
status += MOUNT_SERVICE_STOP_PERCENT;
CharSequence msg = mContext.getText(
com.android.internal.R.string.reboot_to_update_package);
sInstance.setRebootProgress(status, msg);
} else if (status == 100) {
Log.d(TAG, "uncrypt successfully finished.");
sInstance.setUncryptProgress(status);
CharSequence msg = mContext.getText(
com.android.internal.R.string.reboot_to_update_reboot);
sInstance.setRebootProgress(status, msg);
break;
} else {
// Error in /system/bin/uncrypt. Or it's rebooting to recovery