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

Commit 438d399f authored by Nikita Ioffe's avatar Nikita Ioffe Committed by android-build-merger
Browse files

Merge "Add a skeleton of userspace reboot" am: f1933c91

am: 5e0e30db

Change-Id: I5f98df438bb7026b8c6200f484b466d05f16605d
parents 35cf5f20 5e0e30db
Loading
Loading
Loading
Loading
+12 −7
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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();
    }
    }
}
}


@@ -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.
+1 −0
Original line number Original line Diff line number Diff line
@@ -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);


+9 −3
Original line number Original line Diff line number Diff line
@@ -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;


@@ -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;
@@ -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;
    }
    }
@@ -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:
@@ -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, {})) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -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;
    };
    };
}
}
+67 −18
Original line number Original line Diff line number Diff line
@@ -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"
@@ -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. */
@@ -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;
@@ -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" &&
@@ -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" ||
@@ -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";
            }
            }
@@ -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";
@@ -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