summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/res/res/values/strings.xml10
-rwxr-xr-xcore/res/res/values/symbols.xml8
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java150
3 files changed, 113 insertions, 55 deletions
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3f828e7..8a26e7d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -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>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c7f27e1..c765563 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -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" />
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 4b62c40..dd8648d 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -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