Merge "Improve the reboot-to-recovery dialogs"
This commit is contained in:
@@ -394,8 +394,14 @@
|
|||||||
<string name="silent_mode_ring">Ringer on</string>
|
<string name="silent_mode_ring">Ringer on</string>
|
||||||
|
|
||||||
<!-- Reboot to Recovery Progress Dialog. This is shown before it reboots to recovery. -->
|
<!-- 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_update_title">Android system update</string>
|
||||||
<string name="reboot_to_recovery_progress">Processing the update package\u2026</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. -->
|
<!-- Shutdown Progress Dialog. This is shown if the user chooses to power off the phone. -->
|
||||||
<string name="shutdown_progress">Shutting down\u2026</string>
|
<string name="shutdown_progress">Shutting down\u2026</string>
|
||||||
|
|||||||
@@ -780,8 +780,12 @@
|
|||||||
<java-symbol type="string" name="mobile_provisioning_url" />
|
<java-symbol type="string" name="mobile_provisioning_url" />
|
||||||
<java-symbol type="string" name="mobile_redirected_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="quick_contacts_not_available" />
|
||||||
<java-symbol type="string" name="reboot_to_recovery_progress" />
|
<java-symbol type="string" name="reboot_to_update_package" />
|
||||||
<java-symbol type="string" name="reboot_to_recovery_title" />
|
<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_confirm" />
|
||||||
<java-symbol type="string" name="reboot_safemode_title" />
|
<java-symbol type="string" name="reboot_safemode_title" />
|
||||||
<java-symbol type="string" name="relationTypeAssistant" />
|
<java-symbol type="string" name="relationTypeAssistant" />
|
||||||
|
|||||||
@@ -66,6 +66,12 @@ public final class ShutdownThread extends Thread {
|
|||||||
private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
|
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_RADIO_WAIT_TIME = 12*1000;
|
||||||
private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*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
|
// length of vibration before shutting down
|
||||||
private static final int SHUTDOWN_VIBRATE_MS = 500;
|
private static final int SHUTDOWN_VIBRATE_MS = 500;
|
||||||
@@ -74,11 +80,13 @@ public final class ShutdownThread extends Thread {
|
|||||||
private static Object sIsStartedGuard = new Object();
|
private static Object sIsStartedGuard = new Object();
|
||||||
private static boolean sIsStarted = false;
|
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_STATUS_FILE = "/cache/recovery/uncrypt_status";
|
||||||
|
private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
|
||||||
|
|
||||||
private static boolean mReboot;
|
private static boolean mReboot;
|
||||||
private static boolean mRebootSafeMode;
|
private static boolean mRebootSafeMode;
|
||||||
|
private static boolean mRebootUpdate;
|
||||||
private static String mRebootReason;
|
private static String mRebootReason;
|
||||||
|
|
||||||
// Provides shutdown assurance in case the system_server is killed
|
// Provides shutdown assurance in case the system_server is killed
|
||||||
@@ -202,6 +210,7 @@ public final class ShutdownThread extends Thread {
|
|||||||
public static void reboot(final Context context, String reason, boolean confirm) {
|
public static void reboot(final Context context, String reason, boolean confirm) {
|
||||||
mReboot = true;
|
mReboot = true;
|
||||||
mRebootSafeMode = false;
|
mRebootSafeMode = false;
|
||||||
|
mRebootUpdate = false;
|
||||||
mRebootReason = reason;
|
mRebootReason = reason;
|
||||||
shutdownInner(context, confirm);
|
shutdownInner(context, confirm);
|
||||||
}
|
}
|
||||||
@@ -216,6 +225,7 @@ public final class ShutdownThread extends Thread {
|
|||||||
public static void rebootSafeMode(final Context context, boolean confirm) {
|
public static void rebootSafeMode(final Context context, boolean confirm) {
|
||||||
mReboot = true;
|
mReboot = true;
|
||||||
mRebootSafeMode = true;
|
mRebootSafeMode = true;
|
||||||
|
mRebootUpdate = false;
|
||||||
mRebootReason = null;
|
mRebootReason = null;
|
||||||
shutdownInner(context, confirm);
|
shutdownInner(context, confirm);
|
||||||
}
|
}
|
||||||
@@ -229,16 +239,44 @@ public final class ShutdownThread extends Thread {
|
|||||||
sIsStarted = true;
|
sIsStarted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw up an indeterminate system dialog to indicate radio is
|
// Throw up a system dialog to indicate the device is rebooting / shutting down.
|
||||||
// shutting down.
|
|
||||||
ProgressDialog pd = new ProgressDialog(context);
|
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)) {
|
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 {
|
} else {
|
||||||
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
|
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
|
||||||
}
|
|
||||||
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
|
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
|
||||||
pd.setIndeterminate(true);
|
pd.setIndeterminate(true);
|
||||||
|
}
|
||||||
pd.setCancelable(false);
|
pd.setCancelable(false);
|
||||||
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||||
|
|
||||||
@@ -333,13 +371,20 @@ public final class ShutdownThread extends Thread {
|
|||||||
if (delay <= 0) {
|
if (delay <= 0) {
|
||||||
Log.w(TAG, "Shutdown broadcast timed out");
|
Log.w(TAG, "Shutdown broadcast timed out");
|
||||||
break;
|
break;
|
||||||
|
} else if (mRebootUpdate) {
|
||||||
|
int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
|
||||||
|
BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
|
||||||
|
sInstance.setRebootProgress(status, null);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mActionDoneSync.wait(delay);
|
mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mRebootUpdate) {
|
||||||
|
sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Shutting down activity manager...");
|
Log.i(TAG, "Shutting down activity manager...");
|
||||||
|
|
||||||
@@ -351,6 +396,9 @@ public final class ShutdownThread extends Thread {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mRebootUpdate) {
|
||||||
|
sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
|
||||||
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Shutting down package manager...");
|
Log.i(TAG, "Shutting down package manager...");
|
||||||
|
|
||||||
@@ -359,9 +407,15 @@ public final class ShutdownThread extends Thread {
|
|||||||
if (pm != null) {
|
if (pm != null) {
|
||||||
pm.shutdown();
|
pm.shutdown();
|
||||||
}
|
}
|
||||||
|
if (mRebootUpdate) {
|
||||||
|
sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
|
||||||
|
}
|
||||||
|
|
||||||
// Shutdown radios.
|
// Shutdown radios.
|
||||||
shutdownRadios(MAX_RADIO_WAIT_TIME);
|
shutdownRadios(MAX_RADIO_WAIT_TIME);
|
||||||
|
if (mRebootUpdate) {
|
||||||
|
sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
|
||||||
|
}
|
||||||
|
|
||||||
// Shutdown MountService to ensure media is in a safe state
|
// Shutdown MountService to ensure media is in a safe state
|
||||||
IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
|
IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
|
||||||
@@ -393,64 +447,44 @@ public final class ShutdownThread extends Thread {
|
|||||||
if (delay <= 0) {
|
if (delay <= 0) {
|
||||||
Log.w(TAG, "Shutdown wait timed out");
|
Log.w(TAG, "Shutdown wait timed out");
|
||||||
break;
|
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 {
|
try {
|
||||||
mActionDoneSync.wait(delay);
|
mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
|
||||||
} catch (InterruptedException e) {
|
} 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 it's to reboot to install update, invoke uncrypt via init service.
|
||||||
if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
|
|
||||||
uncrypt();
|
uncrypt();
|
||||||
}
|
}
|
||||||
|
|
||||||
rebootOrShutdown(mContext, mReboot, mRebootReason);
|
rebootOrShutdown(mContext, mReboot, mRebootReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareUncryptProgress() {
|
private void setRebootProgress(final int progress, final CharSequence message) {
|
||||||
// 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) {
|
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mProgressDialog != null) {
|
if (mProgressDialog != null) {
|
||||||
mProgressDialog.setProgress(progress);
|
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,
|
// If a radio is wedged, disabling it may hang so we do this work in another thread,
|
||||||
// just in case.
|
// just in case.
|
||||||
final long endTime = SystemClock.elapsedRealtime() + timeout;
|
final long endTime = SystemClock.elapsedRealtime() + timeout;
|
||||||
@@ -505,7 +539,15 @@ public final class ShutdownThread extends Thread {
|
|||||||
|
|
||||||
Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
|
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) {
|
if (!bluetoothOff) {
|
||||||
try {
|
try {
|
||||||
bluetoothOff = !bluetooth.isEnabled();
|
bluetoothOff = !bluetooth.isEnabled();
|
||||||
@@ -546,6 +588,8 @@ public final class ShutdownThread extends Thread {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
|
SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
|
||||||
|
|
||||||
|
delay = endTime - SystemClock.elapsedRealtime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -598,9 +642,6 @@ public final class ShutdownThread extends Thread {
|
|||||||
private void uncrypt() {
|
private void uncrypt() {
|
||||||
Log.i(TAG, "Calling uncrypt and monitoring the progress...");
|
Log.i(TAG, "Calling uncrypt and monitoring the progress...");
|
||||||
|
|
||||||
// Update the ProcessDialog message and style.
|
|
||||||
sInstance.prepareUncryptProgress();
|
|
||||||
|
|
||||||
final boolean[] done = new boolean[1];
|
final boolean[] done = new boolean[1];
|
||||||
done[0] = false;
|
done[0] = false;
|
||||||
Thread t = new Thread() {
|
Thread t = new Thread() {
|
||||||
@@ -621,25 +662,32 @@ public final class ShutdownThread extends Thread {
|
|||||||
try (BufferedReader reader = new BufferedReader(
|
try (BufferedReader reader = new BufferedReader(
|
||||||
new FileReader(UNCRYPT_STATUS_FILE))) {
|
new FileReader(UNCRYPT_STATUS_FILE))) {
|
||||||
|
|
||||||
int last_status = Integer.MIN_VALUE;
|
int lastStatus = Integer.MIN_VALUE;
|
||||||
while (true) {
|
while (true) {
|
||||||
String str = reader.readLine();
|
String str = reader.readLine();
|
||||||
try {
|
try {
|
||||||
int status = Integer.parseInt(str);
|
int status = Integer.parseInt(str);
|
||||||
|
|
||||||
// Avoid flooding the log with the same message.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
last_status = status;
|
lastStatus = status;
|
||||||
|
|
||||||
if (status >= 0 && status < 100) {
|
if (status >= 0 && status < 100) {
|
||||||
// Update status
|
// Update status
|
||||||
Log.d(TAG, "uncrypt read status: " + 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) {
|
} else if (status == 100) {
|
||||||
Log.d(TAG, "uncrypt successfully finished.");
|
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;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Error in /system/bin/uncrypt. Or it's rebooting to recovery
|
// Error in /system/bin/uncrypt. Or it's rebooting to recovery
|
||||||
|
|||||||
Reference in New Issue
Block a user