Loading init/init.cpp +12 −7 Original line number Original line Diff line number Diff line Loading @@ -98,7 +98,6 @@ static int property_fd = -1; static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::string wait_prop_name; static std::string wait_prop_name; static std::string wait_prop_value; static std::string wait_prop_value; static bool shutting_down; static std::string shutdown_command; static std::string shutdown_command; static bool do_shutdown = false; static bool do_shutdown = false; static bool load_debug_prop = false; static bool load_debug_prop = false; Loading Loading @@ -624,7 +623,15 @@ void SendStopSendingMessagesMessage() { auto init_message = InitMessage{}; auto init_message = InitMessage{}; init_message.set_stop_sending_messages(true); init_message.set_stop_sending_messages(true); if (auto result = SendMessage(property_fd, init_message); !result) { if (auto result = SendMessage(property_fd, init_message); !result) { LOG(ERROR) << "Failed to send load persistent properties message: " << result.error(); LOG(ERROR) << "Failed to send 'stop sending messages' message: " << result.error(); } } void SendStartSendingMessagesMessage() { auto init_message = InitMessage{}; init_message.set_start_sending_messages(true); if (auto result = SendMessage(property_fd, init_message); !result) { LOG(ERROR) << "Failed to send 'start sending messages' message: " << result.error(); } } } } Loading Loading @@ -811,18 +818,16 @@ int SecondStageMain(int argc, char** argv) { // By default, sleep until something happens. // By default, sleep until something happens. auto epoll_timeout = std::optional<std::chrono::milliseconds>{}; auto epoll_timeout = std::optional<std::chrono::milliseconds>{}; if (do_shutdown && !shutting_down) { if (do_shutdown && !IsShuttingDown()) { do_shutdown = false; do_shutdown = false; if (HandlePowerctlMessage(shutdown_command)) { HandlePowerctlMessage(shutdown_command); shutting_down = true; } } } if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!(waiting_for_prop || Service::is_exec_service_running())) { am.ExecuteOneCommand(); am.ExecuteOneCommand(); } } if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!shutting_down) { if (!IsShuttingDown()) { auto next_process_action_time = HandleProcessActions(); auto next_process_action_time = HandleProcessActions(); // If there's a process that needs restarting, wake up in time for that. // If there's a process that needs restarting, wake up in time for that. Loading init/init.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -41,6 +41,7 @@ void ResetWaitForProp(); void SendLoadPersistentPropertiesMessage(); void SendLoadPersistentPropertiesMessage(); void SendStopSendingMessagesMessage(); void SendStopSendingMessagesMessage(); void SendStartSendingMessagesMessage(); int SecondStageMain(int argc, char** argv); int SecondStageMain(int argc, char** argv); Loading init/property_service.cpp +9 −3 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,7 @@ static bool persistent_properties_loaded = false; static int property_set_fd = -1; static int property_set_fd = -1; static int init_socket = -1; static int init_socket = -1; static bool accept_messages = false; static PropertyInfoAreaFile property_info_area; static PropertyInfoAreaFile property_info_area; Loading Loading @@ -211,7 +212,7 @@ static uint32_t PropertySet(const std::string& name, const std::string& value, s } } // If init hasn't started its main loop, then it won't be handling property changed messages // If init hasn't started its main loop, then it won't be handling property changed messages // anyway, so there's no need to try to send them. // anyway, so there's no need to try to send them. if (init_socket != -1) { if (accept_messages) { SendPropertyChanged(name, value); SendPropertyChanged(name, value); } } return PROP_SUCCESS; return PROP_SUCCESS; Loading Loading @@ -389,7 +390,7 @@ class SocketConnection { static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid, static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid, SocketConnection* socket, std::string* error) { SocketConnection* socket, std::string* error) { if (init_socket == -1) { if (!accept_messages) { *error = "Received control message after shutdown, ignoring"; *error = "Received control message after shutdown, ignoring"; return PROP_ERROR_HANDLE_CONTROL_MESSAGE; return PROP_ERROR_HANDLE_CONTROL_MESSAGE; } } Loading Loading @@ -1035,7 +1036,11 @@ static void HandleInitSocket() { break; break; } } case InitMessage::kStopSendingMessages: { case InitMessage::kStopSendingMessages: { init_socket = -1; accept_messages = false; break; } case InitMessage::kStartSendingMessages: { accept_messages = true; break; break; } } default: default: Loading Loading @@ -1078,6 +1083,7 @@ void StartPropertyService(int* epoll_socket) { } } *epoll_socket = sockets[0]; *epoll_socket = sockets[0]; init_socket = sockets[1]; init_socket = sockets[1]; accept_messages = true; if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, false, 0666, 0, 0, {})) { false, 0666, 0, 0, {})) { Loading init/property_service.proto +1 −0 Original line number Original line Diff line number Diff line Loading @@ -40,5 +40,6 @@ message InitMessage { oneof msg { oneof msg { bool load_persistent_properties = 1; bool load_persistent_properties = 1; bool stop_sending_messages = 2; bool stop_sending_messages = 2; bool start_sending_messages = 3; }; }; } } init/reboot.cpp +67 −18 Original line number Original line Diff line number Diff line Loading @@ -50,7 +50,9 @@ #include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h> #include <selinux/selinux.h> #include <selinux/selinux.h> #include "action.h" #include "action_manager.h" #include "action_manager.h" #include "builtin_arguments.h" #include "init.h" #include "init.h" #include "property_service.h" #include "property_service.h" #include "reboot_utils.h" #include "reboot_utils.h" Loading @@ -71,6 +73,8 @@ using android::base::WriteStringToFile; namespace android { namespace android { namespace init { namespace init { static bool shutting_down = false; // represents umount status during reboot / shutdown. // represents umount status during reboot / shutdown. enum UmountStat { enum UmountStat { /* umount succeeded. */ /* umount succeeded. */ Loading Loading @@ -655,12 +659,58 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str abort(); abort(); } } bool HandlePowerctlMessage(const std::string& command) { static void EnterShutdown() { shutting_down = true; // Skip wait for prop if it is in progress ResetWaitForProp(); // Clear EXEC flag if there is one pending for (const auto& s : ServiceList::GetInstance()) { s->UnSetExec(); } // We no longer process messages about properties changing coming from property service, so we // need to tell property service to stop sending us these messages, otherwise it'll fill the // buffers and block indefinitely, causing future property sets, including those that init makes // during shutdown in Service::NotifyStateChange() to also block indefinitely. SendStopSendingMessagesMessage(); } static void LeaveShutdown() { shutting_down = false; SendStartSendingMessagesMessage(); } static void DoUserspaceReboot() { // Triggering userspace-reboot-requested will result in a bunch of set_prop // actions. We should make sure, that all of them are propagated before // proceeding with userspace reboot. // TODO(b/135984674): implement proper synchronization logic. std::this_thread::sleep_for(500ms); EnterShutdown(); // TODO(b/135984674): tear down post-data services LeaveShutdown(); // TODO(b/135984674): remount userdata ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume"); } static void HandleUserspaceReboot() { LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger"; auto& am = ActionManager::GetInstance(); am.ClearQueue(); am.QueueEventTrigger("userspace-reboot-requested"); auto handler = [](const BuiltinArguments&) { DoUserspaceReboot(); return Result<void>{}; }; am.QueueBuiltinAction(handler, "userspace-reboot"); } void HandlePowerctlMessage(const std::string& command) { unsigned int cmd = 0; unsigned int cmd = 0; std::vector<std::string> cmd_params = Split(command, ","); std::vector<std::string> cmd_params = Split(command, ","); std::string reboot_target = ""; std::string reboot_target = ""; bool run_fsck = false; bool run_fsck = false; bool command_invalid = false; bool command_invalid = false; bool userspace_reboot = false; if (cmd_params[0] == "shutdown") { if (cmd_params[0] == "shutdown") { cmd = ANDROID_RB_POWEROFF; cmd = ANDROID_RB_POWEROFF; Loading @@ -680,6 +730,10 @@ bool HandlePowerctlMessage(const std::string& command) { cmd = ANDROID_RB_RESTART2; cmd = ANDROID_RB_RESTART2; if (cmd_params.size() >= 2) { if (cmd_params.size() >= 2) { reboot_target = cmd_params[1]; reboot_target = cmd_params[1]; if (reboot_target == "userspace") { LOG(INFO) << "Userspace reboot requested"; userspace_reboot = true; } // adb reboot fastboot should boot into bootloader for devices not // adb reboot fastboot should boot into bootloader for devices not // supporting logical partitions. // supporting logical partitions. if (reboot_target == "fastboot" && if (reboot_target == "fastboot" && Loading @@ -706,7 +760,7 @@ bool HandlePowerctlMessage(const std::string& command) { strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); if (std::string err; !write_bootloader_message(boot, &err)) { if (std::string err; !write_bootloader_message(boot, &err)) { LOG(ERROR) << "Failed to set bootloader message: " << err; LOG(ERROR) << "Failed to set bootloader message: " << err; return false; return; } } } } } else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" || } else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" || Loading @@ -719,7 +773,7 @@ bool HandlePowerctlMessage(const std::string& command) { std::string err; std::string err; if (!write_bootloader_message(options, &err)) { if (!write_bootloader_message(options, &err)) { LOG(ERROR) << "Failed to set bootloader message: " << err; LOG(ERROR) << "Failed to set bootloader message: " << err; return false; return; } } reboot_target = "recovery"; reboot_target = "recovery"; } } Loading @@ -734,7 +788,12 @@ bool HandlePowerctlMessage(const std::string& command) { } } if (command_invalid) { if (command_invalid) { LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; return false; return; } if (userspace_reboot) { HandleUserspaceReboot(); return; } } LOG(INFO) << "Clear action queue and start shutdown trigger"; LOG(INFO) << "Clear action queue and start shutdown trigger"; Loading @@ -748,21 +807,11 @@ bool HandlePowerctlMessage(const std::string& command) { }; }; ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); // Skip wait for prop if it is in progress EnterShutdown(); ResetWaitForProp(); // Clear EXEC flag if there is one pending for (const auto& s : ServiceList::GetInstance()) { s->UnSetExec(); } } // We no longer process messages about properties changing coming from property service, so we bool IsShuttingDown() { // need to tell property service to stop sending us these messages, otherwise it'll fill the return shutting_down; // buffers and block indefinitely, causing future property sets, including those that init makes // during shutdown in Service::NotifyStateChange() to also block indefinitely. SendStopSendingMessagesMessage(); return true; } } } // namespace init } // namespace init Loading Loading
init/init.cpp +12 −7 Original line number Original line Diff line number Diff line Loading @@ -98,7 +98,6 @@ static int property_fd = -1; static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::string wait_prop_name; static std::string wait_prop_name; static std::string wait_prop_value; static std::string wait_prop_value; static bool shutting_down; static std::string shutdown_command; static std::string shutdown_command; static bool do_shutdown = false; static bool do_shutdown = false; static bool load_debug_prop = false; static bool load_debug_prop = false; Loading Loading @@ -624,7 +623,15 @@ void SendStopSendingMessagesMessage() { auto init_message = InitMessage{}; auto init_message = InitMessage{}; init_message.set_stop_sending_messages(true); init_message.set_stop_sending_messages(true); if (auto result = SendMessage(property_fd, init_message); !result) { if (auto result = SendMessage(property_fd, init_message); !result) { LOG(ERROR) << "Failed to send load persistent properties message: " << result.error(); LOG(ERROR) << "Failed to send 'stop sending messages' message: " << result.error(); } } void SendStartSendingMessagesMessage() { auto init_message = InitMessage{}; init_message.set_start_sending_messages(true); if (auto result = SendMessage(property_fd, init_message); !result) { LOG(ERROR) << "Failed to send 'start sending messages' message: " << result.error(); } } } } Loading Loading @@ -811,18 +818,16 @@ int SecondStageMain(int argc, char** argv) { // By default, sleep until something happens. // By default, sleep until something happens. auto epoll_timeout = std::optional<std::chrono::milliseconds>{}; auto epoll_timeout = std::optional<std::chrono::milliseconds>{}; if (do_shutdown && !shutting_down) { if (do_shutdown && !IsShuttingDown()) { do_shutdown = false; do_shutdown = false; if (HandlePowerctlMessage(shutdown_command)) { HandlePowerctlMessage(shutdown_command); shutting_down = true; } } } if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!(waiting_for_prop || Service::is_exec_service_running())) { am.ExecuteOneCommand(); am.ExecuteOneCommand(); } } if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!(waiting_for_prop || Service::is_exec_service_running())) { if (!shutting_down) { if (!IsShuttingDown()) { auto next_process_action_time = HandleProcessActions(); auto next_process_action_time = HandleProcessActions(); // If there's a process that needs restarting, wake up in time for that. // If there's a process that needs restarting, wake up in time for that. Loading
init/init.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -41,6 +41,7 @@ void ResetWaitForProp(); void SendLoadPersistentPropertiesMessage(); void SendLoadPersistentPropertiesMessage(); void SendStopSendingMessagesMessage(); void SendStopSendingMessagesMessage(); void SendStartSendingMessagesMessage(); int SecondStageMain(int argc, char** argv); int SecondStageMain(int argc, char** argv); Loading
init/property_service.cpp +9 −3 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,7 @@ static bool persistent_properties_loaded = false; static int property_set_fd = -1; static int property_set_fd = -1; static int init_socket = -1; static int init_socket = -1; static bool accept_messages = false; static PropertyInfoAreaFile property_info_area; static PropertyInfoAreaFile property_info_area; Loading Loading @@ -211,7 +212,7 @@ static uint32_t PropertySet(const std::string& name, const std::string& value, s } } // If init hasn't started its main loop, then it won't be handling property changed messages // If init hasn't started its main loop, then it won't be handling property changed messages // anyway, so there's no need to try to send them. // anyway, so there's no need to try to send them. if (init_socket != -1) { if (accept_messages) { SendPropertyChanged(name, value); SendPropertyChanged(name, value); } } return PROP_SUCCESS; return PROP_SUCCESS; Loading Loading @@ -389,7 +390,7 @@ class SocketConnection { static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid, static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid, SocketConnection* socket, std::string* error) { SocketConnection* socket, std::string* error) { if (init_socket == -1) { if (!accept_messages) { *error = "Received control message after shutdown, ignoring"; *error = "Received control message after shutdown, ignoring"; return PROP_ERROR_HANDLE_CONTROL_MESSAGE; return PROP_ERROR_HANDLE_CONTROL_MESSAGE; } } Loading Loading @@ -1035,7 +1036,11 @@ static void HandleInitSocket() { break; break; } } case InitMessage::kStopSendingMessages: { case InitMessage::kStopSendingMessages: { init_socket = -1; accept_messages = false; break; } case InitMessage::kStartSendingMessages: { accept_messages = true; break; break; } } default: default: Loading Loading @@ -1078,6 +1083,7 @@ void StartPropertyService(int* epoll_socket) { } } *epoll_socket = sockets[0]; *epoll_socket = sockets[0]; init_socket = sockets[1]; init_socket = sockets[1]; accept_messages = true; if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, false, 0666, 0, 0, {})) { false, 0666, 0, 0, {})) { Loading
init/property_service.proto +1 −0 Original line number Original line Diff line number Diff line Loading @@ -40,5 +40,6 @@ message InitMessage { oneof msg { oneof msg { bool load_persistent_properties = 1; bool load_persistent_properties = 1; bool stop_sending_messages = 2; bool stop_sending_messages = 2; bool start_sending_messages = 3; }; }; } }
init/reboot.cpp +67 −18 Original line number Original line Diff line number Diff line Loading @@ -50,7 +50,9 @@ #include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h> #include <selinux/selinux.h> #include <selinux/selinux.h> #include "action.h" #include "action_manager.h" #include "action_manager.h" #include "builtin_arguments.h" #include "init.h" #include "init.h" #include "property_service.h" #include "property_service.h" #include "reboot_utils.h" #include "reboot_utils.h" Loading @@ -71,6 +73,8 @@ using android::base::WriteStringToFile; namespace android { namespace android { namespace init { namespace init { static bool shutting_down = false; // represents umount status during reboot / shutdown. // represents umount status during reboot / shutdown. enum UmountStat { enum UmountStat { /* umount succeeded. */ /* umount succeeded. */ Loading Loading @@ -655,12 +659,58 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str abort(); abort(); } } bool HandlePowerctlMessage(const std::string& command) { static void EnterShutdown() { shutting_down = true; // Skip wait for prop if it is in progress ResetWaitForProp(); // Clear EXEC flag if there is one pending for (const auto& s : ServiceList::GetInstance()) { s->UnSetExec(); } // We no longer process messages about properties changing coming from property service, so we // need to tell property service to stop sending us these messages, otherwise it'll fill the // buffers and block indefinitely, causing future property sets, including those that init makes // during shutdown in Service::NotifyStateChange() to also block indefinitely. SendStopSendingMessagesMessage(); } static void LeaveShutdown() { shutting_down = false; SendStartSendingMessagesMessage(); } static void DoUserspaceReboot() { // Triggering userspace-reboot-requested will result in a bunch of set_prop // actions. We should make sure, that all of them are propagated before // proceeding with userspace reboot. // TODO(b/135984674): implement proper synchronization logic. std::this_thread::sleep_for(500ms); EnterShutdown(); // TODO(b/135984674): tear down post-data services LeaveShutdown(); // TODO(b/135984674): remount userdata ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume"); } static void HandleUserspaceReboot() { LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger"; auto& am = ActionManager::GetInstance(); am.ClearQueue(); am.QueueEventTrigger("userspace-reboot-requested"); auto handler = [](const BuiltinArguments&) { DoUserspaceReboot(); return Result<void>{}; }; am.QueueBuiltinAction(handler, "userspace-reboot"); } void HandlePowerctlMessage(const std::string& command) { unsigned int cmd = 0; unsigned int cmd = 0; std::vector<std::string> cmd_params = Split(command, ","); std::vector<std::string> cmd_params = Split(command, ","); std::string reboot_target = ""; std::string reboot_target = ""; bool run_fsck = false; bool run_fsck = false; bool command_invalid = false; bool command_invalid = false; bool userspace_reboot = false; if (cmd_params[0] == "shutdown") { if (cmd_params[0] == "shutdown") { cmd = ANDROID_RB_POWEROFF; cmd = ANDROID_RB_POWEROFF; Loading @@ -680,6 +730,10 @@ bool HandlePowerctlMessage(const std::string& command) { cmd = ANDROID_RB_RESTART2; cmd = ANDROID_RB_RESTART2; if (cmd_params.size() >= 2) { if (cmd_params.size() >= 2) { reboot_target = cmd_params[1]; reboot_target = cmd_params[1]; if (reboot_target == "userspace") { LOG(INFO) << "Userspace reboot requested"; userspace_reboot = true; } // adb reboot fastboot should boot into bootloader for devices not // adb reboot fastboot should boot into bootloader for devices not // supporting logical partitions. // supporting logical partitions. if (reboot_target == "fastboot" && if (reboot_target == "fastboot" && Loading @@ -706,7 +760,7 @@ bool HandlePowerctlMessage(const std::string& command) { strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); strlcpy(boot.command, "boot-recovery", sizeof(boot.command)); if (std::string err; !write_bootloader_message(boot, &err)) { if (std::string err; !write_bootloader_message(boot, &err)) { LOG(ERROR) << "Failed to set bootloader message: " << err; LOG(ERROR) << "Failed to set bootloader message: " << err; return false; return; } } } } } else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" || } else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" || Loading @@ -719,7 +773,7 @@ bool HandlePowerctlMessage(const std::string& command) { std::string err; std::string err; if (!write_bootloader_message(options, &err)) { if (!write_bootloader_message(options, &err)) { LOG(ERROR) << "Failed to set bootloader message: " << err; LOG(ERROR) << "Failed to set bootloader message: " << err; return false; return; } } reboot_target = "recovery"; reboot_target = "recovery"; } } Loading @@ -734,7 +788,12 @@ bool HandlePowerctlMessage(const std::string& command) { } } if (command_invalid) { if (command_invalid) { LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; return false; return; } if (userspace_reboot) { HandleUserspaceReboot(); return; } } LOG(INFO) << "Clear action queue and start shutdown trigger"; LOG(INFO) << "Clear action queue and start shutdown trigger"; Loading @@ -748,21 +807,11 @@ bool HandlePowerctlMessage(const std::string& command) { }; }; ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); // Skip wait for prop if it is in progress EnterShutdown(); ResetWaitForProp(); // Clear EXEC flag if there is one pending for (const auto& s : ServiceList::GetInstance()) { s->UnSetExec(); } } // We no longer process messages about properties changing coming from property service, so we bool IsShuttingDown() { // need to tell property service to stop sending us these messages, otherwise it'll fill the return shutting_down; // buffers and block indefinitely, causing future property sets, including those that init makes // during shutdown in Service::NotifyStateChange() to also block indefinitely. SendStopSendingMessagesMessage(); return true; } } } // namespace init } // namespace init Loading