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

Commit c34d735f authored by Santos Cordon's avatar Santos Cordon Committed by Android (Google) Code Review
Browse files

Merge "Add force suspend API to PowerManager."

parents f7066969 12f92eb6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5328,6 +5328,7 @@ package android.os {
  public final class PowerManager {
    method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
    method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
    method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveMode();
    method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
    method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
+27 −1
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.os.SystemClock;
import android.os.SystemProperties;

public class PowerCommand extends Svc.Command {
    private static final int FORCE_SUSPEND_DELAY_DEFAULT_MILLIS = 0;

    public PowerCommand() {
        super("power");
    }
@@ -42,7 +44,17 @@ public class PowerCommand extends Svc.Command {
                + "       svc power reboot [reason]\n"
                + "         Perform a runtime shutdown and reboot device with specified reason.\n"
                + "       svc power shutdown\n"
                + "         Perform a runtime shutdown and power off the device.\n";
                + "         Perform a runtime shutdown and power off the device.\n"
                + "       svc power forcesuspend [t]\n"
                + "         Force the system into suspend, ignoring all wakelocks.\n"
                + "         t - Number of milliseconds to wait before issuing force-suspend.\n"
                + "             Helps with devices that can't suspend while plugged in.\n"
                + "             Defaults to " + FORCE_SUSPEND_DELAY_DEFAULT_MILLIS + ".\n"
                + "             When using a delay, you must use the nohup shell modifier:\n"
                + "             'adb shell nohup svc power forcesuspend [time]'\n"
                + "         Use caution; this is dangerous. It puts the device to sleep\n"
                + "         immediately without giving apps or the system an opportunity to\n"
                + "         save their state.\n";
    }

    public void run(String[] args) {
@@ -101,6 +113,20 @@ public class PowerCommand extends Svc.Command {
                        maybeLogRemoteException("Failed to shutdown.");
                    }
                    return;
                } else if ("forcesuspend".equals(args[1])) {
                    int delayMillis = args.length > 2
                            ? Integer.parseInt(args[2]) : FORCE_SUSPEND_DELAY_DEFAULT_MILLIS;
                    try {
                        Thread.sleep(delayMillis);
                        if (!pm.forceSuspend()) {
                            System.err.println("Failed to force suspend.");
                        }
                    } catch (InterruptedException e) {
                        System.err.println("Failed to force suspend: " + e);
                    } catch (RemoteException e) {
                        maybeLogRemoteException("Failed to force-suspend with exception: " + e);
                    }
                    return;
                }
            }
        }
+3 −0
Original line number Diff line number Diff line
@@ -74,4 +74,7 @@ interface IPowerManager

    // controls whether PowerManager should doze after the screen turns off or not
    void setDozeAfterScreenOff(boolean on);

    // Forces the system to suspend even if there are held wakelocks.
    boolean forceSuspend();
}
+44 −1
Original line number Diff line number Diff line
@@ -362,11 +362,16 @@ public final class PowerManager {
    @SystemApi
    public static final int USER_ACTIVITY_FLAG_INDIRECT = 1 << 1;

    /**
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_MIN = 0;

    /**
     * Go to sleep reason code: Going to sleep due by application request.
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_APPLICATION = 0;
    public static final int GO_TO_SLEEP_REASON_APPLICATION = GO_TO_SLEEP_REASON_MIN;

    /**
     * Go to sleep reason code: Going to sleep due by request of the
@@ -411,6 +416,17 @@ public final class PowerManager {
     */
    public static final int GO_TO_SLEEP_REASON_ACCESSIBILITY = 7;

    /**
     * Go to sleep reason code: Going to sleep due to force-suspend.
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_FORCE_SUSPEND = 8;

    /**
     * @hide
     */
    public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_FORCE_SUSPEND;

    /**
     * @hide
     */
@@ -424,6 +440,7 @@ public final class PowerManager {
            case GO_TO_SLEEP_REASON_HDMI: return "hdmi";
            case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
            case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
            case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
            default: return Integer.toString(sleepReason);
        }
    }
