diff --git a/init/README.md b/init/README.md index 9fcc6e49d..929f0e413 100644 --- a/init/README.md +++ b/init/README.md @@ -412,6 +412,10 @@ Commands not already running. See the start entry for more information on starting services. +`class_start_post_data ` +> Like `class_start`, but only considers services that were started + after /data was mounted. Only used for FDE devices. + `class_stop ` > Stop and disable all services of the specified class if they are currently running. @@ -421,6 +425,10 @@ Commands currently running, without disabling them. They can be restarted later using `class_start`. +`class_reset_post_data ` +> Like `class_reset`, but only considers services that were started + after /data was mounted. Only used for FDE devices. + `class_restart ` > Restarts all services of the specified class. @@ -490,6 +498,10 @@ Commands `loglevel ` > Sets the kernel log level to level. Properties are expanded within _level_. +`mark_post_data` +> Used to mark the point right after /data is mounted. Used to implement the + `class_reset_post_data` and `class_start_post_data` commands. + `mkdir [mode] [owner] [group]` > Create a directory at _path_, optionally with the given mode, owner, and group. If not provided, the directory is created with permissions 755 and diff --git a/init/builtins.cpp b/init/builtins.cpp index fc75072b6..34f229b7f 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -104,23 +104,37 @@ static void ForEachServiceInClass(const std::string& classname, F function) { } } -static Result do_class_start(const BuiltinArguments& args) { +static Result class_start(const std::string& class_name, bool post_data_only) { // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1. - if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) + if (android::base::GetBoolProperty("persist.init.dont_start_class." + class_name, false)) return Success(); // Starting a class does not start services which are explicitly disabled. // They must be started individually. for (const auto& service : ServiceList::GetInstance()) { - if (service->classnames().count(args[1])) { + if (service->classnames().count(class_name)) { + if (post_data_only && !service->is_post_data()) { + continue; + } if (auto result = service->StartIfNotDisabled(); !result) { LOG(ERROR) << "Could not start service '" << service->name() - << "' as part of class '" << args[1] << "': " << result.error(); + << "' as part of class '" << class_name << "': " << result.error(); } } } return Success(); } +static Result do_class_start(const BuiltinArguments& args) { + return class_start(args[1], false /* post_data_only */); +} + +static Result do_class_start_post_data(const BuiltinArguments& args) { + if (args.context != kInitContext) { + return Error() << "command 'class_start_post_data' only available in init context"; + } + return class_start(args[1], true /* post_data_only */); +} + static Result do_class_stop(const BuiltinArguments& args) { ForEachServiceInClass(args[1], &Service::Stop); return Success(); @@ -131,6 +145,14 @@ static Result do_class_reset(const BuiltinArguments& args) { return Success(); } +static Result do_class_reset_post_data(const BuiltinArguments& args) { + if (args.context != kInitContext) { + return Error() << "command 'class_reset_post_data' only available in init context"; + } + ForEachServiceInClass(args[1], &Service::ResetIfPostData); + return Success(); +} + static Result do_class_restart(const BuiltinArguments& args) { // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1. if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) @@ -1119,6 +1141,12 @@ static Result do_init_user0(const BuiltinArguments& args) { {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); } +static Result do_mark_post_data(const BuiltinArguments& args) { + ServiceList::GetInstance().MarkPostData(); + + return Success(); +} + static Result do_parse_apex_configs(const BuiltinArguments& args) { glob_t glob_result; // @ is added to filter out the later paths, which are bind mounts of the places @@ -1170,8 +1198,10 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"chmod", {2, 2, {true, do_chmod}}}, {"chown", {2, 3, {true, do_chown}}}, {"class_reset", {1, 1, {false, do_class_reset}}}, + {"class_reset_post_data", {1, 1, {false, do_class_reset_post_data}}}, {"class_restart", {1, 1, {false, do_class_restart}}}, {"class_start", {1, 1, {false, do_class_start}}}, + {"class_start_post_data", {1, 1, {false, do_class_start_post_data}}}, {"class_stop", {1, 1, {false, do_class_stop}}}, {"copy", {2, 2, {true, do_copy}}}, {"domainname", {1, 1, {true, do_domainname}}}, @@ -1191,6 +1221,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"load_persist_props", {0, 0, {false, do_load_persist_props}}}, {"load_system_props", {0, 0, {false, do_load_system_props}}}, {"loglevel", {1, 1, {false, do_loglevel}}}, + {"mark_post_data", {0, 0, {false, do_mark_post_data}}}, {"mkdir", {1, 4, {true, do_mkdir}}}, // TODO: Do mount operations in vendor_init. // mount_all is currently too complex to run in vendor_init as it queues action triggers, diff --git a/init/service.cpp b/init/service.cpp index 276c2aa92..2f9668107 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -362,7 +362,7 @@ void Service::Reap(const siginfo_t& siginfo) { // Oneshot processes go into the disabled state on exit, // except when manually restarted. - if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) { + if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART) && !(flags_ & SVC_RESET)) { flags_ |= SVC_DISABLED; } @@ -951,6 +951,8 @@ Result Service::Start() { pre_apexd_ = true; } + post_data_ = ServiceList::GetInstance().IsPostData(); + LOG(INFO) << "starting service '" << name_ << "'..."; pid_t pid = -1; @@ -1150,6 +1152,12 @@ void Service::Reset() { StopOrReset(SVC_RESET); } +void Service::ResetIfPostData() { + if (post_data_) { + StopOrReset(SVC_RESET); + } +} + void Service::Stop() { StopOrReset(SVC_DISABLED); } @@ -1343,6 +1351,14 @@ void ServiceList::DumpState() const { } } +void ServiceList::MarkPostData() { + post_data_ = true; +} + +bool ServiceList::IsPostData() { + return post_data_; +} + void ServiceList::MarkServicesUpdate() { services_update_finished_ = true; diff --git a/init/service.h b/init/service.h index c42a5a371..dc2b12883 100644 --- a/init/service.h +++ b/init/service.h @@ -81,6 +81,7 @@ class Service { Result StartIfNotDisabled(); Result Enable(); void Reset(); + void ResetIfPostData(); void Stop(); void Terminate(); void Timeout(); @@ -124,6 +125,7 @@ class Service { std::optional timeout_period() const { return timeout_period_; } const std::vector& args() const { return args_; } bool is_updatable() const { return updatable_; } + bool is_post_data() const { return post_data_; } private: using OptionParser = Result (Service::*)(std::vector&& args); @@ -244,6 +246,8 @@ class Service { std::vector> reap_callbacks_; bool pre_apexd_ = false; + + bool post_data_ = false; }; class ServiceList { @@ -285,6 +289,8 @@ class ServiceList { const std::vector>& services() const { return services_; } const std::vector services_in_shutdown_order() const; + void MarkPostData(); + bool IsPostData(); void MarkServicesUpdate(); bool IsServicesUpdated() const { return services_update_finished_; } void DelayService(const Service& service); @@ -292,6 +298,7 @@ class ServiceList { private: std::vector> services_; + bool post_data_ = false; bool services_update_finished_ = false; std::vector delayed_service_names_; }; diff --git a/rootdir/init.rc b/rootdir/init.rc index dfde53ccb..cb45c42f8 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -405,6 +405,8 @@ on late-fs class_start early_hal on post-fs-data + mark_post_data + # Start checkpoint before we touch data start vold exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint @@ -753,9 +755,6 @@ on property:sys.init_log_level=* on charger class_start charger -on property:vold.decrypt=trigger_reset_main - class_reset main - on property:vold.decrypt=trigger_load_persist_props load_persist_props start logd @@ -773,6 +772,8 @@ on property:vold.decrypt=trigger_restart_min_framework on property:vold.decrypt=trigger_restart_framework # A/B update verifier that marks a successful boot. exec_start update_verifier + class_start_post_data hal + class_start_post_data core class_start main class_start late_start setprop service.bootanim.exit 0 @@ -781,6 +782,8 @@ on property:vold.decrypt=trigger_restart_framework on property:vold.decrypt=trigger_shutdown_framework class_reset late_start class_reset main + class_reset_post_data core + class_reset_post_data hal on property:sys.boot_completed=1 bootchart stop