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

Commit 9cbf5704 authored by Tom Cherry's avatar Tom Cherry
Browse files

Move all Action parsing into ActionParser

Bug: 36970783
Test: Build
Change-Id: Iea2d97fb45c3e88bc83fb72d6fa67049be42cfa9
parent 7fd3bc27
Loading
Loading
Loading
Loading
+9 −83
Original line number Diff line number Diff line
@@ -21,11 +21,9 @@
#include <android-base/properties.h>
#include <android-base/strings.h>

#include "stable_properties.h"
#include "util.h"

using android::base::Join;
using android::base::StartsWith;

namespace android {
namespace init {
@@ -70,8 +68,15 @@ std::string Command::BuildCommandString() const {
    return Join(args_, ' ');
}

Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line)
    : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {}
Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
               const std::string& event_trigger,
               const std::map<std::string, std::string>& property_triggers)
    : property_triggers_(property_triggers),
      event_trigger_(event_trigger),
      oneshot_(oneshot),
      subcontext_(subcontext),
      filename_(filename),
      line_(line) {}

const KeywordFunctionMap* Action::function_map_ = nullptr;

@@ -135,85 +140,6 @@ void Action::ExecuteCommand(const Command& command) const {
    }
}

static bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
    static bool enabled =
        android::base::GetBoolProperty("ro.actionable_compatible_property.enabled", false);

    if (subcontext == nullptr || !enabled) {
        return true;
    }

    if (kExportedActionableProperties.count(prop_name) == 1) {
        return true;
    }
    for (const auto& prefix : kPartnerPrefixes) {
        if (android::base::StartsWith(prop_name, prefix)) {
            return true;
        }
    }
    return false;
}

Result<Success> Action::ParsePropertyTrigger(const std::string& trigger) {
    const static std::string prop_str("property:");
    std::string prop_name(trigger.substr(prop_str.length()));
    size_t equal_pos = prop_name.find('=');
    if (equal_pos == std::string::npos) {
        return Error() << "property trigger found without matching '='";
    }

    std::string prop_value(prop_name.substr(equal_pos + 1));
    prop_name.erase(equal_pos);

    if (!IsActionableProperty(subcontext_, prop_name)) {
        return Error() << "unexported property tigger found: " << prop_name;
    }

    if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) {
        return Error() << "multiple property triggers found for same property";
    }
    return Success();
}

Result<Success> Action::InitTriggers(const std::vector<std::string>& args) {
    const static std::string prop_str("property:");
    for (std::size_t i = 0; i < args.size(); ++i) {
        if (args[i].empty()) {
            return Error() << "empty trigger is not valid";
        }

        if (i % 2) {
            if (args[i] != "&&") {
                return Error() << "&& is the only symbol allowed to concatenate actions";
            } else {
                continue;
            }
        }

        if (!args[i].compare(0, prop_str.length(), prop_str)) {
            if (auto result = ParsePropertyTrigger(args[i]); !result) {
                return result;
            }
        } else {
            if (!event_trigger_.empty()) {
                return Error() << "multiple event triggers are not allowed";
            }

            event_trigger_ = args[i];
        }
    }

    return Success();
}

Result<Success> Action::InitSingleTrigger(const std::string& trigger) {
    std::vector<std::string> name_vector{trigger};
    if (auto result = InitTriggers(name_vector); !result) {
        return Error() << "InitTriggers() failed: " << result.error();
    }
    return Success();
}

// This function checks that all property triggers are satisfied, that is
// for each (name, value) in property_triggers_, check that the current
// value of the property 'name' == value.
+3 −4
Original line number Diff line number Diff line
@@ -57,12 +57,12 @@ using BuiltinAction = class Action*;

class Action {
  public:
    Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line);
    Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
           const std::string& event_trigger,
           const std::map<std::string, std::string>& property_triggers);

    Result<Success> AddCommand(const std::vector<std::string>& args, int line);
    void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
    Result<Success> InitTriggers(const std::vector<std::string>& args);
    Result<Success> InitSingleTrigger(const std::string& trigger);
    std::size_t NumCommands() const;
    void ExecuteOneCommand(std::size_t command) const;
    void ExecuteAllCommands() const;
