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

Commit 7a2d54df authored by Martijn Coenen's avatar Martijn Coenen Committed by Android (Google) Code Review
Browse files

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

parents 10401090 f0bc58a4
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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.

@@ -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
+35 −4
Original line number Diff line number Diff line
@@ -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))
@@ -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
@@ -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,
+17 −1
Original line number Diff line number Diff line
@@ -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;

+7 −0
Original line number Diff line number Diff line
@@ -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_;
};
+6 −3
Original line number Diff line number Diff line
@@ -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