diff --git a/init/builtins.cpp b/init/builtins.cpp index a55514b82..8f5814536 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -65,6 +65,7 @@ #include "action_manager.h" #include "bootchart.h" +#include "builtin_arguments.h" #include "fscrypt_init_extensions.h" #include "init.h" #include "mount_namespace.h" @@ -1216,6 +1217,15 @@ static Result do_enter_default_mount_ns(const BuiltinArguments& args) { } } +static Result do_finish_userspace_reboot(const BuiltinArguments&) { + LOG(INFO) << "Userspace reboot successfully finished"; + boot_clock::time_point now = boot_clock::now(); + property_set("sys.init.userspace_reboot.last_finished", + std::to_string(now.time_since_epoch().count())); + property_set(kUserspaceRebootInProgress, "0"); + return {}; +} + // Builtin-function-map start const BuiltinFunctionMap& GetBuiltinFunctionMap() { constexpr std::size_t kMax = std::numeric_limits::max(); @@ -1237,6 +1247,7 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { {"exec_background", {1, kMax, {false, do_exec_background}}}, {"exec_start", {1, 1, {false, do_exec_start}}}, {"export", {2, 2, {false, do_export}}}, + {"finish_userspace_reboot", {0, 0, {false, do_finish_userspace_reboot}}}, {"hostname", {1, 1, {true, do_hostname}}}, {"ifup", {1, 1, {true, do_ifup}}}, {"init_user0", {0, 0, {false, do_init_user0}}}, diff --git a/init/reboot.cpp b/init/reboot.cpp index 64ec1fb6d..7040f26a4 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -69,10 +69,13 @@ using namespace std::literals; +using android::base::boot_clock; using android::base::GetBoolProperty; +using android::base::SetProperty; using android::base::Split; using android::base::Timer; using android::base::unique_fd; +using android::base::WaitForProperty; using android::base::WriteStringToFile; namespace android { @@ -728,16 +731,21 @@ static Result UnmountAllApexes() { static Result DoUserspaceReboot() { LOG(INFO) << "Userspace reboot initiated"; + boot_clock::time_point now = boot_clock::now(); + property_set("sys.init.userspace_reboot.last_started", + std::to_string(now.time_since_epoch().count())); auto guard = android::base::make_scope_guard([] { // Leave shutdown so that we can handle a full reboot. LeaveShutdown(); trigger_shutdown("reboot,abort-userspace-reboot"); }); - // Triggering userspace-reboot-requested will result in a bunch of set_prop + // Triggering userspace-reboot-requested will result in a bunch of setprop // 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); + // proceeding with userspace reboot. Synchronously setting kUserspaceRebootInProgress property + // is not perfect, but it should do the trick. + if (property_set(kUserspaceRebootInProgress, "1") != 0) { + return Error() << "Failed to set property " << kUserspaceRebootInProgress; + } EnterShutdown(); std::vector stop_first; // Remember the services that were enabled. We will need to manually enable them again otherwise diff --git a/init/reboot.h b/init/reboot.h index 81c3edc12..cdfa024ea 100644 --- a/init/reboot.h +++ b/init/reboot.h @@ -22,6 +22,8 @@ namespace android { namespace init { +static const constexpr char* kUserspaceRebootInProgress = "sys.init.userspace_reboot.in_progress"; + // Parses and handles a setprop sys.powerctl message. void HandlePowerctlMessage(const std::string& command); diff --git a/rootdir/init.rc b/rootdir/init.rc index bc18e2746..5ac7781a1 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -925,7 +925,6 @@ on init && property:ro.debuggable=1 on userspace-reboot-requested # TODO(b/135984674): reset all necessary properties here. - setprop sys.init.userspace_reboot_in_progress 1 setprop sys.boot_completed 0 setprop sys.init.updatable_crashing 0 setprop apexd.status "" @@ -945,3 +944,6 @@ on userspace-reboot-resume trigger zygote-start trigger early-boot trigger boot + +on property:sys.boot_completed=1 && property:sys.init.userspace_reboot.in_progress=1 + finish_userspace_reboot