1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "startup_manager.h"
17 
18 #include <set>
19 
20 #include "hilog_tag_wrapper.h"
21 
22 namespace OHOS {
23 namespace AbilityRuntime {
StartupManager()24 StartupManager::StartupManager()
25 {
26     mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
27 }
28 
29 StartupManager::~StartupManager() = default;
30 
RegisterStartupTask(const std::string & name,const std::shared_ptr<StartupTask> & startupTask)31 int32_t StartupManager::RegisterStartupTask(const std::string &name, const std::shared_ptr<StartupTask> &startupTask)
32 {
33     auto result = startupTasks_.emplace(name, startupTask);
34     if (!result.second) {
35         TAG_LOGE(AAFwkTag::STARTUP, "%{public}s exist", name.c_str());
36         return ERR_STARTUP_INVALID_VALUE;
37     }
38     return ERR_OK;
39 }
40 
BuildAutoStartupTaskManager(std::shared_ptr<StartupTaskManager> & startupTaskManager)41 int32_t StartupManager::BuildAutoStartupTaskManager(std::shared_ptr<StartupTaskManager> &startupTaskManager)
42 {
43     std::map<std::string, std::shared_ptr<StartupTask>> autoStartupTasks;
44     std::set<std::string> dependenciesSet;
45     for (auto &iter : startupTasks_) {
46         if (iter.second == nullptr) {
47             TAG_LOGE(AAFwkTag::STARTUP, "startup task null");
48             return ERR_STARTUP_INTERNAL_ERROR;
49         }
50         if (iter.second->GetIsExcludeFromAutoStart()) {
51             continue;
52         }
53         autoStartupTasks.emplace(iter.first, iter.second);
54         auto dependencies = iter.second->GetDependencies();
55         for (auto &dep : dependencies) {
56             dependenciesSet.insert(dep);
57         }
58     }
59     for (auto &dep : dependenciesSet) {
60         if (autoStartupTasks.find(dep) != autoStartupTasks.end()) {
61             continue;
62         }
63         TAG_LOGI(AAFwkTag::STARTUP, "try to add excludeFromAutoStart task: %{public}s", dep.c_str());
64         AddStartupTask(dep, autoStartupTasks);
65     }
66 
67     TAG_LOGD(AAFwkTag::STARTUP, "autoStartupTasksManager build, id: %{public}u, tasks num: %{public}zu",
68         startupTaskManagerId, autoStartupTasks.size());
69     startupTaskManager = std::make_shared<StartupTaskManager>(startupTaskManagerId, autoStartupTasks);
70     startupTaskManager->SetConfig(defaultConfig_);
71     startupTaskManagerMap_.emplace(startupTaskManagerId, startupTaskManager);
72     startupTaskManagerId++;
73     return ERR_OK;
74 }
75 
BuildStartupTaskManager(const std::vector<std::string> & inputDependencies,std::shared_ptr<StartupTaskManager> & startupTaskManager)76 int32_t StartupManager::BuildStartupTaskManager(const std::vector<std::string> &inputDependencies,
77     std::shared_ptr<StartupTaskManager> &startupTaskManager)
78 {
79     std::map<std::string, std::shared_ptr<StartupTask>> currentStartupTasks;
80     std::set<std::string> dependenciesSet;
81     for (auto &iter : inputDependencies) {
82         auto findResult = startupTasks_.find(iter);
83         if (findResult == startupTasks_.end()) {
84             TAG_LOGE(AAFwkTag::STARTUP, "startup task %{public}s not found", iter.c_str());
85             return ERR_STARTUP_DEPENDENCY_NOT_FOUND;
86         }
87         if (findResult->second == nullptr) {
88             TAG_LOGE(AAFwkTag::STARTUP, "%{public}s startup task null", iter.c_str());
89             return ERR_STARTUP_INTERNAL_ERROR;
90         }
91         currentStartupTasks.emplace(iter, findResult->second);
92         auto dependencies = findResult->second->GetDependencies();
93         for (auto &dep : dependencies) {
94             dependenciesSet.insert(dep);
95         }
96     }
97 
98     for (auto &dep : dependenciesSet) {
99         if (currentStartupTasks.find(dep) != currentStartupTasks.end()) {
100             continue;
101         }
102         AddStartupTask(dep, currentStartupTasks);
103     }
104     TAG_LOGD(AAFwkTag::STARTUP, "startupTasksManager build, id: %{public}u, tasks num: %{public}zu",
105         startupTaskManagerId, currentStartupTasks.size());
106     startupTaskManager = std::make_shared<StartupTaskManager>(startupTaskManagerId, currentStartupTasks);
107     startupTaskManager->SetConfig(defaultConfig_);
108     startupTaskManagerMap_.emplace(startupTaskManagerId, startupTaskManager);
109     startupTaskManagerId++;
110     return ERR_OK;
111 }
112 
OnStartupTaskManagerComplete(uint32_t id)113 int32_t StartupManager::OnStartupTaskManagerComplete(uint32_t id)
114 {
115     auto result = startupTaskManagerMap_.find(id);
116     if (result == startupTaskManagerMap_.end()) {
117         TAG_LOGE(AAFwkTag::STARTUP, "StartupTaskManager id: %{public}u not found", id);
118         return ERR_STARTUP_INTERNAL_ERROR;
119     }
120     TAG_LOGD(AAFwkTag::STARTUP, "erase StartupTaskManager id: %{public}u", id);
121     startupTaskManagerMap_.erase(result);
122     return ERR_OK;
123 }
124 
SetDefaultConfig(const std::shared_ptr<StartupConfig> & config)125 void StartupManager::SetDefaultConfig(const std::shared_ptr<StartupConfig> &config)
126 {
127     defaultConfig_ = config;
128 }
129 
GetDefaultConfig() const130 const std::shared_ptr<StartupConfig>& StartupManager::GetDefaultConfig() const
131 {
132     return defaultConfig_;
133 }
134 
RemoveAllResult()135 int32_t StartupManager::RemoveAllResult()
136 {
137     TAG_LOGD(AAFwkTag::STARTUP, "called");
138     for (auto &iter : startupTasks_) {
139         if (iter.second != nullptr) {
140             iter.second->RemoveResult();
141         }
142     }
143     return ERR_OK;
144 }
145 
RemoveResult(const std::string & name)146 int32_t StartupManager::RemoveResult(const std::string &name)
147 {
148     TAG_LOGD(AAFwkTag::STARTUP, "called, name: %{public}s", name.c_str());
149     auto findResult = startupTasks_.find(name);
150     if (findResult == startupTasks_.end() || findResult->second == nullptr) {
151         TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not found", name.c_str());
152         return ERR_STARTUP_INVALID_VALUE;
153     }
154     return findResult->second->RemoveResult();
155 }
156 
GetResult(const std::string & name,std::shared_ptr<StartupTaskResult> & result)157 int32_t StartupManager::GetResult(const std::string &name, std::shared_ptr<StartupTaskResult> &result)
158 {
159     TAG_LOGD(AAFwkTag::STARTUP, "called, name: %{public}s", name.c_str());
160     auto findResult = startupTasks_.find(name);
161     if (findResult == startupTasks_.end() || findResult->second == nullptr) {
162         TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not found", name.c_str());
163         return ERR_STARTUP_INVALID_VALUE;
164     }
165     StartupTask::State state = findResult->second->GetState();
166     if (state != StartupTask::State::INITIALIZED) {
167         TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not initialized", name.c_str());
168         return ERR_STARTUP_INVALID_VALUE;
169     }
170     result = findResult->second->GetResult();
171     return ERR_OK;
172 }
173 
IsInitialized(const std::string & name,bool & isInitialized)174 int32_t StartupManager::IsInitialized(const std::string &name, bool &isInitialized)
175 {
176     TAG_LOGD(AAFwkTag::STARTUP, "called, name: %{public}s", name.c_str());
177     auto findResult = startupTasks_.find(name);
178     if (findResult == startupTasks_.end() || findResult->second == nullptr) {
179         TAG_LOGE(AAFwkTag::STARTUP, "%{public}s, not found", name.c_str());
180         return ERR_STARTUP_INVALID_VALUE;
181     }
182     StartupTask::State state = findResult->second->GetState();
183     isInitialized = state == StartupTask::State::INITIALIZED;
184     return ERR_OK;
185 }
186 
PostMainThreadTask(const std::function<void ()> & task)187 int32_t StartupManager::PostMainThreadTask(const std::function<void()> &task)
188 {
189     if (mainHandler_ == nullptr) {
190         TAG_LOGE(AAFwkTag::STARTUP, "get mainHandler failed");
191         return ERR_STARTUP_INTERNAL_ERROR;
192     }
193     mainHandler_->PostTask(task);
194     return ERR_OK;
195 }
196 
AddStartupTask(const std::string & name,std::map<std::string,std::shared_ptr<StartupTask>> & taskMap)197 int32_t StartupManager::AddStartupTask(const std::string &name,
198     std::map<std::string, std::shared_ptr<StartupTask>> &taskMap)
199 {
200     auto isAdded = taskMap.find(name);
201     if (isAdded != taskMap.end()) {
202         // already added
203         return ERR_OK;
204     }
205     std::stack<std::string> taskStack;
206     taskStack.push(name);
207     while (!taskStack.empty()) {
208         auto taskName = taskStack.top();
209         taskStack.pop();
210         auto findResult = startupTasks_.find(taskName);
211         if (findResult == startupTasks_.end()) {
212             TAG_LOGE(AAFwkTag::STARTUP, "startup task not found %{public}s", taskName.c_str());
213             return ERR_STARTUP_DEPENDENCY_NOT_FOUND;
214         }
215         taskMap.emplace(taskName, findResult->second);
216         if (findResult->second == nullptr) {
217             TAG_LOGE(AAFwkTag::STARTUP, "null task:%{public}s", taskName.c_str());
218             return ERR_STARTUP_INTERNAL_ERROR;
219         }
220         auto dependencies = findResult->second->GetDependencies();
221         for (auto &dep : dependencies) {
222             if (taskMap.find(dep) == taskMap.end()) {
223                 taskStack.push(dep);
224             }
225         }
226     }
227     return ERR_OK;
228 }
229 } // namespace AbilityRuntime
230 } // namespace OHOS
231