diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp index e435d21a3f..e90cd54e5d 100644 --- a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp @@ -626,7 +626,7 @@ bool ETSEnvironment::PostFork(void *napiEnv, const std::string &aotPath, std::vector options; std::string aotPathString = ""; if (!aotPath.empty()) { - aotPathString = "--ext:--aot-file=" + aotPath; + aotPathString = "--ext:--aot-files=" + aotPath; options.push_back(ani_option { aotPathString.data(), nullptr }); options.push_back(ani_option { "--ext:--enable-an", nullptr }); TAG_LOGD(AAFwkTag::ETSRUNTIME, "aotPathString: %{public}s", aotPathString.c_str()); diff --git a/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp b/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp index 6a3b70a159..e10896089b 100644 --- a/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp +++ b/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp @@ -296,6 +296,7 @@ HWTEST_F(EtsEnvironmentTest, LoadAbcLinker_0200, TestSize.Level0) etsEnv->vmEntry_.abcLinkerRef_ = reinterpret_cast(0x123); OHOS::AbilityRuntime::CommonHspBundleInfo info; + info.versionCode = 0; info.bundleName = "bundle"; info.moduleName = "module"; info.hapPath = "/data/app/el1/bundle/public/hsp/test.hsp"; @@ -599,6 +600,7 @@ HWTEST_F(EtsEnvironmentTest, SetHspAbcFiles_0300, TestSize.Level0) ASSERT_NE(etsEnv, nullptr); OHOS::AbilityRuntime::CommonHspBundleInfo info; + info.versionCode = 0; info.bundleName = "bundle"; info.moduleName = "module"; info.hapPath = "/data/app/el1/bundle/public/hsp/test.hsp"; @@ -630,6 +632,7 @@ HWTEST_F(EtsEnvironmentTest, SetHspAbcFiles_0400, TestSize.Level0) ASSERT_NE(etsEnv, nullptr); OHOS::AbilityRuntime::CommonHspBundleInfo info; + info.versionCode = 0; info.bundleName = "bundle"; info.moduleName = "module"; info.hapPath = "/data/app/el1/bundle/public/hsp/test.hsp"; @@ -656,6 +659,7 @@ HWTEST_F(EtsEnvironmentTest, SetHspAbcFiles_0500, TestSize.Level0) ASSERT_NE(etsEnv, nullptr); OHOS::AbilityRuntime::CommonHspBundleInfo info; + info.versionCode = 0; info.bundleName = "bundle"; info.moduleName = "module"; info.hapPath = "/data/app/el1/bundle/public/hsp/test.hsp"; @@ -682,6 +686,7 @@ HWTEST_F(EtsEnvironmentTest, SetHspAbcFiles_0600, TestSize.Level0) ASSERT_NE(etsEnv, nullptr); OHOS::AbilityRuntime::CommonHspBundleInfo info; + info.versionCode = 0; info.bundleName = "bundle"; info.moduleName = "module"; info.hapPath = "/data/app/el1/bundle/public/hsp/test.hsp"; diff --git a/frameworks/native/appkit/app/main_thread.cpp b/frameworks/native/appkit/app/main_thread.cpp index 0de8a685b4..ffb181cce0 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -1801,7 +1801,8 @@ void MainThread::HandleLaunchApplication(const AppLaunchData &appLaunchData, con } } for (const auto &hsp : hspList) { - options.commonHspBundleInfos.push_back({hsp.bundleName, hsp.moduleName, hsp.hapPath, hsp.moduleArkTSMode}); + options.commonHspBundleInfos.push_back({hsp.versionCode, hsp.bundleName, hsp.moduleName, + hsp.hapPath, hsp.moduleArkTSMode}); } options.enableWarmStartupSmartGC = (appLaunchData.GetAppPreloadMode() == AppExecFwk::PreloadMode::PRE_MAKE || diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp index e28a75d822..e82cd15e34 100644 --- a/frameworks/native/runtime/ets_runtime.cpp +++ b/frameworks/native/runtime/ets_runtime.cpp @@ -62,7 +62,10 @@ const std::string ETS_SYSLIB_PATH = #endif constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/"; constexpr char SANDBOX_ARK_CACHE_PATH[] = "/data/storage/ark-cache/"; +constexpr char SANDBOX_SHARED_BUNDLE_ARK_CACHE_PATH[] = + "/data/service/el1/public/for-all-app/shared_bundles_ark_cache/"; constexpr char MERGE_ABC_PATH[] = "/ets/modules_static.abc"; +const std::string SYS_HSP_FILE_PATH_PREFIX = "/system/app/"; const char *ETS_ENV_LIBNAME = "libets_environment.z.so"; const char *ETS_ENV_REGISTER_FUNCS = "OHOS_ETS_ENV_RegisterFuncs"; @@ -157,6 +160,48 @@ void ETSRuntime::PreloadLibrary() } } +std::string ETSRuntime::GetAotPath(const Options &options) +{ + std::vector aotFiles; + if (!options.arkNativeFilePath.empty()) { + // Handle Hap and Inner Hsp + // path: /arm64/.an + for (const auto& status: options.aotCompileStatusMap) { + if (status.second) { + aotFiles.push_back(SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath + status.first + ".an"); + } + } + + // Handle Outer Hsp + for (const auto& bundleInfo: options.commonHspBundleInfos) { + if (bundleInfo.moduleArkTSMode == AppExecFwk::Constants::ARKTS_MODE_DYNAMIC) { + continue; + } + + if (bundleInfo.hapPath.compare(0, SYS_HSP_FILE_PATH_PREFIX.size(), SYS_HSP_FILE_PATH_PREFIX) != 0 && + bundleInfo.hapPath.rfind('/') == std::string::npos) { + continue; + } + + // path: //v/arm64/.an + std::string outerHspAnPath = SANDBOX_SHARED_BUNDLE_ARK_CACHE_PATH + bundleInfo.bundleName + + std::string(AbilityBase::Constants::FILE_SEPARATOR) + std::to_string(bundleInfo.versionCode) + + std::string(AbilityBase::Constants::FILE_SEPARATOR) + options.arkNativeFilePath + + bundleInfo.moduleName + ".an"; + aotFiles.push_back(outerHspAnPath); + } + } + + std::string aotFilePath; + for (const auto& path: aotFiles) { + if (!aotFilePath.empty()) { + aotFilePath += ":"; + } + aotFilePath += path; + } + return aotFilePath; +} + bool ETSRuntime::PostFork(const Options &options, std::unique_ptr &jsRuntime, bool isMove) { TAG_LOGD(AAFwkTag::ETSRUNTIME, "PostFork begin"); @@ -184,12 +229,7 @@ bool ETSRuntime::PostFork(const Options &options, std::unique_ptr &jsRu vm, HybridJsModuleReader(options.bundleName, options.hapPath, options.isUnique)); } - std::string aotFilePath = ""; - if (!options.arkNativeFilePath.empty()) { - aotFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath + options.moduleName + ".an"; - } - - g_etsEnvFuncs->PostFork(reinterpret_cast(napiEnv), aotFilePath, options.appInnerHspPathList, + g_etsEnvFuncs->PostFork(reinterpret_cast(napiEnv), GetAotPath(options), options.appInnerHspPathList, options.commonHspBundleInfos, options.eventRunner); return true; } diff --git a/interfaces/inner_api/runtime/include/ets_runtime.h b/interfaces/inner_api/runtime/include/ets_runtime.h index 1aed999233..7d7b1ae424 100644 --- a/interfaces/inner_api/runtime/include/ets_runtime.h +++ b/interfaces/inner_api/runtime/include/ets_runtime.h @@ -107,6 +107,7 @@ private: std::unique_ptr LoadEtsModule(const std::string &moduleName, const std::string &fileName, const std::string &hapPath, const std::string &srcEntrance); bool PostFork(const Options &options, std::unique_ptr &jsRuntime, bool isMove = true); + std::string GetAotPath(const Options &options); std::string HandleOhmUrlSrcEntry(const std::string &srcEntry); void HandleOhmUrlFileName(std::string &fileName); static void PreloadLibrary(); diff --git a/interfaces/inner_api/runtime/include/runtime.h b/interfaces/inner_api/runtime/include/runtime.h index c7d1d0c54b..f844985efb 100644 --- a/interfaces/inner_api/runtime/include/runtime.h +++ b/interfaces/inner_api/runtime/include/runtime.h @@ -28,6 +28,7 @@ class EventRunner; } // namespace AppExecFwk namespace AbilityRuntime { struct CommonHspBundleInfo { + uint32_t versionCode; std::string bundleName; std::string moduleName; std::string hapPath; diff --git a/test/unittest/runtime_test/ets_runtime_test.cpp b/test/unittest/runtime_test/ets_runtime_test.cpp index 573ae536f6..fdada9029a 100644 --- a/test/unittest/runtime_test/ets_runtime_test.cpp +++ b/test/unittest/runtime_test/ets_runtime_test.cpp @@ -22,6 +22,7 @@ #include "ets_runtime.h" #undef private #undef protected +#include "bundle_constants.h" #include "hilog_tag_wrapper.h" #include "js_runtime.h" #include "runtime.h" @@ -338,5 +339,250 @@ HWTEST_F(EtsRuntimeTest, SetExtensionApiCheckCallback_100, TestSize.Level1) etsRuntime->SetExtensionApiCheckCallback(callback); EXPECT_EQ(etsRuntime->GetJsRuntime(), nullptr); } + +/** + * @tc.name: GetHspPathList_100 + * @tc.desc: EtsRuntime test for GetHspPathList. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetHspPathList_100, TestSize.Level1) +{ + std::unique_ptr etsEnvironment = std::make_unique(); + etsEnvironment->commonHspBundleInfos_ = {}; + auto hspPathList = etsEnvironment->GetHspPathList(); + EXPECT_EQ(hspPathList.size(), 0); +} + +/** + * @tc.name: GetHspPathList_200 + * @tc.desc: EtsRuntime test for GetHspPathList. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetHspPathList_200, TestSize.Level1) +{ + std::unique_ptr etsEnvironment = std::make_unique(); + etsEnvironment->commonHspBundleInfos_ = {{0, "", "", "/system/app/path1", "static"}}; + auto hspPathList = etsEnvironment->GetHspPathList(); + EXPECT_EQ(hspPathList[0], "/system/app/path1"); +} + +/** + * @tc.name: GetAotPath_001 + * @tc.desc: EtsRuntime test for GetAotPath with empty arkNativeFilePath. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_001, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = ""; + auto result = etsRuntime->GetAotPath(options); + EXPECT_EQ(result, ""); +} + +/** + * @tc.name: GetAotPath_002 + * @tc.desc: EtsRuntime test for GetAotPath with arkNativeFilePath but empty maps. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_002, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "testModule"; + options.aotCompileStatusMap = {}; + options.commonHspBundleInfos = {}; + auto result = etsRuntime->GetAotPath(options); + EXPECT_EQ(result, ""); +} + +/** + * @tc.name: GetAotPath_003 + * @tc.desc: EtsRuntime test for GetAotPath with aotCompileStatusMap having true values. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_003, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {{"entry", true}, {"module1", true}, {"module2", false}}; + options.commonHspBundleInfos = {}; + auto result = etsRuntime->GetAotPath(options); + // Should contain entry.an and module1.an (true values only) + EXPECT_NE(result.find("entry.an"), std::string::npos); + EXPECT_NE(result.find("module1.an"), std::string::npos); + EXPECT_EQ(result.find("module2.an"), std::string::npos); +} + +/** + * @tc.name: GetAotPath_004 + * @tc.desc: EtsRuntime test for GetAotPath with aotCompileStatusMap all false. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_004, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "test"; + options.aotCompileStatusMap = {{"module1", false}, {"module2", false}}; + options.commonHspBundleInfos = {}; + auto result = etsRuntime->GetAotPath(options); + EXPECT_EQ(result, ""); +} + +/** + * @tc.name: GetAotPath_005 + * @tc.desc: EtsRuntime test for GetAotPath with commonHspBundleInfos ARKTS_MODE_DYNAMIC. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_005, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {}; + // ARKTS_MODE_DYNAMIC should be skipped + std::vector hspInfos = { + {1001, "com.example.hsp1", "hspModule1", "/system/app/hsp1.hap", AppExecFwk::Constants::ARKTS_MODE_DYNAMIC} + }; + options.commonHspBundleInfos = hspInfos; + auto result = etsRuntime->GetAotPath(options); + EXPECT_EQ(result, ""); +} + +/** + * @tc.name: GetAotPath_006 + * @tc.desc: EtsRuntime test for GetAotPath with commonHspBundleInfos static mode, system path. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_006, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {}; + // Static mode with system app path - should be included + std::vector hspInfos = { + {1001, "com.example.hsp1", "hspModule1", "/system/app/hsp1.hap", AppExecFwk::Constants::ARKTS_MODE_STATIC} + }; + options.commonHspBundleInfos = hspInfos; + auto result = etsRuntime->GetAotPath(options); + // Should contain the outer HSP path + EXPECT_NE(result.find("/data/service/el1/public/for-all-app/shared_bundles_ark_cache/"), std::string::npos); + EXPECT_NE(result.find("com.example.hsp1"), std::string::npos); + EXPECT_NE(result.find("hspModule1.an"), std::string::npos); +} + +/** + * @tc.name: GetAotPath_007 + * @tc.desc: EtsRuntime test for GetAotPath with commonHspBundleInfos non-system path without slash. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_007, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {}; + // Non-system path (doesn't start with /system/app/) and has no '/' - should be skipped + std::vector hspInfos = { + {1001, "com.example.hsp1", "hspModule1", "relativePathWithoutSlash", AppExecFwk::Constants::ARKTS_MODE_STATIC} + }; + options.commonHspBundleInfos = hspInfos; + auto result = etsRuntime->GetAotPath(options); + EXPECT_EQ(result, ""); +} + +/** + * @tc.name: GetAotPath_008 + * @tc.desc: EtsRuntime test for GetAotPath with commonHspBundleInfos non-system path with slash. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_008, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {}; + // Non-system path but has '/' - should be included + std::vector hspInfos = { + {1001, "com.example.hsp1", "hspModule1", "/data/app/hsp1.hap", AppExecFwk::Constants::ARKTS_MODE_STATIC} + }; + options.commonHspBundleInfos = hspInfos; + auto result = etsRuntime->GetAotPath(options); + // Should contain the outer HSP path + EXPECT_NE(result.find("com.example.hsp1"), std::string::npos); + EXPECT_NE(result.find("hspModule1.an"), std::string::npos); +} + +/** + * @tc.name: GetAotPath_009 + * @tc.desc: EtsRuntime test for GetAotPath with multiple commonHspBundleInfos entries. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_009, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {{"entry", true}}; + // Mix of different HSP types + std::vector hspInfos = { + // Dynamic mode - should be skipped + {1001, "com.example.hsp1", "hspModule1", "/system/app/hsp1.hap", AppExecFwk::Constants::ARKTS_MODE_DYNAMIC}, + // Static mode, system path - should be included + {1002, "com.example.hsp2", "hspModule2", "/system/app/hsp2.hap", AppExecFwk::Constants::ARKTS_MODE_STATIC}, + // Static mode, non-system path with slash - should be included + {1003, "com.example.hsp3", "hspModule3", "/data/app/hsp3.hap", AppExecFwk::Constants::ARKTS_MODE_STATIC}, + // Non-system path without slash - should be skipped + {1004, "com.example.hsp4", "hspModule4", "relativePath", AppExecFwk::Constants::ARKTS_MODE_STATIC} + }; + options.commonHspBundleInfos = hspInfos; + auto result = etsRuntime->GetAotPath(options); + // Should contain entry.an (from aotCompileStatusMap) + EXPECT_NE(result.find("entry.an"), std::string::npos); + // Should contain hsp2 (static mode, system path) + EXPECT_NE(result.find("hspModule2.an"), std::string::npos); + // Should contain hsp3 (non-system path with slash) + EXPECT_NE(result.find("hspModule3.an"), std::string::npos); + // Should NOT contain hsp1 (dynamic mode) + EXPECT_EQ(result.find("hspModule1.an"), std::string::npos); + // Should NOT contain hsp4 (relative path without slash) + EXPECT_EQ(result.find("hspModule4.an"), std::string::npos); + // Check that paths are separated by colons + EXPECT_NE(result.find(":"), std::string::npos); +} + +/** + * @tc.name: GetAotPath_010 + * @tc.desc: EtsRuntime test for GetAotPath with complete options including versionCode. + * @tc.type: FUNC + */ +HWTEST_F(EtsRuntimeTest, GetAotPath_010, TestSize.Level1) +{ + auto etsRuntime = std::make_unique(); + Runtime::Options options; + options.arkNativeFilePath = "arm64/"; + options.moduleName = "entry"; + options.aotCompileStatusMap = {{"entry", true}}; + std::vector hspInfos = { + {1002003, "com.example.hsp", "hspModule", "/system/app/hsp.hap", AppExecFwk::Constants::ARKTS_MODE_STATIC} + }; + options.commonHspBundleInfos = hspInfos; + auto result = etsRuntime->GetAotPath(options); + // Should include version in the path + EXPECT_NE(result.find("1002003"), std::string::npos); + // Should have proper path structure + EXPECT_NE(result.find("/data/service/el1/public/for-all-app/shared_bundles_ark_cache/"), std::string::npos); +} } // namespace AbilityRuntime -} // namespace OHOS \ No newline at end of file +} // namespace OHOS