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

Commit 92116e41 authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

Properly fail userspace reboot if it's not supported

Previously, after `adb reboot userspace` is called on a device that
doesn't suppor it, init would've logged an error and quietly exit the
shutdown sequence. This was leaving adb handing forever.

With this approach, init will fail setprop
"sys.powerctl=reboot,userspace" in case userspace reboot is not
supported.

Test: adb root
Test: adb setprop init.userspace_reboot.is_supported 0
Test: adb reboot userspace
Test: atest CtsInitTestCases
Bug: 146639622
Change-Id: I1264078f53ed3ff54638c7f3b6846b7437f98ee5
parent 884b5701
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include <thread>
#include <vector>

#include <InitProperties.sysprop.h>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -85,6 +86,7 @@ using android::properties::BuildTrie;
using android::properties::ParsePropertyInfoFile;
using android::properties::PropertyInfoAreaFile;
using android::properties::PropertyInfoEntry;
using android::sysprop::InitProperties::is_userspace_reboot_supported;

namespace android {
namespace init {
@@ -492,6 +494,10 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
        if (!value.empty()) {
            DebugRebootLogging();
        }
        if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) {
            *error = "Userspace reboot is not supported by this device";
            return PROP_ERROR_INVALID_VALUE;
        }
    }

    // If a process other than init is writing a non-empty value, it means that process is
+16 −0
Original line number Diff line number Diff line
@@ -22,8 +22,10 @@
#include <sys/_system_properties.h>

#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <gtest/gtest.h>

using android::base::GetProperty;
using android::base::SetProperty;

namespace android {
@@ -74,5 +76,19 @@ TEST(property_service, non_utf8_value) {
    EXPECT_TRUE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\x80"));
}

TEST(property_service, userspace_reboot_not_supported) {
    if (getuid() != 0) {
        GTEST_SKIP() << "Skipping test, must be run as root.";
        return;
    }
    const std::string original_value = GetProperty("init.userspace_reboot.is_supported", "");
    auto guard = android::base::make_scope_guard([&original_value]() {
        SetProperty("init.userspace_reboot.is_supported", original_value);
    });

    ASSERT_TRUE(SetProperty("init.userspace_reboot.is_supported", "false"));
    EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace"));
}

}  // namespace init
}  // namespace android