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_task_manager.h"
17
18 #include "hilog_tag_wrapper.h"
19 #include "startup_manager.h"
20 #include "startup_topologysort.h"
21
22 namespace OHOS {
23 namespace AbilityRuntime {
StartupTaskManager(uint32_t startupTaskManagerId,std::map<std::string,std::shared_ptr<StartupTask>> tasks)24 StartupTaskManager::StartupTaskManager(uint32_t startupTaskManagerId,
25 std::map<std::string, std::shared_ptr<StartupTask>> tasks)
26 : startupTaskManagerId_(startupTaskManagerId), tasks_(std::move(tasks))
27 {}
28
~StartupTaskManager()29 StartupTaskManager::~StartupTaskManager()
30 {
31 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u deconstruct", startupTaskManagerId_);
32 }
33
AddTask(const std::shared_ptr<StartupTask> & task)34 int32_t StartupTaskManager::AddTask(const std::shared_ptr<StartupTask> &task)
35 {
36 if (task == nullptr) {
37 TAG_LOGE(AAFwkTag::STARTUP, "null task");
38 return ERR_STARTUP_INVALID_VALUE;
39 }
40 std::string name = task->GetName();
41 auto result = tasks_.emplace(name, task);
42 if (!result.second) {
43 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s exist", name.c_str());
44 return ERR_STARTUP_INVALID_VALUE;
45 }
46 return ERR_OK;
47 }
48
SetConfig(const std::shared_ptr<StartupConfig> & config)49 void StartupTaskManager::SetConfig(const std::shared_ptr<StartupConfig> &config)
50 {
51 config_ = config;
52 }
53
GetStartupTaskCount() const54 size_t StartupTaskManager::GetStartupTaskCount() const
55 {
56 return tasks_.size();
57 }
58
Prepare()59 int32_t StartupTaskManager::Prepare()
60 {
61 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u, task number: %{public}zu", startupTaskManagerId_, tasks_.size());
62 std::shared_ptr<StartupSortResult> startupSortResult = nullptr;
63 int32_t result = StartupTopologySort::Sort(tasks_, startupSortResult);
64 if (result != ERR_OK) {
65 CallListenerOnCompleted(result);
66 return result;
67 }
68 if (startupSortResult == nullptr) {
69 TAG_LOGE(AAFwkTag::STARTUP, "null startupSortResult");
70 CallListenerOnCompleted(ERR_STARTUP_INTERNAL_ERROR);
71 return ERR_STARTUP_INTERNAL_ERROR;
72 }
73 if (tasks_.empty()) {
74 TAG_LOGE(AAFwkTag::STARTUP, "no tasks");
75 return ERR_STARTUP_INTERNAL_ERROR;
76 }
77 dispatcher_ = std::make_shared<StartupTaskDispatcher>(tasks_, startupSortResult);
78 return ERR_OK;
79 }
80
Run(const std::shared_ptr<OnCompletedCallback> & mainThreadAwaitCallback)81 int32_t StartupTaskManager::Run(const std::shared_ptr<OnCompletedCallback> &mainThreadAwaitCallback)
82 {
83 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u, task number: %{public}zu", startupTaskManagerId_, tasks_.size());
84 if (dispatcher_ == nullptr) {
85 TAG_LOGE(AAFwkTag::STARTUP, "null dispatcher");
86 CallListenerOnCompleted(ERR_STARTUP_INTERNAL_ERROR);
87 return ERR_STARTUP_INTERNAL_ERROR;
88 }
89 AddAsyncTimeoutTimer();
90
91 auto completedCallback = std::make_shared<OnCompletedCallback>(
92 [weak = weak_from_this()](const std::shared_ptr<StartupTaskResult> &result) {
93 auto startupTaskManager = weak.lock();
94 if (startupTaskManager == nullptr) {
95 TAG_LOGE(AAFwkTag::STARTUP, "null startupTaskManager");
96 return;
97 }
98 startupTaskManager->CancelAsyncTimeoutTimer();
99 if (result == nullptr) {
100 TAG_LOGE(AAFwkTag::STARTUP, "null result");
101 return;
102 }
103 startupTaskManager->CallListenerOnCompleted(result->GetResultCode(), result->GetResultMessage());
104 });
105
106 int32_t result = dispatcher_->Run(completedCallback, mainThreadAwaitCallback);
107 if (result != ERR_OK) {
108 CancelAsyncTimeoutTimer();
109 if (!completedCallback->IsCalled()) {
110 CallListenerOnCompleted(result);
111 }
112 return result;
113 }
114 return ERR_OK;
115 }
116
TimeoutStop()117 void StartupTaskManager::TimeoutStop()
118 {
119 if (dispatcher_ != nullptr) {
120 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}d is timeout stop", startupTaskManagerId_);
121 dispatcher_->TimeoutStop();
122 }
123 }
124
CallListenerOnCompleted(int32_t result,const std::string & resultMessage)125 void StartupTaskManager::CallListenerOnCompleted(int32_t result, const std::string &resultMessage)
126 {
127 if (config_ == nullptr) {
128 TAG_LOGI(AAFwkTag::STARTUP, "id: %{public}u, null config, result: %{public}d", startupTaskManagerId_, result);
129 return;
130 }
131 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u, complete, result: %{public}d", startupTaskManagerId_, result);
132 if (resultMessage.empty()) {
133 auto startupTaskResult = std::make_shared<StartupTaskResult>(result, StartupUtils::GetErrorMessage(result));
134 config_->ListenerOnCompleted(startupTaskResult);
135 } else {
136 auto startupTaskResult = std::make_shared<StartupTaskResult>(result, resultMessage);
137 config_->ListenerOnCompleted(startupTaskResult);
138 }
139 DelayedSingleton<StartupManager>::GetInstance()->OnStartupTaskManagerComplete(startupTaskManagerId_);
140 }
141
AddAsyncTimeoutTimer()142 void StartupTaskManager::AddAsyncTimeoutTimer()
143 {
144 mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
145 if (mainHandler_ == nullptr) {
146 TAG_LOGE(AAFwkTag::STARTUP, "null mainHandler");
147 return;
148 }
149 int32_t timeoutMs = StartupConfig::DEFAULT_AWAIT_TIMEOUT_MS;
150 if (config_ != nullptr) {
151 timeoutMs = config_->GetAwaitTimeoutMs();
152 }
153 if (timeoutMs == StartupConfig::NO_AWAIT_TIMEOUT) {
154 // some native tasks does not time out, no need to add timeout timer.
155 return;
156 }
157 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}d, add timeout timer: %{public}d", startupTaskManagerId_, timeoutMs);
158 auto callback = [weak = weak_from_this()]() {
159 auto startupTaskManager = weak.lock();
160 if (startupTaskManager == nullptr) {
161 TAG_LOGE(AAFwkTag::STARTUP, "null startupTaskManager");
162 return;
163 }
164 startupTaskManager->OnTimeout();
165 };
166 mainHandler_->PostTask(callback, "StartupTaskManager_" + std::to_string(startupTaskManagerId_), timeoutMs);
167 }
168
CancelAsyncTimeoutTimer()169 void StartupTaskManager::CancelAsyncTimeoutTimer()
170 {
171 if (mainHandler_ == nullptr) {
172 TAG_LOGE(AAFwkTag::STARTUP, "null mainHandler");
173 return;
174 }
175 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}d, cancel timeout timer", startupTaskManagerId_);
176 mainHandler_->RemoveTask("StartupTaskManager_" + std::to_string(startupTaskManagerId_));
177 }
178
OnTimeout()179 void StartupTaskManager::OnTimeout()
180 {
181 CallListenerOnCompleted(ERR_STARTUP_TIMEOUT, StartupUtils::GetErrorMessage(ERR_STARTUP_TIMEOUT));
182 DelayedSingleton<StartupManager>::GetInstance()->OnStartupTaskManagerComplete(startupTaskManagerId_);
183 }
184 } // namespace AbilityRuntime
185 } // namespace OHOS
186