Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfa9a98e authored by Tao Bao's avatar Tao Bao Committed by Gerrit Code Review
Browse files

Merge "Improve the reboot-to-recovery dialogs"

parents e215b464 f2a91ee1
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -394,8 +394,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>
+6 −2
Original line number Diff line number Diff line
@@ -780,8 +780,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" />
+99 −51
Original line number Diff line number Diff line
@@ -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_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;
@@ -74,11 +80,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
@@ -202,6 +210,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);
    }
@@ -216,6 +225,7 @@ public final class ShutdownThread extends Thread {
    public static void rebootSafeMode(final Context context, boolean confirm) {
        mReboot = true;
        mRebootSafeMode = true;
        mRebootUpdate = false;
        mRebootReason = null;
        shutdownInner(context, confirm);
    }
@@ -229,16 +239,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 {
            pd.setTitle(context.getText(com.android.internal.R.string.power_off));
                // 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.setCancelable(false);
        pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);

@@ -333,13 +371,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...");

@@ -351,6 +396,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...");

@@ -359,9 +407,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() {
@@ -393,64 +447,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;
@@ -505,7 +539,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();
@@ -546,6 +588,8 @@ public final class ShutdownThread extends Thread {
                        break;
                    }
                    SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);

                    delay = endTime - SystemClock.elapsedRealtime();
                }
            }
        };
@@ -598,9 +642,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() {
@@ -621,25 +662,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