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