diff options
| -rw-r--r-- | core/java/android/os/IPowerManager.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/os/PowerManager.java | 21 | ||||
| -rw-r--r-- | services/core/java/com/android/server/power/PowerManagerService.java | 44 |
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); } |