diff --git a/frameworks/ets/ani/BUILD.gn b/frameworks/ets/ani/BUILD.gn index f487ec8a1225f3956c9d5fa7ec48d2bfa9ee867f..e66d071925a0a3606f2a41655a82026ded428ebd 100644 --- a/frameworks/ets/ani/BUILD.gn +++ b/frameworks/ets/ani/BUILD.gn @@ -21,6 +21,7 @@ group("ani_packages") { "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", "${ability_runtime_path}/frameworks/ets/ani/ani_wantagent_common:ani_wantagent_common", "${ability_runtime_path}/frameworks/ets/ani/app_manager:ability_app_manager_ani_kit", + "${ability_runtime_path}/frameworks/ets/ani/app_startup/startup_manager:startup_manager_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/form_extension_ability:form_extension_ability_etc", "${ability_runtime_path}/frameworks/ets/ani/insight_intent/insight_intent_driver:insight_intent_driver_ani_kit", "${ability_runtime_path}/frameworks/ets/ani/native_constructor:context_ani", diff --git a/frameworks/ets/ani/app_startup/startup_manager/BUILD.gn b/frameworks/ets/ani/app_startup/startup_manager/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f3ee5bdc35b6c53512adb054d00d487bba38047e --- /dev/null +++ b/frameworks/ets/ani/app_startup/startup_manager/BUILD.gn @@ -0,0 +1,70 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/ability/ability_runtime/ability_runtime.gni") + +ohos_shared_library("startup_manager_ani_kit") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + + include_dirs = [ + "./include", + "${ability_runtime_path}/frameworks/ets/ani/ani_common/include", + "${ability_runtime_path}/interfaces/inner_api/error_utils/include", + "${ability_runtime_path}/interfaces/inner_api/runtime/include", + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_runtime/app", + "${ability_runtime_path}/interfaces/kits/native/ability/native", + "${ability_runtime_path}/interfaces/kits/native/appkit/app_startup", + "${ability_runtime_services_path}/common/include", + ] + + configs = [] + + public_configs = [] + + sources = [ + "./src/ets_startup_manager.cpp", + "./src/ets_startup_config.cpp", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + deps = [ + "${ability_runtime_innerkits_path}/runtime:runtime", + "${ability_runtime_native_path}/appkit:appkit_native", + "${ability_runtime_path}/frameworks/ets/ani/ani_common:ani_common", + ] + + external_deps = [ + "ability_base:base", + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "napi:ace_napi", + "runtime_core:ani", + ] + + innerapi_tags = [ "platformsdk" ] + subsystem_name = "ability" + part_name = "ability_runtime" +} \ No newline at end of file diff --git a/frameworks/ets/ani/app_startup/startup_manager/include/ets_startup_config.h b/frameworks/ets/ani/app_startup/startup_manager/include/ets_startup_config.h new file mode 100644 index 0000000000000000000000000000000000000000..0fca5c3b7dfe1a9a86a2e98574ba80320a706955 --- /dev/null +++ b/frameworks/ets/ani/app_startup/startup_manager/include/ets_startup_config.h @@ -0,0 +1,49 @@ +/* + * 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_ETS_STARTUP_CONFIG_H +#define OHOS_ABILITY_RUNTIME_ETS_STARTUP_CONFIG_H + +#include + +#include "startup_config.h" +#include "startup_utils.h" +#include "sts_runtime.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsStartupConfig : public StartupConfig { +public: + EtsStartupConfig(ani_env *env); + + ~EtsStartupConfig() override; + + int32_t Init(std::unique_ptr &configEntryRef); + + int32_t Init(ani_object config); + + static ani_object GetConfigFromEntry(ani_env *env, std::unique_ptr &configEntryRef); + + static ani_object BuildResult(ani_env *env, const std::shared_ptr &result); + +private: + ani_env *env_; + + void InitAwaitTimeout(ani_env *env, ani_object config); + void InitListener(ani_env *env, ani_object config); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_STARTUP_CONFIG_H diff --git a/frameworks/ets/ani/app_startup/startup_manager/include/ets_startup_manager.h b/frameworks/ets/ani/app_startup/startup_manager/include/ets_startup_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..3992930dc5cbd32bcbbc72dc2d730b953cbbdc2c --- /dev/null +++ b/frameworks/ets/ani/app_startup/startup_manager/include/ets_startup_manager.h @@ -0,0 +1,49 @@ +/* + * 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_ETS_STARTUP_MANAGER_H +#define OHOS_ABILITY_RUNTIME_ETS_STARTUP_MANAGER_H + +#include "ani.h" +#include "startup_manager.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsStartupManager { +public: + EtsStartupManager() = default; + + ~EtsStartupManager() = default; + + static ani_object OnRun(ani_env *env, ani_object startupTasks, + ani_object config, ani_object call); + + static void OnRemoveAllResult(ani_env *env); + + static ani_object OnGetResult(ani_env *env, ani_string startupTask); + + static ani_boolean OnIsInitialized(ani_env *env, ani_string startupTask); + + static void OnRemoveResult(ani_env *env, ani_string startupTask); + +private: + + static int32_t GetConfig(ani_env *env, ani_object value, std::shared_ptr &config); + + static int32_t RunStartupTask(ani_env *env, ani_object startupTasks, ani_object config, + std::shared_ptr &startupTaskManager); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_STARTUP_MANAGER_H diff --git a/frameworks/ets/ani/app_startup/startup_manager/src/ets_startup_config.cpp b/frameworks/ets/ani/app_startup/startup_manager/src/ets_startup_config.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4a31b845d6478b049c73f3c5514c127b08f5b49 --- /dev/null +++ b/frameworks/ets/ani/app_startup/startup_manager/src/ets_startup_config.cpp @@ -0,0 +1,173 @@ +/* + * 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 "ets_startup_config.h" +#include "ets_runtime_utils.h" +#include "hilog_tag_wrapper.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { + +EtsStartupConfig::EtsStartupConfig(ani_env *env) : StartupConfig(), env_(env) +{ + +} + +EtsStartupConfig::~EtsStartupConfig() = default; + +int32_t EtsStartupConfig::Init(std::unique_ptr &configEntryRef) +{ + if (configEntryRef == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null configEntry"); + return ERR_STARTUP_INTERNAL_ERROR; + } + + ani_ref configEntry = configEntryRef->aniRef; + ani_boolean isUndefined = true; + ani_ref onConfig = nullptr; + if (!GetFieldRef(env, configEntry, "onConfig", onConfig, isUndefined)) { + TAG_LOGE(AAFwkTag::STARTUP, "GetFieldRef failed"); + return; + } + + if (isUndefined) { + TAG_LOGD(AAFwkTag::STARTUP, "onConfig undefined"); + return; + } + + ani_ref config; + std::vector argv = { }; + status = env->FunctionalObject_Call(static_cast(onConfig), 0, argv, &config); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "FunctionalObject_Call status: %{public}d", status); + return; + } + + InitAwaitTimeout(env_, config); + InitListener(env_, config); + return ERR_OK; +} + +int32_t EtsStartupConfig::Init(ani_object config) +{ + if (config == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null config"); + return ERR_STARTUP_INTERNAL_ERROR; + } + + InitAwaitTimeout(env_, config); + InitListener(env_, config); + return ERR_OK; +} + +void EtsStartupConfig::InitAwaitTimeout(ani_env *env, ani_object config) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return; + } + + int32_t awaitTimeoutNum = DEFAULT_AWAIT_TIMEOUT_MS; + if (IsExistsProperty(env, config, "timeoutMs")) { + double awaitTimeoutD = 0.0; + if (!GetDoublePropertyObject(env, config, "timeoutMs", awaitTimeoutD)) { + TAG_LOGE(AAFwkTag::STARTUP, "GetDoublePropertyObject failed"); + return; + } + awaitTimeoutNum = static_cast(awaitTimeoutD); + } + + if (awaitTimeoutNum <= 0) { + TAG_LOGE(AAFwkTag::STARTUP, "invalid argc"); + awaitTimeoutNum = DEFAULT_AWAIT_TIMEOUT_MS; + } + TAG_LOGD(AAFwkTag::STARTUP, "set awaitTimeoutMs to %{public}d", awaitTimeoutNum); + awaitTimeoutMs_ = awaitTimeoutNum; +} + +void EtsStartupConfig::InitListener(ani_env *env, ani_object config) +{ + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return; + } + + if (!IsExistsProperty(env, config, "startupListener")) { + TAG_LOGD(AAFwkTag::STARTUP, "null startupListener"); + return; + } + + ani_ref listener = nullptr; + if (!GetRefProperty(env, config, "startupListener", listener)) { + TAG_LOGE(AAFwkTag::STARTUP, "GetRefProperty failed"); + return; + } + + ani_boolean isUndefined = true; + ani_ref onCompleted = nullptr; + if (!GetFieldRef(env, listener, "onCompleted", onCompleted, isUndefined)) { + TAG_LOGE(AAFwkTag::STARTUP, "GetFieldRef failed"); + return; + } + + if (isUndefined) { + TAG_LOGD(AAFwkTag::STARTUP, "onCompleted undefined"); + return; + } + + OnCompletedCallbackFunc onCompletedCallback = + [env, listener](const std::shared_ptr &result) { + if (env == nullptr || listener == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env or listener"); + return; + } + + ani_boolean isUndefined = true; + ani_ref onCompleted = nullptr; + if (!GetFieldRef(env, listener, "onCompleted", onCompleted, isUndefined)) { + TAG_LOGE(AAFwkTag::STARTUP, "GetFieldRef failed"); + return; + } + + if (!isUndefined) { + TAG_LOGE(AAFwkTag::STARTUP, "onCompleted undefined"); + return; + } + ani_object resultObj = EtsStartupConfig::BuildResult(env, result); + ani_ref fnReturn; + std::vector argv = { resultObj }; + status = env->FunctionalObject_Call(static_cast(onCompleted), 1, argv, &fnReturn); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::FORM_EXT, "FunctionalObject_Call status: %{public}d", status); + return; + } + } + listener_ = std::make_shared(onCompletedCallback); +} + +ani_object EtsStartupConfig::BuildResult(ani_env *env, const std::shared_ptr &result) +{ + if (result == nullptr) { + return CreateStsError(env, ERR_STARTUP_INTERNAL_ERROR, + StartupUtils::GetErrorMessage(ERR_STARTUP_INTERNAL_ERROR)); + } + if (result->GetResultCode() != ERR_OK) { + return CreateStsError(env, result->GetResultCode(), result->GetResultMessage()); + } + return CreateEtsNull(env); +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ani/app_startup/startup_manager/src/ets_startup_manager.cpp b/frameworks/ets/ani/app_startup/startup_manager/src/ets_startup_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..498e1423cc4f23b171a3124730c3d5c111f086dc --- /dev/null +++ b/frameworks/ets/ani/app_startup/startup_manager/src/ets_startup_manager.cpp @@ -0,0 +1,304 @@ +/* + * 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 "ets_startup_manager.h" +#include "ets_startup_config.h" +#include "ets_startup_task_result.h" +#include "ability_runtime_error_util.h" +#include "ani_common_util.h" +#include "ets_runtime_utils.h" +#include "hilog_tag_wrapper.h" +#include "sts_error_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +using namespace AppExecFwk; + +ani_object EtsStartupManager::OnRun(ani_env *env, ani_object startupTasks, + ani_object config, ani_object call) +{ + TAG_LOGD(AAFwkTag::STARTUP, "OnRun called"); + if(env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return {}; + } + + std::shared_ptr startupTaskManager = nullptr; + int32_t result = RunStartupTask(env, startupTasks, config, startupTaskManager); + if (result != ERR_OK) { + ThrowStsError(env, result, StartupUtils::GetErrorMessage(result)); + return CreateEtsUndefined(env); + } + + ani_vm *vm = nullptr; + if (env->GetVM(&vm) != ANI_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "GetVM failed"); + ThrowStsError(env, ERR_STARTUP_INTERNAL_ERROR, StartupUtils::GetErrorMessage(ERR_STARTUP_INTERNAL_ERROR)); + return CreateEtsUndefined(env); + } + + ani_ref callRef = nullptr; + if (env->GlobalReference_Create(call, &callRef) != ANI_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "GlobalReference_Create failed"); + ThrowStsError(env, ERR_STARTUP_INTERNAL_ERROR, StartupUtils::GetErrorMessage(ERR_STARTUP_INTERNAL_ERROR)); + return CreateEtsUndefined(env); + } + + auto callback = std::make_shared( + [vm, callRef](const std::shared_ptr &result) { + + ani_env *env = nullptr; + ani_status status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "status: %{public}d", status); + return; + } + + if (result == nullptr || result->GetResultCode() != ERR_OK) { + ani_object error = EtsStartupConfig::BuildResult(env, result); + AppExecFwk::AsyncCallback(env, static_cast(callRef), error, CreateEtsNull(env)); + env->GlobalReference_Delete(callRef); + return; + } + ani_object resolution = EtsStartupConfig::BuildResult(env, result); + AppExecFwk::AsyncCallback(env, static_cast(callRef), resolution, CreateEtsNull(env)); + env->GlobalReference_Delete(callRef); + return; + }); + result = startupTaskManager->Run(callback); + if (result != ERR_OK) { + if (!callback->IsCalled()) { + env->GlobalReference_Delete(callRef); + ThrowStsError(env, result, StartupUtils::GetErrorMessage(result)); + return CreateEtsUndefined(env); + } + } + return CreateEtsNull(env); +} + +void EtsStartupManager::OnRemoveAllResult(ani_env *env) +{ + TAG_LOGD(AAFwkTag::STARTUP, "OnRemoveAllResult called"); + if(env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return; + } + DelayedSingleton::GetInstance()->RemoveAllResult(); + return; +} + +ani_object EtsStartupManager::OnGetResult(ani_env *env, ani_string startupTask) +{ + TAG_LOGD(AAFwkTag::STARTUP, "OnGetResult called"); + if(env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return {}; + } + + std::string startupTaskStd; + if (!AniStringToStdString(env, startupTask, startupTaskStd)) { + TAG_LOGE(AAFwkTag::STARTUP, "convert failed"); + ThrowStsInvalidParamError(env, "Parameter error: Failed to convert startupTask, must be a string."); + return CreateEtsUndefined(env); + } + + std::shared_ptr result; + int32_t res = DelayedSingleton::GetInstance()->GetResult(startupTaskStd, result); + if (res != ERR_OK || result == nullptr || result->GetResultCode() != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "get %{public}s result failed", startupTaskStd.c_str()); + ThrowStsInvalidParamError(env, "Parameter error: Failed to get result."); + return CreateEtsUndefined(env); + } + if (result->GetResultType() != StartupTaskResult::ResultType::ETS) { + return CreateEtsUndefined(env); + } + std::shared_ptr etsResult = std::static_pointer_cast(result); + if (etsResult == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null etsResult: %{public}s", startupTaskStd.c_str()); + ThrowStsInvalidParamError(env, "Parameter error: Failed to convert to js result."); + return CreateEtsUndefined(env); + } + std::shared_ptr etsResultRef = etsResult->GetEtsStartupResultRef(); + if (etsResultRef == nullptr) { + return CreateEtsUndefined(env); + } + return static_cast(etsResultRef->aniRef); +} + +ani_object EtsStartupManager::OnIsInitialized(ani_env *env, ani_string startupTask) +{ + TAG_LOGD(AAFwkTag::STARTUP, "OnIsInitialized called"); + if(env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return {}; + } + + std::string startupTaskStd; + if (!AniStringToStdString(env, startupTask, startupTaskStd)) { + TAG_LOGE(AAFwkTag::STARTUP, "convert failed"); + ThrowStsInvalidParamError(env, "Parameter error: Failed to convert startupTask," + "must be a string or startupTask name is not matched."); + return CreateEtsUndefined(env); + } + + bool isInitialized = false; + int32_t res = DelayedSingleton::GetInstance()->IsInitialized(startupTaskStd, isInitialized); + if (res != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "get %{public}s if initialized failed:%{public}d", startupTaskStd.c_str(), res); + ThrowStsInvalidParamError(env, "Parameter error: Startup manager not initialized."); + return CreateEtsUndefined(env); + } + return createBoolean(env, isInitialized); +} + +void EtsStartupManager::OnRemoveResult(ani_env *env, ani_string startupTask) +{ + TAG_LOGD(AAFwkTag::STARTUP, "OnRemoveResult called"); + if(env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return; + } + + std::string startupTaskStd; + if (!AniStringToStdString(env, startupTask, startupTaskStd)) { + TAG_LOGE(AAFwkTag::STARTUP, "convert failed"); + ThrowStsInvalidParamError(env, "Parameter error: Failed to convert startupTask," + "must be a string or startupTask name is not matched."); + return; + } + + int32_t res = DelayedSingleton::GetInstance()->RemoveResult(startupTaskStd); + if (res != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "remove %{public}s result failed:%{public}d", startupTaskStd.c_str(), res); + ThrowStsInvalidParamError(env, "Parameter error: Failed to remove result."); + return; + } + return; +} + +int32_t EtsStartupManager::GetConfig(ani_env *env, ani_object value, std::shared_ptr &config) +{ + std::shared_ptr startupConfig = std::make_shared(env); + if (startupConfig == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null startupConfig"); + return ERR_STARTUP_INTERNAL_ERROR; + } + if (startupConfig->Init(value) != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "init config failed"); + ThrowStsInvalidParamError(env, "Parameter error: Failed to init config, must be a StartupConfig."); + return ERR_STARTUP_INVALID_VALUE; + } + config = startupConfig; + return ERR_OK; +} + +int32_t EtsStartupManager::RunStartupTask(ani_env *env, ani_object startupTasks, ani_object config, + std::shared_ptr &startupTaskManager) +{ + std::vector dependencies; + if (!UnWrapArrayString(env, startupTasks, dependencies)) { + TAG_LOGE(AAFwkTag::STARTUP, "get dependencies failed"); + return ERR_STARTUP_INVALID_VALUE; + } + std::shared_ptr configCpp; + ani_boolean isUndefined = true; + ani_status status = env->Reference_IsUndefined(config, &isUndefined); + if (status == ANI_OK) { + if (!isUndefined) { + int32_t result = GetConfig(env, config, configCpp); + if (result != ANI_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "get config failed"); + return ERR_STARTUP_INVALID_VALUE; + } + } + } else { + TAG_LOGE(AAFwkTag::STARTUP, "Reference_IsUndefined failed status: %{public}d", status); + return ERR_STARTUP_INTERNAL_ERROR; + } + + int32_t result = DelayedSingleton::GetInstance()->BuildAppStartupTaskManager(dependencies, + startupTaskManager); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "build manager failed: %{public}d", result); + return result; + } + if (startupTaskManager == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null startupTaskMgr"); + return ERR_STARTUP_INTERNAL_ERROR; + } + result = startupTaskManager->Prepare(); + if (result != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "prepare startup failed: %{public}d", result); + return result; + } + if (configCpp != nullptr) { + startupTaskManager->SetConfig(configCpp); + } + return ERR_OK; +} +void EtsStartupManagerInit(ani_env *env) +{ + TAG_LOGD(AAFwkTag::STARTUP, "EtsStartupManagerInit called"); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return; + } + + ani_namespace ns; + ani_status status = env->FindNamespace("L@ohos/app/ability/startupManager/startupManager;", &ns); + if (status != ANI_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "FindNamespace startupManager failed status: %{public}d", status); + return; + } + + std::array kitFunctions = { + ani_native_function {"nativeRunSync", nullptr, + reinterpret_cast(EtsStartupManager::OnRun)}, + ani_native_function {"nativeRemoveAllStartupTaskResults", nullptr, + reinterpret_cast(EtsStartupManager::OnRemoveAllResult)}, + ani_native_function {"nativeGetStartupTaskResult", nullptr, + reinterpret_cast(EtsStartupManager::OnGetResult)}, + ani_native_function {"nativeIsStartupTaskInitialized", nullptr, + reinterpret_cast(EtsStartupManager::OnIsInitialized)}, + ani_native_function {"nativeRemoveStartupTaskResult", nullptr, + reinterpret_cast(EtsStartupManager::OnRemoveResult)}, + }; + + status = env->Namespace_BindNativeFunctions(ns, kitFunctions.data(), kitFunctions.size()); + if (status != ANI_OK && status != ANI_ALREADY_BINDED) { + TAG_LOGE(AAFwkTag::STARTUP, "bind native functions failed status: %{public}d", status); + } +} + +extern "C" { +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + TAG_LOGD(AAFwkTag::STARTUP, "ANI_Constructor"); + ani_env *env = nullptr; + ani_status status = ANI_ERROR; + status = vm->GetEnv(ANI_VERSION_1, &env); + if (status != ANI_OK) { + TAG_LOGD(AAFwkTag::STARTUP, "GetEnv failed status: %{public}d", status); + return ANI_NOT_FOUND; + } + + EtsStartupManagerInit(env); + *result = ANI_VERSION_1; + TAG_LOGD(AAFwkTag::STARTUP, "ANI_Constructor finish"); + return ANI_OK; +} +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/ets/ets/@ohos.app.appstartup.StartupConfig.ets b/frameworks/ets/ets/@ohos.app.appstartup.StartupConfig.ets new file mode 100644 index 0000000000000000000000000000000000000000..69be02293ac597cfe98b3e2971e4921dcc25b974 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.appstartup.StartupConfig.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +import StartupListener from './@ohos.app.appstartup.StartupListener'; + + +export default interface StartupConfig { + + timeoutMs?: number; + + startupListener?: StartupListener; +} + +export class StartupConfigInner implements ExecuteResult{ + + timeoutMs?: number; + + startupListener?: StartupListener; +} \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.appstartup.StartupConfigEntry.ets b/frameworks/ets/ets/@ohos.app.appstartup.StartupConfigEntry.ets new file mode 100644 index 0000000000000000000000000000000000000000..ba36f020eb8ad6280e6c1cf47792c544bacc47fd --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.appstartup.StartupConfigEntry.ets @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import StartupConfig from './@ohos.app.appstartup.StartupConfig'; + +declare class StartupConfigEntry { + + onConfig?(): StartupConfig; +} + +export default StartupConfigEntry; \ No newline at end of file diff --git a/frameworks/ets/ets/@ohos.app.appstartup.StartupListener.ets b/frameworks/ets/ets/@ohos.app.appstartup.StartupListener.ets new file mode 100644 index 0000000000000000000000000000000000000000..0357015830fbf660c94767445f45e9bc5a9df2ba --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.appstartup.StartupListener.ets @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { BusinessError } from './@ohos.base'; + +export default class StartupListener { + + onCompleted?(error: BusinessError): void; +} diff --git a/frameworks/ets/ets/@ohos.app.appstartup.StartupTask.ets b/frameworks/ets/ets/@ohos.app.appstartup.StartupTask.ets new file mode 100644 index 0000000000000000000000000000000000000000..05d0dace526f57ac06cbb77adc492a3c4fbeb78e --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.appstartup.StartupTask.ets @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import AbilityStageContext from './application/AbilityStageContext'; + +@Sendable +export default class StartupTask { + + onDependencyCompleted?(dependency: string, result: Object): void; + + init(context: AbilityStageContext): Promise; +} diff --git a/frameworks/ets/ets/@ohos.app.appstartup.startupManager.ets b/frameworks/ets/ets/@ohos.app.appstartup.startupManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..fe1ff926295c0a42805bc3b1019aa5cce93a1007 --- /dev/null +++ b/frameworks/ets/ets/@ohos.app.appstartup.startupManager.ets @@ -0,0 +1,62 @@ +/* + * 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. + */ + +import StartupConfig from './@ohos.app.appstartup.StartupConfig'; +import AsyncCallbackWrapper from './utils/AbilityUtils'; + +declare namespace startupManager { + + loadLibrary("startupmanager_ani_kit.z") + + native function nativeRunSync(startupTasks: Array, config: StartupConfig, + callback: AsyncCallbackWrapper): void; + native function nativeRemoveAllStartupTaskResults(): void; + native function nativeGetStartupTaskResult(startupTask: string): Object; + native function nativeIsStartupTaskInitialized(startupTask: string): boolean; + native function nativeRemoveStartupTaskResult(startupTask): void; + + export function run(startupTasks: Array, config?: StartupConfig): Promise { + return new Promise((resolve: (data:undefined)=>void, reject:(err: BusinessError)=>void):void => { + let asyncCall = new AsyncCallbackWrapper((err: BusinessError)=>{ + if (err.code == 0) { + resolve(undefined); + } else { + reject(err); + } + }); + taskpool.execute((): void =>{ + nativeRunSync(startupTasks, config, asyncCall); + }); + }); + } + + export function removeAllStartupTaskResults(): void { + nativeRemoveAllStartupTaskResults(); + } + + export function getStartupTaskResult(startupTask: string): Object { + return nativeGetStartupTaskResult(startupTask); + } + + export function isStartupTaskInitialized(startupTask: string): boolean { + return nativeIsStartupTaskInitialized(startupTask); + } + + export function removeStartupTaskResult(startupTask: string): void { + nativeRemoveStartupTaskResult(startupTask); + } +} + +export default startupManager; \ No newline at end of file diff --git a/frameworks/ets/ets/BUILD.gn b/frameworks/ets/ets/BUILD.gn index 08da661a1467ca9860d2f50ed2fe344869e9230c..32ee1e44947ed318b5601895286229218a5e5a30 100644 --- a/frameworks/ets/ets/BUILD.gn +++ b/frameworks/ets/ets/BUILD.gn @@ -867,6 +867,22 @@ ohos_prebuilt_etc("ability_runtime_auto_fill_type_abc_etc") { deps = [ ":ability_runtime_auto_fill_type_abc" ] } +generate_static_abc("ability_runtime_appstartup_startupManager_abc") { + base_url = "./" + files = [ "./@ohos.app.appstartup.startupManager.ets" ] + + is_boot_abc = "True" + device_dst_file = "/system/framework/ability_runtime_appstartup_startupManager_abc.abc" +} + +ohos_prebuilt_etc("ability_runtime_appstartup_startupManager_abc_etc") { + source = "$target_out_dir/ability_runtime_appstartup_startupManager_abc.abc" + module_install_dir = "framework" + subsystem_name = "ability" + part_name = "ability_runtime" + deps = [ ":ability_runtime_appstartup_startupManager_abc" ] +} + group("ets_packages") { deps = [ ":ability_ability_application_abc_etc", @@ -890,6 +906,7 @@ group("ets_packages") { ":ability_runtime_app_manager_abc_etc", ":ability_runtime_app_state_data_abc_etc", ":ability_runtime_application_context_abc_etc", + ":ability_runtime_appstartup_startupManager_abc_etc", ":ability_runtime_auto_fill_type_abc_etc", ":ability_runtime_base_context_abc_etc", ":ability_runtime_configuration_abc_etc", diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index cd68900ebef4d3b8893d886af1424b97ee90fbcd..e4258e79eb8861961a8bf4330a317c6ddfe5534a 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/ohos_application.cpp", "${ability_runtime_native_path}/appkit/app/res_helper.cpp", "${ability_runtime_native_path}/appkit/app_startup/app_startup_task.cpp", + "${ability_runtime_native_path}/appkit/app_startup/ets_startup_task_result.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_config.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_task.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_task_executor.cpp", diff --git a/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp b/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp index f7d1553fe21073f55c63fb29144ae67c6384dfa6..23947cb54a68548e019ed130e82755f91b75d4ce 100644 --- a/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp +++ b/frameworks/native/appkit/ability_runtime/app/sts_ability_stage.cpp @@ -53,6 +53,18 @@ void RegisterStopPreloadSoCallback(STSRuntime& stsRuntime) TAG_LOGE(AAFwkTag::APPKIT, "null startupManager"); return; } + if (!startupManager->HasAppStartupConfig()) { + // no app startup config, no need to register stop preload so callback. + return; + } + stsRuntime.SetStopPreloadSoCallback([]()-> void { + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + if (startupManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupManager"); + return; + } + startupManager->StopAutoPreloadSoTask(); + }); } } // namespace @@ -185,33 +197,190 @@ void STSAbilityStage::OnMemoryLevel(int32_t level) int32_t STSAbilityStage::RunAutoStartupTask(const std::function &callback, bool &isAsyncCallback, const std::shared_ptr &stageContext) { + TAG_LOGD(AAFwkTag::APPKIT, "RunAutoStartupTask called"); isAsyncCallback = false; + auto context = GetContext(); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + return ERR_INVALID_VALUE; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + if (!hapModuleInfo) { + TAG_LOGE(AAFwkTag::APPKIT, "null hapModuleInfo"); + return ERR_INVALID_VALUE; + } + if (hapModuleInfo->moduleType != AppExecFwk::ModuleType::ENTRY) { + TAG_LOGD(AAFwkTag::APPKIT, "not entry module"); + return ERR_INVALID_VALUE; + } + if (hapModuleInfo->appStartup.empty()) { + TAG_LOGD(AAFwkTag::APPKIT, "entry module no app startup config"); + return ERR_INVALID_VALUE; + } + + SetJsAbilityStage(stageContext); + + int32_t result = RegisterAppStartupTask(hapModuleInfo); + if (result != ERR_OK) { + return result; + } return RunAutoStartupTaskInner(callback, isAsyncCallback); } int32_t STSAbilityStage::RegisterAppStartupTask(const std::shared_ptr& hapModuleInfo) { + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + if (startupManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupManager"); + return ERR_INVALID_VALUE; + } + bool needRunAutoStartupTask = false; + int32_t result = startupManager->LoadAppStartupTaskConfig(needRunAutoStartupTask); + if (result != ERR_OK) { + return result; + } + if (!needRunAutoStartupTask) { + return ERR_OK; + } + + //TODO dxp + //stsRuntime_.UpdateModuleNameAndAssetPath(hapModuleInfo->moduleName); + + const std::string &configEntry = startupManager->GetPendingConfigEntry(); + if (!LoadEtsStartupConfig(configEntry)) { + TAG_LOGE(AAFwkTag::APPKIT, "load js appStartup config failed."); + return ERR_INVALID_VALUE; + } + + const std::vector &startupTaskInfos = startupManager->GetStartupTaskInfos(); + for (const auto& item : startupTaskInfos) { + std::unique_ptr startupStsRef = LoadEtsOhmUrl( + item.srcEntry, item.ohmUrl, item.moduleName, item.hapPath, item.esModule); + if (startupStsRef == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "load ets appStartup tasks failed."); + continue; + } + + auto etsStartupTask = std::make_shared(item.name, stsRuntime_, startupJsRef, shellContextRef_); + etsStartupTask->SetDependencies(item.dependencies); + etsStartupTask->SetIsExcludeFromAutoStart(item.excludeFromAutoStart); + etsStartupTask->SetCallCreateOnMainThread(item.callCreateOnMainThread); + etsStartupTask->SetWaitOnMainThread(item.waitOnMainThread); + startupManager->RegisterAppStartupTask(item.name, etsStartupTask); + } return ERR_OK; } int32_t STSAbilityStage::RunAutoStartupTaskInner(const std::function &callback, bool &isAsyncCallback) { + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + if (startupManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupManager"); + return ERR_INVALID_VALUE; + } + std::shared_ptr startupTaskManager = nullptr; + int32_t result = startupManager->BuildAutoAppStartupTaskManager(startupTaskManager); + if (result != ERR_OK) { + return result; + } + result = startupTaskManager->Prepare(); + if (result != ERR_OK) { + return result; + } + auto runAutoStartupCallback = std::make_shared( + [callback](const std::shared_ptr &) { + TAG_LOGI(AAFwkTag::APPKIT, "RunAutoStartupCallback"); + callback(); + }); + result = startupTaskManager->Run(runAutoStartupCallback); + if (result != ERR_OK) { + isAsyncCallback = runAutoStartupCallback->IsCalled(); + return result; + } + isAsyncCallback = true; return ERR_OK; } -std::unique_ptr STSAbilityStage::LoadJsOhmUrl(const std::string &srcEntry, +std::unique_ptr STSAbilityStage::LoadEtsOhmUrl(const std::string &srcEntry, const std::string &ohmUrl, const std::string &moduleName, const std::string &hapPath, bool esmodule) { - return nullptr; + TAG_LOGD(AAFwkTag::APPKIT, "LoadEtsOhmUrl call"); + if (srcEntry.empty() && ohmUrl.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "srcEntry and ohmUrl empty"); + return nullptr; + } + + std::string moduleNameWithStartupTask = moduleName + "::startupTask"; + std::string srcPath(moduleName + "/" + srcEntry); + auto pos = srcPath.rfind('.'); + if (pos == std::string::npos) { + return nullptr; + } + srcPath.erase(pos); + srcPath.append(".abc"); + + return stsRuntime_.LoadModule(moduleNameWithStartupTask, srcPath, hapPath, esmodule, false, ohmUrl); } -std::unique_ptr STSAbilityStage::LoadJsSrcEntry(const std::string &srcEntry) +std::unique_ptr STSAbilityStage::LoadEtsSrcEntry(const std::string &srcEntry) { - return nullptr; + TAG_LOGD(AAFwkTag::APPKIT, "LoadEtsSrcEntry call"); + if (srcEntry.empty()) { + TAG_LOGE(AAFwkTag::APPKIT, "srcEntry invalid"); + return nullptr; + } + auto context = GetContext(); + if (!context) { + TAG_LOGE(AAFwkTag::APPKIT, "null context"); + return nullptr; + } + auto hapModuleInfo = context->GetHapModuleInfo(); + if (!hapModuleInfo) { + TAG_LOGE(AAFwkTag::APPKIT, "null hapModuleInfo"); + return nullptr; + } + + bool esmodule = hapModuleInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE; + std::string moduleName(hapModuleInfo->moduleName); + std::string srcPath(moduleName + "/" + srcEntry); + + auto pos = srcPath.rfind('.'); + if (pos == std::string::npos) { + return nullptr; + } + srcPath.erase(pos); + srcPath.append(".abc"); + + //TODO dxp srcEntry + return stsRuntime_.LoadModule(moduleName, srcPath, hapModuleInfo->hapPath, esmodule); } -bool STSAbilityStage::LoadJsStartupConfig(const std::string &srcEntry) +bool STSAbilityStage::LoadEtsStartupConfig(const std::string &srcEntry) { + std::unique_ptr startupConfigEntry = LoadEtsSrcEntry(srcEntry); + if (startupConfigEntry == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupConfigEntry"); + return false; + } + auto env = stsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null env"); + return false; + } + std::shared_ptr startupConfig = std::make_shared(env); + if (startupConfig == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupConfig"); + return false; + } + if (startupConfig->Init(startupConfigEntry) != ERR_OK) { + return false; + } + std::shared_ptr startupManager = DelayedSingleton::GetInstance(); + if (startupManager == nullptr) { + TAG_LOGE(AAFwkTag::APPKIT, "null startupManager"); + return false; + } + startupManager->SetDefaultConfig(startupConfig); return true; } diff --git a/frameworks/native/appkit/app_startup/ets_startup_task.cpp b/frameworks/native/appkit/app_startup/ets_startup_task.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f01f1b94322a8fa123f9550c01474698b74637fb --- /dev/null +++ b/frameworks/native/appkit/app_startup/ets_startup_task.cpp @@ -0,0 +1,232 @@ +/* + * 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 "ets_startup_task.h" + +#include "hilog_tag_wrapper.h" +#include "ets_runtime_utils.h" +#include "ets_startup_task_executor.h" + +namespace OHOS { +namespace AbilityRuntime { +namespace { + +class AsyncTaskCallBack { +public: + AsyncTaskCallBack() = default; + ~AsyncTaskCallBack() = default; + + static napi_value AsyncTaskCompleted(napi_env env, napi_callback_info info) + { + TAG_LOGD(AAFwkTag::STARTUP, "called"); + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { nullptr }; + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr)); + + std::string startupName; + if (!ConvertFromJsValue(env, argv[INDEX_ZERO], startupName)) { + TAG_LOGE(AAFwkTag::STARTUP, "Convert error"); + return CreateJsUndefined(env); + } + + napi_value resultJs = argv[INDEX_ONE]; + napi_ref resultRef = nullptr; + napi_create_reference(env, resultJs, INDEX_ONE, &resultRef); + std::shared_ptr result(reinterpret_cast(resultRef)); + std::shared_ptr callbackResult = std::make_shared(result); + + std::shared_ptr jsStartupTask; + for (const auto& iter : jsStartupTaskObjects_) { + if (iter.first == startupName) { + jsStartupTask = iter.second.lock(); + } + } + + if (jsStartupTask != nullptr) { + jsStartupTask->OnAsyncTaskCompleted(callbackResult); + jsStartupTaskObjects_.erase(startupName); + } + + return CreateJsUndefined(env); + } + + static napi_value Constructor(napi_env env, napi_callback_info cbinfo) + { + TAG_LOGD(AAFwkTag::STARTUP, "called"); + return CreateJsUndefined(env); + } + + static std::map> etsStartupTaskObjects_; +}; +std::map> AsyncTaskCallBack::etsStartupTaskObjects_; +} + +const std::string EtsStartupTask::TASK_TYPE = "Ets"; + +EtsStartupTask::EtsStartupTask(const std::string& name, STSRuntime& etsRuntime, + std::unique_ptr& startupJsRef, std::shared_ptr& contextJsRef) + : AppStartupTask(name), etsRuntime_(etsRuntime), startupEtsRef_(std::move(startupEtsRef)), contextEtsRef_(contextEtsRef) +{ +} + +EtsStartupTask::~EtsStartupTask() = default; + +const std::string &EtsStartupTask::GetType() const +{ + return TASK_TYPE; +} + +int32_t EtsStartupTask::RunTaskInit(std::unique_ptr callback) +{ + TAG_LOGI(AAFwkTag::STARTUP, "task: %{public}s init", GetName().c_str()); + if (callCreateOnMainThread_) { + return EtsStartupTaskExecutor::RunOnMainThread(etsRuntime_, startupEtsRef_, contextEtsRef_, std::move(callback)); + } + + if (LoadEtsAsyncTaskExecutor() != ERR_OK) { + TAG_LOGE(AAFwkTag::STARTUP, "LoadEtsAsyncTaskExecutor failed"); + return ERR_STARTUP_INTERNAL_ERROR; + } + LoadEtsAsyncTaskCallback(); + + startupTaskResultCallback_ = std::move(callback); + + auto result = EtsStartupTaskExecutor::RunOnTaskPool( + etsRuntime_, startupEtsRef_, contextEtsRef_, AsyncTaskExecutorEtsRef_, AsyncTaskExecutorCallbackEtsRef_, name_); + if (result == ERR_OK) { + AsyncTaskCallBack::etsStartupTaskObjects_.emplace(name_, + std::static_pointer_cast(shared_from_this())); + } + return result; +} + +int32_t EtsStartupTask::LoadEtsAsyncTaskExecutor() +{ + TAG_LOGD(AAFwkTag::STARTUP, "LoadEtsAsyncTaskExecutor called"); + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return ERR_STARTUP_INTERNAL_ERROR; + } + + //New AsyncCallbackWrapper TODO dxp + // new + // napi_value object = nullptr; + // napi_create_object(env, &object); + // if (object == nullptr) { + // TAG_LOGE(AAFwkTag::STARTUP, "null object"); + // return ERR_STARTUP_INTERNAL_ERROR; + // } + + // AsyncTaskExecutorJsRef_ = + // JsRuntime::LoadSystemModuleByEngine(env, "app.appstartup.AsyncTaskExcutor", &object, 1); + return ERR_OK; +} + +void EtsStartupTask::LoadEtsAsyncTaskCallback() +{ + TAG_LOGD(AAFwkTag::STARTUP, "LoadEtsAsyncTaskCallback called"); + //TODO dxp + // auto env = jsRuntime_.GetNapiEnv(); + + // napi_value config; + // std::string value = "This is callback value"; + // NAPI_CALL_RETURN_VOID( + // env, napi_create_string_utf8(env, value.c_str(), value.length(), &config)); + + // napi_property_descriptor props[] = { + // DECLARE_NAPI_STATIC_FUNCTION("onAsyncTaskCompleted", AsyncTaskCallBack::AsyncTaskCompleted), + // DECLARE_NAPI_INSTANCE_PROPERTY("config", config), + // }; + // napi_value asyncTaskCallbackClass = nullptr; + // napi_define_sendable_class(env, "AsyncTaskCallback", NAPI_AUTO_LENGTH, AsyncTaskCallBack::Constructor, + // nullptr, sizeof(props) / sizeof(props[0]), props, nullptr, &asyncTaskCallbackClass); + // AsyncTaskExecutorCallbackJsRef_ = + // JsRuntime::LoadSystemModuleByEngine(env, "app.appstartup.AsyncTaskCallback", &asyncTaskCallbackClass, 1); +} + +void EtsStartupTask::OnAsyncTaskCompleted(const std::shared_ptr &result) +{ + TAG_LOGD(AAFwkTag::STARTUP, "OnAsyncTaskCompleted called"); + if (startupTaskResultCallback_ == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null startupTaskResultCallback"); + return; + } + startupTaskResultCallback_->Call(result); +} + +int32_t EtsStartupTask::RunTaskOnDependencyCompleted(const std::string &dependencyName, + const std::shared_ptr &result) +{ + auto env = etsRuntime_.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return ERR_STARTUP_INTERNAL_ERROR; + } + + if (startupEtsRef_ == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null ref_:%{public}s", name_.c_str()); + return ERR_STARTUP_INTERNAL_ERROR; + } + // napi_value startupValue = startupJsRef_->GetNapiValue(); + // if (!CheckTypeForNapiValue(env, startupValue, napi_object)) { + // TAG_LOGE(AAFwkTag::STARTUP, "%{public}s, not napi object", name_.c_str()); + // return ERR_STARTUP_INTERNAL_ERROR; + // } + // napi_value startupOnDepCompleted = nullptr; + // napi_get_named_property(env, startupValue, "onDependencyCompleted", &startupOnDepCompleted); + // if (startupOnDepCompleted == nullptr) { + // TAG_LOGE(AAFwkTag::STARTUP, "%{public}s, get onDependencyCompleted failed", name_.c_str()); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + // bool isCallable = false; + // napi_is_callable(env, startupOnDepCompleted, &isCallable); + // if (!isCallable) { + // TAG_LOGE(AAFwkTag::STARTUP, "onDependencyCompleted not callable:%{public}s", name_.c_str()); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + + // napi_value jsResult = GetDependencyResult(env, dependencyName, result); + // napi_value dependency = CreateJsValue(env, dependencyName); + // constexpr size_t argc = 2; + // napi_value argv[argc] = { dependency, jsResult }; + // napi_call_function(env, startupValue, startupOnDepCompleted, argc, argv, nullptr); + return ERR_OK; +} + +ani_ref GetDependencyResult(ani_env *env, const std::string &dependencyName, + const std::shared_ptr &result) +{ + if (env == nullptr || + result == nullptr || + result->GetResultType() != StartupTaskResult::ResultType::ETS) { + TAG_LOGE(AAFwkTag::STARTUP, "invalid args"); + return CreateEtsUndefined(env); + } else { + std::shared_ptr etsResultPtr = std::static_pointer_cast(result); + if (etsResultPtr == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "%{public}s, convert failed", dependencyName.c_str()); + return CreateEtsUndefined(env); + } + std::shared_ptr etsResultRef = etsResultPtr->GetEtsStartupResultRef(); + if (etsResultRef == nullptr) { + return CreateEtsUndefined(env); + } + return etsResultRef->aniRef; + } +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/app_startup/ets_startup_task_executor.cpp b/frameworks/native/appkit/app_startup/ets_startup_task_executor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1876644f34b018e4918ef476522bcac79e50237 --- /dev/null +++ b/frameworks/native/appkit/app_startup/ets_startup_task_executor.cpp @@ -0,0 +1,211 @@ +/* + * 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 "ets_startup_task_executor.h" +#include "ets_runtime_utils.h" +#include "ets_startup_task_result.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AbilityRuntime { +int32_t EtsStartupTaskExecutor::RunOnMainThread(STSRuntime &etsRuntime, + const std::unique_ptr &startup, const std::shared_ptr &context, + std::unique_ptr callback) +{ + auto env = etsRuntime.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return ERR_STARTUP_INTERNAL_ERROR; + } + + ani_ref returnVal = nullptr; + int32_t resultCode = CallStartupInit(env, startup, context, callback, returnVal); + if (resultCode != ERR_OK) { + return resultCode; + } + return HandleReturnVal(env, returnVal, callback); +} + +int32_t EtsStartupTaskExecutor::RunOnTaskPool( + STSRuntime &etsRuntime, + const std::unique_ptr &startup, + const std::shared_ptr &context, + const std::unique_ptr &asyncTaskExcutor, + const std::unique_ptr &asyncTaskCallback, + const std::string &startupName) +{ + TAG_LOGD(AAFwkTag::STARTUP, "RunOnMainThread called"); + auto env = etsRuntime.GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null env"); + return ERR_STARTUP_INTERNAL_ERROR; + } + + if (startup == nullptr || context == nullptr || asyncTaskExcutor == nullptr || asyncTaskCallback == nullptr) { + TAG_LOGE(AAFwkTag::STARTUP, "null args"); + return ERR_STARTUP_INTERNAL_ERROR; + } + // napi_value asyncTaskExcutorValue = asyncTaskExcutor->GetNapiValue(); + // if (!CheckTypeForNapiValue(env, asyncTaskExcutorValue, napi_object)) { + // TAG_LOGE(AAFwkTag::STARTUP, "not napi object"); + // return ERR_STARTUP_INTERNAL_ERROR; + // } + // napi_value asyncPushTask = nullptr; + // napi_get_named_property(env, asyncTaskExcutorValue, "asyncPushTask", &asyncPushTask); + // if (asyncPushTask == nullptr) { + // TAG_LOGE(AAFwkTag::STARTUP, "null asyncPushTask"); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + // bool isCallable = false; + // napi_is_callable(env, asyncPushTask, &isCallable); + // if (!isCallable) { + // TAG_LOGE(AAFwkTag::STARTUP, "AsyncPushTask not callable"); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + // napi_value returnVal = nullptr; + // napi_value argv[] = { startup->GetNapiValue(), asyncTaskCallback->GetNapiValue(), + // context->GetNapiValue(), CreateJsValue(env, startupName) }; + // napi_call_function(env, asyncTaskExcutorValue, asyncPushTask, ARGC_FOUR, argv, &returnVal); +} + +int32_t EtsStartupTaskExecutor::CallStartupInit(ani_env *env, const std::unique_ptr &startup, + const std::shared_ptr &context, std::unique_ptr &callback, + ani_ref &returnVal) +{ + // if (startup == nullptr || context == nullptr) { + // ReplyFailed(std::move(callback), ERR_STARTUP_INTERNAL_ERROR, + // "startup task is null or context is null."); + // return ERR_STARTUP_INTERNAL_ERROR; + // } + // napi_value startupValue = startup->GetNapiValue(); + // if (!CheckTypeForNapiValue(env, startupValue, napi_object)) { + // ReplyFailed(std::move(callback), ERR_STARTUP_INTERNAL_ERROR, + // "startup task is not napi object."); + // return ERR_STARTUP_INTERNAL_ERROR; + // } + // napi_value startupInit = nullptr; + // napi_get_named_property(env, startupValue, "init", &startupInit); + // if (startupInit == nullptr) { + // ReplyFailed(std::move(callback), ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP, + // "failed to get property init from startup task."); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + // bool isCallable = false; + // napi_is_callable(env, startupInit, &isCallable); + // if (!isCallable) { + // ReplyFailed(std::move(callback), ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP, + // "startup task init is not callable."); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + // napi_value argv[1] = { context->GetNapiValue() }; + // napi_call_function(env, startupValue, startupInit, 1, argv, &returnVal); + return ERR_OK; +} + +int32_t EtsStartupTaskExecutor::HandleReturnVal(ani_env *env, napi_value returnVal, + std::unique_ptr &callback) +{ + // bool isPromise = false; + // napi_is_promise(env, returnVal, &isPromise); + // if (!isPromise) { + // ReplyFailed(std::move(callback), ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP, + // "the return value of startup task init is not promise."); + // return ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP; + // } + + // auto *callbackPtr = callback.release(); + // napi_value promiseThen = nullptr; + // napi_get_named_property(env, returnVal, "then", &promiseThen); + // napi_value promiseResolveCallback = nullptr; + // napi_create_function(env, TMP_NAPI_ANONYMOUS_FUNC, strlen(TMP_NAPI_ANONYMOUS_FUNC), + // ResolveResultCallback, callbackPtr, &promiseResolveCallback); + // napi_value argvThen[1] = { promiseResolveCallback }; + // napi_call_function(env, returnVal, promiseThen, 1, argvThen, nullptr); + + // napi_value promiseCatch = nullptr; + // napi_get_named_property(env, returnVal, "catch", &promiseCatch); + // napi_value promiseRejectCallback = nullptr; + // napi_create_function(env, TMP_NAPI_ANONYMOUS_FUNC, strlen(TMP_NAPI_ANONYMOUS_FUNC), + // RejectResultCallback, callbackPtr, &promiseRejectCallback); + // napi_value argvCatch[1] = { promiseRejectCallback }; + // napi_call_function(env, returnVal, promiseCatch, 1, argvCatch, nullptr); + return ERR_OK; +} + +napi_value EtsStartupTaskExecutor::ResolveResultCallback(ani_env *env, napi_callback_info info) +{ + // TAG_LOGD(AAFwkTag::STARTUP, "enter"); + // size_t argc = 1; + // napi_value argv[1] = { nullptr }; + // void *data = nullptr; + // napi_get_cb_info(env, info, &argc, argv, nullptr, &data); + // auto *callback = static_cast(data); + // napi_value resultJs = argv[0]; + // napi_ref resultRef = nullptr; + // napi_create_reference(env, resultJs, 1, &resultRef); + // std::shared_ptr result(reinterpret_cast(resultRef)); + // ReplySucceeded(callback, result); + return nullptr; +} + +// napi_value EtsStartupTaskExecutor::RejectResultCallback(napi_env env, napi_callback_info info) +// { +// TAG_LOGD(AAFwkTag::STARTUP, "enter"); +// void *data = nullptr; +// napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data); +// auto *callback = static_cast(data); +// ReplyFailed(callback, ERR_STARTUP_FAILED_TO_EXECUTE_STARTUP, +// "the promise of startup task init is reject."); +// return nullptr; +// } + +// void EtsStartupTaskExecutor::ReplyFailed(StartupTaskResultCallback *callback, +// int32_t resultCode, const std::string &resultMessage) +// { +// TAG_LOGD(AAFwkTag::STARTUP, "enter"); +// if (callback == nullptr) { +// return; +// } +// std::shared_ptr result = std::make_shared(resultCode, resultMessage); +// callback->Call(result); +// delete callback; +// callback = nullptr; +// } + +// void EtsStartupTaskExecutor::ReplyFailed(std::unique_ptr callback, +// int32_t resultCode, const std::string &resultMessage) +// { +// TAG_LOGE(AAFwkTag::STARTUP, "execute failed: %{public}s", resultMessage.c_str()); +// if (callback == nullptr) { +// return; +// } +// std::shared_ptr result = std::make_shared(resultCode, resultMessage); +// callback->Call(result); +// } + +// void EtsStartupTaskExecutor::ReplySucceeded(StartupTaskResultCallback *callback, +// const std::shared_ptr &resultRef) +// { +// TAG_LOGD(AAFwkTag::STARTUP, "enter"); +// if (callback == nullptr) { +// return; +// } +// std::shared_ptr result = std::make_shared(resultRef); +// callback->Call(result); +// delete callback; +// callback = nullptr; +// } +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/frameworks/native/appkit/app_startup/ets_startup_task_result.cpp b/frameworks/native/appkit/app_startup/ets_startup_task_result.cpp new file mode 100644 index 0000000000000000000000000000000000000000..086d775f49d93c78e89ba87b768c89292d295b55 --- /dev/null +++ b/frameworks/native/appkit/app_startup/ets_startup_task_result.cpp @@ -0,0 +1,43 @@ +/* + * 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 "ets_startup_task_result.h" + +namespace OHOS { +namespace AbilityRuntime { +EtsStartupTaskResult::EtsStartupTaskResult() : StartupTaskResult() +{} + +EtsStartupTaskResult::~EtsStartupTaskResult() = default; + +EtsStartupTaskResult::EtsStartupTaskResult(int32_t resultCode, const std::string &resultMessage) + : StartupTaskResult(resultCode, resultMessage) +{} + +EtsStartupTaskResult::EtsStartupTaskResult(const std::shared_ptr &result) + : StartupTaskResult(), etsStartupResultRef_(result) +{} + +StartupTaskResult::ResultType EtsStartupTaskResult::GetResultType() const +{ + return ResultType::ETS; +} + +const std::shared_ptr& EtsStartupTaskResult::GetEtsStartupResultRef() const +{ + return etsStartupResultRef_; +} +} // namespace AbilityRuntime +} // namespace OHOS diff --git a/interfaces/inner_api/runtime/include/ets_runtime_utils.h b/interfaces/inner_api/runtime/include/ets_runtime_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..a86516047637f3ac36aa7baf74b254d44641195c --- /dev/null +++ b/interfaces/inner_api/runtime/include/ets_runtime_utils.h @@ -0,0 +1,65 @@ +/* + * 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_ETS_RUNTIME_UTILS_H +#define OHOS_ABILITY_RUNTIME_ETS_RUNTIME_UTILS_H + +#include "ani.h" + +namespace OHOS { +namespace AbilityRuntime { +inline ani_object CreateEtsUndefined(ani_env *env) +{ + if (env == nullptr) { + return nullptr; + } + ani_ref result = nullptr; + env->GetUndefined(&result); + return static_cast(result); +} + +inline ani_ref CreateEtsUndefinedRef(ani_env *env) +{ + if (env == nullptr) { + return nullptr; + } + ani_ref result = nullptr; + env->GetUndefined(&result); + return result; +} + +inline ani_object CreateEtsNull(ani_env *env) +{ + if (env == nullptr) { + return nullptr; + } + ani_ref result = nullptr; + env->GetNull(&result); + return static_cast(result); +} + +inline ani_ref CreateEtsNullRef(ani_env *env) +{ + if (env == nullptr) { + return nullptr; + } + ani_ref result = nullptr; + env->GetNull(&result); + return result; +} + +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_RUNTIME_UTILS_H diff --git a/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h b/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h index d1a7769ceaab30492b00092a232ccfca652146f9..3f005ecb3a07b191f1c1c11066ec636352c72a90 100644 --- a/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h +++ b/interfaces/kits/native/appkit/ability_runtime/app/sts_ability_stage.h @@ -23,7 +23,7 @@ #include "ability_stage.h" #include "configuration.h" -#include "js_startup_task.h" +#include "ets_startup_task.h" #include "resource_manager.h" #include "nlohmann/json.hpp" #include "native_engine/native_value.h" @@ -67,12 +67,12 @@ private: static bool UseCommonChunk(const AppExecFwk::HapModuleInfo& hapModuleInfo); - std::unique_ptr LoadJsOhmUrl(const std::string &srcEntry, const std::string &ohmUrl, + std::unique_ptr LoadEtsOhmUrl(const std::string &srcEntry, const std::string &ohmUrl, const std::string &moduleName, const std::string &hapPath, bool esmodule); std::unique_ptr LoadJsSrcEntry(const std::string &srcEntry); - bool LoadJsStartupConfig(const std::string &srcEntry); + bool LoadEtsStartupConfig(const std::string &srcEntry); int32_t RegisterAppStartupTask(const std::shared_ptr& hapModuleInfo); diff --git a/interfaces/kits/native/appkit/app_startup/ets_startup_task.h b/interfaces/kits/native/appkit/app_startup/ets_startup_task.h new file mode 100644 index 0000000000000000000000000000000000000000..5f116cf30b64696091f40430505f0eddd138ac92 --- /dev/null +++ b/interfaces/kits/native/appkit/app_startup/ets_startup_task.h @@ -0,0 +1,61 @@ +/* + * 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_ETS_STARTUP_TASK_H +#define OHOS_ABILITY_RUNTIME_ETS_STARTUP_TASK_H + +#include "app_startup_task.h" +#include "sts_runtime.h" +#include "ets_runtime_utils.h" +#include "ets_startup_task_result.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsStartupTask : public AppStartupTask { +public: + static const std::string TASK_TYPE; + + EtsStartupTask(const std::string &name, STSRuntime &etsRuntime, + std::unique_ptr &startupJsRef, std::shared_ptr &contextJsRef_); + + ~EtsStartupTask() override; + + const std::string &GetType() const override; + + int32_t RunTaskInit(std::unique_ptr callback) override; + + int32_t RunTaskOnDependencyCompleted(const std::string &dependencyName, + const std::shared_ptr &result) override; + + void OnAsyncTaskCompleted(const std::shared_ptr &result); + +private: + StsRuntime &etsRuntime_; + std::unique_ptr startupEtsRef_; + std::shared_ptr contextEtsRef_; + std::unique_ptr AsyncTaskExecutorEtsRef_; + std::unique_ptr AsyncTaskExecutorCallbackEtsRef_; + std::unique_ptr startupTaskResultCallback_; + + static ani_ref GetDependencyResult(ani_env *env, const std::string &dependencyName, + const std::shared_ptr &result); + + int32_t LoadEtsAsyncTaskExecutor(); + + void LoadEtsAsyncTaskCallback(); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_STARTUP_TASK_H diff --git a/interfaces/kits/native/appkit/app_startup/ets_startup_task_executor.h b/interfaces/kits/native/appkit/app_startup/ets_startup_task_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..a6df685685f20d4dc01f3a0cf7588dd0b6cb95fa --- /dev/null +++ b/interfaces/kits/native/appkit/app_startup/ets_startup_task_executor.h @@ -0,0 +1,61 @@ +/* + * 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_ETS_STARTUP_TASK_EXECUTOR_H +#define OHOS_ABILITY_RUNTIME_ETS_STARTUP_TASK_EXECUTOR_H + +#include "sts_runtime.h" +#include "startup_task_result.h" +#include "startup_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsStartupTaskExecutor { +public: + static int32_t RunOnMainThread(STSRuntime &etsRuntime, + const std::unique_ptr &startup, const std::shared_ptr &context, + std::unique_ptr callback); + + static int32_t RunOnTaskPool(STSRuntime &etsRuntime, + const std::unique_ptr &startup, + const std::shared_ptr &context, + const std::unique_ptr &asynctaskexcutor, + const std::unique_ptr &asyncTaskCallback, + const std::string &startupName); + +private: + static int32_t CallStartupInit(ani_env *env, const std::unique_ptr &startup, + const std::shared_ptr &context, std::unique_ptr &callback, + ani_ref &returnVal); + + static int32_t HandleReturnVal(ani_env *env, napi_value returnVal, + std::unique_ptr &callback); + + static napi_value ResolveResultCallback(ani_env *env, napi_callback_info info); + + static napi_value RejectResultCallback(ani_env *env, napi_callback_info info); + + static void ReplyFailed(StartupTaskResultCallback *callback, + int32_t resultCode, const std::string &resultMessage = ""); + + static void ReplyFailed(std::unique_ptr callback, + int32_t resultCode, const std::string &resultMessage = ""); + + static void ReplySucceeded(StartupTaskResultCallback *callback, + const std::shared_ptr &resultRef); +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_STARTUP_TASK_EXECUTOR_H diff --git a/interfaces/kits/native/appkit/app_startup/ets_startup_task_result.h b/interfaces/kits/native/appkit/app_startup/ets_startup_task_result.h new file mode 100644 index 0000000000000000000000000000000000000000..5aeea57f2857cf53141d6b21a5aa584fbd9a1845 --- /dev/null +++ b/interfaces/kits/native/appkit/app_startup/ets_startup_task_result.h @@ -0,0 +1,43 @@ +/* + * 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_ETS_STARTUP_TASK_RESULT_H +#define OHOS_ABILITY_RUNTIME_ETS_STARTUP_TASK_RESULT_H + +#include "sts_runtime.h" +#include "startup_task_result.h" + +namespace OHOS { +namespace AbilityRuntime { +class EtsStartupTaskResult : public StartupTaskResult { +public: + EtsStartupTaskResult(); + + ~EtsStartupTaskResult() override; + + EtsStartupTaskResult(int32_t resultCode, const std::string &resultMessage); + + explicit EtsStartupTaskResult(const std::shared_ptr &result); + + ResultType GetResultType() const override; + + const std::shared_ptr& GetEtsStartupResultRef() const; + +private: + std::shared_ptr etsStartupResultRef_; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_ETS_STARTUP_TASK_RESULT_H diff --git a/interfaces/kits/native/appkit/app_startup/startup_task_result.h b/interfaces/kits/native/appkit/app_startup/startup_task_result.h index a218c2baa6e619b51dd4181ebb9828bbfd5c153b..e889477ba3a42cf9d4b86ef02e952b70a2148bcf 100644 --- a/interfaces/kits/native/appkit/app_startup/startup_task_result.h +++ b/interfaces/kits/native/appkit/app_startup/startup_task_result.h @@ -27,7 +27,8 @@ class StartupTaskResult { public: enum class ResultType { INVALID, - JS + JS, + ETS, }; StartupTaskResult();