From 18158d344800f891b33d9ac563ad84b5be681eed Mon Sep 17 00:00:00 2001 From: hanchen45 Date: Wed, 20 May 2026 14:47:14 +0800 Subject: [PATCH] abilitystage set launchElement Co-Authored-By: Agent Signed-off-by: hanchen45 --- frameworks/native/appkit/app/main_thread.cpp | 2 +- .../native/appkit/app/ohos_application.cpp | 115 ++++-- .../kits/native/appkit/app/ohos_application.h | 15 +- .../main_thread_test/main_thread_test.cpp | 114 ++++++ .../ohos_application_test.cpp | 352 ++++++++++++++++++ 5 files changed, 565 insertions(+), 33 deletions(-) diff --git a/frameworks/native/appkit/app/main_thread.cpp b/frameworks/native/appkit/app/main_thread.cpp index 12d98fef41..bf6c6c6c4d 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -2371,7 +2371,7 @@ void MainThread::PreloadModule(const BundleInfo &bundleInfo, const AppLaunchData TAG_LOGI(AAFwkTag::APPKIT, "preload module %{public}s", preloadModuleInfo->moduleName.c_str()); auto callback = []() {}; bool isAsyncCallback = false; - application_->AddAbilityStage(*preloadModuleInfo, callback, isAsyncCallback); + application_->AddAbilityStage(*preloadModuleInfo, callback, isAsyncCallback, preloadAbilityName); if (isAsyncCallback) { return; } diff --git a/frameworks/native/appkit/app/ohos_application.cpp b/frameworks/native/appkit/app/ohos_application.cpp index 394271accf..1864be239f 100644 --- a/frameworks/native/appkit/app/ohos_application.cpp +++ b/frameworks/native/appkit/app/ohos_application.cpp @@ -470,6 +470,80 @@ void OHOSApplication::PreloadHybridModule(const HapModuleInfo &hapModuleInfo) co runtime_->PreloadModule(hapModuleInfo.moduleName, hapModuleInfo.hapPath, isEsmode, useCommonTrunk); } +void OHOSApplication::SetLaunchElementForStage( + const std::shared_ptr &stageContext, + const std::shared_ptr &moduleInfo, + const std::string &abilityName) +{ + if (!stageContext || !moduleInfo) { + TAG_LOGE(AAFwkTag::APPKIT, "null stageContext or moduleInfo"); + return; + } + + AppExecFwk::ElementName elementName; + elementName.SetBundleName(moduleInfo->bundleName); + elementName.SetModuleName(moduleInfo->moduleName); + elementName.SetAbilityName(abilityName); + TAG_LOGD(AAFwkTag::APPKIT, "Set launchElement to stageContext: %{public}s/%{public}s", + elementName.GetBundleName().c_str(), elementName.GetAbilityName().c_str()); + stageContext->SetLaunchElement(elementName); +} + +std::shared_ptr OHOSApplication::CreateAndInitStageContext( + const AppExecFwk::HapModuleInfo &hapModuleInfo) +{ + auto stageContext = std::make_shared(); + stageContext->SetParentContext(abilityRuntimeContext_); + stageContext->InitHapModuleInfo(hapModuleInfo); + stageContext->SetConfiguration(GetConfiguration()); + stageContext->SetProcessName(GetProcessName()); + auto moduleInfo = stageContext->GetHapModuleInfo(); + if (moduleInfo == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null moduleInfo"); + return nullptr; + } + + if (abilityRuntimeContext_->GetApplicationInfo() && + abilityRuntimeContext_->GetApplicationInfo()->multiProjects) { + auto rm = stageContext->CreateModuleContext(hapModuleInfo.moduleName)->GetResourceManager(); + stageContext->SetResourceManager(rm); + } + LoadDeduplicatedHarResource(stageContext); + return stageContext; +} + +bool OHOSApplication::ExecuteAutoStartupTasks(std::shared_ptr abilityStage, + const AppExecFwk::HapModuleInfo &hapModuleInfo, + const std::function &callback, + bool &isAsyncCallback, + const std::shared_ptr &stageContext) +{ + if (abilityStage == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); + return false; + } + + auto firstCallback = CreateFirstStartupCallbackForHap(abilityStage, hapModuleInfo, callback); + if (firstCallback != nullptr) { + abilityStage->RunAutoStartupTask(firstCallback, nullptr, isAsyncCallback, stageContext, true); + if (isAsyncCallback) { + TAG_LOGI(AAFwkTag::APPKIT, "wait startup first"); + return false; + } + } + TAG_LOGD(AAFwkTag::APPKIT, "no wait startup first"); + abilityStage->LoadModule(hapModuleInfo); + auto secondCallback = CreateSecondStartupCallbackForHap(abilityStage, hapModuleInfo, callback); + if (firstCallback != nullptr) { + abilityStage->RunAutoStartupTask(secondCallback, nullptr, isAsyncCallback, stageContext, false); + if (isAsyncCallback) { + TAG_LOGI(AAFwkTag::APPKIT, "wait startup second"); + return false; + } + } + return true; +} + std::shared_ptr OHOSApplication::AddAbilityStage( const std::shared_ptr &abilityRecord, const std::function &)> &callback, bool &isAsyncCallback) @@ -805,7 +879,7 @@ void OHOSApplication::UpdateApplicationInfoInstalled(const AppExecFwk::Applicati bool OHOSApplication::AddAbilityStage( const AppExecFwk::HapModuleInfo &hapModuleInfo, - const std::function &callback, bool &isAsyncCallback) + const std::function &callback, bool &isAsyncCallback, const std::string &preloadAbilityName) { TAG_LOGD(AAFwkTag::APPKIT, "called"); if (abilityRuntimeContext_ == nullptr) { @@ -823,48 +897,27 @@ bool OHOSApplication::AddAbilityStage( return false; } - auto stageContext = std::make_shared(); - stageContext->SetParentContext(abilityRuntimeContext_); - stageContext->InitHapModuleInfo(hapModuleInfo); - stageContext->SetConfiguration(GetConfiguration()); - stageContext->SetProcessName(GetProcessName()); - auto moduleInfo = stageContext->GetHapModuleInfo(); - if (moduleInfo == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "null moduleInfo"); + auto stageContext = CreateAndInitStageContext(hapModuleInfo); + if (stageContext == nullptr) { return false; } - if (abilityRuntimeContext_->GetApplicationInfo() && abilityRuntimeContext_->GetApplicationInfo()->multiProjects) { - auto rm = stageContext->CreateModuleContext(hapModuleInfo.moduleName)->GetResourceManager(); - stageContext->SetResourceManager(rm); - } - LoadDeduplicatedHarResource(stageContext); + auto moduleInfo = stageContext->GetHapModuleInfo(); auto &runtime = GetSpecifiedRuntime(moduleInfo->arkTSMode); auto abilityStage = AbilityRuntime::AbilityStage::Create(runtime, *moduleInfo); if (abilityStage == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "null abilityStage"); return false; } + std::string abilityName = preloadAbilityName.empty() ? moduleInfo->mainAbility : preloadAbilityName; + SetLaunchElementForStage(stageContext, moduleInfo, abilityName); + auto application = std::static_pointer_cast(shared_from_this()); std::weak_ptr weak = application; abilityStage->Init(stageContext, weak); - auto firstCallback = CreateFirstStartupCallbackForHap(abilityStage, hapModuleInfo, callback); - if (firstCallback != nullptr) { - abilityStage->RunAutoStartupTask(firstCallback, nullptr, isAsyncCallback, stageContext, true); - if (isAsyncCallback) { - TAG_LOGI(AAFwkTag::APPKIT, "wait startup first"); - return false; - } - } - TAG_LOGD(AAFwkTag::APPKIT, "no wait startup first"); - abilityStage->LoadModule(hapModuleInfo); - auto secondCallback = CreateSecondStartupCallbackForHap(abilityStage, hapModuleInfo, callback); - if (firstCallback != nullptr) { - abilityStage->RunAutoStartupTask(secondCallback, nullptr, isAsyncCallback, stageContext, false); - if (isAsyncCallback) { - TAG_LOGI(AAFwkTag::APPKIT, "wait startup second"); - return false; - } + + if (!ExecuteAutoStartupTasks(abilityStage, hapModuleInfo, callback, isAsyncCallback, stageContext)) { + return false; } TAG_LOGD(AAFwkTag::APPKIT, "no wait startup second"); diff --git a/interfaces/kits/native/appkit/app/ohos_application.h b/interfaces/kits/native/appkit/app/ohos_application.h index 6cffaf6104..a9ba4e1931 100644 --- a/interfaces/kits/native/appkit/app/ohos_application.h +++ b/interfaces/kits/native/appkit/app/ohos_application.h @@ -152,11 +152,13 @@ public: * @brief add the ability stage when a hap first load * * @param hapModuleInfo + * @param preloadAbilityName The ability name for preload scenario * @return Returns true on success, false on failure */ bool AddAbilityStage( const AppExecFwk::HapModuleInfo &hapModuleInfo, - const std::function &callback, bool &isAsyncCallback); + const std::function &callback, bool &isAsyncCallback, + const std::string &preloadAbilityName = ""); /** * @brief remove the ability stage when all of the abilities in the hap have been removed @@ -286,6 +288,17 @@ private: void PreloadHybridModule(const HapModuleInfo &hapModuleInfo) const; void LoadDeduplicatedHarResource( const std::shared_ptr &stageContext); + void SetLaunchElementForStage( + const std::shared_ptr &stageContext, + const std::shared_ptr &moduleInfo, + const std::string &abilityName); + std::shared_ptr CreateAndInitStageContext( + const AppExecFwk::HapModuleInfo &hapModuleInfo); + bool ExecuteAutoStartupTasks(std::shared_ptr abilityStage, + const AppExecFwk::HapModuleInfo &hapModuleInfo, + const std::function &callback, + bool &isAsyncCallback, + const std::shared_ptr &stageContext); const std::function CreateFirstStartupCallbackForRecord( std::shared_ptr abilityStage, diff --git a/test/unittest/appkit/main_thread_test/main_thread_test.cpp b/test/unittest/appkit/main_thread_test/main_thread_test.cpp index eecc68f5db..14f2278b1d 100644 --- a/test/unittest/appkit/main_thread_test/main_thread_test.cpp +++ b/test/unittest/appkit/main_thread_test/main_thread_test.cpp @@ -3024,5 +3024,119 @@ HWTEST_F(MainThreadTest, GetPluginNativeLibPath_0500, TestSize.Level1) EXPECT_EQ(appLibPaths["pluginBundleName/validModule"][0], "/data/storage/el1/bundle/+plugins/libs/arm"); } + +/* +* Feature: MainThread +* Function: PreloadModule +* SubFunction: NA +* FunctionPoints: PreloadModule with preloadAbilityName +* EnvConditions: NA +* CaseDescription: Verify PreloadModule calls AddAbilityStage with preloadAbilityName +*/ +HWTEST_F(MainThreadTest, PreloadModule_WithPreloadAbilityName_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "%{public}s start.", __func__); + + // Setup application + mainThread_->application_ = std::make_shared(); + mainThread_->application_->SetRuntime(std::make_unique()); + + // Prepare BundleInfo + BundleInfo bundleInfo; + bundleInfo.name = "com.example.test"; + bundleInfo.bundleName = "com.example.test"; + + // Prepare HapModuleInfo for preload + HapModuleInfo preloadModuleInfo; + preloadModuleInfo.bundleName = "com.example.test"; + preloadModuleInfo.moduleName = "entry"; + preloadModuleInfo.mainAbility = "MainAbility"; + preloadModuleInfo.arkTSMode = AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0; + bundleInfo.hapModuleInfos.emplace_back(preloadModuleInfo); + + // Prepare AppLaunchData + AppLaunchData appLaunchData; + appLaunchData.SetPreloadModuleName("entry"); + appLaunchData.SetPreloadAbilityName("PreloadTargetAbility"); + + // Call PreloadModule + mainThread_->PreloadModule(bundleInfo, appLaunchData, preloadModuleInfo, + mainThread_->application_->GetRuntime()); + + // Verify abilityStage was created with launchElement set + auto& abilityStages = mainThread_->application_->abilityStages_; + EXPECT_GT(abilityStages.size(), 0u); + + auto it = abilityStages.find("entry"); + if (it != abilityStages.end()) { + auto abilityStage = it->second; + auto stageContext = std::static_pointer_cast(abilityStage->GetContext()); + ASSERT_NE(stageContext, nullptr); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetAbilityName(), "PreloadTargetAbility"); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "entry"); + } + + TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); +} + +/* +* Feature: MainThread +* Function: PreloadModule +* SubFunction: NA +* FunctionPoints: PreloadModule with empty preloadAbilityName +* EnvConditions: NA +* CaseDescription: Verify PreloadModule uses mainAbility when preloadAbilityName is empty +*/ +HWTEST_F(MainThreadTest, PreloadModule_WithEmptyPreloadAbilityName_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "%{public}s start.", __func__); + + // Setup application + mainThread_->application_ = std::make_shared(); + mainThread_->application_->SetRuntime(std::make_unique()); + + // Prepare BundleInfo + BundleInfo bundleInfo; + bundleInfo.name = "com.example.test"; + bundleInfo.bundleName = "com.example.test"; + + // Prepare HapModuleInfo for preload + HapModuleInfo preloadModuleInfo; + preloadModuleInfo.bundleName = "com.example.test"; + preloadModuleInfo.moduleName = "entry"; + preloadModuleInfo.mainAbility = "MainAbility"; + preloadModuleInfo.arkTSMode = AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0; + bundleInfo.hapModuleInfos.emplace_back(preloadModuleInfo); + + // Prepare AppLaunchData with empty preloadAbilityName + AppLaunchData appLaunchData; + appLaunchData.SetPreloadModuleName("entry"); + appLaunchData.SetPreloadAbilityName(""); // Empty - should use mainAbility + + // Call PreloadModule + mainThread_->PreloadModule(bundleInfo, appLaunchData, preloadModuleInfo, + mainThread_->application_->GetRuntime()); + + // Verify abilityStage was created with mainAbility as fallback + auto& abilityStages = mainThread_->application_->abilityStages_; + EXPECT_GT(abilityStages.size(), 0u); + + auto it = abilityStages.find("entry"); + if (it != abilityStages.end()) { + auto abilityStage = it->second; + auto stageContext = std::static_pointer_cast(abilityStage->GetContext()); + ASSERT_NE(stageContext, nullptr); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetAbilityName(), "MainAbility"); // Should use mainAbility + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "entry"); + } + + TAG_LOGI(AAFwkTag::TEST, "%{public}s end.", __func__); +} } // namespace AppExecFwk } // namespace OHOS diff --git a/test/unittest/appkit/ohos_application_test/ohos_application_test.cpp b/test/unittest/appkit/ohos_application_test/ohos_application_test.cpp index 71e4fba9b4..15e0d75d13 100644 --- a/test/unittest/appkit/ohos_application_test/ohos_application_test.cpp +++ b/test/unittest/appkit/ohos_application_test/ohos_application_test.cpp @@ -2289,5 +2289,357 @@ HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_OnTerminate_0200, T ohosApplication_->OnTerminate(); EXPECT_NE(ohosApplication_->abilityRuntimeContext_, nullptr); } + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0100 +* @tc.name: SetLaunchElementForStage +* @tc.desc: Verify SetLaunchElementForStage with valid parameters +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0100 start."; + + auto stageContext = std::make_shared(); + ASSERT_NE(stageContext, nullptr); + + auto moduleInfo = std::make_shared(); + moduleInfo->bundleName = "com.example.test"; + moduleInfo->moduleName = "entry"; + moduleInfo->mainAbility = "MainAbility"; + + std::string abilityName = "MainAbility"; + + ohosApplication_->SetLaunchElementForStage(stageContext, moduleInfo, abilityName); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "entry"); + EXPECT_EQ(launchElement.GetAbilityName(), "MainAbility"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0100 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0200 +* @tc.name: SetLaunchElementForStage +* @tc.desc: Verify SetLaunchElementForStage with null stageContext +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0200, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0200 start."; + + std::shared_ptr stageContext = nullptr; + auto moduleInfo = std::make_shared(); + moduleInfo->bundleName = "com.example.test"; + moduleInfo->moduleName = "entry"; + + std::string abilityName = "MainAbility"; + + ohosApplication_->SetLaunchElementForStage(stageContext, moduleInfo, abilityName); + + EXPECT_TRUE(true); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0200 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0300 +* @tc.name: SetLaunchElementForStage +* @tc.desc: Verify SetLaunchElementForStage with null moduleInfo +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0300, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0300 start."; + + auto stageContext = std::make_shared(); + ASSERT_NE(stageContext, nullptr); + + std::shared_ptr moduleInfo = nullptr; + std::string abilityName = "MainAbility"; + + ohosApplication_->SetLaunchElementForStage(stageContext, moduleInfo, abilityName); + + EXPECT_TRUE(true); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0300 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0400 +* @tc.name: SetLaunchElementForStage +* @tc.desc: Verify SetLaunchElementForStage with custom abilityName (preload scenario) +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0400, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0400 start."; + + auto stageContext = std::make_shared(); + ASSERT_NE(stageContext, nullptr); + + auto moduleInfo = std::make_shared(); + moduleInfo->bundleName = "com.example.test"; + moduleInfo->moduleName = "entry"; + moduleInfo->mainAbility = "MainAbility"; + + std::string abilityName = "PreloadAbility"; + + ohosApplication_->SetLaunchElementForStage(stageContext, moduleInfo, abilityName); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "entry"); + EXPECT_EQ(launchElement.GetAbilityName(), "PreloadAbility"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_SetLaunchElementForStage_0400 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0100 +* @tc.name: CreateAndInitStageContext +* @tc.desc: Verify CreateAndInitStageContext success +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0100 start."; + + // Setup application context + ohosApplication_->abilityRuntimeContext_ = std::make_shared(); + ohosApplication_->configuration_ = std::make_shared(); + + AppExecFwk::HapModuleInfo hapModuleInfo; + hapModuleInfo.bundleName = "com.example.test"; + hapModuleInfo.moduleName = "entry"; + hapModuleInfo.mainAbility = "MainAbility"; + + auto stageContext = ohosApplication_->CreateAndInitStageContext(hapModuleInfo); + + ASSERT_NE(stageContext, nullptr); + + auto moduleInfo = stageContext->GetHapModuleInfo(); + ASSERT_NE(moduleInfo, nullptr); + EXPECT_EQ(moduleInfo->bundleName, "com.example.test"); + EXPECT_EQ(moduleInfo->moduleName, "entry"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0100 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0200 +* @tc.name: CreateAndInitStageContext +* @tc.desc: Verify CreateAndInitStageContext with multiProjects scenario +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0200, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0200 start."; + + // Setup application context with multiProjects + auto applicationContext = std::make_shared(); + auto appInfo = std::make_shared(); + appInfo->multiProjects = true; + applicationContext->SetApplicationInfo(appInfo); + + ohosApplication_->abilityRuntimeContext_ = applicationContext; + ohosApplication_->configuration_ = std::make_shared(); + + AppExecFwk::HapModuleInfo hapModuleInfo; + hapModuleInfo.bundleName = "com.example.test"; + hapModuleInfo.moduleName = "entry"; + + auto stageContext = ohosApplication_->CreateAndInitStageContext(hapModuleInfo); + + ASSERT_NE(stageContext, nullptr); + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_CreateAndInitStageContext_0200 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_ExecuteAutoStartupTasks_0100 +* @tc.name: ExecuteAutoStartupTasks +* @tc.desc: Verify ExecuteAutoStartupTasks with null abilityStage +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_ExecuteAutoStartupTasks_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_ExecuteAutoStartupTasks_0100 start."; + + std::shared_ptr abilityStage = nullptr; + AppExecFwk::HapModuleInfo hapModuleInfo; + auto callback = []() {}; + bool isAsyncCallback = false; + auto stageContext = std::make_shared(); + + auto result = ohosApplication_->ExecuteAutoStartupTasks( + abilityStage, hapModuleInfo, callback, isAsyncCallback, stageContext); + + EXPECT_FALSE(result); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_ExecuteAutoStartupTasks_0100 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0100 +* @tc.name: AddAbilityStage with preloadAbilityName +* @tc.desc: Verify AddAbilityStage with non-empty preloadAbilityName (preload scenario) +*/ +HWTEST_F(OHOSApplicationTest, + AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0100 start."; + + ohosApplication_->abilityRuntimeContext_ = std::make_shared(); + ohosApplication_->runtime_ = std::make_unique(); + ohosApplication_->configuration_ = std::make_shared(); + + AppExecFwk::HapModuleInfo hapModuleInfo; + hapModuleInfo.bundleName = "com.example.test"; + hapModuleInfo.moduleName = "entry"; + hapModuleInfo.mainAbility = "MainAbility"; + hapModuleInfo.arkTSMode = AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0; + + auto callback = []() {}; + bool isAsyncCallback = false; + std::string preloadAbilityName = "PreloadAbility"; + + auto result = ohosApplication_->AddAbilityStage(hapModuleInfo, callback, isAsyncCallback, preloadAbilityName); + + EXPECT_TRUE(result); + EXPECT_FALSE(ohosApplication_->abilityStages_.empty()); + + auto abilityStage = ohosApplication_->abilityStages_["entry"]; + ASSERT_NE(abilityStage, nullptr); + auto stageContext = std::static_pointer_cast(abilityStage->GetContext()); + ASSERT_NE(stageContext, nullptr); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetAbilityName(), "PreloadAbility"); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "entry"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0100 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0200 +* @tc.name: AddAbilityStage with empty preloadAbilityName +* @tc.desc: Verify AddAbilityStage with empty preloadAbilityName (fallback to mainAbility) +*/ +HWTEST_F(OHOSApplicationTest, + AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0200, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0200 start."; + + ohosApplication_->abilityRuntimeContext_ = std::make_shared(); + ohosApplication_->runtime_ = std::make_unique(); + ohosApplication_->configuration_ = std::make_shared(); + + AppExecFwk::HapModuleInfo hapModuleInfo; + hapModuleInfo.bundleName = "com.example.test"; + hapModuleInfo.moduleName = "feature"; + hapModuleInfo.mainAbility = "FeatureAbility"; + hapModuleInfo.arkTSMode = AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0; + + auto callback = []() {}; + bool isAsyncCallback = false; + std::string preloadAbilityName = ""; + + auto result = ohosApplication_->AddAbilityStage(hapModuleInfo, callback, isAsyncCallback, preloadAbilityName); + + EXPECT_TRUE(result); + EXPECT_FALSE(ohosApplication_->abilityStages_.empty()); + + auto abilityStage = ohosApplication_->abilityStages_["feature"]; + ASSERT_NE(abilityStage, nullptr); + auto stageContext = std::static_pointer_cast(abilityStage->GetContext()); + ASSERT_NE(stageContext, nullptr); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetAbilityName(), "FeatureAbility"); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "feature"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0200 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0300 +* @tc.name: AddAbilityStage without preloadAbilityName +* @tc.desc: Verify AddAbilityStage backward compatibility (default parameter) +*/ +HWTEST_F(OHOSApplicationTest, + AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0300, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0300 start."; + + ohosApplication_->abilityRuntimeContext_ = std::make_shared(); + ohosApplication_->runtime_ = std::make_unique(); + ohosApplication_->configuration_ = std::make_shared(); + + AppExecFwk::HapModuleInfo hapModuleInfo; + hapModuleInfo.bundleName = "com.example.test"; + hapModuleInfo.moduleName = "service"; + hapModuleInfo.mainAbility = "ServiceAbility"; + hapModuleInfo.arkTSMode = AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0; + + auto callback = []() {}; + bool isAsyncCallback = false; + + auto result = ohosApplication_->AddAbilityStage(hapModuleInfo, callback, isAsyncCallback); + + EXPECT_TRUE(result); + EXPECT_FALSE(ohosApplication_->abilityStages_.empty()); + + auto abilityStage = ohosApplication_->abilityStages_["service"]; + ASSERT_NE(abilityStage, nullptr); + auto stageContext = std::static_pointer_cast(abilityStage->GetContext()); + ASSERT_NE(stageContext, nullptr); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetAbilityName(), "ServiceAbility"); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.test"); + EXPECT_EQ(launchElement.GetModuleName(), "service"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_WithPreloadAbilityName_0300 end."; +} + +/* +* @tc.number: AppExecFwk_OHOSApplicationTest_AddAbilityStage_PreloadScenario_0100 +* @tc.name: AddAbilityStage preload scenario integration test +* @tc.desc: Verify complete preload scenario with launchElement +*/ +HWTEST_F(OHOSApplicationTest, AppExecFwk_OHOSApplicationTest_AddAbilityStage_PreloadScenario_0100, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_PreloadScenario_0100 start."; + + ohosApplication_->abilityRuntimeContext_ = std::make_shared(); + ohosApplication_->runtime_ = std::make_unique(); + ohosApplication_->configuration_ = std::make_shared(); + + AppExecFwk::HapModuleInfo preloadModuleInfo; + preloadModuleInfo.bundleName = "com.example.preload"; + preloadModuleInfo.moduleName = "preload_entry"; + preloadModuleInfo.mainAbility = "EntryAbility"; + preloadModuleInfo.arkTSMode = AbilityRuntime::CODE_LANGUAGE_ARKTS_1_0; + + std::string preloadAbilityName = "TargetPreloadAbility"; + + auto callback = []() {}; + bool isAsyncCallback = false; + + auto result = ohosApplication_->AddAbilityStage( + preloadModuleInfo, callback, isAsyncCallback, preloadAbilityName); + + EXPECT_TRUE(result); + EXPECT_EQ(ohosApplication_->abilityStages_.size(), 1u); + + auto abilityStage = ohosApplication_->abilityStages_["preload_entry"]; + ASSERT_NE(abilityStage, nullptr); + auto stageContext = std::static_pointer_cast(abilityStage->GetContext()); + ASSERT_NE(stageContext, nullptr); + + auto launchElement = stageContext->GetLaunchElement(); + EXPECT_EQ(launchElement.GetBundleName(), "com.example.preload"); + EXPECT_EQ(launchElement.GetModuleName(), "preload_entry"); + EXPECT_EQ(launchElement.GetAbilityName(), "TargetPreloadAbility"); + + GTEST_LOG_(INFO) << "AppExecFwk_OHOSApplicationTest_AddAbilityStage_PreloadScenario_0100 end."; +} } // namespace AppExecFwk } // namespace OHOS