Merge "Add a skeleton of userspace reboot"
This commit is contained in:
commit
f1933c910d
|
@ -98,7 +98,6 @@ static int property_fd = -1;
|
|||
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
|
||||
static std::string wait_prop_name;
|
||||
static std::string wait_prop_value;
|
||||
static bool shutting_down;
|
||||
static std::string shutdown_command;
|
||||
static bool do_shutdown = false;
|
||||
static bool load_debug_prop = false;
|
||||
|
@ -624,7 +623,15 @@ void SendStopSendingMessagesMessage() {
|
|||
auto init_message = InitMessage{};
|
||||
init_message.set_stop_sending_messages(true);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -811,18 +818,16 @@ int SecondStageMain(int argc, char** argv) {
|
|||
// By default, sleep until something happens.
|
||||
auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
|
||||
|
||||
if (do_shutdown && !shutting_down) {
|
||||
if (do_shutdown && !IsShuttingDown()) {
|
||||
do_shutdown = false;
|
||||
if (HandlePowerctlMessage(shutdown_command)) {
|
||||
shutting_down = true;
|
||||
}
|
||||
HandlePowerctlMessage(shutdown_command);
|
||||
}
|
||||
|
||||
if (!(waiting_for_prop || Service::is_exec_service_running())) {
|
||||
am.ExecuteOneCommand();
|
||||
}
|
||||
if (!(waiting_for_prop || Service::is_exec_service_running())) {
|
||||
if (!shutting_down) {
|
||||
if (!IsShuttingDown()) {
|
||||
auto next_process_action_time = HandleProcessActions();
|
||||
|
||||
// If there's a process that needs restarting, wake up in time for that.
|
||||
|
|
|
@ -41,6 +41,7 @@ void ResetWaitForProp();
|
|||
|
||||
void SendLoadPersistentPropertiesMessage();
|
||||
void SendStopSendingMessagesMessage();
|
||||
void SendStartSendingMessagesMessage();
|
||||
|
||||
int SecondStageMain(int argc, char** argv);
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ static bool persistent_properties_loaded = false;
|
|||
|
||||
static int property_set_fd = -1;
|
||||
static int init_socket = -1;
|
||||
static bool accept_messages = false;
|
||||
|
||||
static PropertyInfoAreaFile property_info_area;
|
||||
|
||||
|
@ -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
|
||||
// anyway, so there's no need to try to send them.
|
||||
if (init_socket != -1) {
|
||||
if (accept_messages) {
|
||||
SendPropertyChanged(name, value);
|
||||
}
|
||||
return PROP_SUCCESS;
|
||||
|
@ -389,7 +390,7 @@ class SocketConnection {
|
|||
|
||||
static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
|
||||
SocketConnection* socket, std::string* error) {
|
||||
if (init_socket == -1) {
|
||||
if (!accept_messages) {
|
||||
*error = "Received control message after shutdown, ignoring";
|
||||
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
|
||||
}
|
||||
|
@ -1035,7 +1036,11 @@ static void HandleInitSocket() {
|
|||
break;
|
||||
}
|
||||
case InitMessage::kStopSendingMessages: {
|
||||
init_socket = -1;
|
||||
accept_messages = false;
|
||||
break;
|
||||
}
|
||||
case InitMessage::kStartSendingMessages: {
|
||||
accept_messages = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1078,6 +1083,7 @@ void StartPropertyService(int* epoll_socket) {
|
|||
}
|
||||
*epoll_socket = sockets[0];
|
||||
init_socket = sockets[1];
|
||||
accept_messages = true;
|
||||
|
||||
if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
|
||||
false, 0666, 0, 0, {})) {
|
||||
|
|
|
@ -40,5 +40,6 @@ message InitMessage {
|
|||
oneof msg {
|
||||
bool load_persistent_properties = 1;
|
||||
bool stop_sending_messages = 2;
|
||||
bool start_sending_messages = 3;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -50,7 +50,9 @@
|
|||
#include <private/android_filesystem_config.h>
|
||||
#include <selinux/selinux.h>
|
||||
|
||||
#include "action.h"
|
||||
#include "action_manager.h"
|
||||
#include "builtin_arguments.h"
|
||||
#include "init.h"
|
||||
#include "property_service.h"
|
||||
#include "reboot_utils.h"
|
||||
|
@ -71,6 +73,8 @@ using android::base::WriteStringToFile;
|
|||
namespace android {
|
||||
namespace init {
|
||||
|
||||
static bool shutting_down = false;
|
||||
|
||||
// represents umount status during reboot / shutdown.
|
||||
enum UmountStat {
|
||||
/* umount succeeded. */
|
||||
|
@ -655,12 +659,58 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
|
|||
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;
|
||||
std::vector<std::string> cmd_params = Split(command, ",");
|
||||
std::string reboot_target = "";
|
||||
bool run_fsck = false;
|
||||
bool command_invalid = false;
|
||||
bool userspace_reboot = false;
|
||||
|
||||
if (cmd_params[0] == "shutdown") {
|
||||
cmd = ANDROID_RB_POWEROFF;
|
||||
|
@ -680,6 +730,10 @@ bool HandlePowerctlMessage(const std::string& command) {
|
|||
cmd = ANDROID_RB_RESTART2;
|
||||
if (cmd_params.size() >= 2) {
|
||||
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
|
||||
// supporting logical partitions.
|
||||
if (reboot_target == "fastboot" &&
|
||||
|
@ -706,7 +760,7 @@ bool HandlePowerctlMessage(const std::string& command) {
|
|||
strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
|
||||
if (std::string err; !write_bootloader_message(boot, &err)) {
|
||||
LOG(ERROR) << "Failed to set bootloader message: " << err;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" ||
|
||||
|
@ -719,7 +773,7 @@ bool HandlePowerctlMessage(const std::string& command) {
|
|||
std::string err;
|
||||
if (!write_bootloader_message(options, &err)) {
|
||||
LOG(ERROR) << "Failed to set bootloader message: " << err;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
reboot_target = "recovery";
|
||||
}
|
||||
|
@ -734,7 +788,12 @@ bool HandlePowerctlMessage(const std::string& command) {
|
|||
}
|
||||
if (command_invalid) {
|
||||
LOG(ERROR) << "powerctl: unrecognized command '" << command << "'";
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (userspace_reboot) {
|
||||
HandleUserspaceReboot();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Clear action queue and start shutdown trigger";
|
||||
|
@ -748,21 +807,11 @@ bool HandlePowerctlMessage(const std::string& command) {
|
|||
};
|
||||
ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done");
|
||||
|
||||
// Skip wait for prop if it is in progress
|
||||
ResetWaitForProp();
|
||||
EnterShutdown();
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
return true;
|
||||
bool IsShuttingDown() {
|
||||
return shutting_down;
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
|
|
|
@ -23,8 +23,9 @@ namespace android {
|
|||
namespace init {
|
||||
|
||||
// Parses and handles a setprop sys.powerctl message.
|
||||
bool HandlePowerctlMessage(const std::string& command);
|
||||
void HandlePowerctlMessage(const std::string& command);
|
||||
|
||||
bool IsShuttingDown();
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
||||
|
|
|
@ -917,3 +917,15 @@ on property:ro.debuggable=1
|
|||
|
||||
on init && property:ro.debuggable=1
|
||||
start console
|
||||
|
||||
on userspace-reboot:
|
||||
# TODO(b/135984674): reset all necessary properties here.
|
||||
setprop sys.init.userspace_reboot_in_progress 1
|
||||
|
||||
on userspace-reboot-resume:
|
||||
# TODO(b/135984674): remount userdata and reset checkpointing
|
||||
trigger nonencrypted
|
||||
trigger post-fs-data
|
||||
trigger zygote-start
|
||||
trigger early-boot
|
||||
trigger boot
|
||||
|
|
Loading…
Reference in New Issue