@@ -1852,6 +1869,32 @@ public final class PowerManager {
        }
    }

    /**
     * Forces the device to go to suspend, even if there are currently wakelocks being held.
     * <b>Caution</b>
     * This is a very dangerous command as it puts the device to sleep immediately. Apps and parts
     * of the system will not be notified and will not have an opportunity to save state prior to
     * the device going to suspend.
     * This method should only be used in very rare circumstances where the device is intended
     * to appear as completely off to the user and they have a well understood, reliable way of
     * re-enabling it.
     * </p><p>
     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
     * </p>
     *
     * @return true on success, false otherwise.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
    public boolean forceSuspend() {
        try {
            return mService.forceSuspend();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
     * This broadcast is only sent to registered receivers.
+66 −35
Original line number Diff line number Diff line
@@ -538,6 +538,9 @@ public final class PowerManagerService extends SystemService
    // True if we are currently in VR Mode.
    private boolean mIsVrModeEnabled;

    // True if we in the process of performing a forceSuspend
    private boolean mForceSuspendActive;

    private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
        @Override
        public void onUserSwitching(int newUserId) throws RemoteException {}
@@ -684,6 +687,11 @@ public final class PowerManagerService extends SystemService
        public void nativeSetFeature(int featureId, int data) {
            PowerManagerService.nativeSetFeature(featureId, data);
        }

        /** Wrapper for PowerManager.nativeForceSuspend */
        public boolean nativeForceSuspend() {
            return PowerManagerService.nativeForceSuspend();
        }
    }

    @VisibleForTesting
@@ -718,6 +726,7 @@ public final class PowerManagerService extends SystemService
    private static native void nativeSetAutoSuspend(boolean enable);
    private static native void nativeSendPowerHint(int hintId, int data);
    private static native void nativeSetFeature(int featureId, int data);
    private static native boolean nativeForceSuspend();

    public PowerManagerService(Context context) {
        this(context, new Injector());
@@ -1427,7 +1436,7 @@ public final class PowerManagerService extends SystemService
        }

        if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
                || !mBootCompleted || !mSystemReady) {
                || !mBootCompleted || !mSystemReady || mForceSuspendActive) {
            return false;
        }

@@ -1463,8 +1472,13 @@ public final class PowerManagerService extends SystemService
        }
    }

    // This method is called goToSleep for historical reasons but we actually start
    // dozing before really going to sleep.
    /**
     * Puts the system in doze.
     *
     * This method is called goToSleep for historical reasons but actually attempts to DOZE,
     * and only tucks itself in to SLEEP if requested with the flag
     * {@link PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE}.
     */
    @SuppressWarnings("deprecation")
    private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
        if (DEBUG_SPEW) {
@@ -1481,35 +1495,10 @@ public final class PowerManagerService extends SystemService

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
        try {
            switch (reason) {
                case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
                    Slog.i(TAG, "Going to sleep due to device administration policy "
            reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
                    Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
            Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
                    + " (uid " + uid + ")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
                    Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
                    Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
                    Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
                    Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_HDMI:
                    Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_ACCESSIBILITY:
                    Slog.i(TAG, "Going to sleep by an accessibility service request (uid "
                            + uid +")...");
                    break;
                default:
                    Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
                    reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
                    break;
            }

            mLastSleepTime = eventTime;
            mLastSleepReason = reason;
@@ -3063,10 +3052,10 @@ public final class PowerManagerService extends SystemService
            if (appid >= Process.FIRST_APPLICATION_UID) {
                // Cached inactive processes are never allowed to hold wake locks.
                if (mConstants.NO_CACHED_WAKE_LOCKS) {
                    disabled = !wakeLock.mUidState.mActive &&
                            wakeLock.mUidState.mProcState
                    disabled = mForceSuspendActive
                            || (!wakeLock.mUidState.mActive && wakeLock.mUidState.mProcState
                                    != ActivityManager.PROCESS_STATE_NONEXISTENT &&
                            wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
                            wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER);
                }
                if (mDeviceIdleMode) {
                    // If we are in idle mode, we will also ignore all partial wake locks that are
@@ -3241,6 +3230,34 @@ public final class PowerManagerService extends SystemService
        }
    }

    private boolean forceSuspendInternal(int uid) {
        try {
            synchronized (mLock) {
                mForceSuspendActive = true;
                // Place the system in an non-interactive state
                goToSleepInternal(SystemClock.uptimeMillis(),
                        PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND,
                        PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid);

                // Disable all the partial wake locks as well
                updateWakeLockDisabledStatesLocked();
            }

            Slog.i(TAG, "Force-Suspending (uid " + uid + ")...");
            boolean success = mNativeWrapper.nativeForceSuspend();
            if (!success) {
                Slog.i(TAG, "Force-Suspending failed in native.");
            }
            return success;
        } finally {
            synchronized (mLock) {
                mForceSuspendActive = false;
                // Re-enable wake locks once again.
                updateWakeLockDisabledStatesLocked();
            }
        }
    }

    /**
     * Low-level function turn the device off immediately, without trying
     * to be clean.  Most people should use {@link ShutdownThread} for a clean shutdown.
@@ -4743,6 +4760,20 @@ public final class PowerManagerService extends SystemService
            }
        }

        @Override // binder call
        public boolean forceSuspend() {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);

            final int uid = Binder.getCallingUid();
            final long ident = Binder.clearCallingIdentity();
            try {
                return forceSuspendInternal(uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Loading