Loading init/README.md +12 −0 Original line number Diff line number Diff line Loading @@ -412,6 +412,10 @@ Commands not already running. See the start entry for more information on starting services. `class_start_post_data <serviceclass>` > Like `class_start`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_stop <serviceclass>` > Stop and disable all services of the specified class if they are currently running. Loading @@ -421,6 +425,10 @@ Commands currently running, without disabling them. They can be restarted later using `class_start`. `class_reset_post_data <serviceclass>` > Like `class_reset`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_restart <serviceclass>` > Restarts all services of the specified class. Loading Loading @@ -490,6 +498,10 @@ Commands `loglevel <level>` > 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 <path> [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 Loading init/builtins.cpp +35 −4 Original line number Diff line number Diff line Loading @@ -104,23 +104,37 @@ static void ForEachServiceInClass(const std::string& classname, F function) { } } static Result<Success> do_class_start(const BuiltinArguments& args) { static Result<Success> 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<Success> do_class_start(const BuiltinArguments& args) { return class_start(args[1], false /* post_data_only */); } static Result<Success> 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<Success> do_class_stop(const BuiltinArguments& args) { ForEachServiceInClass(args[1], &Service::Stop); return Success(); Loading @@ -131,6 +145,14 @@ static Result<Success> do_class_reset(const BuiltinArguments& args) { return Success(); } static Result<Success> 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<Success> 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)) Loading Loading @@ -1119,6 +1141,12 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) { {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); } static Result<Success> do_mark_post_data(const BuiltinArguments& args) { ServiceList::GetInstance().MarkPostData(); return Success(); } static Result<Success> 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 Loading Loading @@ -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}}}, Loading @@ -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, Loading init/service.cpp +17 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -951,6 +951,8 @@ Result<Success> Service::Start() { pre_apexd_ = true; } post_data_ = ServiceList::GetInstance().IsPostData(); LOG(INFO) << "starting service '" << name_ << "'..."; pid_t pid = -1; Loading Loading @@ -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); } Loading Loading @@ -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; Loading init/service.h +7 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ class Service { Result<Success> StartIfNotDisabled(); Result<Success> Enable(); void Reset(); void ResetIfPostData(); void Stop(); void Terminate(); void Timeout(); Loading Loading @@ -124,6 +125,7 @@ class Service { std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; } const std::vector<std::string>& args() const { return args_; } bool is_updatable() const { return updatable_; } bool is_post_data() const { return post_data_; } private: using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args); Loading Loading @@ -244,6 +246,8 @@ class Service { std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_; bool pre_apexd_ = false; bool post_data_ = false; }; class ServiceList { Loading Loading @@ -285,6 +289,8 @@ class ServiceList { const std::vector<std::unique_ptr<Service>>& services() const { return services_; } const std::vector<Service*> services_in_shutdown_order() const; void MarkPostData(); bool IsPostData(); void MarkServicesUpdate(); bool IsServicesUpdated() const { return services_update_finished_; } void DelayService(const Service& service); Loading @@ -292,6 +298,7 @@ class ServiceList { private: std::vector<std::unique_ptr<Service>> services_; bool post_data_ = false; bool services_update_finished_ = false; std::vector<std::string> delayed_service_names_; }; Loading rootdir/init.rc +6 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading
init/README.md +12 −0 Original line number Diff line number Diff line Loading @@ -412,6 +412,10 @@ Commands not already running. See the start entry for more information on starting services. `class_start_post_data <serviceclass>` > Like `class_start`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_stop <serviceclass>` > Stop and disable all services of the specified class if they are currently running. Loading @@ -421,6 +425,10 @@ Commands currently running, without disabling them. They can be restarted later using `class_start`. `class_reset_post_data <serviceclass>` > Like `class_reset`, but only considers services that were started after /data was mounted. Only used for FDE devices. `class_restart <serviceclass>` > Restarts all services of the specified class. Loading Loading @@ -490,6 +498,10 @@ Commands `loglevel <level>` > 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 <path> [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 Loading
init/builtins.cpp +35 −4 Original line number Diff line number Diff line Loading @@ -104,23 +104,37 @@ static void ForEachServiceInClass(const std::string& classname, F function) { } } static Result<Success> do_class_start(const BuiltinArguments& args) { static Result<Success> 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<Success> do_class_start(const BuiltinArguments& args) { return class_start(args[1], false /* post_data_only */); } static Result<Success> 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<Success> do_class_stop(const BuiltinArguments& args) { ForEachServiceInClass(args[1], &Service::Stop); return Success(); Loading @@ -131,6 +145,14 @@ static Result<Success> do_class_reset(const BuiltinArguments& args) { return Success(); } static Result<Success> 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<Success> 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)) Loading Loading @@ -1119,6 +1141,12 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) { {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); } static Result<Success> do_mark_post_data(const BuiltinArguments& args) { ServiceList::GetInstance().MarkPostData(); return Success(); } static Result<Success> 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 Loading Loading @@ -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}}}, Loading @@ -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, Loading
init/service.cpp +17 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -951,6 +951,8 @@ Result<Success> Service::Start() { pre_apexd_ = true; } post_data_ = ServiceList::GetInstance().IsPostData(); LOG(INFO) << "starting service '" << name_ << "'..."; pid_t pid = -1; Loading Loading @@ -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); } Loading Loading @@ -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; Loading
init/service.h +7 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ class Service { Result<Success> StartIfNotDisabled(); Result<Success> Enable(); void Reset(); void ResetIfPostData(); void Stop(); void Terminate(); void Timeout(); Loading Loading @@ -124,6 +125,7 @@ class Service { std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; } const std::vector<std::string>& args() const { return args_; } bool is_updatable() const { return updatable_; } bool is_post_data() const { return post_data_; } private: using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args); Loading Loading @@ -244,6 +246,8 @@ class Service { std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_; bool pre_apexd_ = false; bool post_data_ = false; }; class ServiceList { Loading Loading @@ -285,6 +289,8 @@ class ServiceList { const std::vector<std::unique_ptr<Service>>& services() const { return services_; } const std::vector<Service*> services_in_shutdown_order() const; void MarkPostData(); bool IsPostData(); void MarkServicesUpdate(); bool IsServicesUpdated() const { return services_update_finished_; } void DelayService(const Service& service); Loading @@ -292,6 +298,7 @@ class ServiceList { private: std::vector<std::unique_ptr<Service>> services_; bool post_data_ = false; bool services_update_finished_ = false; std::vector<std::string> delayed_service_names_; }; Loading
rootdir/init.rc +6 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading