diff --git a/frameworks/js/napi/js_child_process_manager/js_child_process_manager.cpp b/frameworks/js/napi/js_child_process_manager/js_child_process_manager.cpp index 9470ea891f..f1dcdba8ca 100644 --- a/frameworks/js/napi/js_child_process_manager/js_child_process_manager.cpp +++ b/frameworks/js/napi/js_child_process_manager/js_child_process_manager.cpp @@ -35,6 +35,12 @@ enum { MODE_SELF_FORK = 0, MODE_APP_SPAWN_FORK = 1, }; +struct ChildProcessNApiParam { + std::string srcEntry; + AppExecFwk::ChildProcessArgs args; + AppExecFwk::ChildProcessOptions options; + int32_t childProcessType; +}; } class JsChildProcessManager { @@ -58,6 +64,11 @@ public: GET_CB_INFO_AND_CALL(env, info, JsChildProcessManager, OnStartArkChildProcess); } + static napi_value StartNativeChildProcess(napi_env env, napi_callback_info info) + { + GET_CB_INFO_AND_CALL(env, info, JsChildProcessManager, OnStartNativeChildProcess); + } + private: napi_value OnStartChildProcess(napi_env env, size_t argc, napi_value* argv) { @@ -153,7 +164,7 @@ private: napi_value OnStartArkChildProcess(napi_env env, size_t argc, napi_value* argv) { TAG_LOGI(AAFwkTag::PROCESSMGR, "called"); - if (ChildProcessManager::GetInstance().IsChildProcess()) { + if (ChildProcessManager::GetInstance().IsChildProcessBySelfFork()) { TAG_LOGE(AAFwkTag::PROCESSMGR, "Already in child process"); ThrowError(env, AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED); return CreateJsUndefined(env); @@ -176,37 +187,100 @@ private: ThrowInvalidParamError(env, "Param srcEntry cannot be empty."); return CreateJsUndefined(env); } + if (!ParseArgsAndOptions(env, argv, argc, args, options)) { + return CreateJsUndefined(env); + } + ChildProcessNApiParam param; + param.srcEntry = srcEntry; + param.args = args; + param.options = options; + param.childProcessType = AppExecFwk::CHILD_PROCESS_TYPE_ARK; + napi_value result = nullptr; + StartChildProcessWithArgsTask(env, result, param); + return result; + } + + napi_value OnStartNativeChildProcess(napi_env env, size_t argc, napi_value* argv) + { + TAG_LOGI(AAFwkTag::PROCESSMGR, "called."); + if (ChildProcessManager::GetInstance().IsChildProcessBySelfFork()) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Already in child process"); + ThrowError(env, AbilityErrorCode::ERROR_CODE_OPERATION_NOT_SUPPORTED); + return CreateJsUndefined(env); + } + if (argc < ARGC_TWO) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Not enough params."); + ThrowTooFewParametersError(env); + return CreateJsUndefined(env); + } + std::string entryPoint; + AppExecFwk::ChildProcessArgs args; + AppExecFwk::ChildProcessOptions options; + if (!ConvertFromJsValue(env, argv[PARAM0], entryPoint)) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Parse param entryPoint failed, must be a valid string."); + ThrowInvalidParamError(env, "Parse param entryPoint failed, must be a valid string."); + return CreateJsUndefined(env); + } + if (entryPoint.empty()) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "entryPoint empty."); + ThrowInvalidParamError(env, "Param entryPoint cannot be empty."); + return CreateJsUndefined(env); + } + if (entryPoint.find(":") == std::string::npos) { + TAG_LOGE(AAFwkTag::PROCESSMGR, + "Param entryPoint must contains a colon to separate library name and entry function."); + ThrowInvalidParamError(env, + "Param entryPoint must contains a colon to separate library name and entry function."); + return CreateJsUndefined(env); + } + if (!ParseArgsAndOptions(env, argv, argc, args, options)) { + return CreateJsUndefined(env); + } + ChildProcessNApiParam param; + param.srcEntry = entryPoint; + param.args = args; + param.options = options; + param.childProcessType = AppExecFwk::CHILD_PROCESS_TYPE_NATIVE_ARGS; + napi_value result = nullptr; + StartChildProcessWithArgsTask(env, result, param); + return result; + } + + bool ParseArgsAndOptions(const napi_env &env, napi_value* argv, size_t argc, AppExecFwk::ChildProcessArgs &args, + AppExecFwk::ChildProcessOptions &options) + { std::string errorMsg; if (!UnwrapChildProcessArgs(env, argv[PARAM1], args, errorMsg)) { TAG_LOGE(AAFwkTag::PROCESSMGR, "Parse param args failed."); ThrowInvalidParamError(env, errorMsg); - return CreateJsUndefined(env); + return false; } if (argc > ARGS_TWO && !UnwrapChildProcessOptions(env, argv[PARAM2], options, errorMsg)) { TAG_LOGE(AAFwkTag::PROCESSMGR, "Parse param options failed."); ThrowInvalidParamError(env, errorMsg); - return CreateJsUndefined(env); + return false; } - napi_value result = nullptr; - StartArkChildProcessTask(env, result, srcEntry, args, options); - return result; + return true; } - void StartArkChildProcessTask(const napi_env &env, napi_value &result, const std::string &srcEntry, - const AppExecFwk::ChildProcessArgs &args, const AppExecFwk::ChildProcessOptions &options) + void StartChildProcessWithArgsTask(const napi_env &env, napi_value &result, const ChildProcessNApiParam ¶m) { - TAG_LOGD(AAFwkTag::PROCESSMGR, "OnStartArkChildProcess, srcEntry:%{private}s, args.entryParams:%{private}s," - " args.fds size:%{public}zu, options.isolationMode:%{public}d", srcEntry.c_str(), - args.entryParams.c_str(), args.fds.size(), options.isolationMode); + auto &srcEntry = param.srcEntry; + auto &args = param.args; + auto &options = param.options; + auto childProcessType = param.childProcessType; + TAG_LOGD(AAFwkTag::PROCESSMGR, "StartChildProcessWithArgs, childProcessType:%{public}d, srcEntry:%{private}s, " + "args.entryParams:%{private}s, args.fds size:%{public}zu, options.isolationMode:%{public}d", + childProcessType, srcEntry.c_str(), args.entryParams.c_str(), args.fds.size(), options.isolationMode); auto innerErrorCode = std::make_shared(ChildProcessManagerErrorCode::ERR_OK); auto pid = std::make_shared(0); - NapiAsyncTask::ExecuteCallback execute = [srcEntry, args, options, pid, innerErrorCode]() { + NapiAsyncTask::ExecuteCallback execute = [srcEntry, args, options, childProcessType, pid, innerErrorCode]() { if (!pid || !innerErrorCode) { TAG_LOGE(AAFwkTag::PROCESSMGR, "innerErrorCode or pid is nullptr"); return; } - *innerErrorCode = ChildProcessManager::GetInstance().StartArkChildProcess(srcEntry, *pid, - AppExecFwk::CHILD_PROCESS_TYPE_ARK, args, options); + *innerErrorCode = ChildProcessManager::GetInstance().StartChildProcessWithArgs(srcEntry, *pid, + childProcessType, args, options); }; NapiAsyncTask::CompleteCallback complete = [pid, innerErrorCode](napi_env env, NapiAsyncTask &task, int32_t status) { @@ -222,7 +296,7 @@ private: ChildProcessManagerErrorUtil::GetAbilityErrorCode(*innerErrorCode))); } }; - NapiAsyncTask::ScheduleHighQos("JsChildProcessManager::OnStartArkChildProcess", + NapiAsyncTask::ScheduleHighQos("JsChildProcessManager::StartChildProcessWithArgsTask", env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result)); } }; @@ -241,6 +315,8 @@ napi_value JsChildProcessManagerInit(napi_env env, napi_value exportObj) const char *moduleName = PROCESS_MANAGER_NAME; BindNativeFunction(env, exportObj, "startChildProcess", moduleName, JsChildProcessManager::StartChildProcess); BindNativeFunction(env, exportObj, "startArkChildProcess", moduleName, JsChildProcessManager::StartArkChildProcess); + BindNativeFunction(env, exportObj, "startNativeChildProcess", moduleName, + JsChildProcessManager::StartNativeChildProcess); return CreateJsUndefined(env); } } // namespace AbilityRuntime diff --git a/frameworks/native/ability/native/child_process_manager/child_process_manager.cpp b/frameworks/native/ability/native/child_process_manager/child_process_manager.cpp index ae88e5982e..14cfc4af94 100644 --- a/frameworks/native/ability/native/child_process_manager/child_process_manager.cpp +++ b/frameworks/native/ability/native/child_process_manager/child_process_manager.cpp @@ -29,6 +29,7 @@ #include "bundle_info.h" #include "bundle_mgr_interface.h" #include "child_process.h" +#include "native_args_child_process.h" #include "native_child_ipc_process.h" #include "child_process_manager_error_utils.h" #include "child_process_request.h" @@ -103,18 +104,19 @@ ChildProcessManagerErrorCode ChildProcessManager::StartChildProcessByAppSpawnFor { AppExecFwk::ChildProcessArgs args; AppExecFwk::ChildProcessOptions options; - return StartArkChildProcess(srcEntry, pid, AppExecFwk::CHILD_PROCESS_TYPE_JS, args, options); + return StartChildProcessWithArgs(srcEntry, pid, AppExecFwk::CHILD_PROCESS_TYPE_JS, args, options); } -ChildProcessManagerErrorCode ChildProcessManager::StartArkChildProcess( +ChildProcessManagerErrorCode ChildProcessManager::StartChildProcessWithArgs( const std::string &srcEntry, pid_t &pid, int32_t childProcessType, const AppExecFwk::ChildProcessArgs &args, const AppExecFwk::ChildProcessOptions &options) { - TAG_LOGI(AAFwkTag::PROCESSMGR, "startWitDebug: %{public}d, processName:" - "%{public}s, native:%{public}d, entryParams:%{private}s, fdsSize:%{public}zu, options.isolationMode:%{public}d", - g_debugOption.isStartWithDebug, g_debugOption.processName.c_str(), g_debugOption.isStartWithNative, - args.entryParams.c_str(), args.fds.size(), options.isolationMode); - ChildProcessManagerErrorCode errorCode = PreCheck(childProcessType != AppExecFwk::CHILD_PROCESS_TYPE_JS); + TAG_LOGI(AAFwkTag::PROCESSMGR, "StartChildProcessWithArgs, childProcessType:%{public}d, startWitDebug: %{public}d," + " processName:%{public}s, native:%{public}d, entryParams:%{private}s, fdsSize:%{public}zu," + " options.isolationMode:%{public}d", childProcessType, g_debugOption.isStartWithDebug, + g_debugOption.processName.c_str(), g_debugOption.isStartWithNative, args.entryParams.c_str(), args.fds.size(), + options.isolationMode); + ChildProcessManagerErrorCode errorCode = PreCheck(childProcessType); if (errorCode != ChildProcessManagerErrorCode::ERR_OK) { return errorCode; } @@ -136,7 +138,7 @@ ChildProcessManagerErrorCode ChildProcessManager::StartArkChildProcess( TAG_LOGD(AAFwkTag::PROCESSMGR, "AppMgr StartChildProcess ret:%{public}d", ret); if (ret != ERR_OK) { TAG_LOGE(AAFwkTag::PROCESSMGR, "StartChildProcess error:%{public}d", ret); - return ChildProcessManagerErrorCode::ERR_GET_APP_MGR_START_PROCESS_FAILED; + return ChildProcessManagerErrorUtil::GetChildProcessManagerErrorCode(ret); } return ChildProcessManagerErrorCode::ERR_OK; } @@ -166,7 +168,7 @@ ChildProcessManagerErrorCode ChildProcessManager::StartNativeChildProcessByAppSp TAG_LOGE(AAFwkTag::PROCESSMGR, "Max native child processes readched"); return ChildProcessManagerErrorCode::ERR_MAX_NATIVE_CHILD_PROCESSES; } - return ChildProcessManagerErrorCode::ERR_GET_APP_MGR_START_PROCESS_FAILED; + return ChildProcessManagerErrorCode::ERR_APP_MGR_FAILED_INNER; } ++childProcessCount_; @@ -189,14 +191,29 @@ void ChildProcessManager::HandleSigChild(int32_t signo) } } -ChildProcessManagerErrorCode ChildProcessManager::PreCheck(bool useNewErrorCode) +ChildProcessManagerErrorCode ChildProcessManager::PreCheck() { if (!AAFwk::AppUtils::GetInstance().IsMultiProcessModel()) { TAG_LOGE(AAFwkTag::PROCESSMGR, "Multi process model disabled"); + return ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED; + } + if (IsChildProcess()) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Already in child process"); + return ChildProcessManagerErrorCode::ERR_ALREADY_IN_CHILD_PROCESS; + } + return ChildProcessManagerErrorCode::ERR_OK; +} + +ChildProcessManagerErrorCode ChildProcessManager::PreCheck(int32_t childProcessType) +{ + if (!AAFwk::AppUtils::GetInstance().IsMultiProcessModel() && + childProcessType != AppExecFwk::CHILD_PROCESS_TYPE_NATIVE_ARGS) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Not support child process."); + auto useNewErrorCode = childProcessType != AppExecFwk::CHILD_PROCESS_TYPE_JS; return useNewErrorCode ? ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED_NEW : ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED; } - if (IsChildProcess()) { + if (isChildProcessBySelfFork_) { TAG_LOGE(AAFwkTag::PROCESSMGR, "Already in child process"); return ChildProcessManagerErrorCode::ERR_ALREADY_IN_CHILD_PROCESS; } @@ -223,6 +240,11 @@ bool ChildProcessManager::IsChildProcess() return isChildProcessBySelfFork_ || HasChildProcessRecord(); } +bool ChildProcessManager::IsChildProcessBySelfFork() +{ + return isChildProcessBySelfFork_; +} + void ChildProcessManager::HandleChildProcessBySelfFork(const std::string &srcEntry, const AppExecFwk::BundleInfo &bundleInfo) { @@ -311,6 +333,31 @@ bool ChildProcessManager::LoadNativeLib(const std::string &moduleName, return true; } +bool ChildProcessManager::LoadNativeLibWithArgs(const std::string &moduleName, const std::string &srcEntry, + const std::string &entryFunc, std::shared_ptr args) +{ + TAG_LOGI(AAFwkTag::PROCESSMGR, "moduleName:%{public}s, srcEntry:%{public}s, entryFunc:%{public}s.", + moduleName.c_str(), srcEntry.c_str(), entryFunc.c_str()); + auto childProcess = NativeArgsChildProcess::Create(); + if (childProcess == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Failed create NativeArgsChildProcess."); + return false; + } + + std::shared_ptr processStartInfo = std::make_shared(); + processStartInfo->moduleName = moduleName; + processStartInfo->srcEntry = srcEntry; + processStartInfo->entryFunc = entryFunc; + if (!childProcess->Init(processStartInfo)) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "NativeArgsChildProcess init failed."); + return false; + } + + childProcess->OnStart(args); + TAG_LOGD(AAFwkTag::PROCESSMGR, "LoadNativeLibWithArgs end."); + return true; +} + std::unique_ptr ChildProcessManager::CreateRuntime(const AppExecFwk::BundleInfo &bundleInfo, const AppExecFwk::HapModuleInfo &hapModuleInfo, const bool fromAppSpawn, const bool jitEnabled) { diff --git a/frameworks/native/ability/native/child_process_manager/child_process_manager_error_utils.cpp b/frameworks/native/ability/native/child_process_manager/child_process_manager_error_utils.cpp index 2c6594274e..2aa00f0f42 100644 --- a/frameworks/native/ability/native/child_process_manager/child_process_manager_error_utils.cpp +++ b/frameworks/native/ability/native/child_process_manager/child_process_manager_error_utils.cpp @@ -28,5 +28,16 @@ AbilityErrorCode ChildProcessManagerErrorUtil::GetAbilityErrorCode(const ChildPr return AbilityErrorCode::ERROR_CODE_INNER; } + +ChildProcessManagerErrorCode ChildProcessManagerErrorUtil::GetChildProcessManagerErrorCode( + int32_t abilityManagerErrorCode) +{ + auto it = ABILITY_MANAGER_ERR_CODE_MAP.find(abilityManagerErrorCode); + if (it != ABILITY_MANAGER_ERR_CODE_MAP.end()) { + return it->second; + } + + return ChildProcessManagerErrorCode::ERR_APP_MGR_FAILED_INNER; +} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/ability/native/child_process_manager/native_args_child_process.cpp b/frameworks/native/ability/native/child_process_manager/native_args_child_process.cpp new file mode 100644 index 0000000000..bbe28ca6a4 --- /dev/null +++ b/frameworks/native/ability/native/child_process_manager/native_args_child_process.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2024 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 "native_args_child_process.h" + +#include +#include "hilog_tag_wrapper.h" +#include "securec.h" + +namespace OHOS { +namespace AbilityRuntime { + +std::shared_ptr NativeArgsChildProcess::Create() +{ + return std::make_shared(); +} + +NativeArgsChildProcess::~NativeArgsChildProcess() +{ + UnloadNativeLib(); +} + +bool NativeArgsChildProcess::Init(const std::shared_ptr &info) +{ + TAG_LOGD(AAFwkTag::PROCESSMGR, "NativeArgsChildProcess init called."); + if (info == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "info is nullptr."); + return false; + } + + if (!ChildProcess::Init(info)) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Base class init failed."); + return false; + } + + return LoadNativeLib(info); +} + +void NativeArgsChildProcess::OnStart(std::shared_ptr args) +{ + if (args == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "args is nullptr."); + return; + } + ChildProcess::OnStart(args); + + TAG_LOGI(AAFwkTag::PROCESSMGR, "Enter native lib entry function"); + auto nativeArgs = ParseToNativeArgs(args->entryParams, args->fds); + + if (!entryFunc_) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "entryFunc nullptr."); + return; + } + entryFunc_(nativeArgs); + TAG_LOGI(AAFwkTag::PROCESSMGR, "Native lib entry function returned"); +} + +NativeChildProcess_Args NativeArgsChildProcess::ParseToNativeArgs(const std::string &entryParams, + const std::map &fds) +{ + NativeChildProcess_Args args; + args.entryParams = new(std::nothrow) char[entryParams.size() + 1]; + if (!args.entryParams) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "entryParams nullptr."); + return args; + } + if (strcpy_s(args.entryParams, entryParams.size() + 1, entryParams.c_str()) != ERR_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "strcpy_s failed."); + return args; + } + NativeChildProcess_Fd *tail = nullptr; + for (const auto &fd : fds) { + auto &fdName = fd.first; + auto fdValue = fd.second; + + NativeChildProcess_Fd *node = new(std::nothrow) NativeChildProcess_Fd; + if (!node) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "fd node nullptr."); + return args; + } + node->fdName = new char[fdName.size() + 1]; + if (strcpy_s(node->fdName, fdName.size() + 1, fdName.c_str()) != ERR_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "strcpy_s failed."); + return args; + } + node->fd = fdValue; + + if (!args.fdList.head) { + args.fdList.head = node; + } else { + tail->next = node; + } + tail = node; + } + return args; +} + +bool NativeArgsChildProcess::LoadNativeLib(const std::shared_ptr &info) +{ + if (info == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "info is nullptr."); + return false; + } + TAG_LOGI(AAFwkTag::PROCESSMGR, "LoadNativeLib, moduleName:%{public}s, srcEntry:%{public}s, entryFunc:%{public}s", + info->moduleName.c_str(), info->srcEntry.c_str(), info->entryFunc.c_str()); + if (nativeLibHandle_ != nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Native lib already loaded."); + return false; + } + + if (info->moduleName.empty()) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "ModuleName is empty"); + return false; + } + + Dl_namespace dlnsApp; + std::string appDlNameSpace = "moduleNs_" + info->moduleName; + int ret = dlns_get(appDlNameSpace.c_str(), &dlnsApp); + if (ret != 0) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Get app dlNamespace(%{private}s) failed, err:%{public}d", + appDlNameSpace.c_str(), ret); + return false; + } + + void *libHandle = dlopen_ns(&dlnsApp, info->srcEntry.c_str(), RTLD_LAZY); + if (libHandle == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Load lib file %{private}s failed, err %{public}s", + info->srcEntry.c_str(), dlerror()); + return false; + } + + auto entryFunc = reinterpret_cast(dlsym(libHandle, info->entryFunc.c_str())); + if (entryFunc == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Get entryFunc address failed, err %{public}s", dlerror()); + dlclose(libHandle); + return false; + } + + entryFunc_ = entryFunc; + nativeLibHandle_ = libHandle; + return true; +} + +void NativeArgsChildProcess::UnloadNativeLib() +{ + if (nativeLibHandle_ != nullptr) { + dlclose(nativeLibHandle_); + nativeLibHandle_ = nullptr; + entryFunc_ = nullptr; + } +} + +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/appkit/BUILD.gn b/frameworks/native/appkit/BUILD.gn index 56cf4b7ce3..6b2fcf649d 100644 --- a/frameworks/native/appkit/BUILD.gn +++ b/frameworks/native/appkit/BUILD.gn @@ -124,6 +124,7 @@ ohos_shared_library("appkit_native") { "${ability_runtime_native_path}/appkit/app/extension_plugin_info.cpp", "${ability_runtime_native_path}/appkit/app/idle_time.cpp", "${ability_runtime_native_path}/appkit/app/main_thread.cpp", + "${ability_runtime_native_path}/appkit/app/native_lib_util.cpp", "${ability_runtime_native_path}/appkit/app/ohos_application.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_config.cpp", "${ability_runtime_native_path}/appkit/app_startup/js_startup_task.cpp", diff --git a/frameworks/native/appkit/app/child_main_thread.cpp b/frameworks/native/appkit/app/child_main_thread.cpp index cfb99f877e..db8d2812d3 100644 --- a/frameworks/native/appkit/app/child_main_thread.cpp +++ b/frameworks/native/appkit/app/child_main_thread.cpp @@ -14,12 +14,16 @@ */ #include "child_main_thread.h" + #include + +#include "bundle_mgr_helper.h" #include "bundle_mgr_proxy.h" #include "child_process_manager.h" #include "constants.h" #include "hilog_tag_wrapper.h" #include "js_runtime.h" +#include "native_lib_util.h" #include "sys_mgr_client.h" #include "system_ability_definition.h" @@ -108,6 +112,7 @@ bool ChildMainThread::Init(const std::shared_ptr &runner, const Chi return false; } processInfo_ = std::make_shared(processInfo); + processArgs_->entryParams = processInfo.entryParams; mainHandler_ = std::make_shared(runner); BundleInfo bundleInfo; if (!ChildProcessManager::GetInstance().GetBundleInfo(bundleInfo)) { @@ -141,9 +146,9 @@ bool ChildMainThread::Attach() return true; } -bool ChildMainThread::ScheduleLoadJs() +bool ChildMainThread::ScheduleLoadChild() { - TAG_LOGI(AAFwkTag::APPKIT, "called"); + TAG_LOGI(AAFwkTag::APPKIT, "ScheduleLoadChild called."); if (mainHandler_ == nullptr) { TAG_LOGE(AAFwkTag::APPKIT, "mainHandler_ is null"); return false; @@ -157,17 +162,19 @@ bool ChildMainThread::ScheduleLoadJs() auto task = [weak, childProcessType]() { auto childMainThread = weak.promote(); if (childMainThread == nullptr) { - TAG_LOGE(AAFwkTag::APPKIT, "childMainThread is nullptr, ScheduleLoadJs failed"); + TAG_LOGE(AAFwkTag::APPKIT, "childMainThread is nullptr, ScheduleLoadChild failed."); return; } if (childProcessType == CHILD_PROCESS_TYPE_ARK) { childMainThread->HandleLoadArkTs(); + } else if (childProcessType == CHILD_PROCESS_TYPE_NATIVE_ARGS) { + childMainThread->HandleLoadNative(); } else { childMainThread->HandleLoadJs(); } }; if (!mainHandler_->PostTask(task, "ChildMainThread::HandleLoadJs")) { - TAG_LOGE(AAFwkTag::APPKIT, "PostTask task failed"); + TAG_LOGE(AAFwkTag::APPKIT, "ChildMainThread::ScheduleLoadChild PostTask task failed."); return false; } return true; @@ -241,18 +248,43 @@ void ChildMainThread::HandleLoadArkTs() processInfo_->processName.c_str(), processInfo_->isDebugApp, processInfo_->isStartWithNative); runtime_->StartDebugMode(debugOption); - processArgs_->entryParams = processInfo_->entryParams; childProcessManager.LoadJsFile(srcEntry, hapModuleInfo, runtime_, processArgs_); } +void ChildMainThread::HandleLoadNative() +{ + TAG_LOGD(AAFwkTag::APPKIT, "HandleLoadNative called."); + if (!processInfo_) { + TAG_LOGE(AAFwkTag::APPKIT, "processInfo_ is null."); + return; + } + if (!processArgs_) { + TAG_LOGE(AAFwkTag::APPKIT, "processArgs_ is nullptr."); + return; + } + ChildProcessManager &childProcessMgr = ChildProcessManager::GetInstance(); + childProcessMgr.LoadNativeLibWithArgs(nativeLibModuleName_, processInfo_->srcEntry, processInfo_->entryFunc, + processArgs_); + TAG_LOGD(AAFwkTag::APPKIT, "HandleLoadNative end."); + ExitProcessSafely(); +} + void ChildMainThread::InitNativeLib(const BundleInfo &bundleInfo) { + HspList hspList; + ErrCode ret = DelayedSingleton::GetInstance()->GetBaseSharedBundleInfos(bundleInfo.name, hspList, + AppExecFwk::GetDependentBundleInfoFlag::GET_ALL_DEPENDENT_BUNDLE_INFO); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::APPKIT, "Get base shared bundle infos failed: %{public}d", ret); + } + AppLibPathMap appLibPaths {}; - GetNativeLibPath(bundleInfo, appLibPaths); + GetNativeLibPath(bundleInfo, hspList, appLibPaths); bool isSystemApp = bundleInfo.applicationInfo.isSystemApp; TAG_LOGD(AAFwkTag::APPKIT, "the application isSystemApp: %{public}d", isSystemApp); - if (processInfo_->childProcessType != CHILD_PROCESS_TYPE_NATIVE) { + if (processInfo_->childProcessType != CHILD_PROCESS_TYPE_NATIVE && + processInfo_->childProcessType != CHILD_PROCESS_TYPE_NATIVE_ARGS) { AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp); } else { UpdateNativeChildLibModuleName(appLibPaths, isSystemApp); @@ -363,7 +395,6 @@ void ChildMainThread::UpdateNativeChildLibModuleName(const AppLibPathMap &appLib if (!nativeLibPath.empty() && nativeLibPath.back() != '/') { nativeLibPath += '/'; } - nativeLibPath += processInfo_->srcEntry; if (access(nativeLibPath.c_str(), F_OK) == 0) { nativeLibModuleName_ = libPathPair.first; @@ -378,7 +409,8 @@ void ChildMainThread::UpdateNativeChildLibModuleName(const AppLibPathMap &appLib processInfo_->srcEntry.c_str()); } -void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, AppLibPathMap &appLibPaths) +void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, + AppLibPathMap &appLibPaths) { std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath; if (!nativeLibraryPath.empty()) { @@ -397,39 +429,12 @@ void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, AppLibPathM hapInfo.moduleName.c_str(), hapInfo.isLibIsolated, hapInfo.compressNativeLibs); GetHapSoPath(hapInfo, appLibPaths, hapInfo.hapPath.find(ABS_CODE_PATH)); } -} -void ChildMainThread::GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) -{ - if (hapInfo.nativeLibraryPath.empty()) { - TAG_LOGD(AAFwkTag::APPKIT, "Lib path of %{public}s is empty, lib isn't isolated or compressed", - hapInfo.moduleName.c_str()); - return; + for (auto &hspInfo : hspList) { + TAG_LOGD(AAFwkTag::APPKIT, "bundle:%s, module:%s, nativeLibraryPath:%s", hspInfo.bundleName.c_str(), + hspInfo.moduleName.c_str(), hspInfo.nativeLibraryPath.c_str()); + GetHspNativeLibPath(hspInfo, appLibPaths, hspInfo.hapPath.find(ABS_CODE_PATH) != 0u); } - - std::string appLibPathKey = hapInfo.bundleName + "/" + hapInfo.moduleName; - std::string libPath = LOCAL_CODE_PATH; - if (!hapInfo.compressNativeLibs) { - TAG_LOGD(AAFwkTag::APPKIT, "Lib of %{public}s will not be extracted from hap", hapInfo.moduleName.c_str()); - libPath = GetLibPath(hapInfo.hapPath, isPreInstallApp); - } - - libPath += (libPath.back() == '/') ? hapInfo.nativeLibraryPath : "/" + hapInfo.nativeLibraryPath; - TAG_LOGI( - AAFwkTag::APPKIT, "appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str()); - appLibPaths[appLibPathKey].emplace_back(libPath); -} - -std::string ChildMainThread::GetLibPath(const std::string &hapPath, bool isPreInstallApp) -{ - std::string libPath = LOCAL_CODE_PATH; - if (isPreInstallApp) { - auto pos = hapPath.rfind("/"); - if (pos != std::string::npos) { - libPath = hapPath.substr(0, pos); - } - } - return libPath; } } // namespace AppExecFwk } // namespace OHOS diff --git a/frameworks/native/appkit/app/main_thread.cpp b/frameworks/native/appkit/app/main_thread.cpp index bf94a4f119..79695cad7e 100644 --- a/frameworks/native/appkit/app/main_thread.cpp +++ b/frameworks/native/appkit/app/main_thread.cpp @@ -74,6 +74,7 @@ #ifdef CJ_FRONTEND #include "cj_runtime.h" #endif +#include "native_lib_util.h" #include "nlohmann/json.hpp" #include "ohos_application.h" #include "overlay_module_info.h" @@ -166,89 +167,6 @@ const int32_t TYPE_RESERVE = 1; const int32_t TYPE_OTHERS = 2; extern "C" int DFX_SetAppRunningUniqueId(const char* appRunningId, size_t len) __attribute__((weak)); - -std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp) -{ - std::string libPath = LOCAL_CODE_PATH; - if (isPreInstallApp) { - auto pos = hapPath.rfind("/"); - libPath = hapPath.substr(0, pos); - } - return libPath; -} - -void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) -{ - if (hapInfo.nativeLibraryPath.empty()) { - TAG_LOGD(AAFwkTag::APPKIT, "Lib path of %{public}s is empty, lib isn't isolated or compressed", - hapInfo.moduleName.c_str()); - return; - } - - std::string appLibPathKey = hapInfo.bundleName + "/" + hapInfo.moduleName; - std::string libPath = LOCAL_CODE_PATH; - if (!hapInfo.compressNativeLibs) { - TAG_LOGD(AAFwkTag::APPKIT, "Lib of %{public}s will not be extracted from hap", hapInfo.moduleName.c_str()); - libPath = GetLibPath(hapInfo.hapPath, isPreInstallApp); - } - - libPath += (libPath.back() == '/') ? hapInfo.nativeLibraryPath : "/" + hapInfo.nativeLibraryPath; - TAG_LOGD( - AAFwkTag::APPKIT, "appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str()); - appLibPaths[appLibPathKey].emplace_back(libPath); -} - -void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) -{ - if (hspInfo.nativeLibraryPath.empty()) { - return; - } - - std::string appLibPathKey = hspInfo.bundleName + "/" + hspInfo.moduleName; - std::string libPath = LOCAL_CODE_PATH; - if (!hspInfo.compressNativeLibs) { - libPath = GetLibPath(hspInfo.hapPath, isPreInstallApp); - libPath = libPath.back() == '/' ? libPath : libPath + "/"; - if (isPreInstallApp) { - libPath += hspInfo.nativeLibraryPath; - } else { - libPath += hspInfo.bundleName + "/" + hspInfo.moduleName + "/" + hspInfo.nativeLibraryPath; - } - } else { - libPath = libPath.back() == '/' ? libPath : libPath + "/"; - libPath += hspInfo.bundleName + "/" + hspInfo.nativeLibraryPath; - } - - TAG_LOGD( - AAFwkTag::APPKIT, "appLibPathKey: %{private}s, libPath: %{private}s", appLibPathKey.c_str(), libPath.c_str()); - appLibPaths[appLibPathKey].emplace_back(libPath); -} - -void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativeLibraryPath, - AppLibPathMap &appLibPaths) -{ - if (hapInfo.isLibIsolated) { - patchNativeLibraryPath = hapInfo.hqfInfo.nativeLibraryPath; - } - - if (patchNativeLibraryPath.empty()) { - TAG_LOGD(AAFwkTag::APPKIT, "Patch lib path of %{public}s is empty", hapInfo.moduleName.c_str()); - return; - } - - if (hapInfo.compressNativeLibs && !hapInfo.isLibIsolated) { - TAG_LOGD(AAFwkTag::APPKIT, "Lib of %{public}s has compressed and isn't isolated, no need to set", - hapInfo.moduleName.c_str()); - return; - } - - std::string appLibPathKey = hapInfo.bundleName + "/" + hapInfo.moduleName; - std::string patchLibPath = LOCAL_CODE_PATH; - patchLibPath += (patchLibPath.back() == '/') ? patchNativeLibraryPath : "/" + patchNativeLibraryPath; - TAG_LOGD(AAFwkTag::APPKIT, "appLibPathKey: %{public}s, patch lib path: %{private}s", appLibPathKey.c_str(), - patchLibPath.c_str()); - appLibPaths[appLibPathKey].emplace_back(patchLibPath); -} } // namespace void MainThread::GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths) diff --git a/frameworks/native/appkit/app/native_lib_util.cpp b/frameworks/native/appkit/app/native_lib_util.cpp new file mode 100644 index 0000000000..152562ab11 --- /dev/null +++ b/frameworks/native/appkit/app/native_lib_util.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024 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 "native_lib_util.h" + +#include "constants.h" +#include "hilog_tag_wrapper.h" + +namespace OHOS { +namespace AppExecFwk { +std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp) +{ + std::string libPath = AbilityBase::Constants::LOCAL_CODE_PATH; + if (isPreInstallApp) { + auto pos = hapPath.rfind("/"); + libPath = hapPath.substr(0, pos); + } + return libPath; +} + +void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) +{ + if (hapInfo.nativeLibraryPath.empty()) { + TAG_LOGD(AAFwkTag::APPKIT, "Lib path of %{public}s is empty, lib isn't isolated or compressed", + hapInfo.moduleName.c_str()); + return; + } + + std::string appLibPathKey = hapInfo.bundleName + "/" + hapInfo.moduleName; + std::string libPath = AbilityBase::Constants::LOCAL_CODE_PATH; + if (!hapInfo.compressNativeLibs) { + TAG_LOGD(AAFwkTag::APPKIT, "Lib of %{public}s will not be extracted from hap", hapInfo.moduleName.c_str()); + libPath = GetLibPath(hapInfo.hapPath, isPreInstallApp); + } + + libPath += (libPath.back() == '/') ? hapInfo.nativeLibraryPath : "/" + hapInfo.nativeLibraryPath; + TAG_LOGD( + AAFwkTag::APPKIT, "appLibPathKey: %{private}s, lib path: %{private}s", appLibPathKey.c_str(), libPath.c_str()); + appLibPaths[appLibPathKey].emplace_back(libPath); +} + +void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp) +{ + if (hspInfo.nativeLibraryPath.empty()) { + return; + } + + std::string appLibPathKey = hspInfo.bundleName + "/" + hspInfo.moduleName; + std::string libPath = AbilityBase::Constants::LOCAL_CODE_PATH; + if (!hspInfo.compressNativeLibs) { + libPath = GetLibPath(hspInfo.hapPath, isPreInstallApp); + libPath = libPath.back() == '/' ? libPath : libPath + "/"; + if (isPreInstallApp) { + libPath += hspInfo.nativeLibraryPath; + } else { + libPath += hspInfo.bundleName + "/" + hspInfo.moduleName + "/" + hspInfo.nativeLibraryPath; + } + } else { + libPath = libPath.back() == '/' ? libPath : libPath + "/"; + libPath += hspInfo.bundleName + "/" + hspInfo.nativeLibraryPath; + } + + TAG_LOGD( + AAFwkTag::APPKIT, "appLibPathKey: %{private}s, libPath: %{private}s", appLibPathKey.c_str(), libPath.c_str()); + appLibPaths[appLibPathKey].emplace_back(libPath); +} + +void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativeLibraryPath, + AppLibPathMap &appLibPaths) +{ + if (hapInfo.isLibIsolated) { + patchNativeLibraryPath = hapInfo.hqfInfo.nativeLibraryPath; + } + + if (patchNativeLibraryPath.empty()) { + TAG_LOGD(AAFwkTag::APPKIT, "Patch lib path of %{public}s is empty", hapInfo.moduleName.c_str()); + return; + } + + if (hapInfo.compressNativeLibs && !hapInfo.isLibIsolated) { + TAG_LOGD(AAFwkTag::APPKIT, "Lib of %{public}s has compressed and isn't isolated, no need to set", + hapInfo.moduleName.c_str()); + return; + } + + std::string appLibPathKey = hapInfo.bundleName + "/" + hapInfo.moduleName; + std::string patchLibPath = AbilityBase::Constants::LOCAL_CODE_PATH; + patchLibPath += (patchLibPath.back() == '/') ? patchNativeLibraryPath : "/" + patchNativeLibraryPath; + TAG_LOGD(AAFwkTag::APPKIT, "appLibPathKey: %{public}s, patch lib path: %{private}s", appLibPathKey.c_str(), + patchLibPath.c_str()); + appLibPaths[appLibPathKey].emplace_back(patchLibPath); +} +} // AppExecFwk +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/child_process/src/native_child_process.cpp b/frameworks/native/child_process/src/native_child_process.cpp index fb3aafbe9e..6dca339f51 100644 --- a/frameworks/native/child_process/src/native_child_process.cpp +++ b/frameworks/native/child_process/src/native_child_process.cpp @@ -28,20 +28,24 @@ namespace { std::mutex g_mutexCallBackObj; sptr g_CallbackStub; OH_Ability_OnNativeChildProcessStarted g_Callback = nullptr; +constexpr size_t MAX_KEY_SIZE = 20; +constexpr size_t MAX_FD_SIZE = 16; const std::map CPM_ERRCODE_MAP = { { ChildProcessManagerErrorCode::ERR_OK, NCP_NO_ERROR }, + { ChildProcessManagerErrorCode::ERR_PERMISSION_DENIED, NCP_ERR_NO_PERMISSION }, { ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED, NCP_ERR_MULTI_PROCESS_DISABLED }, { ChildProcessManagerErrorCode::ERR_ALREADY_IN_CHILD_PROCESS, NCP_ERR_ALREADY_IN_CHILD }, { ChildProcessManagerErrorCode::ERR_GET_APP_MGR_FAILED, NCP_ERR_SERVICE_ERROR }, - { ChildProcessManagerErrorCode::ERR_GET_APP_MGR_START_PROCESS_FAILED, NCP_ERR_SERVICE_ERROR }, + { ChildProcessManagerErrorCode::ERR_APP_MGR_FAILED_INNER, NCP_ERR_SERVICE_ERROR }, { ChildProcessManagerErrorCode::ERR_UNSUPPORT_NATIVE_CHILD_PROCESS, NCP_ERR_NOT_SUPPORTED }, { ChildProcessManagerErrorCode::ERR_MAX_NATIVE_CHILD_PROCESSES, NCP_ERR_MAX_CHILD_PROCESSES_REACHED }, { ChildProcessManagerErrorCode::ERR_LIB_LOADING_FAILED, NCP_ERR_LIB_LOADING_FAILED }, { ChildProcessManagerErrorCode::ERR_CONNECTION_FAILED, NCP_ERR_CONNECTION_FAILED }, + { ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED_NEW, NCP_ERR_NOT_SUPPORTED }, }; -int CvtChildProcessManagerErrCode(ChildProcessManagerErrorCode cpmErr) +Ability_NativeChildProcess_ErrCode CvtChildProcessManagerErrCode(ChildProcessManagerErrorCode cpmErr) { auto it = CPM_ERRCODE_MAP.find(cpmErr); if (it == CPM_ERRCODE_MAP.end()) { @@ -101,3 +105,56 @@ int OH_Ability_CreateNativeChildProcess(const char* libName, OH_Ability_OnNative g_CallbackStub = callbackStub; return NCP_NO_ERROR; } + +Ability_NativeChildProcess_ErrCode OH_Ability_StartNativeChildProcess(const char* entry, + NativeChildProcess_Args args, NativeChildProcess_Options options, int32_t &pid) +{ + if (entry == nullptr || *entry == '\0') { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Invalid entry"); + return NCP_ERR_INVALID_PARAM; + } + + std::string entryName(entry); + if (entryName.find(":") != std::string::npos) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "entry point misses a colon"); + return NCP_ERR_INVALID_PARAM; + } + + if (args.entryParams == nullptr || *(args.entryParams) == '\0') { + TAG_LOGE(AAFwkTag::PROCESSMGR, "Invalid args.entryParams"); + return NCP_ERR_INVALID_PARAM; + } + std::string entryParams(args.entryParams); + + std::map fds; + NativeChildProcess_Fd* cur = args.fdList.head; + while (cur != nullptr) { + std::string key(cur->fdName); + if (key.size() > MAX_KEY_SIZE) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "fd name too long"); + return NCP_ERR_INVALID_PARAM; + } + fds.emplace(key, cur->fd); + cur = cur->next; + } + if (fds.size() > MAX_FD_SIZE) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "too many fds"); + return NCP_ERR_INVALID_PARAM; + } + AppExecFwk::ChildProcessArgs childArgs; + childArgs.entryParams = entryParams; + childArgs.fds = fds; + + AppExecFwk::ChildProcessOptions childProcessOptions; + childProcessOptions.isolationMode = options.isolationMode == NCP_ISOLATION_MODE_ISOLATED; + + int32_t childProcessType = AppExecFwk::CHILD_PROCESS_TYPE_NATIVE_ARGS; + + ChildProcessManager &mgr = ChildProcessManager::GetInstance(); + auto cpmErr = mgr.StartChildProcessWithArgs(entryName, pid, childProcessType, childArgs, childProcessOptions); + if (cpmErr != ChildProcessManagerErrorCode::ERR_OK) { + return CvtChildProcessManagerErrCode(cpmErr); + } + + return NCP_NO_ERROR; +} \ No newline at end of file diff --git a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h index aaa5e10224..e57ce28cd4 100644 --- a/interfaces/inner_api/ability_manager/include/ability_manager_errors.h +++ b/interfaces/inner_api/ability_manager/include/ability_manager_errors.h @@ -575,6 +575,21 @@ enum { */ ERR_KILL_FOUNDATION_UID = 2097261, + /* + * Result (2097264) for not support child process. + */ + ERR_NOT_SUPPORT_CHILD_PROCESS = 2097264, + + /* + * Result (2097265) for already in child process. + */ + ERR_ALREADY_IN_CHILD_PROCESS = 2097265, + + /* + * Result (2097266) for native args child process reach limit. + */ + ERR_NATIVE_ARGS_CHILD_PROCESS_REACH_LIMIT = 2097266, + /** * Native error(3000000) for target bundle not exist. */ diff --git a/interfaces/inner_api/app_manager/include/appmgr/child_process_info.h b/interfaces/inner_api/app_manager/include/appmgr/child_process_info.h index e5c708685f..a412eb2be6 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/child_process_info.h +++ b/interfaces/inner_api/app_manager/include/appmgr/child_process_info.h @@ -27,6 +27,7 @@ constexpr int32_t CHILD_PROCESS_TYPE_NOT_CHILD = -1; constexpr int32_t CHILD_PROCESS_TYPE_JS = 0; constexpr int32_t CHILD_PROCESS_TYPE_NATIVE = 1; constexpr int32_t CHILD_PROCESS_TYPE_ARK = 2; +constexpr int32_t CHILD_PROCESS_TYPE_NATIVE_ARGS = 3; struct ChildProcessInfo : public Parcelable { int32_t pid = 0; @@ -36,6 +37,7 @@ struct ChildProcessInfo : public Parcelable { std::string bundleName; std::string processName; std::string srcEntry; + std::string entryFunc; std::string entryParams; bool jitEnabled = false; bool isDebugApp = true; diff --git a/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_interface.h b/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_interface.h index 89fbfc623f..35ec3c60b7 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_interface.h +++ b/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_interface.h @@ -27,7 +27,7 @@ public: /** * Notify chile process to load js file. */ - virtual bool ScheduleLoadJs() = 0; + virtual bool ScheduleLoadChild() = 0; /** * Notify chile process to exit safely. diff --git a/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_proxy.h b/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_proxy.h index f5cd00d0f1..d57785e961 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_proxy.h +++ b/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_proxy.h @@ -27,7 +27,7 @@ public: explicit ChildSchedulerProxy(const sptr &impl); virtual ~ChildSchedulerProxy() = default; - bool ScheduleLoadJs() override; + bool ScheduleLoadChild() override; bool ScheduleExitProcessSafely() override; bool ScheduleRunNativeProc(const sptr &mainProcessCb) override; diff --git a/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_stub.h b/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_stub.h index eebab13561..02ec8428a1 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_stub.h +++ b/interfaces/inner_api/app_manager/include/appmgr/child_scheduler_stub.h @@ -34,7 +34,7 @@ public: uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; private: - int32_t HandleScheduleLoadJs(MessageParcel &data, MessageParcel &reply); + int32_t HandleScheduleLoadChild(MessageParcel &data, MessageParcel &reply); int32_t HandleScheduleExitProcessSafely(MessageParcel &data, MessageParcel &reply); int32_t HandleScheduleRunNativeProc(MessageParcel &data, MessageParcel &reply); diff --git a/interfaces/inner_api/app_manager/include/appmgr/process_data.h b/interfaces/inner_api/app_manager/include/appmgr/process_data.h index 0181f217b0..2a5a57ee35 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/process_data.h +++ b/interfaces/inner_api/app_manager/include/appmgr/process_data.h @@ -66,6 +66,7 @@ struct ProcessData : public Parcelable { bool isTestMode = false; // Indicates whether the process is started by aa test int32_t exitReason = 0; std::string exitMsg = ""; + int32_t childUid = -1; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/interfaces/inner_api/app_manager/src/appmgr/child_process_info.cpp b/interfaces/inner_api/app_manager/src/appmgr/child_process_info.cpp index 9d1e3962b1..49ad587876 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/child_process_info.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/child_process_info.cpp @@ -41,6 +41,7 @@ bool ChildProcessInfo::ReadFromParcel(Parcel &parcel) bundleName = Str16ToStr8(parcel.ReadString16()); processName = Str16ToStr8(parcel.ReadString16()); srcEntry = Str16ToStr8(parcel.ReadString16()); + entryFunc = Str16ToStr8(parcel.ReadString16()); entryParams = Str16ToStr8(parcel.ReadString16()); jitEnabled = parcel.ReadBool(); isDebugApp = parcel.ReadBool(); @@ -70,6 +71,7 @@ bool ChildProcessInfo::Marshalling(Parcel &parcel) const WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(bundleName)); WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(processName)); WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(srcEntry)); + WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(entryFunc)); WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(entryParams)); WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Bool, parcel, jitEnabled); WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Bool, parcel, isDebugApp); diff --git a/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_proxy.cpp b/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_proxy.cpp index bc0d2df7d9..94bddd23a0 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_proxy.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_proxy.cpp @@ -32,9 +32,9 @@ bool ChildSchedulerProxy::WriteInterfaceToken(MessageParcel &data) return true; } -bool ChildSchedulerProxy::ScheduleLoadJs() +bool ChildSchedulerProxy::ScheduleLoadChild() { - TAG_LOGD(AAFwkTag::APPMGR, "ScheduleLoadJs start"); + TAG_LOGD(AAFwkTag::APPMGR, "ScheduleLoadChild start"); MessageParcel data; MessageParcel reply; MessageOption option(MessageOption::TF_ASYNC); @@ -54,7 +54,7 @@ bool ChildSchedulerProxy::ScheduleLoadJs() TAG_LOGW(AAFwkTag::APPMGR, "SendRequest is failed, error code: %{public}d", ret); return false; } - TAG_LOGD(AAFwkTag::APPMGR, "ScheduleLoadJs end"); + TAG_LOGD(AAFwkTag::APPMGR, "ScheduleLoadChild end"); return true; } diff --git a/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_stub.cpp b/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_stub.cpp index b751b4c850..42e81559df 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_stub.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/child_scheduler_stub.cpp @@ -38,7 +38,7 @@ int32_t ChildSchedulerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, switch (code) { case static_cast(IChildScheduler::Message::SCHEDULE_LOAD_JS): - return HandleScheduleLoadJs(data, reply); + return HandleScheduleLoadChild(data, reply); case static_cast(IChildScheduler::Message::SCHEDULE_EXIT_PROCESS_SAFELY): return HandleScheduleExitProcessSafely(data, reply); case static_cast(IChildScheduler::Message::SCHEDULE_RUN_NATIVE_PROC): @@ -48,9 +48,9 @@ int32_t ChildSchedulerStub::OnRemoteRequest(uint32_t code, MessageParcel &data, return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } -int32_t ChildSchedulerStub::HandleScheduleLoadJs(MessageParcel &data, MessageParcel &reply) +int32_t ChildSchedulerStub::HandleScheduleLoadChild(MessageParcel &data, MessageParcel &reply) { - ScheduleLoadJs(); + ScheduleLoadChild(); return ERR_NONE; } diff --git a/interfaces/inner_api/app_manager/src/appmgr/process_data.cpp b/interfaces/inner_api/app_manager/src/appmgr/process_data.cpp index e194c40028..ffed112f01 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/process_data.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/process_data.cpp @@ -30,7 +30,8 @@ bool ProcessData::Marshalling(Parcel &parcel) const parcel.WriteInt32(processChangeReason) && parcel.WriteString(processName) && parcel.WriteInt32(static_cast(processType)) && parcel.WriteInt32(static_cast(extensionType)) && parcel.WriteInt32(renderUid) && parcel.WriteUint32(accessTokenId) && - parcel.WriteBool(isTestMode) && parcel.WriteInt32(exitReason) && parcel.WriteString16(Str8ToStr16(exitMsg))); + parcel.WriteBool(isTestMode) && parcel.WriteInt32(exitReason) && parcel.WriteString16(Str8ToStr16(exitMsg)) && + parcel.WriteInt32(childUid)); } bool ProcessData::ReadFromParcel(Parcel &parcel) @@ -54,6 +55,7 @@ bool ProcessData::ReadFromParcel(Parcel &parcel) isTestMode = parcel.ReadBool(); exitReason = parcel.ReadInt32(); exitMsg = Str16ToStr8(parcel.ReadString16()); + childUid = parcel.ReadInt32(); return true; } diff --git a/interfaces/inner_api/child_process_manager/BUILD.gn b/interfaces/inner_api/child_process_manager/BUILD.gn index bbd9caaebe..e2d990cfae 100644 --- a/interfaces/inner_api/child_process_manager/BUILD.gn +++ b/interfaces/inner_api/child_process_manager/BUILD.gn @@ -16,7 +16,10 @@ import("//foundation/ability/ability_runtime/ability_runtime.gni") config("child_process_manager_config") { visibility = [ ":*" ] - include_dirs = [ "include" ] + include_dirs = [ + "${ability_runtime_ndk_path}/ability/ability_runtime/child_process", + "include", + ] if (target_cpu == "arm") { cflags = [ "-DBINDER_IPC_32BIT" ] @@ -32,6 +35,7 @@ ohos_shared_library("child_process_manager") { "${ability_runtime_native_path}/ability/native/child_process_manager/child_process_manager.cpp", "${ability_runtime_native_path}/ability/native/child_process_manager/child_process_manager_error_utils.cpp", "${ability_runtime_native_path}/ability/native/child_process_manager/js_child_process.cpp", + "${ability_runtime_native_path}/ability/native/child_process_manager/native_args_child_process.cpp", "${ability_runtime_native_path}/ability/native/child_process_manager/native_child_ipc_process.cpp", ] diff --git a/interfaces/inner_api/child_process_manager/include/child_process_manager.h b/interfaces/inner_api/child_process_manager/include/child_process_manager.h index ff5d974d31..ef7b681b92 100644 --- a/interfaces/inner_api/child_process_manager/include/child_process_manager.h +++ b/interfaces/inner_api/child_process_manager/include/child_process_manager.h @@ -39,10 +39,12 @@ public: static void HandleSigChild(int32_t signo); bool IsChildProcess(); + bool IsChildProcessBySelfFork(); ChildProcessManagerErrorCode StartChildProcessBySelfFork(const std::string &srcEntry, pid_t &pid); ChildProcessManagerErrorCode StartChildProcessByAppSpawnFork(const std::string &srcEntry, pid_t &pid); - ChildProcessManagerErrorCode StartArkChildProcess(const std::string &srcEntry, pid_t &pid, int32_t childProcessType, - const AppExecFwk::ChildProcessArgs &args, const AppExecFwk::ChildProcessOptions &options); + ChildProcessManagerErrorCode StartChildProcessWithArgs(const std::string &srcEntry, pid_t &pid, + int32_t childProcessType, const AppExecFwk::ChildProcessArgs &args, + const AppExecFwk::ChildProcessOptions &options); ChildProcessManagerErrorCode StartNativeChildProcessByAppSpawnFork( const std::string &libName, const sptr &callbackStub); bool GetBundleInfo(AppExecFwk::BundleInfo &bundleInfo); @@ -56,6 +58,8 @@ public: std::shared_ptr args = nullptr); bool LoadNativeLib(const std::string &moduleName, const std::string &libPath, const sptr &mainProcessCb); + bool LoadNativeLibWithArgs(const std::string &moduleName, const std::string &srcEntry, + const std::string &entryFunc, std::shared_ptr args); void SetForkProcessJITEnabled(bool jitEnabled); void SetForkProcessDebugOption(const std::string bundleName, const bool isStartWithDebug, const bool isDebugApp, const bool isStartWithNative); @@ -66,7 +70,8 @@ public: private: ChildProcessManager(); - ChildProcessManagerErrorCode PreCheck(bool useNewErrorCode = false); + ChildProcessManagerErrorCode PreCheck(); + ChildProcessManagerErrorCode PreCheck(int32_t childProcessType); ChildProcessManagerErrorCode PreCheckNativeProcess(); void RegisterSignal(); void HandleChildProcessBySelfFork(const std::string &srcEntry, const AppExecFwk::BundleInfo &bundleInfo); diff --git a/interfaces/inner_api/child_process_manager/include/child_process_manager_error_utils.h b/interfaces/inner_api/child_process_manager/include/child_process_manager_error_utils.h index 7c3daca832..bb05aed780 100644 --- a/interfaces/inner_api/child_process_manager/include/child_process_manager_error_utils.h +++ b/interfaces/inner_api/child_process_manager/include/child_process_manager_error_utils.h @@ -19,6 +19,7 @@ #include #include "ability_business_error.h" +#include "ability_manager_errors.h" namespace OHOS { namespace AbilityRuntime { @@ -30,13 +31,14 @@ enum class ChildProcessManagerErrorCode { ERR_FORK_FAILED = 4, ERR_GET_BUNDLE_INFO_FAILED = 5, ERR_GET_APP_MGR_FAILED = 6, - ERR_GET_APP_MGR_START_PROCESS_FAILED = 7, + ERR_APP_MGR_FAILED_INNER = 7, ERR_UNSUPPORT_NATIVE_CHILD_PROCESS = 8, ERR_MAX_NATIVE_CHILD_PROCESSES = 9, ERR_LIB_LOADING_FAILED = 10, ERR_CONNECTION_FAILED = 11, ERR_UNSUPPORTED_START_MODE = 12, ERR_MULTI_PROCESS_MODEL_DISABLED_NEW = 13, + ERR_PERMISSION_DENIED = 14, }; const std::map INTERNAL_ERR_CODE_MAP = { @@ -49,15 +51,26 @@ const std::map INTERNAL_ERR_CODE { ChildProcessManagerErrorCode::ERR_FORK_FAILED, AbilityErrorCode::ERROR_CODE_INNER }, { ChildProcessManagerErrorCode::ERR_GET_BUNDLE_INFO_FAILED, AbilityErrorCode::ERROR_CODE_INNER }, { ChildProcessManagerErrorCode::ERR_GET_APP_MGR_FAILED, AbilityErrorCode::ERROR_CODE_INNER }, - { ChildProcessManagerErrorCode::ERR_GET_APP_MGR_START_PROCESS_FAILED, AbilityErrorCode::ERROR_CODE_INNER }, + { ChildProcessManagerErrorCode::ERR_APP_MGR_FAILED_INNER, AbilityErrorCode::ERROR_CODE_INNER }, { ChildProcessManagerErrorCode::ERR_UNSUPPORTED_START_MODE, AbilityErrorCode::ERROR_CODE_INVALID_PARAM }, { ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED_NEW, AbilityErrorCode::ERROR_CODE_CAPABILITY_NOT_SUPPORT }, + { ChildProcessManagerErrorCode::ERR_MAX_NATIVE_CHILD_PROCESSES, + AbilityErrorCode::ERROR_CODE_CHILD_PROCESS_NUMBER_EXCEEDS_UPPER_BOUND }, + { ChildProcessManagerErrorCode::ERR_PERMISSION_DENIED, AbilityErrorCode::ERROR_CODE_PERMISSION_DENIED }, +}; + +const std::map ABILITY_MANAGER_ERR_CODE_MAP = { + { ERR_PERMISSION_DENIED, ChildProcessManagerErrorCode::ERR_PERMISSION_DENIED }, + { AAFwk::ERR_NOT_SUPPORT_CHILD_PROCESS, ChildProcessManagerErrorCode::ERR_MULTI_PROCESS_MODEL_DISABLED_NEW }, + { AAFwk::ERR_ALREADY_IN_CHILD_PROCESS, ChildProcessManagerErrorCode::ERR_ALREADY_IN_CHILD_PROCESS }, + { AAFwk::ERR_NATIVE_ARGS_CHILD_PROCESS_REACH_LIMIT, ChildProcessManagerErrorCode::ERR_MAX_NATIVE_CHILD_PROCESSES }, }; class ChildProcessManagerErrorUtil { public: static AbilityErrorCode GetAbilityErrorCode(const ChildProcessManagerErrorCode &internalErrCode); + static ChildProcessManagerErrorCode GetChildProcessManagerErrorCode(int32_t abilityManagerErrorCode); }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/child_process_manager/include/child_process_start_info.h b/interfaces/inner_api/child_process_manager/include/child_process_start_info.h index 07828eae1b..b9238d803d 100644 --- a/interfaces/inner_api/child_process_manager/include/child_process_start_info.h +++ b/interfaces/inner_api/child_process_manager/include/child_process_start_info.h @@ -26,6 +26,7 @@ struct ChildProcessStartInfo { std::string moduleName; std::string srcEntry; std::string hapPath; + std::string entryFunc; bool isEsModule = true; sptr ipcObj; }; diff --git a/interfaces/inner_api/child_process_manager/include/native_args_child_process.h b/interfaces/inner_api/child_process_manager/include/native_args_child_process.h new file mode 100644 index 0000000000..abef91ac75 --- /dev/null +++ b/interfaces/inner_api/child_process_manager/include/native_args_child_process.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 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_NATIVE_ARGS_CHILD_PROCESS_H +#define OHOS_ABILITY_RUNTIME_NATIVE_ARGS_CHILD_PROCESS_H + +#include +#include + +#include "child_process.h" +#include "native_child_process.h" + +namespace OHOS { +namespace AbilityRuntime { + +class NativeArgsChildProcess : public ChildProcess { +public: + NativeArgsChildProcess() = default; + ~NativeArgsChildProcess(); + + static std::shared_ptr Create(); + + bool Init(const std::shared_ptr &info) override; + void OnStart(std::shared_ptr args) override; + +private: + bool LoadNativeLib(const std::shared_ptr &info); + void UnloadNativeLib(); + NativeChildProcess_Args ParseToNativeArgs(const std::string &entryParams, + const std::map &fds); + typedef void (*NativeArgsChildProcess_EntryFunc)(NativeChildProcess_Args args); + + void *nativeLibHandle_ = nullptr; + NativeArgsChildProcess_EntryFunc entryFunc_ = nullptr; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_NATIVE_ARGS_CHILD_PROCESS_H \ No newline at end of file diff --git a/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h b/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h index 60ab59bc0f..7ab4286eed 100644 --- a/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h +++ b/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h @@ -53,6 +53,11 @@ typedef enum Ability_NativeChildProcess_ErrCode { */ NCP_NO_ERROR = 0, + /** + * @error Operation not permitted. + */ + NCP_ERR_NO_PERMISSION = 201, + /** * @error Invalid parameter. */ @@ -172,7 +177,101 @@ typedef void (*OH_Ability_OnNativeChildProcessStarted)(int errCode, OHIPCRemoteP int OH_Ability_CreateNativeChildProcess(const char* libName, OH_Ability_OnNativeChildProcessStarted onProcessStarted); +/** + * @brief The info of the file descriptors passed to child process. + * @since 12 + */ +typedef struct NativeChildProcess_Fd { + /** the key of the file descriptor. */ + char* fdName; + /** the value of the file descriptor. */ + int32_t fd; + + /** the next pointer of the linked list. */ + struct NativeChildProcess_Fd* next; +} NativeChildProcess_Fd; + +/** + * @brief The list of the info of the file descriptors passed to child process. + * @since 12 + */ +typedef struct NativeChildProcess_FdList { + /** the head of the list. + * For details, see {@link NativeChildProcess_Fd}. + */ + struct NativeChildProcess_Fd* head; +} NativeChildProcess_FdList; + +/** + * @brief Enumerates the isolation modes used by the native child process module. + * @since 12 + */ +typedef enum NativeChildProcess_IsolationMode { + /** + * Normal isolation mode, parent process shares the same sandbox or internet with the child process. + */ + NCP_ISOLATION_MODE_NORMAL = 0, + + /** + * Isolated mode, parent process does not share the same sandbox or internet with the child process. + */ + NCP_ISOLATION_MODE_ISOLATED = 1, +} NativeChildProcess_IsolationMode; + +/** + * @brief The options used by the child process. + * @since 12 + */ +typedef struct NativeChildProcess_Options { + /** the isolation mode used by the child process. + * For details, see {@link NativeChildProcess_IsolationMode}. + */ + NativeChildProcess_IsolationMode isolationMode; + + /** reserved field for future extension purposes */ + int64_t reserved; +} NativeChildProcess_Options; + +/** + * @brief The arguments passed to the child process. + * @since 12 + */ +typedef struct NativeChildProcess_Args { + /** the entry parameter. */ + char* entryParams; + + /** the list of the info of the file descriptors passed to child process. + * For details, see {@link NativeChildProcess_FdList}. + */ + struct NativeChildProcess_FdList fdList; +} NativeChildProcess_Args; + +/** + * @brief Starts a child process, loads the specified dynamic library file. + * + * @permission {@code ohos.permission.START_NATIVE_CHILD_PROCESS} + * @param entry Name of the entry of the dynamic library file loaded in the child process. The value cannot be nullptr. + * @param args The arguments passed to the child process. + * For details, see {@link NativeChildProcess_Args}. + * @param options The child process options. + * For details, see {@link NativeChildProcess_Options}. + * @param pid The started child process id. + * @return Returns {@link NCP_NO_ERROR} if the call is successful.\n + * Returns {@link NCP_ERR_NO_PERMISSION} if the operation is not permitted. + * The permission {@code ohos.permission.START_NATIVE_CHILD_PROCESS} is needed.\n + * Returns {@link NCP_ERR_INVALID_PARAM} if the dynamic library name or callback function pointer is invalid.\n + * Returns {@link NCP_ERR_NOT_SUPPORTED} if the device does not support the creation of native child processes.\n + * Returns {@link NCP_ERR_ALREADY_IN_CHILD} if it is not allowed to create another child process in the child process.\n + * Returns {@link NCP_ERR_MAX_CHILD_PROCESSES_REACHED} if the maximum number of native child processes is reached.\n + * For details, see {@link Ability_NativeChildProcess_ErrCode}. + * @see OH_Ability_OnNativeChildProcessStarted + * @since 12 + */ +Ability_NativeChildProcess_ErrCode OH_Ability_StartNativeChildProcess( + const char* entry, NativeChildProcess_Args args, + NativeChildProcess_Options options, int32_t &pid); + #ifdef __cplusplus } // extern "C" #endif diff --git a/interfaces/kits/native/appkit/app/child_main_thread.h b/interfaces/kits/native/appkit/app/child_main_thread.h index 89bdaffb55..bed8c395ff 100644 --- a/interfaces/kits/native/appkit/app/child_main_thread.h +++ b/interfaces/kits/native/appkit/app/child_main_thread.h @@ -21,6 +21,7 @@ #include #include "app_mgr_interface.h" +#include "base_shared_bundle_info.h" #include "bundle_info.h" #include "bundle_mgr_interface.h" #include "child_scheduler_interface.h" @@ -32,13 +33,14 @@ namespace OHOS { namespace AppExecFwk { +using HspList = std::vector; class ChildMainThread : public ChildSchedulerStub { DECLARE_DELAYED_IPCSINGLETON(ChildMainThread); public: static void Start(const std::map &fds); void SetFds(const std::map &fds); - bool ScheduleLoadJs() override; + bool ScheduleLoadChild() override; bool ScheduleExitProcessSafely() override; bool ScheduleRunNativeProc(const sptr &mainProcessCb) override; @@ -48,14 +50,13 @@ private: bool Attach(); void HandleLoadJs(); void HandleLoadArkTs(); + void HandleLoadNative(); void InitNativeLib(const BundleInfo &bundleInfo); void HandleExitProcessSafely(); void ExitProcessSafely(); - void GetNativeLibPath(const BundleInfo &bundleInfo, AppLibPathMap &appLibPaths); - void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp); + void GetNativeLibPath(const BundleInfo &bundleInfo, const HspList &hspList, AppLibPathMap &appLibPaths); void HandleRunNativeProc(const sptr &mainProcessCb); void UpdateNativeChildLibModuleName(const AppLibPathMap &appLibPaths, bool isSystemApp); - std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp); sptr appMgr_ = nullptr; std::shared_ptr mainHandler_ = nullptr; diff --git a/interfaces/kits/native/appkit/app/native_lib_util.h b/interfaces/kits/native/appkit/app/native_lib_util.h new file mode 100644 index 0000000000..2bfd80626b --- /dev/null +++ b/interfaces/kits/native/appkit/app/native_lib_util.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 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_NATIVE_LIB_UTIL_H +#define OHOS_ABILITY_RUNTIME_NATIVE_LIB_UTIL_H + +#include + +#include "base_shared_bundle_info.h" +#include "hap_module_info.h" +#include "js_runtime.h" + +namespace OHOS { +namespace AppExecFwk { +std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp); + +void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp); + +void GetHspNativeLibPath(const BaseSharedBundleInfo &hspInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp); + +void GetPatchNativeLibPath(const HapModuleInfo &hapInfo, std::string &patchNativeLibraryPath, + AppLibPathMap &appLibPaths); +} // namespace AppExecFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_NATIVE_LIB_UTIL_H diff --git a/services/abilitymgr/etc/appfwk.para b/services/abilitymgr/etc/appfwk.para index 744752292a..8c50599c89 100644 --- a/services/abilitymgr/etc/appfwk.para +++ b/services/abilitymgr/etc/appfwk.para @@ -36,4 +36,5 @@ persist.sys.abilityms.prevent_startability = true const.abilityms.launch_embeded_ui_ability = false const.sys.abilityms.limit_maximum_extensions_of_per_process = 10 const.sys.abilityms.limit_maximum_extensions_of_per_device = 100 -const.sys.abilityms.cache_extension = 260 \ No newline at end of file +const.sys.abilityms.cache_extension = 260 +const.max_native_child_process = 0 \ No newline at end of file diff --git a/services/abilitymgr/etc/appfwk.para.dac b/services/abilitymgr/etc/appfwk.para.dac index 2d31be0f30..ae4d042c6a 100644 --- a/services/abilitymgr/etc/appfwk.para.dac +++ b/services/abilitymgr/etc/appfwk.para.dac @@ -36,4 +36,5 @@ persist.sys.abilityms.prevent_startability = foundation:foundation:0755 const.abilityms.launch_embeded_ui_ability = foundation:foundation:0755 const.sys.abilityms.limit_maximum_extensions_of_per_process = foundation:foundation:0755 const.sys.abilityms.limit_maximum_extensions_of_per_device = foundation:foundation:0755 -const.sys.abilityms.cache_extension = foundation:foundation:0755 \ No newline at end of file +const.sys.abilityms.cache_extension = foundation:foundation:0755 +const.max_native_child_process = foundation:foundation:0755 \ No newline at end of file diff --git a/services/appmgr/include/app_mgr_service_inner.h b/services/appmgr/include/app_mgr_service_inner.h index 4bb1957b80..04be7d38ea 100644 --- a/services/appmgr/include/app_mgr_service_inner.h +++ b/services/appmgr/include/app_mgr_service_inner.h @@ -1316,10 +1316,13 @@ private: void ApplicationTerminatedSendProcessEvent(const std::shared_ptr &appRecord); void ClearAppRunningDataForKeepAlive(const std::shared_ptr &appRecord); - int32_t StartChildProcessPreCheck(const pid_t callingPid); + int32_t StartChildProcessPreCheckNative(const pid_t callingPid); + + int32_t StartChildProcessPreCheck(pid_t callingPid, const ChildProcessRequest &request); int32_t StartChildProcessImpl(const std::shared_ptr childProcessRecord, - const std::shared_ptr appRecord, pid_t &childPid, const ChildProcessArgs &args); + const std::shared_ptr appRecord, pid_t &childPid, const ChildProcessArgs &args, + const ChildProcessOptions &options); int32_t GetChildProcessInfo(const std::shared_ptr childProcessRecord, const std::shared_ptr appRecord, ChildProcessInfo &info); diff --git a/services/appmgr/include/app_running_manager.h b/services/appmgr/include/app_running_manager.h index 99aba7d501..16cfcf59ff 100644 --- a/services/appmgr/include/app_running_manager.h +++ b/services/appmgr/include/app_running_manager.h @@ -302,6 +302,7 @@ public: std::shared_ptr GetAppRunningRecordByChildProcessPid(const pid_t pid); std::shared_ptr OnChildProcessRemoteDied(const wptr &remote); + bool IsNativeArgsChildProcessReachLimit(pid_t callingPid); /** * @brief Obtain number of app through bundlename. diff --git a/services/appmgr/include/app_spawn_client.h b/services/appmgr/include/app_spawn_client.h index 7e0018a11d..8d386a177c 100644 --- a/services/appmgr/include/app_spawn_client.h +++ b/services/appmgr/include/app_spawn_client.h @@ -76,6 +76,7 @@ struct AppSpawnStartMsg { int32_t maxChildProcess = 0; int32_t childProcessType = CHILD_PROCESS_TYPE_NOT_CHILD; std::map fds; + bool isolationMode = false; }; constexpr auto LEN_PID = sizeof(pid_t); @@ -227,6 +228,8 @@ private: int32_t SetChildProcessTypeStartFlag(const AppSpawnReqMsgHandle &reqHandle, int32_t childProcessType); int32_t SetExtMsgFds(const AppSpawnReqMsgHandle &reqHandle, const std::map &fds); + + int32_t SetIsolationModeFlag(const AppSpawnStartMsg &startMsg, const AppSpawnReqMsgHandle &reqHandle); }; } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/include/app_state_observer_manager.h b/services/appmgr/include/app_state_observer_manager.h index 1263902d04..983734bfb9 100644 --- a/services/appmgr/include/app_state_observer_manager.h +++ b/services/appmgr/include/app_state_observer_manager.h @@ -66,8 +66,10 @@ public: void OnProcessCreated(const std::shared_ptr &appRecord); void OnProcessStateChanged(const std::shared_ptr &appRecord); void OnRenderProcessCreated(const std::shared_ptr &RenderRecord); + void OnChildProcessCreated(std::shared_ptr childRecord); void OnProcessDied(const std::shared_ptr &appRecord); void OnRenderProcessDied(const std::shared_ptr &renderRecord); + void OnChildProcessDied(std::shared_ptr childRecord); void OnProcessReused(const std::shared_ptr &appRecord); void OnPageShow(const PageStateData pageStateData); void OnPageHide(const PageStateData pageStateData); @@ -81,8 +83,10 @@ private: const AbilityStateData abilityStateData, bool isAbility, bool isFromWindowFocusChanged); void HandleOnAppProcessCreated(const std::shared_ptr &appRecord); void HandleOnRenderProcessCreated(const std::shared_ptr &RenderRecord); + void HandleOnChildProcessCreated(std::shared_ptr childRecord); void HandleOnAppProcessDied(const std::shared_ptr &appRecord); void HandleOnRenderProcessDied(const std::shared_ptr &RenderRecord); + void HandleOnChildProcessDied(std::shared_ptr childRecord); bool ObserverExist(const sptr &observer); bool IsAppForegroundObserverExist(const sptr &observer); bool IsAbilityForegroundObserverExist(const sptr &observer); @@ -93,6 +97,7 @@ private: AbilityforegroundObserverSet GetAbilityforegroundObserverSetCopy(); ProcessData WrapProcessData(const std::shared_ptr &appRecord); ProcessData WrapRenderProcessData(const std::shared_ptr &renderRecord); + int32_t WrapChildProcessData(ProcessData &processData, std::shared_ptr childRecord); void OnObserverDied(const wptr &remote, const ObserverType &type); AppStateData WrapAppStateData(const std::shared_ptr &appRecord, const ApplicationState state); diff --git a/services/appmgr/include/child_process_record.h b/services/appmgr/include/child_process_record.h index f752641bea..cdc00f3f48 100644 --- a/services/appmgr/include/child_process_record.h +++ b/services/appmgr/include/child_process_record.h @@ -51,6 +51,7 @@ public: int32_t GetUid() const; std::string GetProcessName() const; std::string GetSrcEntry() const; + std::string GetEntryFunc() const; std::shared_ptr GetHostRecord() const; void SetScheduler(const sptr &scheduler); sptr GetScheduler() const; @@ -76,6 +77,7 @@ private: int32_t childProcessType_ = CHILD_PROCESS_TYPE_JS; std::string processName_; std::string srcEntry_; + std::string entryFunc_; std::weak_ptr hostRecord_; sptr scheduler_ = nullptr; sptr deathRecipient_ = nullptr; diff --git a/services/appmgr/include/remote_client_manager.h b/services/appmgr/include/remote_client_manager.h index 175396082a..06b95784c1 100644 --- a/services/appmgr/include/remote_client_manager.h +++ b/services/appmgr/include/remote_client_manager.h @@ -61,11 +61,14 @@ public: std::shared_ptr GetCJSpawnClient(); + std::shared_ptr GetNativeSpawnClient(); + private: std::shared_ptr appSpawnClient_; std::shared_ptr bundleManagerHelper_; std::shared_ptr nwebSpawnClient_; std::shared_ptr cjAppSpawnClient_; + std::shared_ptr nativeSpawnClient_; }; } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 1a320c79cb..51870b041c 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -6297,8 +6297,8 @@ int32_t AppMgrServiceInner::UnregisterAppRunningStatusListener(const sptrSetEntryParams(args.entryParams); - TAG_LOGI(AAFwkTag::APPMGR, "StartChildProcess, srcEntry:%{private}s, args.entryParams:%{public}s," - " args.fds size:%{public}zu, options.isolationMode:%{public}d", request.srcEntry.c_str(), - args.entryParams.c_str(), args.fds.size(), request.options.isolationMode); - return StartChildProcessImpl(childProcessRecord, appRecord, childPid, args); + TAG_LOGI(AAFwkTag::APPMGR, "StartChildProcess, srcEntry:%{private}s, args.entryParams:%{private}s," + " processName:%{public}s, args.fds size:%{public}zu, options.isolationMode:%{public}d", + request.srcEntry.c_str(), args.entryParams.c_str(), childProcessRecord->GetProcessName().c_str(), + args.fds.size(), options.isolationMode); + return StartChildProcessImpl(childProcessRecord, appRecord, childPid, args, options); } -int32_t AppMgrServiceInner::StartChildProcessPreCheck(const pid_t callingPid) +int32_t AppMgrServiceInner::StartChildProcessPreCheckNative(const pid_t callingPid) { if (!AAFwk::AppUtils::GetInstance().IsMultiProcessModel()) { TAG_LOGE(AAFwkTag::APPMGR, "Multi process model is not enabled"); return ERR_INVALID_OPERATION; } + if (!appRunningManager_) { + TAG_LOGE(AAFwkTag::APPMGR, "appRunningManager nullptr"); + return ERR_NO_INIT; + } auto appRecord = appRunningManager_->GetAppRunningRecordByChildProcessPid(callingPid); if (appRecord) { TAG_LOGE(AAFwkTag::APPMGR, "Already in child process."); @@ -6339,8 +6345,41 @@ int32_t AppMgrServiceInner::StartChildProcessPreCheck(const pid_t callingPid) return ERR_OK; } +int32_t AppMgrServiceInner::StartChildProcessPreCheck(const pid_t callingPid, const ChildProcessRequest &request) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called."); + auto childProcessType = request.childProcessType; + auto isMultiProcessModel = AAFwk::AppUtils::GetInstance().IsMultiProcessModel(); + if (!isMultiProcessModel) { + if (childProcessType == CHILD_PROCESS_TYPE_NATIVE_ARGS) { + if (!AAFwk::PermissionVerification::GetInstance()->VerifyPreloadApplicationPermission()) { + return ERR_PERMISSION_DENIED; + } + } else { + TAG_LOGE(AAFwkTag::APPMGR, "Not support child process."); + return AAFwk::ERR_NOT_SUPPORT_CHILD_PROCESS; + } + } + + if (!appRunningManager_) { + TAG_LOGE(AAFwkTag::APPMGR, "appRunningManager nullptr."); + return ERR_NO_INIT; + } + auto appRecord = appRunningManager_->GetAppRunningRecordByChildProcessPid(callingPid); + if (appRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "Already in child process."); + return AAFwk::ERR_ALREADY_IN_CHILD_PROCESS; + } + if (appRunningManager_->IsNativeArgsChildProcessReachLimit(callingPid)) { + TAG_LOGE(AAFwkTag::APPMGR, "Native child process count reach limit."); + return AAFwk::ERR_NATIVE_ARGS_CHILD_PROCESS_REACH_LIMIT; + } + return ERR_OK; +} + int32_t AppMgrServiceInner::StartChildProcessImpl(const std::shared_ptr childProcessRecord, - const std::shared_ptr appRecord, pid_t &childPid, const ChildProcessArgs &args) + const std::shared_ptr appRecord, pid_t &childPid, const ChildProcessArgs &args, + const ChildProcessOptions &options) { TAG_LOGD(AAFwkTag::APPMGR, "called"); if (!appRecord) { @@ -6351,7 +6390,9 @@ int32_t AppMgrServiceInner::StartChildProcessImpl(const std::shared_ptrGetSpawnClient(); + bool isNativeFromJs = childProcessRecord->GetChildProcessType() == CHILD_PROCESS_TYPE_NATIVE_ARGS; + auto spawnClient = isNativeFromJs ? remoteClientManager_->GetNativeSpawnClient() : + remoteClientManager_->GetSpawnClient(); if (!spawnClient) { TAG_LOGE(AAFwkTag::APPMGR, "spawnClient is null"); AppMgrEventUtil::SendChildProcessStartFailedEvent(childProcessRecord, @@ -6368,6 +6409,7 @@ int32_t AppMgrServiceInner::StartChildProcessImpl(const std::shared_ptrGetProcessName(); startMsg.childProcessType = childProcessRecord->GetChildProcessType(); startMsg.fds = args.fds; + startMsg.isolationMode = options.isolationMode; pid_t pid = 0; { std::lock_guard lock(startChildProcessLock_); @@ -6378,14 +6420,15 @@ int32_t AppMgrServiceInner::StartChildProcessImpl(const std::shared_ptr(errCode)); return ERR_APPEXECFWK_BAD_APPSPAWN_CLIENT; } - childPid = pid; childProcessRecord->SetPid(pid); childProcessRecord->SetUid(startMsg.uid); appRecord->AddChildProcessRecord(pid, childProcessRecord); } - TAG_LOGI(AAFwkTag::APPMGR, "Start child process success, pid:%{public}d, hostPid:%{public}d,uid:%{public}d", - pid, childProcessRecord->GetHostPid(), startMsg.uid); + TAG_LOGI(AAFwkTag::APPMGR, "Start child process success,pid:%{public}d,hostPid:%{public}d,uid:%{public}d," + "processName:%{public}s", pid, childProcessRecord->GetHostPid(), startMsg.uid, + childProcessRecord->GetProcessName().c_str()); + DelayedSingleton::GetInstance()->OnChildProcessCreated(childProcessRecord); return ERR_OK; } @@ -6435,6 +6478,7 @@ int32_t AppMgrServiceInner::GetChildProcessInfo(const std::shared_ptrGetBundleName(); info.processName = childProcessRecord->GetProcessName(); info.srcEntry = childProcessRecord->GetSrcEntry(); + info.entryFunc = childProcessRecord->GetEntryFunc(); info.entryParams = childProcessRecord->GetEntryParams(); info.jitEnabled = appRecord->IsJITEnabled(); info.isStartWithDebug = childProcessRecord->isStartWithDebug(); @@ -6482,7 +6526,7 @@ void AppMgrServiceInner::AttachChildProcess(const pid_t pid, const sptrRegisterDeathRecipient(); if (childRecord->GetChildProcessType() != CHILD_PROCESS_TYPE_NATIVE) { - childScheduler->ScheduleLoadJs(); + childScheduler->ScheduleLoadChild(); } else { childScheduler->ScheduleRunNativeProc(childRecord->GetMainProcessCallback()); childRecord->ClearMainProcessCallback(); @@ -6492,7 +6536,10 @@ void AppMgrServiceInner::AttachChildProcess(const pid_t pid, const sptr &remote) { if (appRunningManager_) { - appRunningManager_->OnChildProcessRemoteDied(remote); + auto childRecord = appRunningManager_->OnChildProcessRemoteDied(remote); + if (childRecord) { + DelayedSingleton::GetInstance()->OnChildProcessDied(childRecord); + } } } @@ -6515,6 +6562,7 @@ void AppMgrServiceInner::KillChildProcess(const std::shared_ptrGetUid()); KillProcessByPid(childPid, "KillChildProcess"); + DelayedSingleton::GetInstance()->OnChildProcessDied(childRecord); } } } @@ -6543,6 +6591,7 @@ void AppMgrServiceInner::ExitChildProcessSafelyByChildPid(const pid_t pid) if (WaitForRemoteProcessExit(pids, startTime)) { TAG_LOGI(AAFwkTag::APPMGR, "The remote child process exited successfully, pid:%{public}d.", pid); appRecord->RemoveChildProcessRecord(childRecord); + DelayedSingleton::GetInstance()->OnChildProcessDied(childRecord); return; } childRecord->RegisterDeathRecipient(); @@ -7138,7 +7187,7 @@ int32_t AppMgrServiceInner::StartNativeChildProcess(const pid_t hostPid, const s return ERR_INVALID_OPERATION; } - int32_t errCode = StartChildProcessPreCheck(hostPid); + int32_t errCode = StartChildProcessPreCheckNative(hostPid); if (errCode != ERR_OK) { return errCode; } @@ -7164,7 +7213,8 @@ int32_t AppMgrServiceInner::StartNativeChildProcess(const pid_t hostPid, const s auto nativeChildRecord = ChildProcessRecord::CreateNativeChildProcessRecord( hostPid, libName, appRecord, callback, childProcessCount, false); ChildProcessArgs args; - return StartChildProcessImpl(nativeChildRecord, appRecord, dummyChildPid, args); + ChildProcessOptions options; + return StartChildProcessImpl(nativeChildRecord, appRecord, dummyChildPid, args, options); } void AppMgrServiceInner::CacheLoabAbilityTask(const LoabAbilityTaskFunc& func) diff --git a/services/appmgr/src/app_running_manager.cpp b/services/appmgr/src/app_running_manager.cpp index 5edcfcd3b7..7caaa2f6b8 100644 --- a/services/appmgr/src/app_running_manager.cpp +++ b/services/appmgr/src/app_running_manager.cpp @@ -1279,6 +1279,23 @@ std::shared_ptr AppRunningManager::GetAppRunningRecordByChildP return nullptr; } +bool AppRunningManager::IsNativeArgsChildProcessReachLimit(pid_t callingPid) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called."); + auto hostRecord = GetAppRunningRecordByPid(callingPid); + if (!hostRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "hostRecord nullptr."); + return false; + } + int32_t nativeArgsChildCount = 0; + auto childRecordMap = hostRecord->GetChildProcessRecordMap(); + auto count = std::count_if(childRecordMap.begin(), childRecordMap.end(), [](auto &pair) { + auto childRecord = pair.second; + return childRecord && childRecord->GetChildProcessType() == CHILD_PROCESS_TYPE_NATIVE_ARGS; + }); + return count >= AAFwk::AppUtils::GetInstance().MaxNativeArgsChildProcess(); +} + std::shared_ptr AppRunningManager::OnChildProcessRemoteDied(const wptr &remote) { TAG_LOGE(AAFwkTag::APPMGR, "On child process remote died."); diff --git a/services/appmgr/src/app_spawn_client.cpp b/services/appmgr/src/app_spawn_client.cpp index ea3ec9d155..52e7c8b3eb 100644 --- a/services/appmgr/src/app_spawn_client.cpp +++ b/services/appmgr/src/app_spawn_client.cpp @@ -57,6 +57,8 @@ AppSpawnClient::AppSpawnClient(const char* serviceName) serviceName_ = CJAPPSPAWN_SERVER_NAME; } else if (serviceName__ == NWEBSPAWN_SERVER_NAME) { serviceName_ = NWEBSPAWN_SERVER_NAME; + } else if (serviceName__ == NATIVESPAWN_SERVER_NAME) { + serviceName_ = NATIVESPAWN_SERVER_NAME; } else { TAG_LOGE(AAFwkTag::APPMGR, "unknown service name"); serviceName_ = NWEBSPAWN_SERVER_NAME; @@ -239,6 +241,7 @@ int32_t AppSpawnClient::SetStartFlags(const AppSpawnStartMsg &startMsg, AppSpawn TAG_LOGE(AAFwkTag::APPMGR, "Set childProcessType flag failed, ret: %{public}d", ret); return ret; } + ret = SetIsolationModeFlag(startMsg, reqHandle); return ret; } @@ -563,5 +566,24 @@ int32_t AppSpawnClient::SetExtMsgFds(const AppSpawnReqMsgHandle &reqHandle, } return ERR_OK; } + +int32_t AppSpawnClient::SetIsolationModeFlag(const AppSpawnStartMsg &startMsg, const AppSpawnReqMsgHandle &reqHandle) +{ + TAG_LOGD(AAFwkTag::APPMGR, "SetIsolationFlag, isolationMode:%{public}d", startMsg.isolationMode); + if (!startMsg.isolationMode) { + return ERR_OK; + } + auto ret = AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_ISOLATED_SANDBOX_TYPE); + if (ret != 0) { + TAG_LOGE(AAFwkTag::APPMGR, "SetIsolationFlag failed, ret: %{public}d", ret); + return ret; + } + ret = AppSpawnReqMsgSetAppFlag(reqHandle, APP_FLAGS_ISOLATED_NETWORK); + if (ret != 0) { + TAG_LOGE(AAFwkTag::APPMGR, "SetIsolationFlag failed, ret: %{public}d", ret); + return ret; + } + return ERR_OK; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/services/appmgr/src/app_state_observer_manager.cpp b/services/appmgr/src/app_state_observer_manager.cpp index e5c8a68fc4..9056b7d94f 100644 --- a/services/appmgr/src/app_state_observer_manager.cpp +++ b/services/appmgr/src/app_state_observer_manager.cpp @@ -297,6 +297,25 @@ void AppStateObserverManager::OnRenderProcessDied(const std::shared_ptrSubmitTask(task); } +void AppStateObserverManager::OnChildProcessDied(std::shared_ptr childRecord) +{ + if (handler_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "handler is nullptr, OnChildProcessDied failed."); + return; + } + + auto task = [weak = weak_from_this(), childRecord]() { + auto self = weak.lock(); + if (self == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "self is nullptr, OnChildProcessDied failed."); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "OnChildProcessDied come."); + self->HandleOnChildProcessDied(childRecord); + }; + handler_->SubmitTask(task); +} + void AppStateObserverManager::OnProcessStateChanged(const std::shared_ptr &appRecord) { if (handler_ == nullptr) { @@ -372,6 +391,25 @@ void AppStateObserverManager::OnRenderProcessCreated(const std::shared_ptrSubmitTask(task); } +void AppStateObserverManager::OnChildProcessCreated(std::shared_ptr childRecord) +{ + if (handler_ == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "handler is nullptr, OnChildProcessCreated failed."); + return; + } + + auto task = [weak = weak_from_this(), childRecord]() { + auto self = weak.lock(); + if (self == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "self is nullptr, OnChildProcessCreated failed."); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, "OnChildProcessCreated come."); + self->HandleOnChildProcessCreated(childRecord); + }; + handler_->SubmitTask(task); +} + void AppStateObserverManager::StateChangedNotifyObserver( const AbilityStateData abilityStateData, bool isAbility, bool isFromWindowFocusChanged) { @@ -580,6 +618,24 @@ void AppStateObserverManager::HandleOnRenderProcessCreated(const std::shared_ptr HandleOnProcessCreated(data); } +void AppStateObserverManager::HandleOnChildProcessCreated(std::shared_ptr childRecord) +{ + if (!childRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "ChildProcessRecord record is nullptr."); + return; + } + ProcessData data; + if (WrapChildProcessData(data, childRecord) != ERR_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "WrapChildProcessData failed."); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, + "ChildProcess Create, bundleName:%{public}s, pid:%{public}d, uid:%{public}d, " + "processType:%{public}d, processName:%{public}s", + data.bundleName.c_str(), data.pid, data.uid, data.processType, data.processName.c_str()); + HandleOnProcessCreated(data); +} + void AppStateObserverManager::HandleOnProcessCreated(const ProcessData &data) { auto appStateObserverMapCopy = GetAppStateObserverMapCopy(); @@ -643,6 +699,24 @@ void AppStateObserverManager::HandleOnRenderProcessDied(const std::shared_ptr childRecord) +{ + if (!childRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "childRecord is nullptr."); + return; + } + ProcessData data; + if (WrapChildProcessData(data, childRecord) != ERR_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "WrapChildProcessData failed."); + return; + } + TAG_LOGD(AAFwkTag::APPMGR, + "ChildProcess died, bundleName:%{public}s, pid:%{public}d, uid:%{public}d, " + "processType:%{public}d, processName:%{public}s", + data.bundleName.c_str(), data.pid, data.uid, data.processType, data.processName.c_str()); + HandleOnProcessDied(data); +} + void AppStateObserverManager::HandleOnProcessDied(const ProcessData &data) { auto appStateObserverMapCopy = GetAppStateObserverMapCopy(); @@ -696,6 +770,28 @@ ProcessData AppStateObserverManager::WrapRenderProcessData(const std::shared_ptr return processData; } +int32_t AppStateObserverManager::WrapChildProcessData(ProcessData &processData, + std::shared_ptr childRecord) +{ + if (!childRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "childRecord is nullptr."); + return ERR_INVALID_VALUE; + } + auto hostRecord = childRecord->GetHostRecord(); + if (!hostRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "hostRecord is nullptr."); + return ERR_INVALID_VALUE; + } + processData.bundleName = hostRecord->GetBundleName(); + processData.uid = hostRecord->GetUid(); + processData.hostPid = childRecord->GetHostPid(); + processData.pid = childRecord->GetPid(); + processData.childUid = childRecord->GetUid(); + processData.processName = childRecord->GetProcessName(); + processData.processType = childRecord->GetProcessType(); + return ERR_OK; +} + bool AppStateObserverManager::ObserverExist(const sptr &observer) { if (observer == nullptr) { diff --git a/services/appmgr/src/child_process_record.cpp b/services/appmgr/src/child_process_record.cpp index e919787161..4e4ca909bb 100644 --- a/services/appmgr/src/child_process_record.cpp +++ b/services/appmgr/src/child_process_record.cpp @@ -24,8 +24,16 @@ namespace AppExecFwk { ChildProcessRecord::ChildProcessRecord(pid_t hostPid, const ChildProcessRequest &request, const std::shared_ptr hostRecord) : hostPid_(hostPid), childProcessCount_(request.childProcessCount), childProcessType_(request.childProcessType), - srcEntry_(request.srcEntry), hostRecord_(hostRecord), isStartWithDebug_(request.isStartWithDebug) + hostRecord_(hostRecord), isStartWithDebug_(request.isStartWithDebug) { + srcEntry_ = request.srcEntry; + if (childProcessType_ == CHILD_PROCESS_TYPE_NATIVE_ARGS) { + auto pos = request.srcEntry.rfind(":"); + if (pos != std::string::npos) { + srcEntry_ = request.srcEntry.substr(0, pos); + entryFunc_ = request.srcEntry.substr(pos + 1); + } + } MakeProcessName(hostRecord); } @@ -107,6 +115,11 @@ ProcessType ChildProcessRecord::GetProcessType() const return processType_; } +std::string ChildProcessRecord::GetEntryFunc() const +{ + return entryFunc_; +} + std::shared_ptr ChildProcessRecord::GetHostRecord() const { return hostRecord_.lock(); @@ -174,7 +187,7 @@ void ChildProcessRecord::MakeProcessName(const std::shared_ptr std::string filename = std::filesystem::path(srcEntry_).stem(); if (!filename.empty()) { processName_.append(":"); - if (childProcessType_ == CHILD_PROCESS_TYPE_NATIVE) { + if (childProcessType_ == CHILD_PROCESS_TYPE_NATIVE || childProcessType_ == CHILD_PROCESS_TYPE_NATIVE_ARGS) { processName_.append("Native_"); } diff --git a/services/appmgr/src/remote_client_manager.cpp b/services/appmgr/src/remote_client_manager.cpp index edb5cafe12..5e45e64d90 100644 --- a/services/appmgr/src/remote_client_manager.cpp +++ b/services/appmgr/src/remote_client_manager.cpp @@ -24,7 +24,8 @@ namespace OHOS { namespace AppExecFwk { RemoteClientManager::RemoteClientManager() : appSpawnClient_(std::make_shared()), nwebSpawnClient_(std::make_shared(true)), - cjAppSpawnClient_(std::make_shared("cjappspawn")) + cjAppSpawnClient_(std::make_shared("cjappspawn")), + nativeSpawnClient_(std::make_shared("nativespawn")) {} RemoteClientManager::~RemoteClientManager() @@ -68,5 +69,10 @@ std::shared_ptr RemoteClientManager::GetCJSpawnClient() } return nullptr; } + +std::shared_ptr RemoteClientManager::GetNativeSpawnClient() +{ + return nativeSpawnClient_; +} } // namespace AppExecFwk } // namespace OHOS diff --git a/services/common/include/app_utils.h b/services/common/include/app_utils.h index 9e32ac88e7..ab93430f06 100644 --- a/services/common/include/app_utils.h +++ b/services/common/include/app_utils.h @@ -25,6 +25,7 @@ namespace AAFwk { constexpr const int32_t DEFAULT_MAX_EXT_PER_PROC = 10; constexpr const int32_t DEFAULT_MAX_EXT_PER_DEV = 100; constexpr const int32_t DEFAULT_INVALID_VALUE = -1; +constexpr const int32_t DEFAULT_MAX_NATIVE_ARGS_CHILD_PROCESS = 0; template class DeviceConfiguration { public: @@ -60,6 +61,7 @@ public: std::string GetBrokerDelegateBundleName(); int32_t GetCollaboratorBrokerUID(); int32_t GetCollaboratorBrokerReserveUID(); + int32_t MaxNativeArgsChildProcess(); private: void LoadResidentProcessInExtremeMemory(); @@ -89,6 +91,7 @@ private: DeviceConfiguration brokerDelegateBundleName_ = {false, ""}; volatile DeviceConfiguration collaboratorBrokerUid_ = {false, DEFAULT_INVALID_VALUE}; volatile DeviceConfiguration collaboratorBrokerReserveUid_ = {false, DEFAULT_INVALID_VALUE}; + volatile DeviceConfiguration maxNativeArgsChildProcess_ = {false, DEFAULT_MAX_NATIVE_ARGS_CHILD_PROCESS}; DISALLOW_COPY_AND_MOVE(AppUtils); }; } // namespace AAFwk diff --git a/services/common/include/permission_constants.h b/services/common/include/permission_constants.h index 17535d45a7..95963f75fe 100644 --- a/services/common/include/permission_constants.h +++ b/services/common/include/permission_constants.h @@ -62,6 +62,7 @@ constexpr const char* PERMISSION_PRELOAD_UI_EXTENSION_ABILITY = "ohos.permission constexpr const char* PERMISSION_PRE_START_ATOMIC_SERVICE = "ohos.permission.PRE_START_ATOMIC_SERVICE"; constexpr const char* PERMISSION_KILL_APP_PROCESSES = "ohos.permission.KILL_APP_PROCESSES"; constexpr const char* PERMISSION_KILL_PROCESS_DEPENDED_ON_WEB = "ohos.permission.KILL_PROCESS_DEPENDED_ON_ARKWEB"; +constexpr const char* PERMISSION_START_NATIVE_CHILD_PROCESS = "ohos.permission.START_NATIVE_CHILD_PROCESS"; } // namespace PermissionConstants } // namespace AAFwk } // namespace OHOS diff --git a/services/common/include/permission_verification.h b/services/common/include/permission_verification.h index 02f09653e4..d3f7399afb 100644 --- a/services/common/include/permission_verification.h +++ b/services/common/include/permission_verification.h @@ -103,6 +103,8 @@ struct VerificationInfo { bool VerifyKillProcessDependedOnWebPermission() const; + bool VerifyStartNativeChildProcessPermission() const; + private: DISALLOW_COPY_AND_MOVE(PermissionVerification); diff --git a/services/common/src/app_utils.cpp b/services/common/src/app_utils.cpp index 1f466f040f..c36260df20 100644 --- a/services/common/src/app_utils.cpp +++ b/services/common/src/app_utils.cpp @@ -61,6 +61,7 @@ constexpr const char* START_ABILITY_WITHOUT_CALLERTOKEN_TITLE = "startAbilityWit constexpr const char* BROKER_DELEGATE_BUNDLE_NAME = "const.sys.abilityms.broker_delegate_bundle_name"; constexpr const char* COLLABORATOR_BROKER_UID = "const.sys.abilityms.collaborator_broker_uid"; constexpr const char* COLLABORATOR_BROKER_RESERVE_UID = "const.sys.abilityms.collaborator_broker_reserve_uid"; +constexpr const char* MAX_NATIVE_ARGS_CHILD_PROCESS = "const.max_native_child_process"; } AppUtils::~AppUtils() {} @@ -387,5 +388,16 @@ int32_t AppUtils::GetCollaboratorBrokerReserveUID() TAG_LOGD(AAFwkTag::DEFAULT, "collaboratorBrokerReserveUid_ is %{public}d", collaboratorBrokerReserveUid_.value); return collaboratorBrokerReserveUid_.value; } + +int32_t AppUtils::MaxNativeArgsChildProcess() +{ + if (!maxNativeArgsChildProcess_.isLoaded) { + maxNativeArgsChildProcess_.value = + system::GetIntParameter(MAX_NATIVE_ARGS_CHILD_PROCESS, DEFAULT_MAX_NATIVE_ARGS_CHILD_PROCESS); + maxNativeArgsChildProcess_.isLoaded = true; + } + TAG_LOGD(AAFwkTag::DEFAULT, "maxNativeArgsChildProcess: %{public}d", maxNativeArgsChildProcess_.value); + return maxNativeArgsChildProcess_.value; +} } // namespace AAFwk } // namespace OHOS diff --git a/services/common/src/permission_verification.cpp b/services/common/src/permission_verification.cpp index b8d7ea8257..403f5ed918 100644 --- a/services/common/src/permission_verification.cpp +++ b/services/common/src/permission_verification.cpp @@ -496,5 +496,17 @@ bool PermissionVerification::VerifyKillProcessDependedOnWebPermission() const TAG_LOGW(AAFwkTag::APPMGR, "Permission denied"); return false; } + +bool PermissionVerification::VerifyStartNativeChildProcessPermission() const +{ + if (VerifyCallingPermission(PermissionConstants::PERMISSION_START_NATIVE_CHILD_PROCESS)) { + TAG_LOGD(AAFwkTag::DEFAULT, "Permission %{public}s granted", + PermissionConstants::PERMISSION_START_NATIVE_CHILD_PROCESS); + return true; + } + TAG_LOGE(AAFwkTag::DEFAULT, "Permission %{public}s denied", + PermissionConstants::PERMISSION_START_NATIVE_CHILD_PROCESS); + return false; +} } // namespace AAFwk } // namespace OHOS diff --git a/test/fuzztest/abilityinterfacesappmgrchildschedulerproxy_fuzzer/abilityinterfacesappmgrchildschedulerproxy_fuzzer.cpp b/test/fuzztest/abilityinterfacesappmgrchildschedulerproxy_fuzzer/abilityinterfacesappmgrchildschedulerproxy_fuzzer.cpp index 4e155c7e5c..bcf5577014 100644 --- a/test/fuzztest/abilityinterfacesappmgrchildschedulerproxy_fuzzer/abilityinterfacesappmgrchildschedulerproxy_fuzzer.cpp +++ b/test/fuzztest/abilityinterfacesappmgrchildschedulerproxy_fuzzer/abilityinterfacesappmgrchildschedulerproxy_fuzzer.cpp @@ -69,7 +69,7 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size) { sptr impl; std::shared_ptr infosProxy = std::make_shared(impl); - infosProxy->ScheduleLoadJs(); + infosProxy->ScheduleLoadChild(); infosProxy->ScheduleExitProcessSafely(); sptr mainProcessCb; infosProxy->ScheduleRunNativeProc(mainProcessCb); diff --git a/test/fuzztest/abilityinterfacesappmgrchildschedulerstub_fuzzer/abilityinterfacesappmgrchildschedulerstub_fuzzer.cpp b/test/fuzztest/abilityinterfacesappmgrchildschedulerstub_fuzzer/abilityinterfacesappmgrchildschedulerstub_fuzzer.cpp index 4c213c7ffd..78cf21b090 100644 --- a/test/fuzztest/abilityinterfacesappmgrchildschedulerstub_fuzzer/abilityinterfacesappmgrchildschedulerstub_fuzzer.cpp +++ b/test/fuzztest/abilityinterfacesappmgrchildschedulerstub_fuzzer/abilityinterfacesappmgrchildschedulerstub_fuzzer.cpp @@ -57,7 +57,7 @@ public: virtual ~ ChildSchedulerStubFUZZ() {}; int OnRemoteRequest( uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override{ return 0; }; - bool ScheduleLoadJs() override{ return true; }; + bool ScheduleLoadChild() override{ return true; }; bool ScheduleExitProcessSafely() override{ return true; }; bool ScheduleRunNativeProc(const sptr &mainProcessCb) override{ return true; }; }; diff --git a/test/unittest/appkit/child_main_thread_test/child_main_thread_test.cpp b/test/unittest/appkit/child_main_thread_test/child_main_thread_test.cpp index f37749eb88..80abb091cd 100644 --- a/test/unittest/appkit/child_main_thread_test/child_main_thread_test.cpp +++ b/test/unittest/appkit/child_main_thread_test/child_main_thread_test.cpp @@ -99,13 +99,13 @@ HWTEST_F(ChildMainThreadTest, Attach_0100, TestSize.Level0) } /** - * @tc.number: ScheduleLoadJs_0100 - * @tc.desc: Test ScheduleLoadJs_0100 works + * @tc.number: ScheduleLoadChild_0100 + * @tc.desc: Test ScheduleLoadChild_0100 works * @tc.type: FUNC */ -HWTEST_F(ChildMainThreadTest, ScheduleLoadJs_0100, TestSize.Level0) +HWTEST_F(ChildMainThreadTest, ScheduleLoadChild_0100, TestSize.Level0) { - TAG_LOGD(AAFwkTag::TEST, "ScheduleLoadJs_0100 called."); + TAG_LOGD(AAFwkTag::TEST, "ScheduleLoadChild_0100 called."); sptr thread = sptr(new (std::nothrow) ChildMainThread()); ASSERT_NE(thread, nullptr); @@ -114,7 +114,7 @@ HWTEST_F(ChildMainThreadTest, ScheduleLoadJs_0100, TestSize.Level0) thread->mainHandler_ = handler; thread->processInfo_ = std::make_shared(); - auto ret = thread->ScheduleLoadJs(); + auto ret = thread->ScheduleLoadChild(); EXPECT_TRUE(ret); }