Home | History | Annotate | Download | only in init
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "action_manager.h"
     18 
     19 #include <android-base/logging.h>
     20 
     21 namespace android {
     22 namespace init {
     23 
     24 ActionManager::ActionManager() : current_command_(0) {}
     25 
     26 ActionManager& ActionManager::GetInstance() {
     27     static ActionManager instance;
     28     return instance;
     29 }
     30 
     31 void ActionManager::AddAction(std::unique_ptr<Action> action) {
     32     actions_.emplace_back(std::move(action));
     33 }
     34 
     35 void ActionManager::QueueEventTrigger(const std::string& trigger) {
     36     event_queue_.emplace(trigger);
     37 }
     38 
     39 void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
     40     event_queue_.emplace(std::make_pair(name, value));
     41 }
     42 
     43 void ActionManager::QueueAllPropertyActions() {
     44     QueuePropertyChange("", "");
     45 }
     46 
     47 void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
     48     auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
     49                                            std::map<std::string, std::string>{});
     50     std::vector<std::string> name_vector{name};
     51 
     52     action->AddCommand(func, name_vector, 0);
     53 
     54     event_queue_.emplace(action.get());
     55     actions_.emplace_back(std::move(action));
     56 }
     57 
     58 void ActionManager::ExecuteOneCommand() {
     59     // Loop through the event queue until we have an action to execute
     60     while (current_executing_actions_.empty() && !event_queue_.empty()) {
     61         for (const auto& action : actions_) {
     62             if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
     63                            event_queue_.front())) {
     64                 current_executing_actions_.emplace(action.get());
     65             }
     66         }
     67         event_queue_.pop();
     68     }
     69 
     70     if (current_executing_actions_.empty()) {
     71         return;
     72     }
     73 
     74     auto action = current_executing_actions_.front();
     75 
     76     if (current_command_ == 0) {
     77         std::string trigger_name = action->BuildTriggersString();
     78         LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
     79                   << ":" << action->line() << ")";
     80     }
     81 
     82     action->ExecuteOneCommand(current_command_);
     83 
     84     // If this was the last command in the current action, then remove
     85     // the action from the executing list.
     86     // If this action was oneshot, then also remove it from actions_.
     87     ++current_command_;
     88     if (current_command_ == action->NumCommands()) {
     89         current_executing_actions_.pop();
     90         current_command_ = 0;
     91         if (action->oneshot()) {
     92             auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
     93             actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
     94         }
     95     }
     96 }
     97 
     98 bool ActionManager::HasMoreCommands() const {
     99     return !current_executing_actions_.empty() || !event_queue_.empty();
    100 }
    101 
    102 void ActionManager::DumpState() const {
    103     for (const auto& a : actions_) {
    104         a->DumpState();
    105     }
    106 }
    107 
    108 void ActionManager::ClearQueue() {
    109     // We are shutting down so don't claim the oneshot builtin actions back
    110     current_executing_actions_ = {};
    111     event_queue_ = {};
    112     current_command_ = 0;
    113 }
    114 
    115 }  // namespace init
    116 }  // namespace android
    117