@@ -83,7 +83,6 @@ class Action {
    void ExecuteCommand(const Command& command) const;
    bool CheckPropertyTriggers(const std::string& name = "",
                               const std::string& value = "") const;
    Result<Success> ParsePropertyTrigger(const std::string& trigger);

    std::map<std::string, std::string> property_triggers_;
    std::string event_trigger_;
+2 −6
Original line number Diff line number Diff line
@@ -45,14 +45,10 @@ void ActionManager::QueueAllPropertyActions() {
}

void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
    auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0);
    auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
                                           std::map<std::string, std::string>{});
    std::vector<std::string> name_vector{name};

    if (auto result = action->InitSingleTrigger(name); !result) {
        LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error();
        return;
    }

    action->AddCommand(func, name_vector, 0);

    event_queue_.emplace(action.get());
+90 −3
Original line number Diff line number Diff line
@@ -16,13 +16,95 @@

#include "action_parser.h"

#include <android-base/properties.h>
#include <android-base/strings.h>

#include "stable_properties.h"

using android::base::GetBoolProperty;
using android::base::StartsWith;

namespace android {
namespace init {

namespace {

bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
    static bool enabled = GetBoolProperty("ro.actionable_compatible_property.enabled", false);

    if (subcontext == nullptr || !enabled) {
        return true;
    }

    if (kExportedActionableProperties.count(prop_name) == 1) {
        return true;
    }
    for (const auto& prefix : kPartnerPrefixes) {
        if (android::base::StartsWith(prop_name, prefix)) {
            return true;
        }
    }
    return false;
}

Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
                                     std::map<std::string, std::string>* property_triggers) {
    const static std::string prop_str("property:");
    std::string prop_name(trigger.substr(prop_str.length()));
    size_t equal_pos = prop_name.find('=');
    if (equal_pos == std::string::npos) {
        return Error() << "property trigger found without matching '='";
    }

    std::string prop_value(prop_name.substr(equal_pos + 1));
    prop_name.erase(equal_pos);

    if (!IsActionableProperty(subcontext, prop_name)) {
        return Error() << "unexported property tigger found: " << prop_name;
    }

    if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
        return Error() << "multiple property triggers found for same property";
    }
    return Success();
}

Result<Success> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
                              std::string* event_trigger,
                              std::map<std::string, std::string>* property_triggers) {
    const static std::string prop_str("property:");
    for (std::size_t i = 0; i < args.size(); ++i) {
        if (args[i].empty()) {
            return Error() << "empty trigger is not valid";
        }

        if (i % 2) {
            if (args[i] != "&&") {
                return Error() << "&& is the only symbol allowed to concatenate actions";
            } else {
                continue;
            }
        }

        if (!args[i].compare(0, prop_str.length(), prop_str)) {
            if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers);
                !result) {
                return result;
            }
        } else {
            if (!event_trigger->empty()) {
                return Error() << "multiple event triggers are not allowed";
            }

            *event_trigger = args[i];
        }
    }

    return Success();
}

}  // namespace

Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
                                           const std::string& filename, int line) {
    std::vector<std::string> triggers(args.begin() + 1, args.end());
@@ -40,12 +122,17 @@ Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
        }
    }

    auto action = std::make_unique<Action>(false, action_subcontext, filename, line);
    std::string event_trigger;
    std::map<std::string, std::string> property_triggers;

    if (auto result = action->InitTriggers(triggers); !result) {
        return Error() << "InitTriggers() failed: " << result.error();
    if (auto result = ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers);
        !result) {
        return Error() << "ParseTriggers() failed: " << result.error();
    }

    auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger,
                                           property_triggers);

    action_ = std::move(action);
    return Success();
}
+3 −4
Original line number Diff line number Diff line
@@ -189,7 +189,8 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
      capabilities_(capabilities),
      namespace_flags_(namespace_flags),
      seclabel_(seclabel),
      onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0),
      onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
                 "onrestart", {}),
      keychord_id_(0),
      ioprio_class_(IoSchedClass_NONE),
      ioprio_pri_(0),
@@ -199,9 +200,7 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
      soft_limit_in_bytes_(-1),
      limit_in_bytes_(-1),
      start_order_(0),
      args_(args) {
    onrestart_.InitSingleTrigger("onrestart");
}
      args_(args) {}

void Service::NotifyStateChange(const std::string& new_state) const {
    if ((flags_ & SVC_TEMPORARY) != 0) {