Merge "Support for stopping/starting post-data-mount class subsets."

am: fc78be2935

Change-Id: I3dad9a80217cc2d33576be4d681168566d991c77
This commit is contained in:
Martijn Coenen 2019-05-06 23:57:02 -07:00 committed by android-build-merger
commit 741fef7395
5 changed files with 77 additions and 8 deletions

View file

@ -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.
@ -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.
@ -494,6 +502,10 @@ Commands
`write` command to write to `/proc/sys/kernel/printk` to change that.
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

View file

@ -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();
@ -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))
@ -1042,6 +1064,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
@ -1093,8 +1121,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}}},
@ -1114,6 +1144,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,

View file

@ -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<Success> 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;

View file

@ -81,6 +81,7 @@ class Service {
Result<Success> StartIfNotDisabled();
Result<Success> Enable();
void Reset();
void ResetIfPostData();
void Stop();
void Terminate();
void Timeout();
@ -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);
@ -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 {
@ -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);
@ -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_;
};

View file

@ -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
@ -747,9 +749,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
@ -767,6 +766,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
@ -775,6 +776,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