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

Commit 717dbbf1 authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

Add an API to tell whenever device supports userspace reboot

If device doesn't support userspace reboot then call to
PowerManager.reboot("userspace") will throw an
UnsupportedOperationException.

For the case of upgrading devices, Treble enforces that previous vendor
image should work with the new system image. Since userspace reboot
requires services to be stopped and restarted cleanly, which upgrading
devices might not be able to comply with, we need to have an API to
distinguish between devices that support userspace reboot and the ones
that do not.

Test: atest PowerManagerTest
Test: atest CtsUserspaceRebootHostSideTestCases
Bug: 138605273
Bug: 135984674
Change-Id: I8303f43ab29499eb2995f0256854c787055d9560
parent f5b6267d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -35016,11 +35016,12 @@ package android.os {
    method public boolean isIgnoringBatteryOptimizations(String);
    method public boolean isInteractive();
    method public boolean isPowerSaveMode();
    method public boolean isRebootingUserspaceSupported();
    method @Deprecated public boolean isScreenOn();
    method public boolean isSustainedPerformanceModeSupported();
    method public boolean isWakeLockLevelSupported(int);
    method public android.os.PowerManager.WakeLock newWakeLock(int, String);
    method public void reboot(String);
    method public void reboot(@Nullable String);
    method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
    field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
    field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
+1 −0
Original line number Diff line number Diff line
@@ -5986,6 +5986,7 @@ package android.os {
    method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
    field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
    field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
    field public static final String REBOOT_USERSPACE = "userspace";
    field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
    field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
    field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
+23 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
@@ -604,6 +605,13 @@ public final class PowerManager {
     */
    public static final String REBOOT_SAFE_MODE = "safemode";

    /**
     * The 'reason' value used for rebooting userspace.
     * @hide
     */
    @SystemApi
    public static final String REBOOT_USERSPACE = "userspace";

    /**
     * The 'reason' value used when rebooting the device without turning on the screen.
     * @hide
@@ -1382,6 +1390,14 @@ public final class PowerManager {
        }
    }

    /**
     * Returns {@code true} if this device supports rebooting userspace.
     */
    // TODO(b/138605180): add link to documentation once it's ready.
    public boolean isRebootingUserspaceSupported() {
        return SystemProperties.getBoolean("ro.init.userspace_reboot.is_supported", false);
    }

    /**
     * Reboot the device.  Will not return if the reboot is successful.
     * <p>
@@ -1390,8 +1406,14 @@ public final class PowerManager {
     *
     * @param reason code to pass to the kernel (e.g., "recovery") to
     *               request special boot modes, or null.
     * @throws UnsupportedOperationException if userspace reboot was requested on a device that
     *                                       doesn't support it.
     */
    public void reboot(String reason) {
    public void reboot(@Nullable String reason) {
        if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
            throw new UnsupportedOperationException(
                    "Attempted userspace reboot on a device that doesn't support it");
        }
        try {
            mService.reboot(false, reason, true);
        } catch (RemoteException e) {
+13 −0
Original line number Diff line number Diff line
@@ -239,4 +239,17 @@ public class PowerManagerTest extends AndroidTestCase {
        verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onThermalStatusChanged(status);
    }

    @Test
    public void testUserspaceRebootNotSupported_throwsUnsupportedOperationException() {
        // Can't use assumption framework with AndroidTestCase :(
        if (mPm.isRebootingUserspaceSupported()) {
            return;
        }
        try {
            mPm.reboot(PowerManager.REBOOT_USERSPACE);
            fail("UnsupportedOperationException not thrown");
        } catch (UnsupportedOperationException expected) {
        }
    }
}