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 21namespace android { 22namespace init { 23 24ActionManager::ActionManager() : current_command_(0) {} 25 26ActionManager& ActionManager::GetInstance() { 27 static ActionManager instance; 28 return instance; 29} 30 31void ActionManager::AddAction(std::unique_ptr<Action> action) { 32 actions_.emplace_back(std::move(action)); 33} 34 35void ActionManager::QueueEventTrigger(const std::string& trigger) { 36 event_queue_.emplace(trigger); 37} 38 39void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) { 40 event_queue_.emplace(std::make_pair(name, value)); 41} 42 43void ActionManager::QueueAllPropertyActions() { 44 QueuePropertyChange("", ""); 45} 46 47void 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 58void 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 98bool ActionManager::HasMoreCommands() const { 99 return !current_executing_actions_.empty() || !event_queue_.empty(); 100} 101 102void ActionManager::DumpState() const { 103 for (const auto& a : actions_) { 104 a->DumpState(); 105 } 106} 107 108void 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