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