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, "Invalid 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
Prepare()54 int32_t StartupTaskManager::Prepare()
55 {
56 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u, task number: %{public}zu", startupTaskManagerId_, tasks_.size());
57 std::shared_ptr<StartupSortResult> startupSortResult = nullptr;
58 int32_t result = StartupTopologySort::Sort(tasks_, startupSortResult);
59 if (result != ERR_OK) {
60 CallListenerOnCompleted(result);
61 return result;
62 }
63 if (startupSortResult == nullptr) {
64 TAG_LOGE(AAFwkTag::STARTUP, "startupSortResult null");
65 CallListenerOnCompleted(ERR_STARTUP_INTERNAL_ERROR);
66 return ERR_STARTUP_INTERNAL_ERROR;
67 }
68 if (tasks_.empty()) {
69 TAG_LOGE(AAFwkTag::STARTUP, "no tasks");
70 return ERR_STARTUP_INTERNAL_ERROR;
71 }
72 dispatcher_ = std::make_shared<StartupTaskDispatcher>(tasks_, startupSortResult);
73 return ERR_OK;
74 }
75
Run(const std::shared_ptr<OnCompletedCallback> & mainThreadAwaitCallback)76 int32_t StartupTaskManager::Run(const std::shared_ptr<OnCompletedCallback> &mainThreadAwaitCallback)
77 {
78 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u, task number: %{public}zu", startupTaskManagerId_, tasks_.size());
79 if (dispatcher_ == nullptr) {
80 TAG_LOGE(AAFwkTag::STARTUP, "dispatcher null");
81 CallListenerOnCompleted(ERR_STARTUP_INTERNAL_ERROR);
82 return ERR_STARTUP_INTERNAL_ERROR;
83 }
84 AddAsyncTimeoutTimer();
85 auto completedCallback = std::make_shared<OnCompletedCallback>(
86 [weak = weak_from_this()](const std::shared_ptr<StartupTaskResult> &result) {
87 auto startupTaskManager = weak.lock();
88 if (startupTaskManager == nullptr) {
89 TAG_LOGE(AAFwkTag::STARTUP, "startupTaskManager null");
90 return;
91 }
92 startupTaskManager->CancelAsyncTimeoutTimer();
93 if (result == nullptr) {
94 TAG_LOGE(AAFwkTag::STARTUP, "result null");
95 return;
96 }
97 startupTaskManager->CallListenerOnCompleted(result->GetResultCode(), result->GetResultMessage());
98 });
99
100 int32_t result = dispatcher_->Run(completedCallback, mainThreadAwaitCallback);
101 if (result != ERR_OK) {
102 CancelAsyncTimeoutTimer();
103 if (!completedCallback->IsCalled()) {
104 CallListenerOnCompleted(result);
105 }
106 return result;
107 }
108 return ERR_OK;
109 }
110
CallListenerOnCompleted(int32_t result,const std::string & resultMessage)111 void StartupTaskManager::CallListenerOnCompleted(int32_t result, const std::string &resultMessage)
112 {
113 if (config_ == nullptr) {
114 TAG_LOGI(AAFwkTag::STARTUP,
115 "id: %{public}u, config is null, result: %{public}d", startupTaskManagerId_, result);
116 return;
117 }
118 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}u, complete, result: %{public}d", startupTaskManagerId_, result);
119 if (resultMessage.empty()) {
120 auto startupTaskResult = std::make_shared<StartupTaskResult>(result, StartupUtils::GetErrorMessage(result));
121 config_->ListenerOnCompleted(startupTaskResult);
122 } else {
123 auto startupTaskResult = std::make_shared<StartupTaskResult>(result, resultMessage);
124 config_->ListenerOnCompleted(startupTaskResult);
125 }
126 DelayedSingleton<StartupManager>::GetInstance()->OnStartupTaskManagerComplete(startupTaskManagerId_);
127 }
128
AddAsyncTimeoutTimer()129 void StartupTaskManager::AddAsyncTimeoutTimer()
130 {
131 mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
132 if (mainHandler_ == nullptr) {
133 TAG_LOGE(AAFwkTag::STARTUP, "get mainHandler failed");
134 return;
135 }
136 int32_t timeoutMs = StartupConfig::DEFAULT_AWAIT_TIMEOUT_MS;
137 if (config_ != nullptr) {
138 timeoutMs = config_->GetAwaitTimeoutMs();
139 }
140 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}d, add timeout timer: %{public}d", startupTaskManagerId_, timeoutMs);
141 auto callback = [weak = weak_from_this()]() {
142 auto startupTaskManager = weak.lock();
143 if (startupTaskManager == nullptr) {
144 TAG_LOGE(AAFwkTag::STARTUP, "startupTaskManager null");
145 return;
146 }
147 startupTaskManager->OnTimeout();
148 };
149 mainHandler_->PostTask(callback, "StartupTaskManager_" + std::to_string(startupTaskManagerId_), timeoutMs);
150 }
151
CancelAsyncTimeoutTimer()152 void StartupTaskManager::CancelAsyncTimeoutTimer()
153 {
154 if (mainHandler_ == nullptr) {
155 TAG_LOGE(AAFwkTag::STARTUP, "get mainHandler failed");
156 return;
157 }
158 TAG_LOGD(AAFwkTag::STARTUP, "id: %{public}d, cancel timeout timer", startupTaskManagerId_);
159 mainHandler_->RemoveTask("StartupTaskManager_" + std::to_string(startupTaskManagerId_));
160 }
161
OnTimeout()162 void StartupTaskManager::OnTimeout()
163 {
164 CallListenerOnCompleted(ERR_STARTUP_TIMEOUT, StartupUtils::GetErrorMessage(ERR_STARTUP_TIMEOUT));
165 DelayedSingleton<StartupManager>::GetInstance()->OnStartupTaskManagerComplete(startupTaskManagerId_);
166 }
167 } // namespace AbilityRuntime
168 } // namespace OHOS
169