summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/IPowerManager.aidl1
-rw-r--r--core/java/android/os/PowerManager.java21
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java44
3 files changed, 60 insertions, 6 deletions
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index dd10df33fe60..1d464c005cb9 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -50,6 +50,7 @@ interface IPowerManager
boolean isLightDeviceIdleMode();
void reboot(boolean confirm, String reason, boolean wait);
+ void rebootSafeMode(boolean confirm, boolean wait);
void shutdown(boolean confirm, String reason, boolean wait);
void crash(String message);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index cb4caea93adb..8bc903b96bcf 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -426,6 +426,12 @@ public final class PowerManager {
public static final String REBOOT_REQUESTED_BY_DEVICE_OWNER = "deviceowner";
/**
+ * The 'reason' value used when rebooting in safe mode
+ * @hide
+ */
+ public static final String REBOOT_SAFE_MODE = "safemode";
+
+ /**
* The value to pass as the 'reason' argument to android_reboot().
* @hide
*/
@@ -903,6 +909,21 @@ public final class PowerManager {
}
/**
+ * Reboot the device. Will not return if the reboot is successful.
+ * <p>
+ * Requires the {@link android.Manifest.permission#REBOOT} permission.
+ * </p>
+ * @hide
+ */
+ public void rebootSafeMode() {
+ try {
+ mService.rebootSafeMode(false, true);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns true if the device is currently in power save mode. When in this mode,
* applications should reduce their functionality in order to conserve battery as
* much as possible. You can monitor for changes to this state with
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 91d86710a1a9..cbd77d4bcfe2 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.power;
import android.Manifest;
+import android.annotation.IntDef;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -74,6 +75,8 @@ import libcore.util.Objects;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
@@ -162,6 +165,14 @@ public final class PowerManagerService extends SystemService
// Default setting for double tap to wake.
private static final int DEFAULT_DOUBLE_TAP_TO_WAKE = 0;
+ /** Constants for {@link #shutdownOrRebootInternal} */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({HALT_MODE_SHUTDOWN, HALT_MODE_REBOOT, HALT_MODE_REBOOT_SAFE_MODE})
+ public @interface HaltMode {}
+ private static final int HALT_MODE_SHUTDOWN = 0;
+ private static final int HALT_MODE_REBOOT = 1;
+ private static final int HALT_MODE_REBOOT_SAFE_MODE = 2;
+
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
@@ -2392,7 +2403,7 @@ public final class PowerManagerService extends SystemService
updatePowerStateLocked();
}
- private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
+ private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
throw new IllegalStateException("Too early to call shutdown() or reboot()");
@@ -2402,10 +2413,12 @@ public final class PowerManagerService extends SystemService
@Override
public void run() {
synchronized (this) {
- if (shutdown) {
- ShutdownThread.shutdown(mContext, reason, confirm);
- } else {
+ if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
+ ShutdownThread.rebootSafeMode(mContext, confirm);
+ } else if (haltMode == HALT_MODE_REBOOT) {
ShutdownThread.reboot(mContext, reason, confirm);
+ } else {
+ ShutdownThread.shutdown(mContext, reason, confirm);
}
}
}
@@ -3465,7 +3478,26 @@ public final class PowerManagerService extends SystemService
final long ident = Binder.clearCallingIdentity();
try {
- shutdownOrRebootInternal(false, confirm, reason, wait);
+ shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Reboots the device into safe mode
+ *
+ * @param confirm If true, shows a reboot confirmation dialog.
+ * @param wait If true, this call waits for the reboot to complete and does not return.
+ */
+ @Override // Binder call
+ public void rebootSafeMode(boolean confirm, boolean wait) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm,
+ PowerManager.REBOOT_SAFE_MODE, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3483,7 +3515,7 @@ public final class PowerManagerService extends SystemService
final long ident = Binder.clearCallingIdentity();
try {
- shutdownOrRebootInternal(true, confirm, reason, wait);
+ shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}