diff --git a/init/README.md b/init/README.md index fc507300f..8cb1e52a3 100644 --- a/init/README.md +++ b/init/README.md @@ -370,10 +370,6 @@ Commands _options_ include "barrier=1", "noauto\_da\_alloc", "discard", ... as a comma separated string, eg: barrier=1,noauto\_da\_alloc -`powerctl` -> Internal implementation detail used to respond to changes to the - "sys.powerctl" system property, used to implement rebooting. - `restart ` > Stops and restarts a running service, does nothing if the service is currently restarting, otherwise, it just starts the service. diff --git a/init/builtins.cpp b/init/builtins.cpp index 2327cdfb4..43eb42075 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -598,58 +598,6 @@ static int do_restart(const std::vector& args) { return 0; } -static int do_powerctl(const std::vector& args) { - const std::string& command = args[1]; - unsigned int cmd = 0; - std::vector cmd_params = android::base::Split(command, ","); - std::string reason_string = cmd_params[0]; - std::string reboot_target = ""; - bool runFsck = false; - bool commandInvalid = false; - - if (cmd_params.size() > 3) { - commandInvalid = true; - } else if (cmd_params[0] == "shutdown") { - cmd = ANDROID_RB_POWEROFF; - if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") { - // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED. - // Run fsck once the file system is remounted in read-only mode. - runFsck = true; - reason_string = cmd_params[1]; - } - } else if (cmd_params[0] == "reboot") { - cmd = ANDROID_RB_RESTART2; - if (cmd_params.size() >= 2) { - reboot_target = cmd_params[1]; - // When rebooting to the bootloader notify the bootloader writing - // also the BCB. - if (reboot_target == "bootloader") { - std::string err; - if (!write_reboot_bootloader(&err)) { - LOG(ERROR) << "reboot-bootloader: Error writing " - "bootloader_message: " - << err; - } - } - // If there is an additional bootloader parameter, pass it along - if (cmd_params.size() == 3) { - reboot_target += "," + cmd_params[2]; - } - } - } else if (command == "thermal-shutdown") { // no additional parameter allowed - cmd = ANDROID_RB_THERMOFF; - } else { - commandInvalid = true; - } - if (commandInvalid) { - LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; - return -EINVAL; - } - - DoReboot(cmd, reason_string, reboot_target, runFsck); - return 0; -} - static int do_trigger(const std::vector& args) { ActionManager::GetInstance().QueueEventTrigger(args[1]); return 0; @@ -919,7 +867,6 @@ BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"mount_all", {1, kMax, do_mount_all}}, {"mount", {3, kMax, do_mount}}, {"umount", {1, 1, do_umount}}, - {"powerctl", {1, 1, do_powerctl}}, {"restart", {1, 1, do_restart}}, {"restorecon", {1, kMax, do_restorecon}}, {"restorecon_recursive", {1, kMax, do_restorecon_recursive}}, diff --git a/init/init.cpp b/init/init.cpp index 181b18d0b..9a4aa246e 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -67,6 +67,7 @@ #include "keychords.h" #include "log.h" #include "property_service.h" +#include "reboot.h" #include "service.h" #include "signal_handler.h" #include "ueventd.h" @@ -153,8 +154,13 @@ bool start_waiting_for_property(const char *name, const char *value) return true; } -void property_changed(const char *name, const char *value) -{ +void property_changed(const std::string& name, const std::string& value) { + // If the property is sys.powerctl, we bypass the event queue and immediately handle it. + // This is to ensure that init will always and immediately shutdown/reboot, regardless of + // if there are other pending events to process or if init is waiting on an exec service or + // waiting on a property. + if (name == "sys.powerctl") HandlePowerctlMessage(value); + if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyTrigger(name, value); if (waiting_for_prop) { diff --git a/init/init.h b/init/init.h index fe850efd7..1da335030 100644 --- a/init/init.h +++ b/init/init.h @@ -26,7 +26,7 @@ extern struct selabel_handle *sehandle_prop; void handle_control_message(const std::string& msg, const std::string& arg); -void property_changed(const char *name, const char *value); +void property_changed(const std::string& name, const std::string& value); void register_epoll_handler(int fd, void (*fn)()); diff --git a/init/property_service.cpp b/init/property_service.cpp index 2aa89ff96..20a2aa1fb 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -205,7 +205,7 @@ uint32_t property_set(const std::string& name, const std::string& value) { if (persistent_properties_loaded && android::base::StartsWith(name, "persist.")) { write_persistent_property(name.c_str(), value.c_str()); } - property_changed(name.c_str(), value.c_str()); + property_changed(name, value); return PROP_SUCCESS; } diff --git a/init/reboot.cpp b/init/reboot.cpp index d9ebd91ee..4d65437de 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -425,3 +425,54 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re RebootSystem(cmd, rebootTarget); abort(); } + +bool HandlePowerctlMessage(const std::string& command) { + unsigned int cmd = 0; + std::vector cmd_params = android::base::Split(command, ","); + std::string reason_string = cmd_params[0]; + std::string reboot_target = ""; + bool run_fsck = false; + bool command_invalid = false; + + if (cmd_params.size() > 3) { + command_invalid = true; + } else if (cmd_params[0] == "shutdown") { + cmd = ANDROID_RB_POWEROFF; + if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") { + // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED. + // Run fsck once the file system is remounted in read-only mode. + run_fsck = true; + reason_string = cmd_params[1]; + } + } else if (cmd_params[0] == "reboot") { + cmd = ANDROID_RB_RESTART2; + if (cmd_params.size() >= 2) { + reboot_target = cmd_params[1]; + // When rebooting to the bootloader notify the bootloader writing + // also the BCB. + if (reboot_target == "bootloader") { + std::string err; + if (!write_reboot_bootloader(&err)) { + LOG(ERROR) << "reboot-bootloader: Error writing " + "bootloader_message: " + << err; + } + } + // If there is an additional bootloader parameter, pass it along + if (cmd_params.size() == 3) { + reboot_target += "," + cmd_params[2]; + } + } + } else if (command == "thermal-shutdown") { // no additional parameter allowed + cmd = ANDROID_RB_THERMOFF; + } else { + command_invalid = true; + } + if (command_invalid) { + LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; + return false; + } + + DoReboot(cmd, reason_string, reboot_target, run_fsck); + return true; +} diff --git a/init/reboot.h b/init/reboot.h index 6432fa5df..b304b3cd9 100644 --- a/init/reboot.h +++ b/init/reboot.h @@ -29,4 +29,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) __attribute__((__noreturn__)); +// Parses and handles a setprop sys.powerctl message. +bool HandlePowerctlMessage(const std::string& command); + #endif diff --git a/rootdir/init.rc b/rootdir/init.rc index a666f755a..56e736eb2 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -638,9 +638,6 @@ on property:vold.decrypt=trigger_shutdown_framework class_reset late_start class_reset main -on property:sys.powerctl=* - powerctl ${sys.powerctl} - on property:sys.boot_completed=1 bootchart stop