Add shutdown assurance
If something kills system_server before it completes its shutdown
action, the runtime will just restart giving the illusion that a reboot
for an OTA or something else has happened.
To prevent this, write a system property containing the reboot reason
before initiating the shutdown with all the services. If the
system_server is killed before it completes, the next time the main
thread of system_server starts up, it will immediately execute the
shutdown action.
Bug: 3022556
Change-Id: I81723bac333430f04205e7a7b799914d96f170eb
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index d1aff2a..714b259 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -33,6 +33,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.Vibrator;
import android.os.storage.IMountService;
import android.os.storage.IMountShutdownObserver;
@@ -60,6 +61,9 @@
private static boolean mReboot;
private static String mRebootReason;
+ // Provides shutdown assurance in case the system_server is killed
+ public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
+
// static instance of this thread
private static final ShutdownThread sInstance = new ShutdownThread();
@@ -195,7 +199,17 @@
actionDone();
}
};
-
+
+ /*
+ * Write a system property in case the system_server reboots before we
+ * get to the actual hardware restart. If that happens, we'll retry at
+ * the beginning of the SystemServer startup.
+ */
+ {
+ String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
+ SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
+ }
+
Log.i(TAG, "Sending shutdown broadcast...");
// First send the high-level shut down broadcast.
@@ -325,10 +339,21 @@
}
}
- if (mReboot) {
- Log.i(TAG, "Rebooting, reason: " + mRebootReason);
+ rebootOrShutdown(mReboot, mRebootReason);
+ }
+
+ /**
+ * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
+ * or {@link #shutdown(Context, boolean)} instead.
+ *
+ * @param reboot true to reboot or false to shutdown
+ * @param reason reason for reboot
+ */
+ public static void rebootOrShutdown(boolean reboot, String reason) {
+ if (reboot) {
+ Log.i(TAG, "Rebooting, reason: " + reason);
try {
- Power.reboot(mRebootReason);
+ Power.reboot(reason);
} catch (Exception e) {
Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
}