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
ActionManager()24 ActionManager::ActionManager() : current_command_(0) {}
25
CheckAllCommands()26 size_t ActionManager::CheckAllCommands() {
27 size_t failures = 0;
28 for (const auto& action : actions_) {
29 failures += action->CheckAllCommands();
30 }
31 return failures;
32 }
33
GetInstance()34 ActionManager& ActionManager::GetInstance() {
35 static ActionManager instance;
36 return instance;
37 }
38
AddAction(std::unique_ptr<Action> action)39 void ActionManager::AddAction(std::unique_ptr<Action> action) {
40 actions_.emplace_back(std::move(action));
41 }
42
QueueEventTrigger(const std::string & trigger)43 void ActionManager::QueueEventTrigger(const std::string& trigger) {
44 auto lock = std::lock_guard{event_queue_lock_};
45 event_queue_.emplace(trigger);
46 }
47
QueuePropertyChange(const std::string & name,const std::string & value)48 void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
49 auto lock = std::lock_guard{event_queue_lock_};
50 event_queue_.emplace(std::make_pair(name, value));
51 }
52
QueueAllPropertyActions()53 void ActionManager::QueueAllPropertyActions() {
54 QueuePropertyChange("", "");
55 }
56
QueueBuiltinAction(BuiltinFunction func,const std::string & name)57 void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
58 auto lock = std::lock_guard{event_queue_lock_};
59 auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
60 std::map<std::string, std::string>{});
61 action->AddCommand(std::move(func), {name}, 0);
62
63 event_queue_.emplace(action.get());
64 actions_.emplace_back(std::move(action));
65 }
66
ExecuteOneCommand()67 void ActionManager::ExecuteOneCommand() {
68 {
69 auto lock = std::lock_guard{event_queue_lock_};
70 // Loop through the event queue until we have an action to execute
71 while (current_executing_actions_.empty() && !event_queue_.empty()) {
72 for (const auto& action : actions_) {
73 if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
74 event_queue_.front())) {
75 current_executing_actions_.emplace(action.get());
76 }
77 }
78 event_queue_.pop();
79 }
80 }
81
82 if (current_executing_actions_.empty()) {
83 return;
84 }
85
86 auto action = current_executing_actions_.front();
87
88 if (current_command_ == 0) {
89 std::string trigger_name = action->BuildTriggersString();
90 LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
91 << ":" << action->line() << ")";
92 }
93
94 action->ExecuteOneCommand(current_command_);
95
96 // If this was the last command in the current action, then remove
97 // the action from the executing list.
98 // If this action was oneshot, then also remove it from actions_.
99 ++current_command_;
100 if (current_command_ == action->NumCommands()) {
101 current_executing_actions_.pop();
102 current_command_ = 0;
103 if (action->oneshot()) {
104 auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
105 actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
106 actions_.end());
107 }
108 }
109 }
110
HasMoreCommands() const111 bool ActionManager::HasMoreCommands() const {
112 auto lock = std::lock_guard{event_queue_lock_};
113 return !current_executing_actions_.empty() || !event_queue_.empty();
114 }
115
DumpState() const116 void ActionManager::DumpState() const {
117 for (const auto& a : actions_) {
118 a->DumpState();
119 }
120 }
121
ClearQueue()122 void ActionManager::ClearQueue() {
123 auto lock = std::lock_guard{event_queue_lock_};
124 // We are shutting down so don't claim the oneshot builtin actions back
125 current_executing_actions_ = {};
126 event_queue_ = {};
127 current_command_ = 0;
128 }
129
130 } // namespace init
131 } // namespace android
132