From 8ca707346f60bff76ebebaa389914249d573f412 Mon Sep 17 00:00:00 2001 From: yuechunyang Date: Thu, 3 Jul 2025 21:45:15 +0800 Subject: [PATCH] add preload system so code Signed-off-by: yuechunyang --- frameworks/native/appkit/BUILD.gn | 2 + .../preload_system_so_startup_task.cpp | 116 +++++++++ .../appkit/app_startup/startup_manager.cpp | 170 ++++++++++++- .../app_startup/preload_so_startup_task.h | 5 +- .../preload_system_so_startup_task.h | 38 +++ .../appkit/app_startup/startup_manager.h | 18 +- .../BUILD.gn | 4 + .../startup_manager_test.cpp | 237 +++++++++++++++++- 8 files changed, 572 insertions(+), 18 deletions(-) create mode 100644 frameworks/native/appkit/app_startup/preload_system_so_startup_task.cpp create mode 100644 interfaces/kits/native/appkit/app_startup/preload_system_so_startup_task.h diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index e36e6ad0678..0dd2cb2d962 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -134,6 +134,7 @@ ohos_shared_library("appkit_native") { "${ability_runtime_native_path}/appkit/app_startup/js_startup_task_result.cpp", "${ability_runtime_native_path}/appkit/app_startup/native_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/preload_so_startup_task.cpp", + "${ability_runtime_native_path}/appkit/app_startup/preload_system_so_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_config.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_listener.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_manager.cpp", @@ -186,6 +187,7 @@ ohos_shared_library("appkit_native") { "bundle_framework:appexecfwk_core", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", "ets_runtime:libark_jsruntime", "eventhandler:libeventhandler", "faultloggerd:libbacktrace_local", diff --git a/frameworks/native/appkit/app_startup/preload_system_so_startup_task.cpp b/frameworks/native/appkit/app_startup/preload_system_so_startup_task.cpp new file mode 100644 index 00000000000..ae4dad7b48b --- /dev/null +++ b/frameworks/native/appkit/app_startup/preload_system_so_startup_task.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "preload_system_so_startup_task.h" + +#include "event_report.h" +#include "hilog_tag_wrapper.h" +#include "native_module_manager.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { +constexpr char OHM_URL_OHOS_PREFIX[] = "@ohos:"; +constexpr char OHM_URL_APP_COLON_TAG = ':'; + +bool StringStartWith(const std::string& str, const std::string& startStr) +{ + size_t startStrLen = startStr.length(); + return ((str.length() > startStrLen) && (str.compare(0, startStrLen, startStr) == 0)); +} + +int32_t ParseSystemSoOhmUrl(const std::string& ohmUrl, std::string& soName) +{ + // @ohos: + size_t pos = ohmUrl.find(OHM_URL_APP_COLON_TAG); + if (pos == std::string::npos) { + TAG_LOGE(AAFwkTag::STARTUP, "invalid app ohmUrl: %{public}s", ohmUrl.c_str()); + return ERR_STARTUP_INVALID_VALUE; + } + soName = ohmUrl.substr(pos + 1); + + return ERR_OK; +} + +int32_t ParseOhmUrl(const std::string& ohmUrl, std::string& soName) +{ + if (ohmUrl.empty()) { + TAG_LOGE(AAFwkTag::STARTUP, "ohmUrl is empty"); + return ERR_STARTUP_INVALID_VALUE; + } + + if (!StringStartWith(ohmUrl, OHM_URL_OHOS_PREFIX)) { + TAG_LOGE(AAFwkTag::STARTUP, "invalid ohmUrl: %{public}s", ohmUrl.c_str()); + return ERR_STARTUP_INVALID_VALUE; + } + + return ParseSystemSoOhmUrl(ohmUrl, soName); +} +} // namespace +const std::string PreloadSystemSoStartupTask::TASK_TYPE = "PreloadSystemSo"; + +PreloadSystemSoStartupTask::PreloadSystemSoStartupTask(const std::string& name, const std::string& ohmUrl) + : PreloadSoStartupTask(name, ohmUrl) +{ + SetWaitOnMainThread(false); + SetCallCreateOnMainThread(false); +} + +PreloadSystemSoStartupTask::~PreloadSystemSoStartupTask() = default; + +const std::string &PreloadSystemSoStartupTask::GetType() const +{ + return TASK_TYPE; +} + +int32_t PreloadSystemSoStartupTask::RunTaskInit(std::unique_ptr callback) +{ + std::string soName; + int32_t code = ParseOhmUrl(ohmUrl_, soName); + AAFwk::EventInfo eventInfo; + if (code != ERR_OK) { + TAG_LOGW(AAFwkTag::STARTUP, + "task %{public}s, parse ohmUrl failed: %{public}s", name_.c_str(), ohmUrl_.c_str()); + return ERR_OK; + } + TAG_LOGI(AAFwkTag::STARTUP, "task: %{public}s, soName: %{public}s", name_.c_str(), soName.c_str()); + + NativeModuleManager* moduleManager = NativeModuleManager::GetInstance(); + if (moduleManager == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "moduleManager is null"); + OnCompletedCallback::OnCallback(std::move(callback), ERR_STARTUP_INTERNAL_ERROR); + eventInfo.errCode = ERR_NATIVE_MODULE_MANAGER_CONSTRUCTION; + eventInfo.errReason = "moduleManager is null"; + AAFwk::EventReport::SendLaunchFrameworkEvent( + AAFwk::EventName::STARTUP_TASK_ERROR, HiSysEventType::FAULT, eventInfo); + return ERR_STARTUP_INTERNAL_ERROR; + } + + std::string errInfo; + NativeModule* module = moduleManager->LoadNativeModule(soName.c_str(), nullptr, false, errInfo, false, ""); + if (module == nullptr) { + TAG_LOGW(AAFwkTag::STARTUP, "module is null, errInfo: %{public}s", errInfo.c_str()); + OnCompletedCallback::OnCallback(std::move(callback), ERR_OK); + eventInfo.errCode = ERR_LOAD_NATIVE_MODULE; + eventInfo.errReason = errInfo; + AAFwk::EventReport::SendLaunchFrameworkEvent( + AAFwk::EventName::STARTUP_TASK_ERROR, HiSysEventType::FAULT, eventInfo); + return ERR_STARTUP_INTERNAL_ERROR; + } + OnCompletedCallback::OnCallback(std::move(callback), ERR_OK); + return ERR_OK; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/app_startup/startup_manager.cpp b/frameworks/native/appkit/app_startup/startup_manager.cpp index 6b550263b83..a730ac62586 100644 --- a/frameworks/native/appkit/app_startup/startup_manager.cpp +++ b/frameworks/native/appkit/app_startup/startup_manager.cpp @@ -15,15 +15,18 @@ #include "startup_manager.h" +#include #include #include #include "app_startup_task_matcher.h" +#include "config_policy_utils.h" #include "event_report.h" #include "hilog_tag_wrapper.h" #include "extractor.h" #include "hitrace_meter.h" #include "native_startup_task.h" +#include "preload_system_so_startup_task.h" #include "preload_so_startup_task.h" #include "startup_utils.h" @@ -54,6 +57,9 @@ constexpr const char* URIS = "uris"; constexpr const char* INSIGHT_INTENTS = "insightIntents"; constexpr const char* ACTIONS = "actions"; constexpr const char* CUSTOMIZATION = "customization"; +constexpr const char* PRELOAD_SYSTEM_SO_STARTUP_TASKS = "systemPreloadHintStartupTasks"; +constexpr const char* PRELOAD_SYSTEM_SO_ALLOWLIST_FILE_PATH = "/etc/ability_runtime_app_startup.json"; +constexpr const char* SYSTEM_PRELOAD_SO_ALLOW_LIST = "systemPreloadSoAllowList"; struct StartupTaskResultCallbackInfo { std::unique_ptr callback_; @@ -377,10 +383,13 @@ void StartupManager::StopAutoPreloadSoTask() std::lock_guard guard(autoPreloadSoTaskManagerMutex_); autoPreloadSoStopped_ = true; auto task = autoPreloadSoTaskManager_.lock(); - if (task == nullptr) { - return; + if (task != nullptr) { + task->TimeoutStop(); + } + auto systemSoTask = autoPreloadSystemSoTaskManager_.lock(); + if (systemSoTask != nullptr) { + systemSoTask->TimeoutStop(); } - task->TimeoutStop(); } bool StartupManager::HasAppStartupConfig() const @@ -640,10 +649,11 @@ int32_t StartupManager::RunLoadModuleStartupConfigTask( return result; } std::map> preloadSoStartupTasks; + std::map> preloadSystemSoStartupTasks; std::vector pendingStartupTaskInfos; std::string pendingConfigEntry; - bool success = AnalyzeStartupConfig(configInfo, configStr, - preloadSoStartupTasks_, pendingStartupTaskInfos_, pendingConfigEntry); + bool success = AnalyzeStartupConfig(configInfo, configStr, preloadSoStartupTasks, + preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); if (!success) { TAG_LOGE(AAFwkTag::STARTUP, "failed to parse app startup module %{public}s, type: %{public}d", configInfo.name_.c_str(), configInfo.moduleType_); @@ -669,7 +679,9 @@ int32_t StartupManager::RunLoadAppStartupConfigTask() } HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); + InitPreloadSystemSoAllowlist(); std::map> preloadSoStartupTasks; + std::map> preloadSystemSoStartupTasks; std::vector pendingStartupTaskInfos; std::string pendingConfigEntry; for (const auto& item : moduleStartupConfigInfos_) { @@ -682,8 +694,8 @@ int32_t StartupManager::RunLoadAppStartupConfigTask() if (result != ERR_OK) { return result; } - bool success = AnalyzeStartupConfig(item, configStr, - preloadSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); + bool success = AnalyzeStartupConfig(item, configStr, preloadSoStartupTasks, + preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); if (!success) { TAG_LOGE(AAFwkTag::STARTUP, "failed to parse app startup module %{public}s, type: %{public}d", item.name_.c_str(), item.moduleType_); @@ -698,6 +710,7 @@ int32_t StartupManager::RunLoadAppStartupConfigTask() return ERR_OK; } preloadSoStartupTasks_ = preloadSoStartupTasks; + preloadSystemSoStartupTasks_ = preloadSystemSoStartupTasks; pendingStartupTaskInfos_ = pendingStartupTaskInfos; pendingConfigEntry_ = pendingConfigEntry; isAppStartupConfigInited_ = true; @@ -721,6 +734,7 @@ int32_t StartupManager::AddAppAutoPreloadSoTask( return ERR_STARTUP_INTERNAL_ERROR; } int32_t result = self->RunAppAutoPreloadSoTask(data); + self->RunAppAutoPreloadSystemSoTask(); OnCompletedCallback::OnCallback(std::move(callback), result); return result; }); @@ -751,8 +765,24 @@ int32_t StartupManager::RunAppAutoPreloadSoTask(std::shared_ptr> appAutoPreloadSystemSoTasks; + for (const auto& [name, task] : preloadSystemSoStartupTasks_) { + appAutoPreloadSystemSoTasks.emplace(name, task); + } + + return RunAppPreloadSoTask(appAutoPreloadSystemSoTasks, true); +} + int32_t StartupManager::RunAppPreloadSoTask( - const std::map> &appPreloadSoTasks) + const std::map> &appPreloadSoTasks, bool isSystemSo) { std::shared_ptr startupTaskManager; int32_t result = BuildStartupTaskManager(appPreloadSoTasks, startupTaskManager); @@ -767,7 +797,8 @@ int32_t StartupManager::RunAppPreloadSoTask( startupTaskManager->OnTimeout(); return ERR_STARTUP_TIMEOUT; } - autoPreloadSoTaskManager_ = startupTaskManager; + isSystemSo ? (autoPreloadSystemSoTaskManager_ = startupTaskManager) + : (autoPreloadSoTaskManager_ = startupTaskManager); } result = startupTaskManager->Prepare(); @@ -921,6 +952,7 @@ int32_t StartupManager::GetStartupConfigString(const ModuleStartupConfigInfo &in bool StartupManager::AnalyzeStartupConfig(const ModuleStartupConfigInfo& info, const std::string& startupConfig, std::map>& preloadSoStartupTasks, + std::map>& preloadSystemSoStartupTasks, std::vector& pendingStartupTaskInfos, std::string& pendingConfigEntry) { if (startupConfig.empty()) { @@ -952,6 +984,7 @@ bool StartupManager::AnalyzeStartupConfig(const ModuleStartupConfigInfo& info, c if (!AnalyzePreloadSoStartupTask(info, startupConfigJson, preloadSoStartupTasks)) { return false; } + AnalyzePreloadSystemSoStartupTask(startupConfigJson, preloadSystemSoStartupTasks); return true; } @@ -1044,6 +1077,52 @@ bool StartupManager::AnalyzePreloadSoStartupTaskInner(const ModuleStartupConfigI return true; } +void StartupManager::AnalyzePreloadSystemSoStartupTask(nlohmann::json &startupConfigJson, + std::map>& preloadSoStartupTasks) +{ + if (preloadSystemSoAllowlist_.empty()) { + TAG_LOGD(AAFwkTag::STARTUP, "preload system so allowlist is empty, skip analyzing"); + return; + } + + if (!startupConfigJson.contains(PRELOAD_SYSTEM_SO_STARTUP_TASKS) || + !startupConfigJson[PRELOAD_SYSTEM_SO_STARTUP_TASKS].is_array()) { + TAG_LOGD(AAFwkTag::STARTUP, "no preload system so startup tasks"); + return; + } + + for (const auto& module : startupConfigJson.at(PRELOAD_SYSTEM_SO_STARTUP_TASKS).get()) { + AnalyzePreloadSystemSoStartupTaskInner(module, preloadSoStartupTasks); + } +} + +void StartupManager::AnalyzePreloadSystemSoStartupTaskInner( + const nlohmann::json &preloadStartupTaskJson, + std::map>& preloadSoStartupTasks) +{ + if (!preloadStartupTaskJson.is_object() || + !preloadStartupTaskJson.contains(NAME) || !preloadStartupTaskJson[NAME].is_string() || + !preloadStartupTaskJson.contains(OHMURL) || !preloadStartupTaskJson[OHMURL].is_string()) { + TAG_LOGE(AAFwkTag::STARTUP, "Invalid preload system so startup task JSON data"); + return; + } + + std::string ohmUrl = preloadStartupTaskJson.at(OHMURL).get(); + if (preloadSystemSoAllowlist_.find(ohmUrl) == preloadSystemSoAllowlist_.end()) { + TAG_LOGE(AAFwkTag::STARTUP, "ohmUrl %{public}s is in forbidden whitelist", ohmUrl.c_str()); + return; + } + + std::string name = preloadStartupTaskJson.at(NAME).get(); + if (name.empty()) { + TAG_LOGE(AAFwkTag::STARTUP, "field name cannot be empty, ohmUrl is %{public}s", ohmUrl.c_str()); + return; + } + auto task = std::make_shared(name, ohmUrl); + preloadSoStartupTasks.emplace(name, task); + return; +} + void StartupManager::SetOptionalParameters(const nlohmann::json& module, AppExecFwk::ModuleType moduleType, StartupTaskInfo& startupTaskInfo) { @@ -1129,5 +1208,78 @@ void StartupManager::SetMatchRules(const nlohmann::json &module, StartupTaskMatc matchRules.uris.size(), matchRules.insightIntents.size(), matchRules.actions.size(), matchRules.customization.size()); } + +void StartupManager::InitPreloadSystemSoAllowlist() +{ + nlohmann::json parseResult; + if (!ReadPreloadSystemSoAllowlistFile(parseResult)) { + TAG_LOGE(AAFwkTag::STARTUP, "failed to parse preload system so allowlist file"); + preloadSystemSoAllowlist_.clear(); + return; + } + + if (!ParsePreloadSystemSoAllowlist(parseResult, preloadSystemSoAllowlist_)) { + TAG_LOGE(AAFwkTag::STARTUP, "parsing failed. Clear the blank list of names."); + preloadSystemSoAllowlist_.clear(); + } +} + +bool StartupManager::ReadPreloadSystemSoAllowlistFile(nlohmann::json &jsonStr) +{ + auto getConfigPath = []() -> const std::string { + char buf[MAX_PATH_LEN] = {0}; + char *configPath = GetOneCfgFile(PRELOAD_SYSTEM_SO_ALLOWLIST_FILE_PATH, buf, MAX_PATH_LEN); + if (configPath == nullptr || configPath[0] == '\0' || strlen(configPath) > MAX_PATH_LEN) { + return ""; + } + char path[PATH_MAX] = {0}; + if (realpath(configPath, path) == nullptr) { + return ""; + } + return std::string(path); + }; + + std::string configPath = getConfigPath(); + if (configPath.empty()) { + TAG_LOGD(AAFwkTag::STARTUP, "failed to get preload system so allowlist config path"); + return true; + } + + std::ifstream preloadSystemSoAllowFile; + preloadSystemSoAllowFile.open(configPath, std::ios::in); + if (!preloadSystemSoAllowFile.is_open()) { + TAG_LOGE(AAFwkTag::STARTUP, "failed to open preload system so allowlist file: %{public}s", + configPath.c_str()); + return false; + } + + std::string fileContent( + (std::istreambuf_iterator(preloadSystemSoAllowFile)), std::istreambuf_iterator()); + preloadSystemSoAllowFile.close(); + + jsonStr = nlohmann::json::parse(fileContent, nullptr, false); + return true; +} + +bool StartupManager::ParsePreloadSystemSoAllowlist( + const nlohmann::json &jsonStr, std::unordered_set &allowlist) +{ + if (jsonStr.is_discarded() || !jsonStr.is_object()) { + TAG_LOGE(AAFwkTag::STARTUP, "failed to parse JSON string for allowlist."); + return false; + } + if (!jsonStr.contains(SYSTEM_PRELOAD_SO_ALLOW_LIST) || !jsonStr[SYSTEM_PRELOAD_SO_ALLOW_LIST].is_array()) { + TAG_LOGE(AAFwkTag::STARTUP, "json does not contain valid 'systemPreloadSoAllowList' array."); + return false; + } + allowlist.clear(); + for (const auto &item : jsonStr[SYSTEM_PRELOAD_SO_ALLOW_LIST]) { + if (!item.is_string()) { + continue; + } + allowlist.insert(item.get()); + } + return true; +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/appkit/app_startup/preload_so_startup_task.h b/interfaces/kits/native/appkit/app_startup/preload_so_startup_task.h index 3461ca9a04d..ad61230e53e 100644 --- a/interfaces/kits/native/appkit/app_startup/preload_so_startup_task.h +++ b/interfaces/kits/native/appkit/app_startup/preload_so_startup_task.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -35,10 +35,9 @@ public: int32_t RunTaskOnDependencyCompleted(const std::string& dependencyName, const std::shared_ptr& result) override; -private: +protected: std::string ohmUrl_; std::string path_; - bool isExcludeFromAutoStart_ = false; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/kits/native/appkit/app_startup/preload_system_so_startup_task.h b/interfaces/kits/native/appkit/app_startup/preload_system_so_startup_task.h new file mode 100644 index 00000000000..3488d306ebc --- /dev/null +++ b/interfaces/kits/native/appkit/app_startup/preload_system_so_startup_task.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ABILITY_RUNTIME_PRELOAD_SYSTEM_SO_STARTUP_TASK_H +#define OHOS_ABILITY_RUNTIME_PRELOAD_SYSTEM_SO_STARTUP_TASK_H + +#include +#include "preload_so_startup_task.h" + +namespace OHOS { +namespace AbilityRuntime { +class PreloadSystemSoStartupTask : public PreloadSoStartupTask { +public: + static const std::string TASK_TYPE; + + PreloadSystemSoStartupTask(const std::string& name, const std::string& ohmUrl); + + ~PreloadSystemSoStartupTask() override; + + const std::string &GetType() const override; + + int32_t RunTaskInit(std::unique_ptr callback) override; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_PRELOAD_SYSTEM_SO_STARTUP_TASK_H diff --git a/interfaces/kits/native/appkit/app_startup/startup_manager.h b/interfaces/kits/native/appkit/app_startup/startup_manager.h index 588272da741..dc9802d7d5e 100644 --- a/interfaces/kits/native/appkit/app_startup/startup_manager.h +++ b/interfaces/kits/native/appkit/app_startup/startup_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -127,18 +127,21 @@ private: // read only after initialization std::map> preloadSoStartupTasks_; + std::map> preloadSystemSoStartupTasks_; std::map> appStartupTasks_; std::vector pendingStartupTaskInfos_; std::string pendingConfigEntry_; std::mutex autoPreloadSoTaskManagerMutex_; std::weak_ptr autoPreloadSoTaskManager_; + std::weak_ptr autoPreloadSystemSoTaskManager_; bool autoPreloadSoStopped_ = false; std::shared_ptr defaultConfig_; std::map> moduleConfigs_; std::shared_ptr mainHandler_; std::shared_ptr preloadHandler_; + std::unordered_set preloadSystemSoAllowlist_; static int32_t AddStartupTask(const std::string &name, std::map> &taskMap, std::map> &allTasks); @@ -155,13 +158,19 @@ private: std::shared_ptr CreateAppPreloadSoTask( const std::map> ¤tPreloadSoTasks); + void InitPreloadSystemSoAllowlist(); + bool ReadPreloadSystemSoAllowlistFile(nlohmann::json &jsonStr); + bool ParsePreloadSystemSoAllowlist(const nlohmann::json &jsonStr, std::unordered_set &allowlist); + void PreloadAppHintStartupTask(std::shared_ptr startupTaskData); int32_t AddLoadAppStartupConfigTask(std::map> &preloadAppHintTasks); int32_t RunLoadAppStartupConfigTask(); int32_t AddAppAutoPreloadSoTask(std::map> &preloadAppHintTasks, std::shared_ptr startupTaskData); int32_t RunAppAutoPreloadSoTask(std::shared_ptr startupTaskData); - int32_t RunAppPreloadSoTask(const std::map> &appPreloadSoTasks); + int32_t RunAppAutoPreloadSystemSoTask(); + int32_t RunAppPreloadSoTask(const std::map> &appPreloadSoTasks, + bool isSystemSo = false); int32_t GetAppAutoPreloadSoTasks(std::map> &appAutoPreloadSoTasks, std::shared_ptr startupTaskData); int32_t RunAppPreloadSoTaskMainThread(const std::map> &appPreloadSoTasks, @@ -170,6 +179,7 @@ private: static int32_t GetStartupConfigString(const ModuleStartupConfigInfo& info, std::string& config); bool AnalyzeStartupConfig(const ModuleStartupConfigInfo& info, const std::string& startupConfig, std::map>& preloadSoStartupTasks, + std::map>& preloadSystemSoStartupTasks, std::vector& pendingStartupTaskInfos, std::string& pendingConfigEntry); static bool AnalyzeAppStartupTask(const ModuleStartupConfigInfo& info, nlohmann::json &startupConfigJson, std::vector& pendingStartupTaskInfos); @@ -181,6 +191,10 @@ private: bool AnalyzePreloadSoStartupTaskInner(const ModuleStartupConfigInfo& info, const nlohmann::json &preloadStartupTaskJson, std::map>& preloadSoStartupTasks); + void AnalyzePreloadSystemSoStartupTask(nlohmann::json &startupConfigJson, + std::map>& preloadSoStartupTasks); + void AnalyzePreloadSystemSoStartupTaskInner(const nlohmann::json &preloadStartupTaskJson, + std::map>& preloadSoStartupTasks); static void SetOptionalParameters(const nlohmann::json& module, AppExecFwk::ModuleType moduleType, StartupTaskInfo& startupTaskInfo); static void SetOptionalParameters(const nlohmann::json &module, AppExecFwk::ModuleType moduleType, diff --git a/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn b/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn index 8e8ebf472b2..553b9be9125 100644 --- a/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn +++ b/test/unittest/frameworks_kits_appkit_native_test/BUILD.gn @@ -1128,6 +1128,7 @@ ohos_unittest("startup_manager_test") { "${ability_runtime_native_path}/appkit/app_startup/js_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_task_executor.cpp", "${ability_runtime_native_path}/appkit/app_startup/preload_so_startup_task.cpp", + "${ability_runtime_native_path}/appkit/app_startup/preload_system_so_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_config.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_listener.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_manager.cpp", @@ -1152,6 +1153,7 @@ ohos_unittest("startup_manager_test") { "ability_base:zuri", "ability_runtime:runtime", "c_utils:utils", + "config_policy:configpolicy_util", "eventhandler:libeventhandler", "faultloggerd:libfaultloggerd", "googletest:gtest_main", @@ -1188,6 +1190,7 @@ ohos_unittest("startup_manager_mock_test") { "${ability_runtime_native_path}/appkit/app_startup/js_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_task_executor.cpp", "${ability_runtime_native_path}/appkit/app_startup/preload_so_startup_task.cpp", + "${ability_runtime_native_path}/appkit/app_startup/preload_system_so_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_config.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_listener.cpp", "${ability_runtime_native_path}/appkit/app_startup/startup_manager.cpp", @@ -1210,6 +1213,7 @@ ohos_unittest("startup_manager_mock_test") { "ability_base:zuri", "ability_runtime:runtime", "c_utils:utils", + "config_policy:configpolicy_util", "eventhandler:libeventhandler", "faultloggerd:libfaultloggerd", "googletest:gtest_main", diff --git a/test/unittest/frameworks_kits_appkit_native_test/startup_manager_test.cpp b/test/unittest/frameworks_kits_appkit_native_test/startup_manager_test.cpp index 5b4b2f3d5bf..3f2309df51b 100644 --- a/test/unittest/frameworks_kits_appkit_native_test/startup_manager_test.cpp +++ b/test/unittest/frameworks_kits_appkit_native_test/startup_manager_test.cpp @@ -12,11 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include #define private public #define protected public #include "startup_manager.h" #include "extractor.h" +#include "preload_system_so_startup_task.h" #undef private #undef protected @@ -509,6 +512,9 @@ HWTEST_F(StartupManagerTest, RunAppPreloadSoTask_0100, Function | MediumTest | L appPreloadSoTasks.emplace(name, startupTask); ret = startupManager->RunAppPreloadSoTask(appPreloadSoTasks); EXPECT_EQ(ret, ERR_OK); + appPreloadSoTasks.emplace(name, startupTask); + ret = startupManager->RunAppPreloadSoTask(appPreloadSoTasks, true); + EXPECT_EQ(ret, ERR_OK); startupManager->autoPreloadSoStopped_ = true; ret = startupManager->RunAppPreloadSoTask(appPreloadSoTasks); EXPECT_NE(ret, ERR_OK); @@ -608,15 +614,16 @@ HWTEST_F(StartupManagerTest, AnalyzeStartupConfig_0100, Function | MediumTest | ModuleStartupConfigInfo info(name, "", "", AppExecFwk::ModuleType::UNKNOWN, false); std::string startupConfig; std::map> preloadSoStartupTasks; + std::map> preloadSystemSoStartupTasks; std::vector pendingStartupTaskInfos; std::string pendingConfigEntry; bool ret = false; ret = startupManager->AnalyzeStartupConfig(info, startupConfig, preloadSoStartupTasks, - pendingStartupTaskInfos, pendingConfigEntry); + preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); EXPECT_EQ(ret, false); startupConfig = "test_startupConfig"; ret = startupManager->AnalyzeStartupConfig(info, startupConfig, preloadSoStartupTasks, - pendingStartupTaskInfos, pendingConfigEntry); + preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); EXPECT_EQ(ret, false); const nlohmann::json startupConfig_json = R"( { @@ -630,7 +637,7 @@ HWTEST_F(StartupManagerTest, AnalyzeStartupConfig_0100, Function | MediumTest | )"_json; startupConfig = startupConfig_json.dump(); ret = startupManager->AnalyzeStartupConfig(info, startupConfig, preloadSoStartupTasks, - pendingStartupTaskInfos, pendingConfigEntry); + preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); EXPECT_EQ(ret, true); info.moduleType_ = AppExecFwk::ModuleType::ENTRY; @@ -641,7 +648,7 @@ HWTEST_F(StartupManagerTest, AnalyzeStartupConfig_0100, Function | MediumTest | }; startupConfig = startupConfigJson.dump(); ret = startupManager->AnalyzeStartupConfig(info, startupConfig, preloadSoStartupTasks, - pendingStartupTaskInfos, pendingConfigEntry); + preloadSystemSoStartupTasks, pendingStartupTaskInfos, pendingConfigEntry); EXPECT_EQ(ret, false); GTEST_LOG_(INFO) << "StartupManagerTest AnalyzeStartupConfig_0100 end"; } @@ -820,6 +827,45 @@ HWTEST_F(StartupManagerTest, AnalyzePreloadSoStartupTask_0200, Function | Medium GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSoStartupTask_0200 end"; } +/** + * @tc.name: AnalyzePreloadSystemSoStartupTask_0100 + * @tc.type: FUNC + * @tc.Function: AnalyzePreloadSystemSoStartupTask + */ +HWTEST_F(StartupManagerTest, AnalyzePreloadSystemSoStartupTask_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSystemSoStartupTask_0100 start"; + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + EXPECT_TRUE(startupManager != nullptr); + std::string name = "test_name"; + std::map> preloadSoStartupTasks; + startupManager->preloadSystemSoAllowlist_.clear(); + + nlohmann::json preloadHintStartupTasksJson1 = R"( + {"systemPreloadHintStartupTasks":""} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTask(preloadHintStartupTasksJson1, preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + startupManager->preloadSystemSoAllowlist_.insert("@ohos:testUrl"); + startupManager->AnalyzePreloadSystemSoStartupTask(preloadHintStartupTasksJson1, preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadHintStartupTasksJson2 = R"( + {"systemPreloadHintStartupTasks":[]} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTask(preloadHintStartupTasksJson2, preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadHintStartupTasksJson3 = R"( + {"systemPreloadHintStartupTasks":[{"name":"testName", "srcEntry":"testEntry", "ohmurl":"@ohos:testUrl"}, {}]} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTask(preloadHintStartupTasksJson3, preloadSoStartupTasks); + EXPECT_FALSE(preloadSoStartupTasks.empty()); + startupManager->preloadSystemSoAllowlist_.clear(); + GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSystemSoStartupTask_0100 end"; +} + /** * @tc.name: AnalyzeAppStartupTaskInner_0100 * @tc.type: FUNC @@ -984,6 +1030,99 @@ HWTEST_F(StartupManagerTest, AnalyzePreloadSoStartupTaskInner_0200, Function | M GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSoStartupTaskInner_0200 end"; } +/** + * @tc.name: AnalyzePreloadSystemSoStartupTaskInner_0100 + * @tc.type: FUNC + * @tc.Function: AnalyzePreloadSystemSoStartupTaskInner + */ +HWTEST_F(StartupManagerTest, AnalyzePreloadSystemSoStartupTaskInner_0100, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSystemSoStartupTaskInner_0100 start"; + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + EXPECT_TRUE(startupManager != nullptr); + std::string name = "test_name"; + std::map> preloadSoStartupTasks; + + nlohmann::json preloadSoStartupTaskInnerJson0 = R"( + {"name":"testName"} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson0.at("name"), + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadSoStartupTaskInnerJson1 = R"( + {} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson1, + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadSoStartupTaskInnerJson2 = R"( + {"name":[]} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson2, + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadSoStartupTaskInnerJson3 = R"( + {"name":"testName"} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson3, + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadSoStartupTaskInnerJson4 = R"( + {"name":"testName", "ohmurl":"[]"} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson4, + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSystemSoStartupTaskInner_0100 end"; +} + +/** + * @tc.name: AnalyzePreloadSystemSoStartupTaskInner_0200 + * @tc.type: FUNC + * @tc.Function: AnalyzePreloadSystemSoStartupTaskInner + */ +HWTEST_F(StartupManagerTest, AnalyzePreloadSystemSoStartupTaskInner_0200, Function | MediumTest | Level1) +{ + GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSystemSoStartupTaskInner_0200 start"; + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + EXPECT_TRUE(startupManager != nullptr); + std::string name = "test_name"; + std::map> preloadSoStartupTasks; + startupManager->preloadSystemSoAllowlist_.clear(); + + nlohmann::json preloadSoStartupTaskInnerJson1 = R"( + {"name":"testName", "srcEntry":"testEntry", "ohmurl":"testOhmurl"} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner( + preloadSoStartupTaskInnerJson1.at("name"), preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson1, + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + startupManager->preloadSystemSoAllowlist_.insert("testOhmurl"); + nlohmann::json preloadSoStartupTaskInnerJson2 = R"( + {"name":"", "srcEntry":"testEntry", "ohmurl":"testOhmurl"} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson2, + preloadSoStartupTasks); + EXPECT_TRUE(preloadSoStartupTasks.empty()); + + nlohmann::json preloadSoStartupTaskInnerJson3 = R"( + {"name":"testName", "srcEntry":"testEntry", "ohmurl":"testOhmurl"} + )"_json; + startupManager->AnalyzePreloadSystemSoStartupTaskInner(preloadSoStartupTaskInnerJson3, + preloadSoStartupTasks); + EXPECT_FALSE(preloadSoStartupTasks.empty()); + startupManager->preloadSystemSoAllowlist_.clear(); + GTEST_LOG_(INFO) << "StartupManagerTest AnalyzePreloadSystemSoStartupTaskInner_0200 end"; +} + /** * @tc.name: GetModuleConfig_0100 * @tc.type: FUNC @@ -1055,5 +1194,95 @@ HWTEST_F(StartupManagerTest, PreloadSoStartupTask_0100, Function | MediumTest | EXPECT_EQ(ret, ERR_STARTUP_INTERNAL_ERROR); } +/** + * @tc.name: InitPreloadSystemSoAllowlist_0100 + * @tc.type: FUNC + * @tc.Function: InitPreloadSystemSoAllowlist + */ +HWTEST_F(StartupManagerTest, InitPreloadSystemSoAllowlist_0100, Function | MediumTest | Level1) +{ + std::string preloadSystemSoAllowlistFilePath = "/etc/ability_runtime_app_startup.json"; + std::string preloadSystemSoAllowlistFile = "/system/etc/ability_runtime_app_startup.json"; + std::unordered_set preloadSystemSoAllowlist; + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + startupManager->preloadSystemSoAllowlist_.clear(); + + nlohmann::json parseResult; + if (!startupManager->ReadPreloadSystemSoAllowlistFile(parseResult)) { + preloadSystemSoAllowlist.clear(); + GTEST_LOG_(INFO) << "LoadConfiguration failed, using default preloadSystemSoAllowlist"; + } + + if (!startupManager->ParsePreloadSystemSoAllowlist(parseResult, preloadSystemSoAllowlist)) { + preloadSystemSoAllowlist.clear(); + GTEST_LOG_(INFO) << "ParsePreloadSystemSoAllowlist failed, using default preloadSystemSoAllowlist"; + } + + startupManager->InitPreloadSystemSoAllowlist(); + EXPECT_EQ(preloadSystemSoAllowlist.size(), startupManager->preloadSystemSoAllowlist_.size()); + startupManager->preloadSystemSoAllowlist_.clear(); +} + +/** + * @tc.name: ParsePreloadSystemSoAllowlist_0100 + * @tc.type: FUNC + * @tc.Function: ParsePreloadSystemSoAllowlist + */ +HWTEST_F(StartupManagerTest, ParsePreloadSystemSoAllowlist_0100, Function | MediumTest | Level1) +{ + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + std::unordered_set allowlist; + + nlohmann::json jsonStr1 = nlohmann::json::parse("", nullptr, false); + allowlist.clear(); + EXPECT_FALSE(startupManager->ParsePreloadSystemSoAllowlist(jsonStr1, allowlist)); + EXPECT_TRUE(allowlist.empty()); + + nlohmann::json jsonStr2 = R"({})"_json; + allowlist.clear(); + EXPECT_FALSE(startupManager->ParsePreloadSystemSoAllowlist(jsonStr2, allowlist)); + EXPECT_TRUE(allowlist.empty()); + + nlohmann::json jsonStr3 = R"({"systemPreloadSoAllowList":""})"_json; + allowlist.clear(); + EXPECT_FALSE(startupManager->ParsePreloadSystemSoAllowlist(jsonStr3, allowlist)); + EXPECT_TRUE(allowlist.empty()); + + nlohmann::json jsonStr4 = R"({"systemPreloadSoAllowList":[]})"_json; + allowlist.clear(); + EXPECT_TRUE(startupManager->ParsePreloadSystemSoAllowlist(jsonStr4, allowlist)); + EXPECT_TRUE(allowlist.empty()); + + nlohmann::json jsonStr5 = R"({"systemPreloadSoAllowList":["testOhmurl"]})"_json; + allowlist.clear(); + EXPECT_TRUE(startupManager->ParsePreloadSystemSoAllowlist(jsonStr5, allowlist)); + EXPECT_FALSE(allowlist.empty()); +} + +/** + * @tc.name: RunAppAutoPreloadSystemSoTask_0100 + * @tc.type: FUNC + * @tc.Function: RunAppAutoPreloadSystemSoTask + */ +HWTEST_F(StartupManagerTest, RunAppAutoPreloadSystemSoTask_0100, Function | MediumTest | Level1) +{ + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + + startupManager->preloadSystemSoStartupTasks_.clear(); + EXPECT_EQ(ERR_OK, startupManager->RunAppAutoPreloadSystemSoTask()); + + startupManager->preloadSystemSoStartupTasks_.emplace("testName1", + std::make_shared("testName1", "")); + startupManager->preloadSystemSoStartupTasks_.emplace("testName2", + std::make_shared("testName2", "url")); + startupManager->preloadSystemSoStartupTasks_.emplace("testName3", + std::make_shared("testName3", "testUrl")); + startupManager->preloadSystemSoStartupTasks_.emplace("testName4", + std::make_shared("testName4", "@ohos:testUrl")); + startupManager->preloadSystemSoStartupTasks_.emplace("testName4", + std::make_shared("testName4", "@ohos:account.osAccount")); + + EXPECT_EQ(ERR_STARTUP_TIMEOUT, startupManager->RunAppAutoPreloadSystemSoTask()); +} } } \ No newline at end of file -- Gitee