blob: b45f5cd1871e112044387e9cfefeb7dc7deaee71 [file] [log] [blame]
Tom Cherry7fd3bc22018-02-13 15:36:14 -08001/*
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
Tom Cherry4772f1d2019-07-30 09:34:41 -070026size_t ActionManager::CheckAllCommands() {
27 size_t failures = 0;
28 for (const auto& action : actions_) {
29 failures += action->CheckAllCommands();
30 }
31 return failures;
32}
33
Tom Cherry7fd3bc22018-02-13 15:36:14 -080034ActionManager& ActionManager::GetInstance() {
35 static ActionManager instance;
36 return instance;
37}
38
39void ActionManager::AddAction(std::unique_ptr<Action> action) {
40 actions_.emplace_back(std::move(action));
41}
42
43void ActionManager::QueueEventTrigger(const std::string& trigger) {
Tom Cherryd2dab832020-01-29 14:09:24 -080044 auto lock = std::lock_guard{event_queue_lock_};
Tom Cherry7fd3bc22018-02-13 15:36:14 -080045 event_queue_.emplace(trigger);
46}
47
48void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
Tom Cherryd2dab832020-01-29 14:09:24 -080049 auto lock = std::lock_guard{event_queue_lock_};
Tom Cherry7fd3bc22018-02-13 15:36:14 -080050 event_queue_.emplace(std::make_pair(name, value));
51}
52
53void ActionManager::QueueAllPropertyActions() {
54 QueuePropertyChange("", "");
55}
56
57void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
Tom Cherryd2dab832020-01-29 14:09:24 -080058 auto lock = std::lock_guard{event_queue_lock_};
Tom Cherry9cbf5702018-02-13 16:24:51 -080059 auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
60 std::map<std::string, std::string>{});
Tom Cherry7c1d87e2019-07-10 11:18:24 -070061 action->AddCommand(std::move(func), {name}, 0);
Tom Cherry7fd3bc22018-02-13 15:36:14 -080062
63 event_queue_.emplace(action.get());
64 actions_.emplace_back(std::move(action));
65}
66
67void ActionManager::ExecuteOneCommand() {
Tom Cherryd2dab832020-01-29 14:09:24 -080068 {
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 }
Tom Cherry7fd3bc22018-02-13 15:36:14 -080077 }
Tom Cherryd2dab832020-01-29 14:09:24 -080078 event_queue_.pop();
Tom Cherry7fd3bc22018-02-13 15:36:14 -080079 }
Tom Cherry7fd3bc22018-02-13 15:36:14 -080080 }
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; };
Tom Cherry247ffbf2019-07-08 15:09:36 -0700105 actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
106 actions_.end());
Tom Cherry7fd3bc22018-02-13 15:36:14 -0800107 }
108 }
109}
110
111bool ActionManager::HasMoreCommands() const {
Tom Cherryd2dab832020-01-29 14:09:24 -0800112 auto lock = std::lock_guard{event_queue_lock_};
Tom Cherry7fd3bc22018-02-13 15:36:14 -0800113 return !current_executing_actions_.empty() || !event_queue_.empty();
114}
115
116void ActionManager::DumpState() const {
117 for (const auto& a : actions_) {
118 a->DumpState();
119 }
120}
121
122void ActionManager::ClearQueue() {
Tom Cherryd2dab832020-01-29 14:09:24 -0800123 auto lock = std::lock_guard{event_queue_lock_};
Tom Cherry7fd3bc22018-02-13 15:36:14 -0800124 // 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