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 <fstream>
19 #include <set>
20 #include <nlohmann/json.hpp>
21
22 #include "app_startup_task_matcher.h"
23 #include "config_policy_utils.h"
24 #include "event_report.h"
25 #include "hilog_tag_wrapper.h"
26 #include "extractor.h"
27 #include "hitrace_meter.h"
28 #include "native_startup_task.h"
29 #include "preload_system_so_startup_task.h"
30 #include "preload_so_startup_task.h"
31 #include "startup_utils.h"
32
33 namespace OHOS {
34 namespace AbilityRuntime {
35 namespace {
36 constexpr char LOAD_APP_STARTUP_CONFIG_TASK[] = "_LoadAppStartupConfigTask";
37 constexpr char APP_AUTO_PRELOAD_SO_TASK[] = "_AppPreloadSoTask";
38 constexpr char APP_PRELOAD_SO_TASK[] = "_AppLoadSoTask";
39 constexpr const char* PROFILE_FILE_PREFIX = "$profile:";
40 constexpr const char* PROFILE_PATH = "resources/base/profile/";
41 constexpr const char* JSON_SUFFIX = ".json";
42 constexpr const char* STARTUP_TASKS = "startupTasks";
43 constexpr const char* PRELOAD_STARTUP_TASKS = "appPreloadHintStartupTasks";
44 constexpr const char* NAME = "name";
45 constexpr const char* SRC_ENTRY = "srcEntry";
46 constexpr const char* DEPENDENCIES = "dependencies";
47 constexpr const char* EXCLUDE_FROM_AUTO_START = "excludeFromAutoStart";
48 constexpr const char* RUN_ON_THREAD = "runOnThread";
49 constexpr const char* WAIT_ON_MAIN_THREAD = "waitOnMainThread";
50 constexpr const char* CONFIG_ENTRY = "configEntry";
51 constexpr const char* TASK_POOL = "taskPool";
52 constexpr const char* TASK_POOL_LOWER = "taskpool";
53 constexpr const char* MAIN_THREAD = "mainThread";
54 constexpr const char* OHMURL = "ohmurl";
55 constexpr const char* MATCH_RULES = "matchRules";
56 constexpr const char* URIS = "uris";
57 constexpr const char* INSIGHT_INTENTS = "insightIntents";
58 constexpr const char* ACTIONS = "actions";
59 constexpr const char* CUSTOMIZATION = "customization";
60 constexpr const char* PRELOAD_SYSTEM_SO_STARTUP_TASKS = "systemPreloadHintStartupTasks";
61 constexpr const char* PRELOAD_SYSTEM_SO_ALLOWLIST_FILE_PATH = "/etc/ability_runtime_app_startup.json";
62 constexpr const char* SYSTEM_PRELOAD_SO_ALLOW_LIST = "systemPreloadSoAllowList";
63
64 struct StartupTaskResultCallbackInfo {
65 std::unique_ptr<StartupTaskResultCallback> callback_;
66
StartupTaskResultCallbackInfoOHOS::AbilityRuntime::__anone28aee6c0111::StartupTaskResultCallbackInfo67 explicit StartupTaskResultCallbackInfo(std::unique_ptr<StartupTaskResultCallback> callback)
68 : callback_(std::move(callback))
69 {
70 }
71 };
72 } // namespace
73
ModuleStartupConfigInfo(std::string name,std::string startupConfig,std::string hapPath,const AppExecFwk::ModuleType & moduleType,bool esModule)74 ModuleStartupConfigInfo::ModuleStartupConfigInfo(std::string name, std::string startupConfig, std::string hapPath,
75 const AppExecFwk::ModuleType& moduleType, bool esModule)
76 : name_(std::move(name)), startupConfig_(std::move(startupConfig)), hapPath_(std::move(hapPath)),
77 moduleType_(moduleType), esModule_(esModule)
78 {
79 }
80
StartupManager()81 StartupManager::StartupManager()
82 {
83 mainHandler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
84 }
85
86 StartupManager::~StartupManager() = default;
87
PreloadAppHintStartup(const AppExecFwk::BundleInfo & bundleInfo,const AppExecFwk::HapModuleInfo & preloadHapModuleInfo,const std::string & preloadModuleName,std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)88 int32_t StartupManager::PreloadAppHintStartup(const AppExecFwk::BundleInfo& bundleInfo,
89 const AppExecFwk::HapModuleInfo& preloadHapModuleInfo, const std::string &preloadModuleName,
90 std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)
91 {
92 moduleStartupConfigInfos_.clear();
93 if (preloadHapModuleInfo.appStartup.empty()) {
94 TAG_LOGD(AAFwkTag::STARTUP, "module no app startup config");
95 return ERR_OK;
96 }
97 bundleName_ = bundleInfo.name;
98 moduleStartupConfigInfos_.emplace_back(preloadHapModuleInfo.name, preloadHapModuleInfo.appStartup,
99 preloadHapModuleInfo.hapPath, preloadHapModuleInfo.moduleType,
100 preloadHapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE);
101 isModuleStartupConfigInited_.emplace(preloadHapModuleInfo.name);
102
103 for (const auto& module : bundleInfo.hapModuleInfos) {
104 if (module.appStartup.empty()) {
105 continue;
106 }
107 if (module.moduleType != AppExecFwk::ModuleType::SHARED) {
108 // ENTRY or FEATURE has been added.
109 continue;
110 }
111 moduleStartupConfigInfos_.emplace_back(module.name, module.appStartup, module.hapPath, module.moduleType,
112 module.compileMode == AppExecFwk::CompileMode::ES_MODULE);
113 }
114 preloadHandler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::Create());
115 if (preloadHandler_ == nullptr) {
116 TAG_LOGE(AAFwkTag::STARTUP, "failed to create handler");
117 return ERR_STARTUP_INTERNAL_ERROR;
118 }
119
120 if (preloadHapModuleInfo.name != preloadModuleName) {
121 TAG_LOGD(AAFwkTag::STARTUP, "preload module name: %{public}s", preloadModuleName.c_str());
122 return ERR_OK;
123 }
124 TAG_LOGD(AAFwkTag::STARTUP, "appStartup modules: %{public}zu", moduleStartupConfigInfos_.size());
125 preloadHandler_->PostTask([weak = weak_from_this(), data = startupTaskData]() {
126 auto self = weak.lock();
127 if (self == nullptr) {
128 TAG_LOGE(AAFwkTag::STARTUP, "self is null");
129 return;
130 }
131 self->PreloadAppHintStartupTask(data);
132 });
133 return ERR_OK;
134 }
135
BuildAutoAppStartupTaskManager(std::shared_ptr<AAFwk::Want> want,std::shared_ptr<StartupTaskManager> & startupTaskManager,const std::string & moduleName)136 int32_t StartupManager::BuildAutoAppStartupTaskManager(std::shared_ptr<AAFwk::Want> want,
137 std::shared_ptr<StartupTaskManager> &startupTaskManager, const std::string &moduleName)
138 {
139 std::map<std::string, std::shared_ptr<StartupTask>> autoStartupTasks;
140 std::set<std::string> dependenciesSet;
141
142 auto startupConfig = moduleConfigs_[moduleName];
143 bool filteredByFeature = false;
144 if (want) {
145 MatchRulesStartupTaskMatcher taskMatcher(want);
146 auto moduleMatcher = std::make_shared<ModuleStartStartupTaskMatcher>(moduleName);
147 taskMatcher.SetModuleMatcher(moduleMatcher);
148 if (startupConfig) {
149 TAG_LOGI(AAFwkTag::STARTUP, "customization: %{public}s", startupConfig->GetCustomization().c_str());
150 auto customizationMatcher =
151 std::make_shared<CustomizationStartupTaskMatcher>(startupConfig->GetCustomization());
152 taskMatcher.SetCustomizationMatcher(customizationMatcher);
153 }
154 filteredByFeature = FilterMatchedStartupTask(taskMatcher, appStartupTasks_, autoStartupTasks, dependenciesSet);
155 }
156 if (!filteredByFeature) {
157 DefaultStartupTaskMatcher taskMatcher(moduleName);
158 FilterMatchedStartupTask(taskMatcher, appStartupTasks_, autoStartupTasks, dependenciesSet);
159 }
160
161 for (auto &dep : dependenciesSet) {
162 if (autoStartupTasks.find(dep) != autoStartupTasks.end()) {
163 continue;
164 }
165 TAG_LOGI(AAFwkTag::STARTUP, "try to add excludeFromAutoStart task: %{public}s", dep.c_str());
166 AddStartupTask(dep, autoStartupTasks, appStartupTasks_);
167 }
168
169 std::lock_guard guard(startupTaskManagerMutex_);
170 TAG_LOGD(AAFwkTag::STARTUP, "autoStartupTasksManager build, id: %{public}u, tasks num: %{public}zu",
171 startupTaskManagerId, autoStartupTasks.size());
172 startupTaskManager = std::make_shared<StartupTaskManager>(startupTaskManagerId, autoStartupTasks);
173 startupTaskManager->SetConfig(startupConfig);
174 startupTaskManagerMap_.emplace(startupTaskManagerId, startupTaskManager);
175 startupTaskManagerId++;
176 return ERR_OK;
177 }
178
FilterMatchedStartupTask(const AppStartupTaskMatcher & taskMatcher,const std::map<std::string,std::shared_ptr<AppStartupTask>> & inTasks,std::map<std::string,std::shared_ptr<StartupTask>> & outTasks,std::set<std::string> & dependenciesSet)179 bool StartupManager::FilterMatchedStartupTask(const AppStartupTaskMatcher &taskMatcher,
180 const std::map<std::string, std::shared_ptr<AppStartupTask>> &inTasks,
181 std::map<std::string, std::shared_ptr<StartupTask>> &outTasks,
182 std::set<std::string> &dependenciesSet)
183 {
184 bool filterResult = false;
185 for (const auto &iter : inTasks) {
186 if (!iter.second) {
187 TAG_LOGE(AAFwkTag::STARTUP, "null task");
188 continue;
189 }
190 if (!taskMatcher.Match(*iter.second)) {
191 continue;
192 }
193
194 TAG_LOGD(AAFwkTag::STARTUP, "match task:%{public}s", iter.second->GetName().c_str());
195 outTasks.emplace(iter.first, iter.second);
196 auto dependencies = iter.second->GetDependencies();
197 for (auto &dep : dependencies) {
198 dependenciesSet.insert(dep);
199 }
200 filterResult = true;
201 }
202 TAG_LOGI(AAFwkTag::STARTUP, "matched task count:%{public}zu", outTasks.size());
203 return filterResult;
204 }
205
LoadAppStartupTaskConfig(bool & needRunAutoStartupTask)206 int32_t StartupManager::LoadAppStartupTaskConfig(bool &needRunAutoStartupTask)
207 {
208 needRunAutoStartupTask = false;
209 if (moduleStartupConfigInfos_.empty()) {
210 return ERR_OK;
211 }
212 int32_t result = RunLoadAppStartupConfigTask();
213 if (result != ERR_OK) {
214 return result;
215 }
216 if (pendingStartupTaskInfos_.empty()) {
217 TAG_LOGD(AAFwkTag::STARTUP, "no app startup task");
218 return ERR_OK;
219 }
220 needRunAutoStartupTask = true;
221 return ERR_OK;
222 }
223
BuildAppStartupTaskManager(const std::vector<std::string> & inputDependencies,std::shared_ptr<StartupTaskManager> & startupTaskManager,bool supportFeatureModule)224 int32_t StartupManager::BuildAppStartupTaskManager(const std::vector<std::string> &inputDependencies,
225 std::shared_ptr<StartupTaskManager> &startupTaskManager, bool supportFeatureModule)
226 {
227 std::map<std::string, std::shared_ptr<StartupTask>> currentStartupTasks;
228 std::set<std::string> dependenciesSet;
229 std::vector<std::string> preloadSoTaskName;
230 for (auto &iter : inputDependencies) {
231 auto findResult = appStartupTasks_.find(iter);
232 if (findResult == appStartupTasks_.end()) {
233 // Not found in appStartupTasks_, tried later in preloadSoStartupTasks_
234 preloadSoTaskName.emplace_back(iter);
235 continue;
236 }
237 if (findResult->second == nullptr) {
238 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s startup task null", iter.c_str());
239 return ERR_STARTUP_INTERNAL_ERROR;
240 }
241 if (!supportFeatureModule && findResult->second->GetModuleType() == AppExecFwk::ModuleType::FEATURE) {
242 TAG_LOGE(AAFwkTag::STARTUP, "manual task of feature type is not supported");
243 return ERR_STARTUP_DEPENDENCY_NOT_FOUND;
244 }
245 currentStartupTasks.emplace(iter, findResult->second);
246 auto dependencies = findResult->second->GetDependencies();
247 for (auto &dep : dependencies) {
248 dependenciesSet.insert(dep);
249 }
250 }
251 for (auto &dep : dependenciesSet) {
252 if (currentStartupTasks.find(dep) != currentStartupTasks.end()) {
253 continue;
254 }
255 AddStartupTask(dep, currentStartupTasks, appStartupTasks_);
256 }
257
258 int32_t result = AddAppPreloadSoTask(preloadSoTaskName, currentStartupTasks);
259 if (result != ERR_OK) {
260 return result;
261 }
262
263 std::lock_guard guard(startupTaskManagerMutex_);
264 TAG_LOGD(AAFwkTag::STARTUP, "startupTasksManager build, id: %{public}u, tasks num: %{public}zu",
265 startupTaskManagerId, currentStartupTasks.size());
266 startupTaskManager = std::make_shared<StartupTaskManager>(startupTaskManagerId, currentStartupTasks);
267 startupTaskManager->SetConfig(defaultConfig_);
268 startupTaskManagerMap_.emplace(startupTaskManagerId, startupTaskManager);
269 startupTaskManagerId++;
270 return ERR_OK;
271 }
272
OnStartupTaskManagerComplete(uint32_t id)273 int32_t StartupManager::OnStartupTaskManagerComplete(uint32_t id)
274 {
275 std::lock_guard guard(startupTaskManagerMutex_);
276 auto result = startupTaskManagerMap_.find(id);
277 if (result == startupTaskManagerMap_.end()) {
278 TAG_LOGE(AAFwkTag::STARTUP, "StartupTaskManager id: %{public}u not found", id);
279 return ERR_STARTUP_INTERNAL_ERROR;
280 }
281 TAG_LOGD(AAFwkTag::STARTUP, "erase StartupTaskManager id: %{public}u", id);
282 startupTaskManagerMap_.erase(result);
283 return ERR_OK;
284 }
285
SetModuleConfig(const std::shared_ptr<StartupConfig> & config,const std::string & moduleName,bool isDefaultConfig=false)286 void StartupManager::SetModuleConfig(const std::shared_ptr<StartupConfig> &config, const std::string &moduleName,
287 bool isDefaultConfig = false)
288 {
289 moduleConfigs_[moduleName] = config;
290 if (isDefaultConfig) {
291 defaultConfig_ = config;
292 }
293 }
294
SetDefaultConfig(const std::shared_ptr<StartupConfig> & config)295 void StartupManager::SetDefaultConfig(const std::shared_ptr<StartupConfig> &config)
296 {
297 defaultConfig_ = config;
298 }
299
GetDefaultConfig() const300 const std::shared_ptr<StartupConfig>& StartupManager::GetDefaultConfig() const
301 {
302 return defaultConfig_;
303 }
304
RemoveAllResult()305 int32_t StartupManager::RemoveAllResult()
306 {
307 TAG_LOGD(AAFwkTag::STARTUP, "called");
308 for (auto &iter : appStartupTasks_) {
309 if (iter.second != nullptr) {
310 iter.second->RemoveResult();
311 }
312 }
313 for (auto &iter: preloadSoStartupTasks_) {
314 if (iter.second != nullptr) {
315 iter.second->RemoveResult();
316 }
317 }
318 return ERR_OK;
319 }
320
RemoveResult(const std::string & name)321 int32_t StartupManager::RemoveResult(const std::string &name)
322 {
323 TAG_LOGD(AAFwkTag::STARTUP, "called, name: %{public}s", name.c_str());
324 auto findResult = appStartupTasks_.find(name);
325 if (findResult == appStartupTasks_.end() || findResult->second == nullptr) {
326 findResult = preloadSoStartupTasks_.find(name);
327 if (findResult == preloadSoStartupTasks_.end() || findResult->second == nullptr) {
328 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not found", name.c_str());
329 return ERR_STARTUP_INVALID_VALUE;
330 }
331 }
332 return findResult->second->RemoveResult();
333 }
334
GetResult(const std::string & name,std::shared_ptr<StartupTaskResult> & result)335 int32_t StartupManager::GetResult(const std::string &name, std::shared_ptr<StartupTaskResult> &result)
336 {
337 TAG_LOGD(AAFwkTag::STARTUP, "called, name: %{public}s", name.c_str());
338 auto findResult = appStartupTasks_.find(name);
339 if (findResult == appStartupTasks_.end() || findResult->second == nullptr) {
340 findResult = preloadSoStartupTasks_.find(name);
341 if (findResult == preloadSoStartupTasks_.end() || findResult->second == nullptr) {
342 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not found", name.c_str());
343 return ERR_STARTUP_INVALID_VALUE;
344 }
345 }
346 StartupTask::State state = findResult->second->GetState();
347 if (state != StartupTask::State::INITIALIZED) {
348 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not initialized", name.c_str());
349 return ERR_STARTUP_INVALID_VALUE;
350 }
351 result = findResult->second->GetResult();
352 return ERR_OK;
353 }
354
IsInitialized(const std::string & name,bool & isInitialized)355 int32_t StartupManager::IsInitialized(const std::string &name, bool &isInitialized)
356 {
357 TAG_LOGD(AAFwkTag::STARTUP, "called, name: %{public}s", name.c_str());
358 auto findResult = appStartupTasks_.find(name);
359 if (findResult == appStartupTasks_.end() || findResult->second == nullptr) {
360 findResult = preloadSoStartupTasks_.find(name);
361 if (findResult == preloadSoStartupTasks_.end() || findResult->second == nullptr) {
362 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s not found", name.c_str());
363 return ERR_STARTUP_INVALID_VALUE;
364 }
365 }
366 StartupTask::State state = findResult->second->GetState();
367 isInitialized = state == StartupTask::State::INITIALIZED;
368 return ERR_OK;
369 }
370
PostMainThreadTask(const std::function<void ()> & task)371 int32_t StartupManager::PostMainThreadTask(const std::function<void()> &task)
372 {
373 if (mainHandler_ == nullptr) {
374 TAG_LOGE(AAFwkTag::STARTUP, "null mainHandler");
375 return ERR_STARTUP_INTERNAL_ERROR;
376 }
377 mainHandler_->PostTask(task);
378 return ERR_OK;
379 }
380
StopAutoPreloadSoTask()381 void StartupManager::StopAutoPreloadSoTask()
382 {
383 std::lock_guard guard(autoPreloadSoTaskManagerMutex_);
384 autoPreloadSoStopped_ = true;
385 auto task = autoPreloadSoTaskManager_.lock();
386 if (task != nullptr) {
387 task->TimeoutStop();
388 }
389 auto systemSoTask = autoPreloadSystemSoTaskManager_.lock();
390 if (systemSoTask != nullptr) {
391 systemSoTask->TimeoutStop();
392 }
393 }
394
HasAppStartupConfig() const395 bool StartupManager::HasAppStartupConfig() const
396 {
397 return !moduleStartupConfigInfos_.empty();
398 }
399
GetStartupTaskInfos(const std::string & name)400 const std::vector<StartupTaskInfo> StartupManager::GetStartupTaskInfos(const std::string &name)
401 {
402 if (!isAppStartupTaskRegistered_) {
403 isAppStartupTaskRegistered_ = true;
404 return pendingStartupTaskInfos_;
405 }
406 std::vector<StartupTaskInfo> pendingStartupTaskInfos;
407 for (const auto &iter : pendingStartupTaskInfos_) {
408 if (iter.moduleName == name) {
409 pendingStartupTaskInfos.emplace_back(iter);
410 }
411 }
412 return pendingStartupTaskInfos;
413 }
414
GetPendingConfigEntry() const415 const std::string &StartupManager::GetPendingConfigEntry() const
416 {
417 return pendingConfigEntry_;
418 }
419
AddStartupTask(const std::string & name,std::map<std::string,std::shared_ptr<StartupTask>> & taskMap,std::map<std::string,std::shared_ptr<AppStartupTask>> & allTasks)420 int32_t StartupManager::AddStartupTask(const std::string &name,
421 std::map<std::string, std::shared_ptr<StartupTask>> &taskMap,
422 std::map<std::string, std::shared_ptr<AppStartupTask>> &allTasks)
423 {
424 auto isAdded = taskMap.find(name);
425 if (isAdded != taskMap.end()) {
426 // already added
427 return ERR_OK;
428 }
429 std::stack<std::string> taskStack;
430 taskStack.push(name);
431 while (!taskStack.empty()) {
432 auto taskName = taskStack.top();
433 taskStack.pop();
434 auto findResult = allTasks.find(taskName);
435 if (findResult == allTasks.end()) {
436 TAG_LOGE(AAFwkTag::STARTUP, "startup task not found %{public}s", taskName.c_str());
437 return ERR_STARTUP_DEPENDENCY_NOT_FOUND;
438 }
439 taskMap.emplace(taskName, findResult->second);
440 if (findResult->second == nullptr) {
441 TAG_LOGE(AAFwkTag::STARTUP, "null task:%{public}s", taskName.c_str());
442 return ERR_STARTUP_INTERNAL_ERROR;
443 }
444 auto dependencies = findResult->second->GetDependencies();
445 for (auto &dep : dependencies) {
446 if (taskMap.find(dep) == taskMap.end()) {
447 taskStack.push(dep);
448 }
449 }
450 }
451 return ERR_OK;
452 }
453
RegisterPreloadSoStartupTask(const std::string & name,const std::shared_ptr<PreloadSoStartupTask> & startupTask)454 int32_t StartupManager::RegisterPreloadSoStartupTask(
455 const std::string &name, const std::shared_ptr<PreloadSoStartupTask> &startupTask)
456 {
457 auto findResult = appStartupTasks_.find(name);
458 if (findResult != appStartupTasks_.end()) {
459 TAG_LOGE(AAFwkTag::STARTUP, "exist app startup task %{public}s", name.c_str());
460 return ERR_STARTUP_INVALID_VALUE;
461 }
462
463 auto result = preloadSoStartupTasks_.emplace(name, startupTask);
464 if (!result.second) {
465 TAG_LOGE(AAFwkTag::STARTUP, "exist preload so startup task %{public}s", name.c_str());
466 return ERR_STARTUP_INVALID_VALUE;
467 }
468 return ERR_OK;
469 }
470
ClearAppStartupTask()471 void StartupManager::ClearAppStartupTask()
472 {
473 appStartupTasks_.clear();
474 }
475
RegisterAppStartupTask(const std::string & name,const std::shared_ptr<AppStartupTask> & startupTask)476 int32_t StartupManager::RegisterAppStartupTask(
477 const std::string &name, const std::shared_ptr<AppStartupTask> &startupTask)
478 {
479 auto findResult = preloadSoStartupTasks_.find(name);
480 if (findResult != preloadSoStartupTasks_.end()) {
481 TAG_LOGE(AAFwkTag::STARTUP, "exist preload so startup task %{public}s", name.c_str());
482 return ERR_STARTUP_INVALID_VALUE;
483 }
484 auto result = appStartupTasks_.emplace(name, startupTask);
485 if (!result.second) {
486 TAG_LOGE(AAFwkTag::STARTUP, "exist app startup task %{public}s", name.c_str());
487 return ERR_STARTUP_INVALID_VALUE;
488 }
489 return ERR_OK;
490 }
491
BuildStartupTaskManager(const std::map<std::string,std::shared_ptr<StartupTask>> & tasks,std::shared_ptr<StartupTaskManager> & startupTaskManager)492 int32_t StartupManager::BuildStartupTaskManager(const std::map<std::string, std::shared_ptr<StartupTask>> &tasks,
493 std::shared_ptr<StartupTaskManager> &startupTaskManager)
494 {
495 if (tasks.empty()) {
496 TAG_LOGE(AAFwkTag::STARTUP, "input tasks empty.");
497 return ERR_STARTUP_INTERNAL_ERROR;
498 }
499 std::lock_guard guard(startupTaskManagerMutex_);
500 startupTaskManager = std::make_shared<StartupTaskManager>(startupTaskManagerId, tasks);
501 if (startupTaskManager == nullptr) {
502 TAG_LOGE(AAFwkTag::STARTUP, "startupTaskManager is null.");
503 return ERR_STARTUP_INTERNAL_ERROR;
504 }
505 // does not time out and no complete callback
506 auto config = std::make_shared<StartupConfig>(StartupConfig::NO_AWAIT_TIMEOUT, nullptr);
507 startupTaskManager->SetConfig(config);
508 startupTaskManagerMap_.emplace(startupTaskManagerId, startupTaskManager);
509 TAG_LOGD(AAFwkTag::STARTUP, "build startup task manager, id: %{public}u, tasks num: %{public}zu",
510 startupTaskManagerId, tasks.size());
511 startupTaskManagerId++;
512 return ERR_OK;
513 }
514
AddAppPreloadSoTask(const std::vector<std::string> & preloadSoList,std::map<std::string,std::shared_ptr<StartupTask>> & currentStartupTasks)515 int32_t StartupManager::AddAppPreloadSoTask(const std::vector<std::string> &preloadSoList,
516 std::map<std::string, std::shared_ptr<StartupTask>> ¤tStartupTasks)
517 {
518 std::map<std::string, std::shared_ptr<StartupTask>> currentPreloadSoTasks;
519 std::set<std::string> dependenciesSet;
520 for (auto &iter : preloadSoList) {
521 auto findResult = preloadSoStartupTasks_.find(iter);
522 if (findResult == preloadSoStartupTasks_.end()) {
523 TAG_LOGE(AAFwkTag::STARTUP, "startup task %{public}s not found", iter.c_str());
524 return ERR_STARTUP_DEPENDENCY_NOT_FOUND;
525 }
526 if (findResult->second == nullptr) {
527 TAG_LOGE(AAFwkTag::STARTUP, "%{public}s startup task null", iter.c_str());
528 return ERR_STARTUP_INTERNAL_ERROR;
529 }
530 currentPreloadSoTasks.emplace(iter, findResult->second);
531 auto dependencies = findResult->second->GetDependencies();
532 for (auto &dep : dependencies) {
533 dependenciesSet.insert(dep);
534 }
535 }
536 for (auto &dep : dependenciesSet) {
537 if (currentPreloadSoTasks.find(dep) != currentPreloadSoTasks.end()) {
538 continue;
539 }
540 int32_t result = AddStartupTask(dep, currentPreloadSoTasks, preloadSoStartupTasks_);
541 if (result != ERR_OK) {
542 return result;
543 }
544 }
545 if (currentPreloadSoTasks.empty()) {
546 // no preload so tasks
547 return ERR_OK;
548 }
549 std::shared_ptr<NativeStartupTask> task = CreateAppPreloadSoTask(currentPreloadSoTasks);
550 if (task == nullptr) {
551 TAG_LOGE(AAFwkTag::STARTUP, "Failed to create load app startup config task");
552 return ERR_STARTUP_INTERNAL_ERROR;
553 }
554 task->SetCallCreateOnMainThread(true);
555 task->SetWaitOnMainThread(false);
556 currentStartupTasks.emplace(task->GetName(), task);
557 return ERR_OK;
558 }
559
CreateAppPreloadSoTask(const std::map<std::string,std::shared_ptr<StartupTask>> & currentTasks)560 std::shared_ptr<NativeStartupTask> StartupManager::CreateAppPreloadSoTask(
561 const std::map<std::string, std::shared_ptr<StartupTask>> ¤tTasks)
562 {
563 auto task = std::make_shared<NativeStartupTask>(APP_PRELOAD_SO_TASK,
564 [weak = weak_from_this(), currentTasks](std::unique_ptr<StartupTaskResultCallback> callback)-> int32_t {
565 auto self = weak.lock();
566 if (self == nullptr) {
567 TAG_LOGE(AAFwkTag::STARTUP, "self is null");
568 OnCompletedCallback::OnCallback(std::move(callback), ERR_STARTUP_INTERNAL_ERROR,
569 "add preload so task failed");
570 return ERR_STARTUP_INTERNAL_ERROR;
571 }
572 int32_t result = self->RunAppPreloadSoTaskMainThread(currentTasks, std::move(callback));
573 return result;
574 });
575 return task;
576 }
577
EnableLazyLoadingAppStartupTasks() const578 bool StartupManager::EnableLazyLoadingAppStartupTasks() const
579 {
580 return enableLazyLoadingAppStartupTasks_;
581 }
582
PreloadAppHintStartupTask(std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)583 void StartupManager::PreloadAppHintStartupTask(std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)
584 {
585 std::map<std::string, std::shared_ptr<StartupTask>> preloadAppHintTasks;
586 int32_t result = AddLoadAppStartupConfigTask(preloadAppHintTasks);
587 if (result != ERR_OK) {
588 return;
589 }
590 result = AddAppAutoPreloadSoTask(preloadAppHintTasks, startupTaskData);
591 if (result != ERR_OK) {
592 return;
593 }
594 std::shared_ptr<StartupTaskManager> startupTaskManager;
595 result = BuildStartupTaskManager(preloadAppHintTasks, startupTaskManager);
596 if (result != ERR_OK || startupTaskManager == nullptr) {
597 TAG_LOGE(AAFwkTag::STARTUP, "build preload startup task manager failed, result: %{public}d", result);
598 return;
599 }
600 result = startupTaskManager->Prepare();
601 if (result != ERR_OK) {
602 TAG_LOGE(AAFwkTag::STARTUP, "preload startup task manager prepare failed, result: %{public}d", result);
603 return;
604 }
605 TAG_LOGD(AAFwkTag::STARTUP, "preload startup task manager run");
606 startupTaskManager->Run(nullptr);
607 }
608
AddLoadAppStartupConfigTask(std::map<std::string,std::shared_ptr<StartupTask>> & preloadAppHintTasks)609 int32_t StartupManager::AddLoadAppStartupConfigTask(
610 std::map<std::string, std::shared_ptr<StartupTask>> &preloadAppHintTasks)
611 {
612 auto task = std::make_shared<NativeStartupTask>(LOAD_APP_STARTUP_CONFIG_TASK,
613 [weak = weak_from_this()](std::unique_ptr<StartupTaskResultCallback> callback)-> int32_t {
614 auto self = weak.lock();
615 if (self == nullptr) {
616 TAG_LOGE(AAFwkTag::STARTUP, "self is null");
617 OnCompletedCallback::OnCallback(std::move(callback), ERR_STARTUP_INTERNAL_ERROR,
618 "AddLoadAppStartupConfigTask failed");
619 return ERR_STARTUP_INTERNAL_ERROR;
620 }
621 int32_t result = self->RunLoadAppStartupConfigTask();
622 OnCompletedCallback::OnCallback(std::move(callback), result);
623 return result;
624 });
625 if (task == nullptr) {
626 TAG_LOGE(AAFwkTag::STARTUP, "Failed to create load app startup config task");
627 return ERR_STARTUP_INTERNAL_ERROR;
628 }
629 task->SetCallCreateOnMainThread(true);
630 task->SetWaitOnMainThread(true);
631 // no dependencies
632 preloadAppHintTasks.emplace(task->GetName(), task);
633 return ERR_OK;
634 }
635
RunLoadModuleStartupConfigTask(bool & needRunAutoStartupTask,const std::shared_ptr<AppExecFwk::HapModuleInfo> & hapModuleInfo)636 int32_t StartupManager::RunLoadModuleStartupConfigTask(
637 bool &needRunAutoStartupTask, const std::shared_ptr<AppExecFwk::HapModuleInfo>& hapModuleInfo)
638 {
639 if (isModuleStartupConfigInited_.count(hapModuleInfo->name) != 0) {
640 TAG_LOGD(AAFwkTag::STARTUP, "module startup config already loaded");
641 return ERR_OK;
642 }
643 ModuleStartupConfigInfo configInfo(hapModuleInfo->name, hapModuleInfo->appStartup, hapModuleInfo->hapPath,
644 hapModuleInfo->moduleType, hapModuleInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE);
645 if (hapModuleInfo->appStartup.empty()) {
646 TAG_LOGD(AAFwkTag::STARTUP, "module startup config is empty");
647 return ERR_OK;
648 }
649 TAG_LOGD(AAFwkTag::STARTUP, "load module %{public}s, type: %{public}d", hapModuleInfo->name.c_str(),
650 hapModuleInfo->moduleType);
651 std::string configStr;
652 int32_t result = GetStartupConfigString(configInfo, configStr);
653 if (result != ERR_OK) {
654 return result;
655 }
656 std::map<std::string, std::shared_ptr<AppStartupTask>> preloadSoStartupTasks;
657 std::map<std::string, std::shared_ptr<AppStartupTask>> preloadSystemSoStartupTasks;
658 std::vector<StartupTaskInfo> pendingStartupTaskInfos;
659 std::string pendingConfigEntry;
660 bool success = AnalyzeStartupConfig(configInfo, configStr, preloadSoStartupTasks,
661 preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry);
662 if (!success) {
663 TAG_LOGE(AAFwkTag::STARTUP, "failed to parse app startup module %{public}s, type: %{public}d",
664 configInfo.name_.c_str(), configInfo.moduleType_);
665 return ERR_STARTUP_CONFIG_PARSE_ERROR;
666 }
667 std::lock_guard guard(appStartupConfigInitializationMutex_);
668 preloadSoStartupTasks_.insert(preloadSoStartupTasks.begin(), preloadSoStartupTasks.end());
669 pendingStartupTaskInfos_.insert(pendingStartupTaskInfos_.end(), pendingStartupTaskInfos.begin(),
670 pendingStartupTaskInfos.end());
671 pendingConfigEntry_ = pendingConfigEntry;
672 isModuleStartupConfigInited_.emplace(hapModuleInfo->name);
673 if (!needRunAutoStartupTask && pendingConfigEntry.size() > 0) {
674 needRunAutoStartupTask = true;
675 }
676 return ERR_OK;
677 }
678
RunLoadAppStartupConfigTask()679 int32_t StartupManager::RunLoadAppStartupConfigTask()
680 {
681 if (isAppStartupConfigInited_) {
682 TAG_LOGD(AAFwkTag::STARTUP, "module startup config already loaded");
683 return ERR_OK;
684 }
685
686 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
687 InitPreloadSystemSoAllowlist();
688 std::map<std::string, std::shared_ptr<AppStartupTask>> preloadSoStartupTasks;
689 std::map<std::string, std::shared_ptr<AppStartupTask>> preloadSystemSoStartupTasks;
690 std::vector<StartupTaskInfo> pendingStartupTaskInfos;
691 std::string pendingConfigEntry;
692 for (const auto& item : moduleStartupConfigInfos_) {
693 if (item.startupConfig_.empty()) {
694 continue;
695 }
696 TAG_LOGD(AAFwkTag::STARTUP, "load module %{public}s, type: %{public}d", item.name_.c_str(), item.moduleType_);
697 std::string configStr;
698 int32_t result = GetStartupConfigString(item, configStr);
699 if (result != ERR_OK) {
700 return result;
701 }
702 bool success = AnalyzeStartupConfig(item, configStr, preloadSoStartupTasks,
703 preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry);
704 if (!success) {
705 TAG_LOGE(AAFwkTag::STARTUP, "failed to parse app startup module %{public}s, type: %{public}d",
706 item.name_.c_str(), item.moduleType_);
707 return ERR_STARTUP_CONFIG_PARSE_ERROR;
708 }
709 }
710
711 std::lock_guard guard(appStartupConfigInitializationMutex_);
712 if (isAppStartupConfigInited_) {
713 // double check
714 TAG_LOGD(AAFwkTag::STARTUP, "module startup config already loaded");
715 return ERR_OK;
716 }
717 preloadSoStartupTasks_ = preloadSoStartupTasks;
718 preloadSystemSoStartupTasks_ = preloadSystemSoStartupTasks;
719 pendingStartupTaskInfos_ = pendingStartupTaskInfos;
720 pendingConfigEntry_ = pendingConfigEntry;
721 isAppStartupConfigInited_ = true;
722 TAG_LOGI(AAFwkTag::STARTUP, "preload so: %{public}zu, app: %{public}zu",
723 preloadSoStartupTasks_.size(), pendingStartupTaskInfos_.size());
724 return ERR_OK;
725 }
726
AddAppAutoPreloadSoTask(std::map<std::string,std::shared_ptr<StartupTask>> & preloadAppHintTasks,std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)727 int32_t StartupManager::AddAppAutoPreloadSoTask(
728 std::map<std::string, std::shared_ptr<StartupTask>> &preloadAppHintTasks,
729 std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)
730 {
731 auto task = std::make_shared<NativeStartupTask>(APP_AUTO_PRELOAD_SO_TASK,
732 [weak = weak_from_this(), data = startupTaskData]
733 (std::unique_ptr<StartupTaskResultCallback> callback)-> int32_t {
734 auto self = weak.lock();
735 if (self == nullptr) {
736 TAG_LOGE(AAFwkTag::STARTUP, "self is null");
737 OnCompletedCallback::OnCallback(std::move(callback), ERR_STARTUP_INTERNAL_ERROR,
738 "AddAppAutoPreloadSoTask failed");
739 return ERR_STARTUP_INTERNAL_ERROR;
740 }
741 int32_t result = self->RunAppAutoPreloadSoTask(data);
742 self->RunAppAutoPreloadSystemSoTask();
743 OnCompletedCallback::OnCallback(std::move(callback), result);
744 return result;
745 });
746 if (task == nullptr) {
747 TAG_LOGE(AAFwkTag::STARTUP, "Failed to create app preload so task");
748 return ERR_STARTUP_INTERNAL_ERROR;
749 }
750 task->SetCallCreateOnMainThread(true);
751 task->SetWaitOnMainThread(true);
752 task->SetDependencies({ LOAD_APP_STARTUP_CONFIG_TASK });
753 preloadAppHintTasks.emplace(task->GetName(), task);
754 return ERR_OK;
755 }
756
RunAppAutoPreloadSoTask(std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)757 int32_t StartupManager::RunAppAutoPreloadSoTask(std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)
758 {
759 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
760 std::map<std::string, std::shared_ptr<StartupTask>> appAutoPreloadSoTasks;
761 int32_t result = GetAppAutoPreloadSoTasks(appAutoPreloadSoTasks, startupTaskData);
762 if (result != ERR_OK) {
763 return result;
764 }
765 if (appAutoPreloadSoTasks.empty()) {
766 TAG_LOGD(AAFwkTag::STARTUP, "no preload so startup task");
767 return ERR_OK;
768 }
769
770 return RunAppPreloadSoTask(appAutoPreloadSoTasks);
771 }
772
RunAppAutoPreloadSystemSoTask()773 int32_t StartupManager::RunAppAutoPreloadSystemSoTask()
774 {
775 if (preloadSystemSoStartupTasks_.empty()) {
776 TAG_LOGD(AAFwkTag::STARTUP, "no preload system so startup task");
777 return ERR_OK;
778 }
779
780 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
781 std::map<std::string, std::shared_ptr<StartupTask>> appAutoPreloadSystemSoTasks;
782 for (const auto& [name, task] : preloadSystemSoStartupTasks_) {
783 appAutoPreloadSystemSoTasks.emplace(name, task);
784 }
785
786 return RunAppPreloadSoTask(appAutoPreloadSystemSoTasks, true);
787 }
788
RunAppPreloadSoTask(const std::map<std::string,std::shared_ptr<StartupTask>> & appPreloadSoTasks,bool isSystemSo)789 int32_t StartupManager::RunAppPreloadSoTask(
790 const std::map<std::string, std::shared_ptr<StartupTask>> &appPreloadSoTasks, bool isSystemSo)
791 {
792 std::shared_ptr<StartupTaskManager> startupTaskManager;
793 int32_t result = BuildStartupTaskManager(appPreloadSoTasks, startupTaskManager);
794 if (result != ERR_OK || startupTaskManager == nullptr) {
795 TAG_LOGE(AAFwkTag::STARTUP, "build preload so startup task manager failed, result: %{public}d", result);
796 return ERR_STARTUP_INTERNAL_ERROR;
797 }
798 {
799 std::lock_guard guard(autoPreloadSoTaskManagerMutex_);
800 if (autoPreloadSoStopped_) {
801 TAG_LOGI(AAFwkTag::STARTUP, "auto preload so is stopped, remove startupTaskManager");
802 startupTaskManager->OnTimeout();
803 return ERR_STARTUP_TIMEOUT;
804 }
805 isSystemSo ? (autoPreloadSystemSoTaskManager_ = startupTaskManager)
806 : (autoPreloadSoTaskManager_ = startupTaskManager);
807 }
808
809 result = startupTaskManager->Prepare();
810 if (result != ERR_OK) {
811 TAG_LOGE(AAFwkTag::STARTUP, "preload so startup task manager prepare failed, result: %{public}d", result);
812 return result;
813 }
814 TAG_LOGI(AAFwkTag::STARTUP, "preload so startup task manager count: %{public}zu", appPreloadSoTasks.size());
815 result = startupTaskManager->Run(nullptr);
816 if (result != ERR_OK) {
817 TAG_LOGE(AAFwkTag::STARTUP, "preload so startup task manager run failed, result: %{public}d", result);
818 }
819 return result;
820 }
821
GetAppAutoPreloadSoTasks(std::map<std::string,std::shared_ptr<StartupTask>> & appAutoPreloadSoTasks,std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)822 int32_t StartupManager::GetAppAutoPreloadSoTasks(
823 std::map<std::string, std::shared_ptr<StartupTask>> &appAutoPreloadSoTasks,
824 std::shared_ptr<AppExecFwk::StartupTaskData> startupTaskData)
825 {
826 std::set<std::string> dependenciesSet;
827 bool filteredByFeature = false;
828 if (startupTaskData) {
829 TAG_LOGD(AAFwkTag::APPMGR,
830 "GetAppAutoPreloadSoTasks uri: %{public}s, action: %{public}s, intentName: %{public}s",
831 startupTaskData->uri.c_str(), startupTaskData->action.c_str(),
832 startupTaskData->insightIntentName.c_str());
833
834 MatchRulesStartupTaskMatcher taskMatcher(startupTaskData->uri, startupTaskData->action,
835 startupTaskData->insightIntentName);
836 filteredByFeature = FilterMatchedStartupTask(taskMatcher, preloadSoStartupTasks_, appAutoPreloadSoTasks,
837 dependenciesSet);
838 }
839 TAG_LOGI(AAFwkTag::APPMGR, "filteredByFeature:%{public}d", filteredByFeature);
840 if (!filteredByFeature) {
841 ExcludeFromAutoStartStartupTaskMatcher taskMatcher;
842 FilterMatchedStartupTask(taskMatcher, preloadSoStartupTasks_, appAutoPreloadSoTasks, dependenciesSet);
843 }
844
845 for (auto &dep : dependenciesSet) {
846 if (appAutoPreloadSoTasks.find(dep) != appAutoPreloadSoTasks.end()) {
847 continue;
848 }
849 TAG_LOGD(AAFwkTag::STARTUP, "try to add excludeFromAutoStart task: %{public}s", dep.c_str());
850 int32_t result = AddStartupTask(dep, appAutoPreloadSoTasks, preloadSoStartupTasks_);
851 if (result != ERR_OK) {
852 return result;
853 }
854 }
855 return ERR_OK;
856 }
857
RunAppPreloadSoTaskMainThread(const std::map<std::string,std::shared_ptr<StartupTask>> & appPreloadSoTasks,std::unique_ptr<StartupTaskResultCallback> callback)858 int32_t StartupManager::RunAppPreloadSoTaskMainThread(
859 const std::map<std::string, std::shared_ptr<StartupTask>> &appPreloadSoTasks,
860 std::unique_ptr<StartupTaskResultCallback> callback)
861 {
862 std::shared_ptr<StartupTaskManager> startupTaskManager;
863 int32_t result = BuildStartupTaskManager(appPreloadSoTasks, startupTaskManager);
864 if (result != ERR_OK || startupTaskManager == nullptr) {
865 TAG_LOGE(AAFwkTag::STARTUP, "build preload so startup task manager failed, result: %{public}d", result);
866 OnCompletedCallback::OnCallback(std::move(callback), ERR_STARTUP_INTERNAL_ERROR,
867 "RunAppPreloadSoTaskMainThread build failed");
868 return ERR_STARTUP_INTERNAL_ERROR;
869 }
870
871 result = startupTaskManager->Prepare();
872 if (result != ERR_OK) {
873 TAG_LOGE(AAFwkTag::STARTUP, "preload so startup task manager prepare failed, result: %{public}d", result);
874 OnCompletedCallback::OnCallback(std::move(callback), result,
875 "RunAppPreloadSoTaskMainThread prepare failed");
876 return result;
877 }
878 TAG_LOGI(AAFwkTag::STARTUP, "preload so startup task manager count: %{public}zu", appPreloadSoTasks.size());
879
880 if (preloadHandler_ == nullptr) {
881 TAG_LOGE(AAFwkTag::STARTUP, "no preload thread");
882 OnCompletedCallback::OnCallback(std::move(callback), result,
883 "RunAppPreloadSoTaskMainThread no preload thread");
884 return ERR_STARTUP_INTERNAL_ERROR;
885 }
886 auto callbackInfo = std::make_shared<StartupTaskResultCallbackInfo>(std::move(callback));
887 std::shared_ptr<StartupListener> listener = std::make_shared<StartupListener>(
888 [callbackInfo, weak = weak_from_this()](const std::shared_ptr<StartupTaskResult> &result) {
889 auto self = weak.lock();
890 if (self == nullptr) {
891 TAG_LOGE(AAFwkTag::STARTUP, "self is null");
892 return;
893 }
894 self->PostMainThreadTask([callbackInfo, result]() {
895 if (callbackInfo == nullptr) {
896 TAG_LOGE(AAFwkTag::STARTUP, "callbackInfo is null");
897 return;
898 }
899 OnCompletedCallback::OnCallback(std::move(callbackInfo->callback_), result);
900 });
901 });
902 startupTaskManager->SetConfig(std::make_shared<StartupConfig>(listener));
903 preloadHandler_->PostTask([startupTaskManager]() {
904 int32_t result = startupTaskManager->Run(nullptr);
905 if (result != ERR_OK) {
906 TAG_LOGE(AAFwkTag::STARTUP, "preload so startup task manager run failed, result: %{public}d", result);
907 }
908 });
909 return ERR_OK;
910 }
911
GetStartupConfigString(const ModuleStartupConfigInfo & info,std::string & config)912 int32_t StartupManager::GetStartupConfigString(const ModuleStartupConfigInfo &info, std::string &config)
913 {
914 TAG_LOGD(AAFwkTag::STARTUP, "start");
915 std::string appStartup = info.startupConfig_;
916 if (appStartup.empty()) {
917 TAG_LOGE(AAFwkTag::STARTUP, "appStartup invalid");
918 return ERR_STARTUP_CONFIG_NOT_FOUND;
919 }
920 AAFwk::EventInfo eventInfo;
921 size_t pos = appStartup.rfind(PROFILE_FILE_PREFIX);
922 if ((pos == std::string::npos) || (pos == appStartup.length() - strlen(PROFILE_FILE_PREFIX))) {
923 TAG_LOGE(AAFwkTag::STARTUP, "appStartup %{public}s is invalid", appStartup.c_str());
924 return ERR_STARTUP_CONFIG_PATH_ERROR;
925 }
926 std::string profileName = appStartup.substr(pos + strlen(PROFILE_FILE_PREFIX));
927 std::string hapPath = info.hapPath_;
928 std::unique_ptr<uint8_t[]> startupConfig = nullptr;
929 size_t len = 0;
930 std::string profilePath = PROFILE_PATH + profileName + JSON_SUFFIX;
931 std::string loadPath = AbilityBase::ExtractorUtil::GetLoadFilePath(hapPath);
932 bool newCreate = false;
933 std::shared_ptr<AbilityBase::Extractor> extractor =
934 AbilityBase::ExtractorUtil::GetExtractor(loadPath, newCreate);
935 if (!extractor->ExtractToBufByName(profilePath, startupConfig, len)) {
936 TAG_LOGE(AAFwkTag::STARTUP, "failed to get startup config, profilePath: %{private}s, hapPath: %{private}s",
937 profilePath.c_str(), hapPath.c_str());
938 eventInfo.errCode = ERR_STARTUP_CONFIG_PATH_ERROR;
939 eventInfo.errReason = "failed to get startup";
940 AAFwk::EventReport::SendLaunchFrameworkEvent(
941 AAFwk::EventName::STARTUP_TASK_ERROR, HiSysEventType::FAULT, eventInfo);
942 return ERR_STARTUP_CONFIG_PATH_ERROR;
943 }
944 std::string configData(startupConfig.get(), startupConfig.get() + len);
945 nlohmann::json profileJson = nlohmann::json::parse(configData, nullptr, false);
946 if (profileJson.is_discarded()) {
947 TAG_LOGE(AAFwkTag::STARTUP, "bad profile file");
948 eventInfo.errCode = ERR_STARTUP_CONFIG_PARSE_ERROR;
949 eventInfo.errReason = "bad profile file";
950 AAFwk::EventReport::SendLaunchFrameworkEvent(
951 AAFwk::EventName::STARTUP_TASK_ERROR, HiSysEventType::FAULT, eventInfo);
952 return ERR_STARTUP_CONFIG_PARSE_ERROR;
953 }
954 config = profileJson.dump();
955 return ERR_OK;
956 }
957
AnalyzeStartupConfig(const ModuleStartupConfigInfo & info,const std::string & startupConfig,std::map<std::string,std::shared_ptr<AppStartupTask>> & preloadSoStartupTasks,std::map<std::string,std::shared_ptr<AppStartupTask>> & preloadSystemSoStartupTasks,std::vector<StartupTaskInfo> & pendingStartupTaskInfos,std::string & pendingConfigEntry)958 bool StartupManager::AnalyzeStartupConfig(const ModuleStartupConfigInfo& info, const std::string& startupConfig,
959 std::map<std::string, std::shared_ptr<AppStartupTask>>& preloadSoStartupTasks,
960 std::map<std::string, std::shared_ptr<AppStartupTask>>& preloadSystemSoStartupTasks,
961 std::vector<StartupTaskInfo>& pendingStartupTaskInfos, std::string& pendingConfigEntry)
962 {
963 if (startupConfig.empty()) {
964 TAG_LOGE(AAFwkTag::STARTUP, "startupConfig invalid");
965 return false;
966 }
967
968 nlohmann::json startupConfigJson = nlohmann::json::parse(startupConfig, nullptr, false);
969 if (startupConfigJson.is_discarded()) {
970 TAG_LOGE(AAFwkTag::STARTUP, "Failed to parse json string");
971 return false;
972 }
973
974 if (info.moduleType_ == AppExecFwk::ModuleType::ENTRY || info.moduleType_ == AppExecFwk::ModuleType::FEATURE) {
975 if (!(startupConfigJson.contains(CONFIG_ENTRY) && startupConfigJson[CONFIG_ENTRY].is_string())) {
976 TAG_LOGE(AAFwkTag::STARTUP, "no config entry.");
977 return false;
978 }
979 pendingConfigEntry = startupConfigJson.at(CONFIG_ENTRY).get<std::string>();
980 if (pendingConfigEntry.empty()) {
981 TAG_LOGE(AAFwkTag::STARTUP, "startup config empty.");
982 return false;
983 }
984 }
985
986 if (!AnalyzeAppStartupTask(info, startupConfigJson, pendingStartupTaskInfos)) {
987 return false;
988 }
989 if (!AnalyzePreloadSoStartupTask(info, startupConfigJson, preloadSoStartupTasks)) {
990 return false;
991 }
992 AnalyzePreloadSystemSoStartupTask(startupConfigJson, preloadSystemSoStartupTasks);
993 return true;
994 }
995
AnalyzeAppStartupTask(const ModuleStartupConfigInfo & info,nlohmann::json & startupConfigJson,std::vector<StartupTaskInfo> & pendingStartupTaskInfos)996 bool StartupManager::AnalyzeAppStartupTask(const ModuleStartupConfigInfo& info, nlohmann::json &startupConfigJson,
997 std::vector<StartupTaskInfo>& pendingStartupTaskInfos)
998 {
999 if (startupConfigJson.contains(STARTUP_TASKS) && startupConfigJson[STARTUP_TASKS].is_array()) {
1000 for (const auto& module : startupConfigJson.at(STARTUP_TASKS).get<nlohmann::json>()) {
1001 if (!module.contains(SRC_ENTRY) || !module[SRC_ENTRY].is_string() ||
1002 !module.contains(NAME) || !module[NAME].is_string()) {
1003 TAG_LOGE(AAFwkTag::STARTUP, "Invalid module data");
1004 return false;
1005 }
1006 int32_t result = AnalyzeAppStartupTaskInner(info, module, pendingStartupTaskInfos);
1007 if (!result) {
1008 return false;
1009 }
1010 }
1011 return true;
1012 }
1013 return true;
1014 }
1015
AnalyzePreloadSoStartupTask(const ModuleStartupConfigInfo & info,nlohmann::json & startupConfigJson,std::map<std::string,std::shared_ptr<AppStartupTask>> & preloadSoStartupTasks)1016 bool StartupManager::AnalyzePreloadSoStartupTask(const ModuleStartupConfigInfo& info, nlohmann::json &startupConfigJson,
1017 std::map<std::string, std::shared_ptr<AppStartupTask>>& preloadSoStartupTasks)
1018 {
1019 if (startupConfigJson.contains(PRELOAD_STARTUP_TASKS) && startupConfigJson[PRELOAD_STARTUP_TASKS].is_array()) {
1020 for (const auto& module : startupConfigJson.at(PRELOAD_STARTUP_TASKS).get<nlohmann::json>()) {
1021 if (!module.contains(SRC_ENTRY) || !module[SRC_ENTRY].is_string() ||
1022 !module.contains(NAME) || !module[NAME].is_string()) {
1023 TAG_LOGE(AAFwkTag::STARTUP, "Invalid module data");
1024 return false;
1025 }
1026 int32_t result = AnalyzePreloadSoStartupTaskInner(info, module, preloadSoStartupTasks);
1027 if (!result) {
1028 return false;
1029 }
1030 }
1031 return true;
1032 }
1033 return true;
1034 }
1035
AnalyzeAppStartupTaskInner(const ModuleStartupConfigInfo & info,const nlohmann::json & startupTaskJson,std::vector<StartupTaskInfo> & pendingStartupTaskInfos)1036 bool StartupManager::AnalyzeAppStartupTaskInner(const ModuleStartupConfigInfo& info,
1037 const nlohmann::json& startupTaskJson,
1038 std::vector<StartupTaskInfo>& pendingStartupTaskInfos)
1039 {
1040 if (!startupTaskJson.contains(SRC_ENTRY) || !startupTaskJson[SRC_ENTRY].is_string() ||
1041 !startupTaskJson.contains(NAME) || !startupTaskJson[NAME].is_string()) {
1042 TAG_LOGE(AAFwkTag::STARTUP, "Invalid startupTaskJson data");
1043 return false;
1044 }
1045 StartupTaskInfo startupTaskInfo;
1046 startupTaskInfo.moduleName = info.name_;
1047 startupTaskInfo.hapPath = info.hapPath_;
1048 startupTaskInfo.esModule = info.esModule_;
1049
1050 startupTaskInfo.name = startupTaskJson.at(NAME).get<std::string>();
1051 startupTaskInfo.srcEntry = startupTaskJson.at(SRC_ENTRY).get<std::string>();
1052 if (startupTaskInfo.name.empty()) {
1053 TAG_LOGE(AAFwkTag::STARTUP, "startup task name is empty");
1054 return false;
1055 }
1056 if (startupTaskInfo.srcEntry.empty()) {
1057 TAG_LOGE(AAFwkTag::STARTUP, "startup task %{public}s no srcEntry", startupTaskInfo.name.c_str());
1058 return false;
1059 }
1060 SetOptionalParameters(startupTaskJson, info.moduleType_, startupTaskInfo);
1061 pendingStartupTaskInfos.emplace_back(startupTaskInfo);
1062 return true;
1063 }
1064
AnalyzePreloadSoStartupTaskInner(const ModuleStartupConfigInfo & info,const nlohmann::json & preloadStartupTaskJson,std::map<std::string,std::shared_ptr<AppStartupTask>> & preloadSoStartupTasks)1065 bool StartupManager::AnalyzePreloadSoStartupTaskInner(const ModuleStartupConfigInfo& info,
1066 const nlohmann::json &preloadStartupTaskJson,
1067 std::map<std::string, std::shared_ptr<AppStartupTask>>& preloadSoStartupTasks)
1068 {
1069 if (!preloadStartupTaskJson.contains(NAME) || !preloadStartupTaskJson[NAME].is_string() ||
1070 !preloadStartupTaskJson.contains(OHMURL) || !preloadStartupTaskJson[OHMURL].is_string()) {
1071 TAG_LOGE(AAFwkTag::STARTUP, "Invalid startupTaskJson data");
1072 return false;
1073 }
1074
1075 std::string name = preloadStartupTaskJson.at(NAME).get<std::string>();
1076 std::string ohmUrl = preloadStartupTaskJson.at(OHMURL).get<std::string>();
1077 std::string path = bundleName_ + "/" + info.name_;
1078 auto task = std::make_shared<PreloadSoStartupTask>(name, ohmUrl, path);
1079
1080 SetOptionalParameters(preloadStartupTaskJson, info.moduleType_, task);
1081 preloadSoStartupTasks.emplace(name, task);
1082 return true;
1083 }
1084
AnalyzePreloadSystemSoStartupTask(nlohmann::json & startupConfigJson,std::map<std::string,std::shared_ptr<AppStartupTask>> & preloadSoStartupTasks)1085 void StartupManager::AnalyzePreloadSystemSoStartupTask(nlohmann::json &startupConfigJson,
1086 std::map<std::string, std::shared_ptr<AppStartupTask>>& preloadSoStartupTasks)
1087 {
1088 if (preloadSystemSoAllowlist_.empty()) {
1089 TAG_LOGD(AAFwkTag::STARTUP, "preload system so allowlist is empty, skip analyzing");
1090 return;
1091 }
1092
1093 if (!startupConfigJson.contains(PRELOAD_SYSTEM_SO_STARTUP_TASKS) ||
1094 !startupConfigJson[PRELOAD_SYSTEM_SO_STARTUP_TASKS].is_array()) {
1095 TAG_LOGD(AAFwkTag::STARTUP, "no preload system so startup tasks");
1096 return;
1097 }
1098
1099 for (const auto& module : startupConfigJson.at(PRELOAD_SYSTEM_SO_STARTUP_TASKS).get<nlohmann::json>()) {
1100 AnalyzePreloadSystemSoStartupTaskInner(module, preloadSoStartupTasks);
1101 }
1102 }
1103
AnalyzePreloadSystemSoStartupTaskInner(const nlohmann::json & preloadStartupTaskJson,std::map<std::string,std::shared_ptr<AppStartupTask>> & preloadSoStartupTasks)1104 void StartupManager::AnalyzePreloadSystemSoStartupTaskInner(
1105 const nlohmann::json &preloadStartupTaskJson,
1106 std::map<std::string, std::shared_ptr<AppStartupTask>>& preloadSoStartupTasks)
1107 {
1108 if (!preloadStartupTaskJson.is_object() ||
1109 !preloadStartupTaskJson.contains(NAME) || !preloadStartupTaskJson[NAME].is_string() ||
1110 !preloadStartupTaskJson.contains(OHMURL) || !preloadStartupTaskJson[OHMURL].is_string()) {
1111 TAG_LOGE(AAFwkTag::STARTUP, "Invalid preload system so startup task JSON data");
1112 return;
1113 }
1114
1115 std::string ohmUrl = preloadStartupTaskJson.at(OHMURL).get<std::string>();
1116 if (preloadSystemSoAllowlist_.find(ohmUrl) == preloadSystemSoAllowlist_.end()) {
1117 TAG_LOGE(AAFwkTag::STARTUP, "ohmUrl %{public}s is in forbidden whitelist", ohmUrl.c_str());
1118 return;
1119 }
1120
1121 std::string name = preloadStartupTaskJson.at(NAME).get<std::string>();
1122 if (name.empty()) {
1123 TAG_LOGE(AAFwkTag::STARTUP, "field name cannot be empty, ohmUrl is %{public}s", ohmUrl.c_str());
1124 return;
1125 }
1126 auto task = std::make_shared<PreloadSystemSoStartupTask>(name, ohmUrl);
1127 preloadSoStartupTasks.emplace(name, task);
1128 return;
1129 }
1130
SetOptionalParameters(const nlohmann::json & module,AppExecFwk::ModuleType moduleType,StartupTaskInfo & startupTaskInfo)1131 void StartupManager::SetOptionalParameters(const nlohmann::json& module, AppExecFwk::ModuleType moduleType,
1132 StartupTaskInfo& startupTaskInfo)
1133 {
1134 if (module.contains(DEPENDENCIES) && module[DEPENDENCIES].is_array()) {
1135 for (const auto& dependency : module.at(DEPENDENCIES)) {
1136 if (dependency.is_string()) {
1137 startupTaskInfo.dependencies.push_back(dependency.get<std::string>());
1138 }
1139 }
1140 }
1141
1142 if (module.contains(RUN_ON_THREAD) && module[RUN_ON_THREAD].is_string()) {
1143 std::string profileName = module.at(RUN_ON_THREAD).get<std::string>();
1144 if (profileName == TASK_POOL || profileName == TASK_POOL_LOWER) {
1145 startupTaskInfo.callCreateOnMainThread = false;
1146 } else {
1147 startupTaskInfo.callCreateOnMainThread = true;
1148 }
1149 }
1150
1151 if (module.contains(WAIT_ON_MAIN_THREAD) && module[WAIT_ON_MAIN_THREAD].is_boolean()) {
1152 startupTaskInfo.waitOnMainThread = module.at(WAIT_ON_MAIN_THREAD).get<bool>();
1153 } else {
1154 startupTaskInfo.waitOnMainThread = true;
1155 }
1156
1157 if (module.contains(OHMURL) && module[OHMURL].is_string()) {
1158 startupTaskInfo.ohmUrl = module.at(OHMURL).get<std::string>();
1159 }
1160
1161 if (moduleType != AppExecFwk::ModuleType::ENTRY && moduleType != AppExecFwk::ModuleType::FEATURE) {
1162 startupTaskInfo.excludeFromAutoStart = true;
1163 return;
1164 }
1165 if (module.contains(EXCLUDE_FROM_AUTO_START) && module[EXCLUDE_FROM_AUTO_START].is_boolean()) {
1166 startupTaskInfo.excludeFromAutoStart = module.at(EXCLUDE_FROM_AUTO_START).get<bool>();
1167 } else {
1168 startupTaskInfo.excludeFromAutoStart = false;
1169 }
1170
1171 SetMatchRules(module, startupTaskInfo.matchRules, false);
1172 }
1173
SetOptionalParameters(const nlohmann::json & module,AppExecFwk::ModuleType moduleType,std::shared_ptr<PreloadSoStartupTask> & task)1174 void StartupManager::SetOptionalParameters(const nlohmann::json &module, AppExecFwk::ModuleType moduleType,
1175 std::shared_ptr<PreloadSoStartupTask> &task)
1176 {
1177 if (task == nullptr) {
1178 TAG_LOGE(AAFwkTag::STARTUP, "task is null");
1179 return;
1180 }
1181 std::vector<std::string> dependencies;
1182 ParseJsonStringArray(module, DEPENDENCIES, dependencies);
1183 task->SetDependencies(dependencies);
1184
1185 if (moduleType != AppExecFwk::ModuleType::ENTRY && moduleType != AppExecFwk::ModuleType::FEATURE) {
1186 task->SetIsExcludeFromAutoStart(true);
1187 return;
1188 }
1189 if (module.contains(EXCLUDE_FROM_AUTO_START) && module[EXCLUDE_FROM_AUTO_START].is_boolean()) {
1190 task->SetIsExcludeFromAutoStart(module.at(EXCLUDE_FROM_AUTO_START).get<bool>());
1191 } else {
1192 task->SetIsExcludeFromAutoStart(false);
1193 }
1194
1195 StartupTaskMatchRules matchRules;
1196 SetMatchRules(module, matchRules, true);
1197 task->SetMatchRules(matchRules);
1198 }
1199
SetMatchRules(const nlohmann::json & module,StartupTaskMatchRules & matchRules,bool isPreloadSoStartupTask)1200 void StartupManager::SetMatchRules(const nlohmann::json &module, StartupTaskMatchRules &matchRules,
1201 bool isPreloadSoStartupTask)
1202 {
1203 if (!module.contains(MATCH_RULES) || !module.at(MATCH_RULES).is_object()) {
1204 return;
1205 }
1206 if (!isPreloadSoStartupTask) {
1207 enableLazyLoadingAppStartupTasks_ = true;
1208 }
1209
1210 const nlohmann::json &matchRulesJson = module.at(MATCH_RULES);
1211 ParseJsonStringArray(matchRulesJson, URIS, matchRules.uris);
1212 ParseJsonStringArray(matchRulesJson, INSIGHT_INTENTS, matchRules.insightIntents);
1213 ParseJsonStringArray(matchRulesJson, ACTIONS, matchRules.actions);
1214 ParseJsonStringArray(matchRulesJson, CUSTOMIZATION, matchRules.customization);
1215 TAG_LOGD(AAFwkTag::STARTUP,
1216 "SetMatchRules uris:%{public}zu, insightIntents:%{public}zu, actions:%{public}zu, customization:%{public}zu",
1217 matchRules.uris.size(), matchRules.insightIntents.size(), matchRules.actions.size(),
1218 matchRules.customization.size());
1219 }
1220
InitPreloadSystemSoAllowlist()1221 void StartupManager::InitPreloadSystemSoAllowlist()
1222 {
1223 nlohmann::json parseResult;
1224 if (!ReadPreloadSystemSoAllowlistFile(parseResult)) {
1225 TAG_LOGE(AAFwkTag::STARTUP, "failed to parse preload system so allowlist file");
1226 preloadSystemSoAllowlist_.clear();
1227 return;
1228 }
1229
1230 if (!ParsePreloadSystemSoAllowlist(parseResult, preloadSystemSoAllowlist_)) {
1231 TAG_LOGW(AAFwkTag::STARTUP, "parsing failed. Clear the blank list of names.");
1232 preloadSystemSoAllowlist_.clear();
1233 }
1234 }
1235
ReadPreloadSystemSoAllowlistFile(nlohmann::json & jsonStr)1236 bool StartupManager::ReadPreloadSystemSoAllowlistFile(nlohmann::json &jsonStr)
1237 {
1238 auto getConfigPath = []() -> const std::string {
1239 char buf[MAX_PATH_LEN] = {0};
1240 char *configPath = GetOneCfgFile(PRELOAD_SYSTEM_SO_ALLOWLIST_FILE_PATH, buf, MAX_PATH_LEN);
1241 if (configPath == nullptr || configPath[0] == '\0' || strlen(configPath) > MAX_PATH_LEN) {
1242 return "";
1243 }
1244 char path[PATH_MAX] = {0};
1245 if (realpath(configPath, path) == nullptr) {
1246 return "";
1247 }
1248 return std::string(path);
1249 };
1250
1251 std::string configPath = getConfigPath();
1252 if (configPath.empty()) {
1253 TAG_LOGD(AAFwkTag::STARTUP, "failed to get preload system so allowlist config path");
1254 return true;
1255 }
1256
1257 std::ifstream preloadSystemSoAllowFile;
1258 preloadSystemSoAllowFile.open(configPath, std::ios::in);
1259 if (!preloadSystemSoAllowFile.is_open()) {
1260 TAG_LOGE(AAFwkTag::STARTUP, "failed to open preload system so allowlist file: %{public}s",
1261 configPath.c_str());
1262 return false;
1263 }
1264
1265 std::string fileContent(
1266 (std::istreambuf_iterator<char>(preloadSystemSoAllowFile)), std::istreambuf_iterator<char>());
1267 preloadSystemSoAllowFile.close();
1268
1269 jsonStr = nlohmann::json::parse(fileContent, nullptr, false);
1270 return true;
1271 }
1272
ParsePreloadSystemSoAllowlist(const nlohmann::json & jsonStr,std::unordered_set<std::string> & allowlist)1273 bool StartupManager::ParsePreloadSystemSoAllowlist(
1274 const nlohmann::json &jsonStr, std::unordered_set<std::string> &allowlist)
1275 {
1276 if (jsonStr.is_discarded() || !jsonStr.is_object()) {
1277 TAG_LOGW(AAFwkTag::STARTUP, "failed to parse JSON string for allowlist.");
1278 return false;
1279 }
1280 if (!jsonStr.contains(SYSTEM_PRELOAD_SO_ALLOW_LIST) || !jsonStr[SYSTEM_PRELOAD_SO_ALLOW_LIST].is_array()) {
1281 TAG_LOGE(AAFwkTag::STARTUP, "json does not contain valid 'systemPreloadSoAllowList' array.");
1282 return false;
1283 }
1284 allowlist.clear();
1285 for (const auto &item : jsonStr[SYSTEM_PRELOAD_SO_ALLOW_LIST]) {
1286 if (!item.is_string()) {
1287 continue;
1288 }
1289 allowlist.insert(item.get<std::string>());
1290 }
1291 return true;
1292 }
1293
ParseJsonStringArray(const nlohmann::json & json,const std::string & key,std::vector<std::string> & arr)1294 bool StartupManager::ParseJsonStringArray(const nlohmann::json &json, const std::string &key,
1295 std::vector<std::string> &arr)
1296 {
1297 if (!json.contains(key) || !json[key].is_array()) {
1298 return false;
1299 }
1300
1301 for (const auto &item : json.at(key)) {
1302 if (item.is_string()) {
1303 arr.push_back(item.get<std::string>());
1304 }
1305 }
1306 return true;
1307 }
1308 } // namespace AbilityRuntime
1309 } // namespace OHOS
1310