• 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_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>> &currentStartupTasks)
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>> &currentTasks)
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