• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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