* 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_application.h"
#include "ani_base_context.h"
#include "ani_common_util.h"
#include "application_context.h"
#include "app_mgr_client.h"
#include "application_context_manager.h"
#include "context_impl.h"
#include "ets_application_context_utils.h"
#include "ets_context_utils.h"
#include "ets_error_utils.h"
#include "ets_native_reference.h"
#include "hilog_tag_wrapper.h"
#include "permission_verification.h"
#include "application_env.h"
#include "ani_enum_convert.h"
namespace OHOS {
namespace AbilityRuntime {
namespace {
constexpr const char* PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED";
constexpr const char* CONTEXT_CLASS_NAME = "application.Context.Context";
constexpr const char* APPLICATION_SPACE_NAME = "@ohos.app.ability.application.application";
constexpr const char* APP_PRELOAD_TYPE_NAME = "@ohos.app.ability.application.application.AppPreloadType";
}
void EtsApplication::DemoteCurrentFromCandidateMasterProcess(ani_env *env, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "DemoteCurrentFromCandidateMasterProcess Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
auto errCode = std::make_shared<int32_t>(ERR_OK);
auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
if (appMgrClient == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Null appMgrClient");
*errCode = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
} else {
*errCode = appMgrClient->DemoteCurrentFromCandidateMasterProcess();
}
if (*errCode == ERR_OK) {
TAG_LOGD(AAFwkTag::APPKIT, "demote to standby master process success");
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK),
nullptr);
} else {
TAG_LOGE(AAFwkTag::APPKIT, "demote to standby master process failed, errCode: %{public}d", *errCode);
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, *errCode),
nullptr);
}
}
void EtsApplication::PromoteCurrentToCandidateMasterProcess(ani_env *env,
ani_boolean isInsertToHead, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "PromoteCurrentToCandidateMasterProcess Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
bool insertToHead = static_cast<bool>(isInsertToHead);
auto errCode = std::make_shared<int32_t>(ERR_OK);
auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
if (appMgrClient == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Null appMgrClient");
*errCode = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
} else {
*errCode = appMgrClient->PromoteCurrentToCandidateMasterProcess(insertToHead);
}
if (*errCode == ERR_OK) {
TAG_LOGD(AAFwkTag::APPKIT, "promote to candidate master process success");
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK),
nullptr);
} else {
TAG_LOGE(AAFwkTag::APPKIT, "promote to candidate master process failed, errCode: %{public}d", *errCode);
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, *errCode), nullptr);
}
}
ani_object CreateEmptyContextObject(ani_env *env)
{
ani_class cls = nullptr;
ani_status status = env->FindClass(CONTEXT_CLASS_NAME, &cls);
if (status != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "find Context failed status: %{public}d", status);
return nullptr;
}
ani_method method = nullptr;
status = env->Class_FindMethod(cls, "<ctor>", ":", &method);
if (status != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "Class_FindMethod ctor failed status: %{public}d", status);
return nullptr;
}
ani_object objValue = nullptr;
if (env->Object_New(cls, method, &objValue) != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "Object_New failed status: %{public}d", status);
return nullptr;
}
return objValue;
}
bool CheckIsSystemAppOrPermisson(ani_env *env, ani_object callback)
{
auto emptyObject = CreateEmptyContextObject(env);
if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) {
TAG_LOGE(AAFwkTag::APPKIT, "no system app");
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env,
static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_NOT_SYSTEM_APP),
"The application is not system-app, can not use system-api."), emptyObject);
return false;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) {
TAG_LOGE(AAFwkTag::APPKIT, "no permission");
AppExecFwk::AsyncCallback(env, callback,
EtsErrorUtil::CreateNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO), emptyObject);
return false;
}
return true;
}
bool SetNativeContextLong(ani_env *env, std::shared_ptr<Context> context, ani_class& cls, ani_object& contextObj)
{
if (env == nullptr || context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "env or context is null");
return false;
}
ani_status status = ANI_ERROR;
ani_method method {};
if ((status = env->Class_FindMethod(cls, "<ctor>", "l:", &method)) != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
return false;
}
std::unique_ptr<ContextUtil::EtsBaseContext> eteBaseContext =
std::make_unique<ContextUtil::EtsBaseContext>(context);
auto workContext = new (std::nothrow) std::weak_ptr<Context>(eteBaseContext->GetContext());
if (workContext == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "workContext nullptr");
return false;
}
if ((status = env->Object_New(cls, method, &contextObj, (ani_long)(eteBaseContext.release()))) != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
delete workContext;
return false;
}
ani_long nativeContextLong = reinterpret_cast<ani_long>(workContext);
if (!ContextUtil::SetNativeContextLong(env, contextObj, nativeContextLong)) {
TAG_LOGE(AAFwkTag::APPKIT, "SetNativeContextLong failed");
delete workContext;
workContext = nullptr;
return false;
}
return true;
}
void SetCreateCompleteCallback(ani_env *env, std::shared_ptr<std::shared_ptr<Context>> contextPtr, ani_object callback)
{
if (env == nullptr || contextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "env or contextPtr is nullptr");
return;
}
auto context = *contextPtr;
if (!context) {
TAG_LOGE(AAFwkTag::APPKIT, "failed to create context");
auto emptyObject = CreateEmptyContextObject(env);
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env,
AbilityErrorCode::ERROR_CODE_INVALID_PARAM), emptyObject);
return;
}
ani_class cls {};
ani_status status = ANI_ERROR;
if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
return;
}
ani_object contextObj = nullptr;
if (!SetNativeContextLong(env, context, cls, contextObj)) {
TAG_LOGE(AAFwkTag::APPKIT, "set nativeContextLong failed");
return;
}
ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context);
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), contextObj);
}
ani_object ThrowErrorCodeAndReturnNull(ani_env *env, const AbilityErrorCode &errCode)
{
EtsErrorUtil::ThrowError(env, errCode);
ani_ref result = nullptr;
env->GetNull(&result);
return static_cast<ani_object>(result);
}
ani_object ThrowInnerErrorAndReturnNull(ani_env *env)
{
return ThrowErrorCodeAndReturnNull(env, AbilityErrorCode::ERROR_CODE_INNER);
}
ani_object ThrowParamErrorAndReturnNull(ani_env *env, const std::string &msg)
{
EtsErrorUtil::ThrowInvalidParamError(env, msg);
ani_ref result = nullptr;
env->GetNull(&result);
return static_cast<ani_object>(result);
}
ani_object CreateSyncContextObject(ani_env *env, std::shared_ptr<Context> context)
{
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return nullptr;
}
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
return ThrowInnerErrorAndReturnNull(env);
}
ani_class cls {};
ani_status status = ANI_ERROR;
if ((status = env->FindClass(CONTEXT_CLASS_NAME, &cls)) != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "status: %{public}d", status);
return ThrowInnerErrorAndReturnNull(env);
}
ani_object contextObj = nullptr;
if (!SetNativeContextLong(env, context, cls, contextObj)) {
TAG_LOGE(AAFwkTag::APPKIT, "set nativeContextLong failed");
return ThrowInnerErrorAndReturnNull(env);
}
ContextUtil::CreateEtsBaseContext(env, cls, contextObj, context);
return contextObj;
}
std::shared_ptr<Context> GetContextByStageMode(ani_env *env, ani_object &contextObj,
ani_object callback, ani_object emptyObject)
{
ani_boolean stageMode = false;
ani_status status = IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
return nullptr;
}
auto context = GetStageModeContext(env, contextObj);
if (context == nullptr) {
return nullptr;
}
return context;
}
void EtsApplication::CreateModuleContextCheck(ani_env *env,
ani_object contextObj, ani_string moduleName, ani_object bundleName)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreateModuleContextCheck Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
ani_boolean stageMode = false;
ani_status status = IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param context failed, must be a context of stageMode.");
return;
}
auto context = GetStageModeContext(env, contextObj);
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param context failed, must not be nullptr.");
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param context failed, must be a context.");
return;
}
ani_boolean isUndefined = false;
if ((status = env->Reference_IsUndefined(bundleName, &isUndefined)) != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "Failed to check undefined status : %{public}d", status);
return;
}
if (!isUndefined) {
if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) {
TAG_LOGE(AAFwkTag::APPKIT, "no system app");
EtsErrorUtil::ThrowNotSystemAppError(env);
return;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) {
TAG_LOGE(AAFwkTag::APPKIT, "no permission");
EtsErrorUtil::ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
return;
}
}
}
void EtsApplication::CreateModuleContext(ani_env *env,
ani_object contextObj, ani_string bundleName, ani_string moduleName, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreateModuleContext Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
ani_object emptyObject = CreateEmptyContextObject(env);
std::string stdBundleName = "";
std::string stdModuleName = "";
AppExecFwk::GetStdString(env, bundleName, stdBundleName);
AppExecFwk::GetStdString(env, moduleName, stdModuleName);
auto context = GetContextByStageMode(env, contextObj, callback, emptyObject);
if (context == nullptr) {
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
return;
}
std::shared_ptr<std::shared_ptr<Context>> moduleContext = std::make_shared<std::shared_ptr<Context>>();
std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
if (contextImpl == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl");
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
"create context failed."), emptyObject);
return;
}
contextImpl->SetProcessName(context->GetProcessName());
if (stdBundleName.empty()) {
*moduleContext = contextImpl->CreateModuleContext(stdModuleName, inputContextPtr);
} else {
if (!CheckIsSystemAppOrPermisson(env, callback)) {
TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed");
}
*moduleContext = contextImpl->CreateModuleContext(stdBundleName, stdModuleName, inputContextPtr);
}
SetCreateCompleteCallback(env, moduleContext, callback);
}
ani_object EtsApplication::CreateModuleContextSync(ani_env *env,
ani_object contextObj, ani_string moduleName)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreateModuleContextSync Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return nullptr;
}
ani_boolean stageMode = false;
ani_status status = IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
return ThrowParamErrorAndReturnNull(env, "Parse param context failed, must be a context of stageMode.");
}
auto context = GetStageModeContext(env, contextObj);
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
return ThrowErrorCodeAndReturnNull(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT);
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
return ThrowErrorCodeAndReturnNull(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT);
}
std::string stdModuleName = "";
if (!AppExecFwk::GetStdString(env, moduleName, stdModuleName)) {
TAG_LOGE(AAFwkTag::APPKIT, "GetStdString failed");
return ThrowParamErrorAndReturnNull(env, "Parse param moduleName failed, moduleName must be string.");
}
std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
if (contextImpl == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl");
return ThrowInnerErrorAndReturnNull(env);
}
contextImpl->SetProcessName(context->GetProcessName());
auto moduleContext = contextImpl->CreateModuleContext(stdModuleName, inputContextPtr);
if (moduleContext == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "failed to create module context");
return ThrowErrorCodeAndReturnNull(env, AbilityErrorCode::ERROR_CODE_INVALID_MODULENAME);
}
return CreateSyncContextObject(env, moduleContext);
}
void EtsApplication::CreateBundleContextCheck(ani_env *env,
ani_object contextObj, ani_string bundleName)
{
if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) {
TAG_LOGE(AAFwkTag::APPKIT, "no system app");
EtsErrorUtil::ThrowNotSystemAppError(env);
return;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) {
TAG_LOGE(AAFwkTag::APPKIT, "no permission");
EtsErrorUtil::ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
return;
}
ani_boolean stageMode = false;
ani_status status = IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
TAG_LOGE(AAFwkTag::APPKIT, "not stageMode");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param context failed, must be a context of stageMode.");
return;
}
auto context = GetStageModeContext(env, contextObj);
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null context");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param context failed, must not be nullptr.");
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param context failed, must be a context.");
return;
}
}
void EtsApplication::CreateBundleContext(ani_env *env,
ani_object contextObj, ani_string bundleName, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreateBundleContext Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
ani_object emptyObject = CreateEmptyContextObject(env);
if (!CheckIsSystemAppOrPermisson(env, callback)) {
TAG_LOGE(AAFwkTag::APPKIT, "CheckCaller failed");
return;
}
std::string stdBundleName = "";
AppExecFwk::GetStdString(env, bundleName, stdBundleName);
auto context = GetContextByStageMode(env, contextObj, callback, emptyObject);
if (context == nullptr) {
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Convert to context failed");
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
"Parse param context failed, must be a context."), emptyObject);
return;
}
auto bundleContext = std::make_shared<std::shared_ptr<Context>>();
std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
if (contextImpl == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null contextImpl");
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateInvalidParamError(env,
"create context failed."), emptyObject);
return;
}
contextImpl->SetProcessName(context->GetProcessName());
contextImpl->CreateBundleContext(*bundleContext, stdBundleName, inputContextPtr);
SetCreateCompleteCallback(env, bundleContext, callback);
}
void EtsApplication::CreatePluginModuleContextCheck(ani_env *env,
ani_object contextObj, ani_string pluginBundleName, ani_string pluginModuleName)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreatePluginModuleContextCheck Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
ani_boolean stageMode = false;
ani_status status = OHOS::AbilityRuntime::IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
EtsErrorUtil::ThrowInvalidParamError(
env, "Parse param context failed, must be a context of stageMode.");
return;
}
auto context = OHOS::AbilityRuntime::GetStageModeContext(env, contextObj);
if (context == nullptr) {
EtsErrorUtil::ThrowInvalidParamError(
env, "Parse param context failed, must not be nullptr.");
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
EtsErrorUtil::ThrowInvalidParamError(
env, "Parse param context failed, must be a context.");
return;
}
}
void EtsApplication::CreatePluginModuleContext(ani_env *env,
ani_object contextObj, ani_string pluginBundleName, ani_string pluginModuleName, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreatePluginModuleContext Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
ani_boolean stageMode = false;
ani_status status = OHOS::AbilityRuntime::IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
AppExecFwk::AsyncCallback(env, callback,
EtsErrorUtil::CreateInvalidParamError(env, "Parse param context failed, must be a context of stageMode."),
nullptr);
return;
}
auto context = OHOS::AbilityRuntime::GetStageModeContext(env, contextObj);
if (context == nullptr) {
AppExecFwk::AsyncCallback(env, callback,
EtsErrorUtil::CreateInvalidParamError(env, "Parse param context failed, must not be nullptr."), nullptr);
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
AppExecFwk::AsyncCallback(env, callback,
EtsErrorUtil::CreateInvalidParamError(env, "Parse param context failed, must be a context."), nullptr);
return;
}
std::string stdPluginBundleName = "";
std::string stdModuleName = "";
AppExecFwk::GetStdString(env, pluginBundleName, stdPluginBundleName);
AppExecFwk::GetStdString(env, pluginModuleName, stdModuleName);
TAG_LOGD(AAFwkTag::APPKIT, "pluginModuleName: %{public}s, pluginBundleName: %{public}s",
stdModuleName.c_str(), stdPluginBundleName.c_str());
if (stdPluginBundleName.empty() || stdModuleName.empty()) {
TAG_LOGE(AAFwkTag::APPKIT, "Empty pluginBundleName or moduleName");
AppExecFwk::AsyncCallback(env, callback,
EtsErrorUtil::CreateInvalidParamError(env, "Empty pluginBundleName or moduleName"), nullptr);
return;
}
auto moduleContext = std::make_shared<std::shared_ptr<Context>>();
auto contextImpl = std::make_shared<ContextImpl>();
if (contextImpl == nullptr) {
AppExecFwk::AsyncCallback(env, callback,
EtsErrorUtil::CreateInvalidParamError(env, "create context failed."), nullptr);
return;
}
contextImpl->SetProcessName(context->GetProcessName());
*moduleContext = contextImpl->CreatePluginContext(stdPluginBundleName, stdModuleName, inputContextPtr);
SetCreateCompleteCallback(env, moduleContext, callback);
}
ani_object EtsApplication::GetApplicationContextInstance(ani_env *env)
{
TAG_LOGD(AAFwkTag::APPKIT, "GetApplicationContextInstance Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return nullptr;
}
auto etsReference =
AbilityRuntime::ApplicationContextManager::GetApplicationContextManager().GetEtsGlobalObject();
if (etsReference == nullptr || etsReference->aniRef == nullptr) {
auto applicationContext = ApplicationContext::GetInstance();
ani_object applicationContextObject =
EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext);
if (applicationContextObject == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null applicationContextObject");
AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER);
ani_ref result = nullptr;
env->GetNull(&result);
return static_cast<ani_object>(result);
}
return applicationContextObject;
}
return reinterpret_cast<ani_object>(etsReference->aniRef);
}
ani_object EtsApplication::GetApplicationContext(ani_env *env)
{
TAG_LOGD(AAFwkTag::APPKIT, "GetApplicationContext Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return nullptr;
}
auto applicationContext = ApplicationContext::GetInstance();
ani_object applicationContextObject =
EtsApplicationContextUtils::CreateEtsApplicationContext(env, applicationContext);
if (applicationContextObject == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null applicationContextObject");
AbilityRuntime::EtsErrorUtil::ThrowError(env, AbilityRuntime::AbilityErrorCode::ERROR_CODE_INNER);
ani_ref result = nullptr;
env->GetNull(&result);
return static_cast<ani_object>(result);
}
return applicationContextObject;
}
ani_enum_item EtsApplication::GetAppPreloadType(ani_env *env)
{
TAG_LOGD(AAFwkTag::APPKIT, "GetAppPreloadType Call");
ani_enum_item appPreloadTypeItem = nullptr;
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return appPreloadTypeItem;
}
auto appPreload = GetAppPreload();
OHOS::AAFwk::AniEnumConvertUtil::EnumConvert_NativeToEts(
env, APP_PRELOAD_TYPE_NAME, appPreload, appPreloadTypeItem);
return appPreloadTypeItem;
}
void EtsApplication::ExitMasterProcessRole(ani_env *env, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "ExitMasterProcessRole Call");
int32_t errCode = ERR_OK;
auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
if (appMgrClient == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Null appMgrClient");
errCode = static_cast<int32_t>(AbilityErrorCode::ERROR_CODE_INNER);
} else {
errCode = appMgrClient->ExitMasterProcessRole();
}
if (errCode == ERR_OK) {
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateError(env, AbilityErrorCode::ERROR_OK), nullptr);
} else {
AppExecFwk::AsyncCallback(env, callback, EtsErrorUtil::CreateErrorByNativeErr(env, errCode), nullptr);
}
}
void EtsApplication::CreatePluginModuleContextForHostBundleCheck(ani_env *env, ani_object contextObj,
ani_string pluginBundleName, ani_string pluginModuleName, ani_string hostBundleName, ani_object callback)
{
TAG_LOGD(AAFwkTag::CONTEXT, "ConnectUIServiceExtensionCheck called");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::CONTEXT, "null env or aniObj");
return;
}
if (!AAFwk::PermissionVerification::GetInstance()->IsSystemAppCall()) {
TAG_LOGE(AAFwkTag::APPKIT, "no system app");
EtsErrorUtil::ThrowNotSystemAppError(env);
return;
}
if (!AAFwk::PermissionVerification::GetInstance()->VerifyGetBundleInfoPrivilegedPermission()) {
TAG_LOGE(AAFwkTag::APPKIT, "no permission");
EtsErrorUtil::ThrowNoPermissionError(env, PERMISSION_GET_BUNDLE_INFO);
return;
}
std::string stdPluginBundleName = "";
std::string stdPluginModuleName = "";
std::string stdHostBundleName = "";
if (!AppExecFwk::GetStdString(env, pluginBundleName, stdPluginBundleName)
|| !AppExecFwk::GetStdString(env, pluginModuleName, stdPluginModuleName)
|| !AppExecFwk::GetStdString(env, hostBundleName, stdHostBundleName)) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
EtsErrorUtil::ThrowInvalidParamError(env,
"Parse param failed, moduleName and pluginBundleName must be string.");
return;
}
ani_boolean stageMode = false;
ani_status status = IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
EtsErrorUtil::ThrowInvalidParamError(env, "Parse param context failed, must be a context of stageMode.");
return;
}
auto context = GetStageModeContext(env, contextObj);
if (context == nullptr) {
EtsErrorUtil::ThrowInvalidParamError(env, "Parse param context failed, must not be nullptr.");
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
EtsErrorUtil::ThrowInvalidParamError(env, "Parse param context failed, must be a context.");
return;
}
}
void EtsApplication::CreatePluginModuleContextForHostBundle(ani_env *env, ani_object contextObj,
ani_string pluginBundleName, ani_string pluginModuleName, ani_string hostBundleName, ani_object callback)
{
TAG_LOGD(AAFwkTag::APPKIT, "CreatePluginModuleContextForHostBundle Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
std::string stdPluginBundleName = "";
std::string stdPluginModuleName = "";
std::string stdHostBundleName = "";
if (!AppExecFwk::GetStdString(env, pluginBundleName, stdPluginBundleName)
|| !AppExecFwk::GetStdString(env, pluginModuleName, stdPluginModuleName)
|| !AppExecFwk::GetStdString(env, hostBundleName, stdHostBundleName)) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid params");
return;
}
ani_boolean stageMode = false;
ani_status status = IsStageContext(env, contextObj, stageMode);
if (status != ANI_OK || !stageMode) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid IsStageContext");
return;
}
auto context = GetStageModeContext(env, contextObj);
if (context == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid context");
return;
}
auto inputContextPtr = Context::ConvertTo<Context>(context);
if (inputContextPtr == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid inputContextPtr");
return;
}
auto moduleContext = std::make_shared<std::shared_ptr<Context>>();
std::shared_ptr<ContextImpl> contextImpl = std::make_shared<ContextImpl>();
if (contextImpl == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "invalid contextImpl");
return;
}
contextImpl->SetProcessName(context->GetProcessName());
*moduleContext = contextImpl->CreateTargetPluginContext(stdHostBundleName, stdPluginBundleName,
stdPluginModuleName, inputContextPtr);
SetCreateCompleteCallback(env, moduleContext, callback);
}
void ApplicationInit(ani_env *env)
{
TAG_LOGD(AAFwkTag::APPKIT, "ApplicationInit Call");
if (env == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null env");
return;
}
ani_status status = ANI_ERROR;
ani_namespace ns;
status = env->FindNamespace(APPLICATION_SPACE_NAME, &ns);
if (status != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "FindNamespace application failed status: %{public}d", status);
return;
}
std::array methods = {
ani_native_function {
"nativeCreateModuleContext",
"C{application.Context.Context}C{std.core.String}C{std.core.String}"
"C{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::CreateModuleContext)
},
ani_native_function {
"nativeCreateModuleContextCheck",
"C{application.Context.Context}C{std.core.String}C{std.core.String}:",
reinterpret_cast<void *>(EtsApplication::CreateModuleContextCheck)
},
ani_native_function {
"nativeCreateModuleContextSync",
"C{application.Context.Context}C{std.core.String}:C{application.Context.Context}",
reinterpret_cast<void *>(EtsApplication::CreateModuleContextSync)
},
ani_native_function {
"nativeCreateBundleContext",
"C{application.Context.Context}C{std.core.String}"
"C{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::CreateBundleContext)
},
ani_native_function {
"nativeCreateBundleContextCheck",
"C{application.Context.Context}C{std.core.String}:",
reinterpret_cast<void *>(EtsApplication::CreateBundleContextCheck)
},
ani_native_function {
"nativeCreatePluginModuleContext",
"C{application.Context.Context}C{std.core.String}C{std.core.String}"
"C{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::CreatePluginModuleContext)
},
ani_native_function {
"nativeCreatePluginModuleContextCheck",
"C{application.Context.Context}C{std.core.String}C{std.core.String}:",
reinterpret_cast<void *>(EtsApplication::CreatePluginModuleContextCheck)
},
ani_native_function {
"nativeGetApplicationContext",
":C{application.ApplicationContext.ApplicationContext}",
reinterpret_cast<void *>(EtsApplication::GetApplicationContext)
},
ani_native_function {
"nativeDemoteCurrentFromCandidateMasterProcess",
"C{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::DemoteCurrentFromCandidateMasterProcess)
},
ani_native_function {
"nativePromoteCurrentToCandidateMasterProcess",
"zC{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::PromoteCurrentToCandidateMasterProcess)
},
ani_native_function {
"nativeGetApplicationContextInstance",
":C{application.ApplicationContext.ApplicationContext}",
reinterpret_cast<void *>(EtsApplication::GetApplicationContextInstance)
},
ani_native_function {
"nativeGetAppPreloadType",
":C{@ohos.app.ability.application.application.AppPreloadType}",
reinterpret_cast<void *>(EtsApplication::GetAppPreloadType)
},
ani_native_function {
"nativeExitMasterProcessRole",
"C{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::ExitMasterProcessRole)
},
ani_native_function {
"nativeCreatePluginModuleContextForHostBundle",
"C{application.Context.Context}C{std.core.String}"
"C{std.core.String}C{std.core.String}"
"C{utils.AbilityUtils.AsyncCallbackWrapper}:",
reinterpret_cast<void *>(EtsApplication::CreatePluginModuleContextForHostBundle)
},
ani_native_function {
"nativeCreatePluginModuleContextForHostBundleCheck",
"C{application.Context.Context}C{std.core.String}"
"C{std.core.String}C{std.core.String}:",
reinterpret_cast<void *>(EtsApplication::CreatePluginModuleContextForHostBundleCheck)
},
};
status = env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size());
if (status != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "Namespace_BindNativeFunctions failed status: %{public}d", status);
}
}
extern "C" {
ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
{
TAG_LOGD(AAFwkTag::APPKIT, "in ApplicationETS.ANI_Constructor");
if (vm == nullptr || result == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "null vm or result");
return ANI_INVALID_ARGS;
}
ani_env *env = nullptr;
ani_status status = ANI_ERROR;
status = vm->GetEnv(ANI_VERSION_1, &env);
if (status != ANI_OK) {
TAG_LOGE(AAFwkTag::APPKIT, "GetEnv failed, status: %{public}d", status);
return ANI_NOT_FOUND;
}
ApplicationInit(env);
*result = ANI_VERSION_1;
TAG_LOGD(AAFwkTag::APPKIT, "AbilityManagerEts.ANI_Constructor finished");
return ANI_OK;
}
}
}
}