新增API支持创建native子进程

Signed-off-by: grs <guoruishuai@huawei.com>
This commit is contained in:
grs
2024-05-13 13:50:53 +08:00
parent ed82781ba8
commit 8178dbcabc
54 changed files with 1592 additions and 4 deletions
+1
View File
@@ -18,6 +18,7 @@ ability_runtime_napi_path = "${ability_runtime_path}/frameworks/js/napi"
ability_base_path = "//foundation/ability/ability_base"
form_fwk_path = "//foundation/ability/form_fwk"
ability_runtime_innerkits_path = "${ability_runtime_path}/interfaces/inner_api"
ability_runtime_ndk_path = "${ability_runtime_path}/interfaces/kits/c"
ability_runtime_native_path = "${ability_runtime_path}/frameworks/native"
ability_runtime_services_path = "${ability_runtime_path}/services"
ability_runtime_abilitymgr_path = "${ability_runtime_services_path}/abilitymgr"
+10
View File
@@ -104,6 +104,7 @@
"//foundation/ability/ability_runtime/interfaces/inner_api:innerkits_target",
"//foundation/ability/ability_runtime/frameworks/native/ability/native:ability_thread",
"//foundation/ability/ability_runtime/frameworks/native/ability/native:extension_module",
"//foundation/ability/ability_runtime/frameworks/native/child_process:child_process",
"//foundation/ability/ability_runtime/frameworks/native/insight_intent:insight_intent_innerkits",
"//foundation/ability/ability_runtime/frameworks/js/napi:napi_packages",
"//foundation/ability/ability_runtime/cj_environment/frameworks/cj_environment:cj_environment",
@@ -312,6 +313,15 @@
},
"name": "//foundation/ability/ability_runtime/frameworks/native/appkit:app_context"
},
{
"header": {
"header_base": "//foundation/ability/ability_runtime/interfaces/kits/c/ability/ability_runtime/child_process",
"header_files": [
"native_child_process.h"
]
},
"name": "//foundation/ability/ability_runtime/frameworks/native/child_process:child_process"
},
{
"header": {
"header_base": "//foundation/ability/ability_runtime/interfaces/inner_api/uri_permission/include/",
@@ -29,6 +29,7 @@
#include "bundle_info.h"
#include "bundle_mgr_interface.h"
#include "child_process.h"
#include "native_child_ipc_process.h"
#include "child_process_manager_error_utils.h"
#include "child_process_start_info.h"
#include "constants.h"
@@ -115,6 +116,37 @@ ChildProcessManagerErrorCode ChildProcessManager::StartChildProcessByAppSpawnFor
return ChildProcessManagerErrorCode::ERR_OK;
}
ChildProcessManagerErrorCode ChildProcessManager::StartNativeChildProcessByAppSpawnFork(
const std::string &libName, const sptr<IRemoteObject> &callbackStub)
{
TAG_LOGI(AAFwkTag::PROCESSMGR, "called, libName:%{private}s", libName.c_str());
ChildProcessManagerErrorCode errorCode = PreCheckNativeProcess();
if (errorCode != ChildProcessManagerErrorCode::ERR_OK) {
return errorCode;
}
sptr<AppExecFwk::IAppMgr> appMgr = GetAppMgr();
if (appMgr == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "GetAppMgr for native child process failed.");
return ChildProcessManagerErrorCode::ERR_GET_APP_MGR_FAILED;
}
auto ret = appMgr->StartNativeChildProcess(libName, childProcessCount_, callbackStub);
TAG_LOGD(AAFwkTag::PROCESSMGR, "AppMgr StartNativeChildProcess ret:%{public}d", ret);
if (ret != ERR_OK) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "AppMgr StartNativeChildProcess failed, ret:%{public}d", ret);
if (ret == ERR_OVERFLOW) {
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;
}
++childProcessCount_;
return ChildProcessManagerErrorCode::ERR_OK;
}
void ChildProcessManager::RegisterSignal()
{
if (!signalRegistered_) {
@@ -144,6 +176,21 @@ ChildProcessManagerErrorCode ChildProcessManager::PreCheck()
return ChildProcessManagerErrorCode::ERR_OK;
}
ChildProcessManagerErrorCode ChildProcessManager::PreCheckNativeProcess()
{
ChildProcessManagerErrorCode errCode = PreCheck();
if (errCode != ChildProcessManagerErrorCode::ERR_OK) {
return errCode;
}
if (!AAFwk::AppUtils::GetInstance().IsSupportNativeChildProcess()) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Unsupport native child process");
return ChildProcessManagerErrorCode::ERR_UNSUPPORT_NATIVE_CHILD_PROCESS;
}
return ChildProcessManagerErrorCode::ERR_OK;
}
bool ChildProcessManager::IsChildProcess()
{
return isChildProcessBySelfFork_ || hasChildProcessRecord();
@@ -207,6 +254,28 @@ bool ChildProcessManager::LoadJsFile(const std::string &srcEntry, const AppExecF
return true;
}
bool ChildProcessManager::LoadNativeLib(const std::string &libPath, const sptr<IRemoteObject> &mainProcessCb)
{
auto childProcess = NativeChildIpcProcess::Create();
if (childProcess == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Failed create NativeChildIpcProcess");
return false;
}
std::shared_ptr<ChildProcessStartInfo> processStartInfo = std::make_shared<ChildProcessStartInfo>();
processStartInfo->name = std::filesystem::path(libPath).stem();
processStartInfo->srcEntry = libPath;
processStartInfo->ipcObj = mainProcessCb;
if (!childProcess->Init(processStartInfo)) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "NativeChildIpcProcess init failed.");
return false;
}
childProcess->OnStart();
TAG_LOGD(AAFwkTag::PROCESSMGR, "LoadNativeLib end.");
return true;
}
std::unique_ptr<AbilityRuntime::Runtime> ChildProcessManager::CreateRuntime(const AppExecFwk::BundleInfo &bundleInfo,
const AppExecFwk::HapModuleInfo &hapModuleInfo, const bool fromAppSpawn, const bool jitEnabled)
{
@@ -0,0 +1,146 @@
/*
* 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_child_ipc_process.h"
#include <dlfcn.h>
#include <thread>
#include <chrono>
#include "hilog_tag_wrapper.h"
#include "hilog_wrapper.h"
#include "child_process_manager_error_utils.h"
namespace OHOS {
namespace AbilityRuntime {
std::shared_ptr<ChildProcess> NativeChildIpcProcess::Create()
{
return std::make_shared<NativeChildIpcProcess>();
}
NativeChildIpcProcess::~NativeChildIpcProcess()
{
UnloadNativeLib();
}
bool NativeChildIpcProcess::Init(const std::shared_ptr<ChildProcessStartInfo> &info)
{
TAG_LOGD(AAFwkTag::PROCESSMGR, "NativeChildIpcProcess init");
if (info == nullptr || info->ipcObj == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "info or ipc callback is null");
return false;
}
if (!ChildProcess::Init(info)) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Base class init failed.");
return false;
}
auto iNotify = iface_cast<OHOS::AppExecFwk::INativeChildNotify>(info->ipcObj);
if (iNotify == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Faild cvt interface to INativeChildNotify");
return false;
}
if (!LoadNativeLib(info)) {
iNotify->OnError(static_cast<int32_t>(ChildProcessManagerErrorCode::ERR_NATIVE_CHILD_PROCESS_LOAD_LIB));
return false;
}
mainProcessCb_ = iNotify;
return true;
}
void NativeChildIpcProcess::OnStart()
{
if (funcNativeLibOnConnect_ == nullptr || funcNativeLibMainProc_ == nullptr || mainProcessCb_ == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "No init");
return;
}
ChildProcess::OnStart();
OHIPCRemoteStub *ipcStub = funcNativeLibOnConnect_();
if (ipcStub == nullptr || ipcStub->remote == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Native lib OnConnect function return null stub");
mainProcessCb_->OnError(static_cast<int32_t>(ChildProcessManagerErrorCode::ERR_NATIVE_CHILD_PROCESS_CONNECT));
return;
}
std::thread cbThread([this, childIpcStub = std::move(ipcStub->remote)] () -> void {
// Wait MainProc run first
std::this_thread::sleep_for(std::chrono::milliseconds(1));
TAG_LOGI(AAFwkTag::PROCESSMGR, "Notify native child process started");
mainProcessCb_->OnNativeChildStarted(childIpcStub);
});
TAG_LOGI(AAFwkTag::PROCESSMGR, "Enter native lib MainProc");
funcNativeLibMainProc_();
TAG_LOGI(AAFwkTag::PROCESSMGR, "Native lib MainProc returned");
if (cbThread.joinable()) {
cbThread.join();
}
}
bool NativeChildIpcProcess::LoadNativeLib(const std::shared_ptr<ChildProcessStartInfo> &info)
{
if (nativeLibHandle_ != nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Native lib already loaded");
return false;
}
void *libHandle = dlopen(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;
}
do {
NativeChildProcess_OnConnect funcOnConnect =
reinterpret_cast<NativeChildProcess_OnConnect>(dlsym(libHandle, "NativeChildProcess_OnConnect"));
if (funcOnConnect == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Get OnConnect function address failed, err %{public}s", dlerror());
break;
}
NativeChildProcess_MainProc funcMainProc =
reinterpret_cast<NativeChildProcess_MainProc>(dlsym(libHandle, "NativeChildProcess_MainProc"));
if (funcMainProc == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Get MainProc function address failed, err %{public}s", dlerror());
break;
}
funcNativeLibOnConnect_ = funcOnConnect;
funcNativeLibMainProc_ = funcMainProc;
nativeLibHandle_ = libHandle;
return true;
} while (false);
dlclose(libHandle);
return false;
}
void NativeChildIpcProcess::UnloadNativeLib()
{
if (nativeLibHandle_ != nullptr) {
dlclose(nativeLibHandle_);
nativeLibHandle_ = nullptr;
funcNativeLibOnConnect_ = nullptr;
funcNativeLibMainProc_ = nullptr;
}
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -14,7 +14,7 @@
*/
#include "child_main_thread.h"
#include <unistd.h>
#include "bundle_mgr_proxy.h"
#include "child_process_manager.h"
#include "constants.h"
@@ -172,7 +172,12 @@ void ChildMainThread::InitNativeLib(const BundleInfo &bundleInfo)
GetNativeLibPath(bundleInfo, appLibPaths);
bool isSystemApp = bundleInfo.applicationInfo.isSystemApp;
TAG_LOGD(AAFwkTag::APPKIT, "the application isSystemApp: %{public}d", isSystemApp);
AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp);
if (processInfo_->processType != CHILD_PROCESS_TYPE_NATIVE) {
AbilityRuntime::JsRuntime::SetAppLibPath(appLibPaths, isSystemApp);
} else {
UpdateNativeChildLibPath(appLibPaths);
}
}
void ChildMainThread::ExitProcessSafely()
@@ -222,6 +227,67 @@ void ChildMainThread::HandleExitProcessSafely()
}
}
bool ChildMainThread::ScheduleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb)
{
TAG_LOGD(AAFwkTag::APPKIT, "ScheduleRunNativeProc");
if (mainProcessCb == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "Main process callback is null");
return false;
}
if (mainHandler_ == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "mainHandler_ is null");
return false;
}
auto task = [weak = wptr<ChildMainThread>(this), callback = sptr<IRemoteObject>(mainProcessCb)]() {
auto childMainThread = weak.promote();
if (childMainThread == nullptr) {
TAG_LOGE(AAFwkTag::APPKIT, "childMainThread is nullptr, ScheduleRunNativeProc failed.");
return;
}
childMainThread->HandleRunNativeProc(callback);
};
if (!mainHandler_->PostTask(task, "ChildMainThread::HandleRunNativeProc")) {
TAG_LOGE(AAFwkTag::APPKIT, "HandleRunNativeProc PostTask task failed.");
return false;
}
return true;
}
void ChildMainThread::HandleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb)
{
TAG_LOGD(AAFwkTag::APPKIT, "HandleRunNativeProc called start.");
if (!processInfo_) {
TAG_LOGE(AAFwkTag::APPKIT, "processInfo is null.");
return;
}
ChildProcessManager &childProcessMgr = ChildProcessManager::GetInstance();
childProcessMgr.LoadNativeLib(processInfo_->srcEntry, mainProcessCb);
TAG_LOGD(AAFwkTag::APPKIT, "HandleRunNativeProc end.");
ExitProcessSafely();
}
void ChildMainThread::UpdateNativeChildLibPath(const AppLibPathMap &appLibPaths)
{
std::string nativeLibPath;
for (const auto &libPathPair : appLibPaths) {
for (const auto &libDir : libPathPair.second) {
nativeLibPath = libDir;
if (!nativeLibPath.empty() && nativeLibPath.back() != '/') {
nativeLibPath += '/';
}
nativeLibPath += processInfo_->srcEntry;
if (access(nativeLibPath.c_str(), F_OK) == 0) {
processInfo_->srcEntry = nativeLibPath;
break;
}
}
}
}
void ChildMainThread::GetNativeLibPath(const BundleInfo &bundleInfo, AppLibPathMap &appLibPaths)
{
std::string nativeLibraryPath = bundleInfo.applicationInfo.nativeLibraryPath;
+66
View File
@@ -0,0 +1,66 @@
# 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.
import("//build/ohos.gni")
import("//foundation/ability/ability_runtime/ability_runtime.gni")
config("child_process_ndk_config") {
include_dirs =
[ "${ability_runtime_ndk_path}/ability/ability_runtime/child_process" ]
if (target_cpu == "arm") {
cflags = [ "-DBINDER_IPC_32BIT" ]
}
}
ohos_shared_library("child_process") {
sanitize = {
integer_overflow = true
ubsan = true
boundary_sanitize = true
cfi = true
cfi_cross_dso = true
cfi_vcall_icall_only = true
debug = false
}
branch_protector_ret = "pac_ret"
include_dirs = [ "include" ]
configs = [ "${ability_runtime_services_path}/common:common_config" ]
public_configs = [ ":child_process_ndk_config" ]
sources = [
"${ability_runtime_native_path}/child_process/src/native_child_callback.cpp",
"${ability_runtime_native_path}/child_process/src/native_child_process.cpp",
]
deps = [
"${ability_runtime_innerkits_path}/app_manager:app_manager",
"${ability_runtime_innerkits_path}/child_process_manager:child_process_manager",
"${ability_runtime_native_path}/ability/native:ability_business_error",
]
external_deps = [
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_capi",
"ipc:ipc_core",
]
output_extension = "so"
innerapi_tags = [ "ndk" ]
install_images = [ "system" ]
subsystem_name = "ability"
part_name = "ability_runtime"
}
@@ -0,0 +1,40 @@
/*
* 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_CHILD_CALLBACK_H
#define OHOS_ABILITY_RUNTIME_NATIVE_CHILD_CALLBACK_H
#include "native_child_notify_stub.h"
#include "native_child_process.h"
namespace OHOS {
namespace AbilityRuntime {
class NativeChildCallback : public OHOS::AppExecFwk::NativeChildNotifyStub {
public:
explicit NativeChildCallback(OH_Ability_OnNativeChildProcessStarted cb);
~NativeChildCallback() = default;
void OnNativeChildStarted(const sptr<IRemoteObject> &nativeChild) override;
void OnError(int32_t errCode) override;
private:
OH_Ability_OnNativeChildProcessStarted callback_ = nullptr;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_NATIVE_CHILD_CALLBACK_H
@@ -0,0 +1,66 @@
/*
* 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_child_callback.h"
#include "hilog_tag_wrapper.h"
#include "hilog_wrapper.h"
#include "ipc_inner_object.h"
#include "child_process_manager_error_utils.h"
namespace OHOS {
namespace AbilityRuntime {
NativeChildCallback::NativeChildCallback(OH_Ability_OnNativeChildProcessStarted cb)
: NativeChildNotifyStub(), callback_(cb)
{
}
void NativeChildCallback::OnNativeChildStarted(const sptr<IRemoteObject> &nativeChild)
{
if (callback_ == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Native child process started, but callback is null?");
return;
}
if (!nativeChild) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Native child process ipc object is null");
return;
}
TAG_LOGI(AAFwkTag::PROCESSMGR, "Native child process started");
sptr<IRemoteObject> ipcRemote = nativeChild;
OHIPCRemoteProxy *ipcProxy = CreateIPCRemoteProxy(ipcRemote);
if (ipcProxy == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Convert inner ipc object to OHIPCRemoteProxy point failed");
callback_(NCP_ERR_INTERNAL, nullptr);
return;
}
callback_(static_cast<int32_t>(ChildProcessManagerErrorCode::ERR_OK), ipcProxy);
}
void NativeChildCallback::OnError(int32_t errCode)
{
if (callback_ == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Native child process start failed, but callback is null?");
return;
}
TAG_LOGI(AAFwkTag::PROCESSMGR, "Native child process start failed, err %{public}d", errCode);
callback_(errCode, nullptr);
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,104 @@
/*
* 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_child_process.h"
#include <map>
#include <mutex>
#include "hilog_tag_wrapper.h"
#include "hilog_wrapper.h"
#include "native_child_callback.h"
#include "child_process_manager.h"
using namespace OHOS;
using namespace OHOS::AbilityRuntime;
namespace {
std::mutex g_MutexCallBackObj;
sptr<IRemoteObject> g_CallbackStub;
OH_Ability_OnNativeChildProcessStarted g_Callback = nullptr;
const std::map<ChildProcessManagerErrorCode, Ability_NativeChildProcess_ErrCode> CPM_ERRCODE_MAP = {
{ ChildProcessManagerErrorCode::ERR_OK, NCP_NOERROR },
{ 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 },
{ ChildProcessManagerErrorCode::ERR_GET_APP_MGR_START_PROCESS_FAILED, NCP_ERR_SERVICE },
{ ChildProcessManagerErrorCode::ERR_UNSUPPORT_NATIVE_CHILD_PROCESS, NCP_ERR_NOT_SUPPORTED },
{ ChildProcessManagerErrorCode::ERR_MAX_NATIVE_CHILD_PROCESSES, NCP_ERR_MAX_CHILD_PROCESSES_REACHED },
{ ChildProcessManagerErrorCode::ERR_NATIVE_CHILD_PROCESS_LOAD_LIB, NCP_ERR_CHILD_PROCESS_LOAD_LIB },
{ ChildProcessManagerErrorCode::ERR_NATIVE_CHILD_PROCESS_CONNECT, NCP_ERR_CHILD_PROCESS_CONNECT },
};
int CvtChildProcessManagerErrCode(ChildProcessManagerErrorCode cpmErr)
{
auto it = CPM_ERRCODE_MAP.find(cpmErr);
if (it == CPM_ERRCODE_MAP.end()) {
return NCP_ERR_INTERNAL;
}
return it->second;
}
void OnNativeChildProcessStartedWapper(int errCode, OHIPCRemoteProxy *ipcProxy)
{
std::unique_lock autoLock(g_MutexCallBackObj);
if (g_Callback != nullptr) {
g_Callback(CvtChildProcessManagerErrCode(static_cast<ChildProcessManagerErrorCode>(errCode)), ipcProxy);
g_Callback = nullptr;
} else {
TAG_LOGW(AAFwkTag::PROCESSMGR, "Remote call twice?");
}
g_CallbackStub.clear();
}
} // Anonymous namespace
int OH_Ability_CreateNativeChildProcess(const char* libName, OH_Ability_OnNativeChildProcessStarted onProcessStarted)
{
if (libName == nullptr || *libName == '\0' || onProcessStarted == nullptr) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Invalid libname or callback");
return NCP_ERR_INVALID_PARAM;
}
std::string strLibName(libName);
if (strLibName.find("../") != std::string::npos) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Do not allow use relative path");
return NCP_ERR_INVALID_PARAM;
}
std::unique_lock autoLock(g_MutexCallBackObj);
if (g_Callback != nullptr || g_CallbackStub != nullptr) {
TAG_LOGW(AAFwkTag::PROCESSMGR, "Another native process process starting, try again later");
return NCP_ERR_BUSY;
}
sptr<IRemoteObject> callbackStub(new (std::nothrow) NativeChildCallback(OnNativeChildProcessStartedWapper));
if (!callbackStub) {
TAG_LOGE(AAFwkTag::PROCESSMGR, "Alloc callback ipc stub object faild.");
return NCP_ERR_INTERNAL;
}
ChildProcessManager &mgr = ChildProcessManager::GetInstance();
auto cpmErr = mgr.StartNativeChildProcessByAppSpawnFork(strLibName, callbackStub);
if (cpmErr != ChildProcessManagerErrorCode::ERR_OK) {
return CvtChildProcessManagerErrCode(cpmErr);
}
g_Callback = onProcessStarted;
g_CallbackStub = callbackStub;
return NCP_NOERROR;
}
@@ -88,6 +88,8 @@ ohos_shared_library("app_manager") {
"src/appmgr/configuration_observer_stub.cpp",
"src/appmgr/fault_data.cpp",
"src/appmgr/memory_level_info.cpp",
"src/appmgr/native_child_notify_proxy.cpp",
"src/appmgr/native_child_notify_stub.cpp",
"src/appmgr/page_state_data.cpp",
"src/appmgr/priority_object.cpp",
"src/appmgr/process_data.cpp",
@@ -652,6 +652,16 @@ public:
}
virtual int32_t SetSupportedProcessCacheSelf(bool isSupport) = 0;
/**
* Start native child process, callde by ChildProcessManager.
* @param libName lib file name to be load in child process
* @param childProcessCount current started child process count
* @param callback callback for notify start result
* @return Returns ERR_OK on success, others on failure.
*/
virtual int32_t StartNativeChildProcess(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback) = 0;
};
} // namespace AppExecFwk
} // namespace OHOS
@@ -99,6 +99,7 @@ enum class AppMgrInterfaceCode {
PRELOAD_APPLICATION = 73,
SET_SUPPORTED_PROCESS_CACHE_SELF = 74,
APP_GET_RUNNING_PROCESSES_BY_BUNDLE_TYPE = 75,
START_NATIVE_CHILD_PROCESS = 76,
};
} // AppExecFwk
} // OHOS
@@ -568,6 +568,17 @@ public:
virtual int32_t NotifyMemorySizeStateChanged(bool isMemorySizeSufficent) override;
int32_t SetSupportedProcessCacheSelf(bool isSupport) override;
/**
* Start native child process, callde by ChildProcessManager.
* @param libName lib file name to be load in child process
* @param childProcessCount current started child process count
* @param callback callback for notify start result
* @return Returns ERR_OK on success, others on failure.
*/
int32_t StartNativeChildProcess(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback) override;
private:
bool SendTransactCmd(AppMgrInterfaceCode code, MessageParcel &data, MessageParcel &reply);
bool WriteInterfaceToken(MessageParcel &data);
@@ -135,6 +135,7 @@ private:
int32_t HandleGetAllUIExtensionProviderPid(MessageParcel &data, MessageParcel &reply);
int32_t HandleNotifyMemorySizeStateChanged(MessageParcel &data, MessageParcel &reply);
int32_t HandleSetSupportedProcessCacheSelf(MessageParcel &data, MessageParcel &reply);
int32_t HandleStartNativeChildProcess(MessageParcel &data, MessageParcel &reply);
using AppMgrFunc = int32_t (AppMgrStub::*)(MessageParcel &data, MessageParcel &reply);
std::map<uint32_t, AppMgrFunc> memberFuncMap_;
@@ -22,10 +22,15 @@
namespace OHOS {
namespace AppExecFwk {
constexpr int32_t CHILD_PROCESS_TYPE_JS = 0;
constexpr int32_t CHILD_PROCESS_TYPE_NATIVE = 1;
struct ChildProcessInfo : public Parcelable {
std::int32_t pid;
std::int32_t hostPid;
std::int32_t uid;
std::int32_t processType;
std::string bundleName;
std::string processName;
std::string srcEntry;
@@ -34,9 +34,16 @@ public:
*/
virtual bool ScheduleExitProcessSafely() = 0;
/**
* Notify child process run main proc from shared lib.
* @param mainProcessCb Main process callback ipc object
*/
virtual bool ScheduleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb) = 0;
enum class Message {
SCHEDULE_LOAD_JS = 0,
SCHEDULE_EXIT_PROCESS_SAFELY = 1,
SCHEDULE_RUN_NATIVE_PROC = 2,
};
};
} // namespace AppExecFwk
@@ -29,6 +29,7 @@ public:
bool ScheduleLoadJs() override;
bool ScheduleExitProcessSafely() override;
bool ScheduleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb) override;
private:
bool WriteInterfaceToken(MessageParcel &data);
@@ -36,6 +36,7 @@ public:
private:
int32_t HandleScheduleLoadJs(MessageParcel &data, MessageParcel &reply);
int32_t HandleScheduleExitProcessSafely(MessageParcel &data, MessageParcel &reply);
int32_t HandleScheduleRunNativeProc(MessageParcel &data, MessageParcel &reply);
using ChildSchedulerFunc = int32_t (ChildSchedulerStub::*)(MessageParcel &data, MessageParcel &reply);
std::map<uint32_t, ChildSchedulerFunc> memberFuncMap_;
@@ -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_CHILD_NOTIFY_INTERFACE_H
#define OHOS_ABILITY_RUNTIME_NATIVE_CHILD_NOTIFY_INTERFACE_H
#include "iremote_broker.h"
namespace OHOS {
namespace AppExecFwk {
class INativeChildNotify : public IRemoteBroker {
public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.appexecfwk.NativeChildNotify");
/**
* Notify native child process started.
*
* @param nativeChild child process ipc object
*/
virtual void OnNativeChildStarted(const sptr<IRemoteObject> &nativeChild) = 0;
/**
* Notify native child process start failed.
*
* @param errCode failed error code
*/
virtual void OnError(int32_t errCode) = 0;
protected:
static constexpr uint32_t IPC_ID_ON_NATIVE_CHILD_STARTED = 0;
static constexpr uint32_t IPC_ID_ON_ERROR = 1;
};
} // OHOS
} // AppExecFwk
#endif // OHOS_ABILITY_RUNTIME_NATIVE_CHILD_NOTIFY_INTERFACE_H
@@ -0,0 +1,43 @@
/*
* 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_CHILD_NOTIFY_PROXY_H
#define OHOS_ABILITY_RUNTIME_NATIVE_CHILD_NOTIFY_PROXY_H
#include "native_child_notify_interface.h"
#include "iremote_proxy.h"
namespace OHOS {
namespace AppExecFwk {
class NativeChildNotifyProxy : public IRemoteProxy<INativeChildNotify> {
public:
explicit NativeChildNotifyProxy(const sptr<IRemoteObject> &impl);
virtual ~NativeChildNotifyProxy() = default;
void OnNativeChildStarted(const sptr<IRemoteObject> &nativeChild) override;
void OnError(int32_t errCode) override;
private:
bool WriteInterfaceToken(MessageParcel &data);
int32_t SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption& option);
static inline BrokerDelegator<NativeChildNotifyProxy> delegator_;
};
} // OHOS
} // AppExecFwk
#endif // OHOS_ABILITY_RUNTIME_NATIVE_CHILD_NOTIFY_PROXY_H
@@ -0,0 +1,41 @@
/*
* 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_CHILD_NOTIFY_STUB_H
#define OHOS_ABILITY_RUNTIME_NATIVE_CHILD_NOTIFY_STUB_H
#include "native_child_notify_interface.h"
#include "iremote_stub.h"
namespace OHOS {
namespace AppExecFwk {
class NativeChildNotifyStub : public IRemoteStub<INativeChildNotify> {
public:
NativeChildNotifyStub() = default;
virtual ~NativeChildNotifyStub() = default;
int OnRemoteRequest(
uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
private:
int32_t HandleOnNativeChildStarted(MessageParcel &data, MessageParcel &reply);
int32_t HandleOnError(MessageParcel &data, MessageParcel &reply);
};
} // OHOS
} // AppExecFwk
#endif // OHOS_ABILITY_RUNTIME_NATIVE_CHILD_NOTIFY_STUB_H
@@ -1989,5 +1989,46 @@ int32_t AppMgrProxy::SetSupportedProcessCacheSelf(bool isSupport)
}
return reply.ReadInt32();
}
int32_t AppMgrProxy::StartNativeChildProcess(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback)
{
TAG_LOGD(AAFwkTag::APPMGR, "Called.");
if (libName.empty() || !callback) {
TAG_LOGE(AAFwkTag::APPMGR, "Invalid params, libName:%{private}s", libName.c_str());
return ERR_INVALID_VALUE;
}
MessageParcel data;
if (!WriteInterfaceToken(data)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write interface token failed.");
return IPC_PROXY_ERR;
}
if (!data.WriteString(libName)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write lib name failed.");
return IPC_PROXY_ERR;
}
if (!data.WriteInt32(childProcessCount)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write param childProcessCount failed.");
return IPC_PROXY_ERR;
}
if (!data.WriteRemoteObject(callback)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write call back ipc object failed.");
return IPC_PROXY_ERR;
}
MessageParcel reply;
MessageOption option;
auto error = SendRequest(AppMgrInterfaceCode::START_NATIVE_CHILD_PROCESS, data, reply, option);
if (error != NO_ERROR) {
TAG_LOGE(AAFwkTag::APPMGR, "Send request error: %{public}d", error);
return error;
}
return reply.ReadInt32();
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -190,6 +190,8 @@ AppMgrStub::AppMgrStub()
&AppMgrStub::HandleSetSupportedProcessCacheSelf;
memberFuncMap_[static_cast<uint32_t>(AppMgrInterfaceCode::APP_GET_RUNNING_PROCESSES_BY_BUNDLE_TYPE)] =
&AppMgrStub::HandleGetRunningProcessesByBundleType;
memberFuncMap_[static_cast<uint32_t>(AppMgrInterfaceCode::START_NATIVE_CHILD_PROCESS)] =
&AppMgrStub::HandleStartNativeChildProcess;
}
AppMgrStub::~AppMgrStub()
@@ -1312,5 +1314,21 @@ int32_t AppMgrStub::HandleSetSupportedProcessCacheSelf(MessageParcel &data, Mess
}
return NO_ERROR;
}
int32_t AppMgrStub::HandleStartNativeChildProcess(MessageParcel &data, MessageParcel &reply)
{
TAG_LOGD(AAFwkTag::APPMGR, "Called.");
std::string libName = data.ReadString();
int32_t childCount = data.ReadInt32();
sptr<IRemoteObject> callback = data.ReadRemoteObject();
int32_t result = StartNativeChildProcess(libName, childCount, callback);
if (!reply.WriteInt32(result)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write ret error.");
return IPC_STUB_ERR;
}
return NO_ERROR;
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -37,6 +37,8 @@ bool ChildProcessInfo::ReadFromParcel(Parcel &parcel)
READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, uidData);
uid = static_cast<int32_t>(uidData);
READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, processType);
bundleName = Str16ToStr8(parcel.ReadString16());
processName = Str16ToStr8(parcel.ReadString16());
srcEntry = Str16ToStr8(parcel.ReadString16());
@@ -64,6 +66,7 @@ bool ChildProcessInfo::Marshalling(Parcel &parcel) const
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(pid));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(hostPid));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(uid));
WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, static_cast<int32_t>(processType));
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));
@@ -84,5 +84,39 @@ bool ChildSchedulerProxy::ScheduleExitProcessSafely()
TAG_LOGD(AAFwkTag::APPMGR, "ScheduleExitProcessSafely end.");
return true;
}
bool ChildSchedulerProxy::ScheduleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb)
{
TAG_LOGD(AAFwkTag::APPMGR, "ScheduleRunNativeProc start.");
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_ASYNC);
if (!WriteInterfaceToken(data)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write interface token failed.");
return false;
}
if (!data.WriteRemoteObject(mainProcessCb)) {
TAG_LOGE(AAFwkTag::APPMGR, "Write main process callback ipc object failed.");
return false;
}
sptr<IRemoteObject> remote = Remote();
if (remote == nullptr) {
TAG_LOGE(AAFwkTag::APPMGR, "Remote() is null.");
return false;
}
int32_t ret = remote->SendRequest(
static_cast<uint32_t>(IChildScheduler::Message::SCHEDULE_RUN_NATIVE_PROC), data, reply, option);
if (ret != NO_ERROR) {
TAG_LOGE(AAFwkTag::APPMGR, "SendRequest is failed, error code: %{public}d.", ret);
return false;
}
TAG_LOGD(AAFwkTag::APPMGR, "ScheduleRunNativeProc end.");
return true;
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -27,6 +27,8 @@ ChildSchedulerStub::ChildSchedulerStub()
&ChildSchedulerStub::HandleScheduleLoadJs;
memberFuncMap_[static_cast<uint32_t>(IChildScheduler::Message::SCHEDULE_EXIT_PROCESS_SAFELY)] =
&ChildSchedulerStub::HandleScheduleExitProcessSafely;
memberFuncMap_[static_cast<uint32_t>(IChildScheduler::Message::SCHEDULE_RUN_NATIVE_PROC)] =
&ChildSchedulerStub::HandleScheduleRunNativeProc;
}
ChildSchedulerStub::~ChildSchedulerStub()
@@ -68,5 +70,13 @@ int32_t ChildSchedulerStub::HandleScheduleExitProcessSafely(MessageParcel &data,
ScheduleExitProcessSafely();
return ERR_NONE;
}
int32_t ChildSchedulerStub::HandleScheduleRunNativeProc(MessageParcel &data, MessageParcel &reply)
{
sptr<IRemoteObject> cb = data.ReadRemoteObject();
ScheduleRunNativeProc(cb);
return ERR_NONE;
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -0,0 +1,94 @@
/*
* 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_child_notify_proxy.h"
#include "hilog_tag_wrapper.h"
#include "hilog_wrapper.h"
#include "ipc_types.h"
namespace OHOS {
namespace AppExecFwk {
NativeChildNotifyProxy::NativeChildNotifyProxy(const sptr<IRemoteObject> &impl)
: IRemoteProxy<INativeChildNotify>(impl)
{
}
bool NativeChildNotifyProxy::WriteInterfaceToken(MessageParcel &data)
{
if (!data.WriteInterfaceToken(NativeChildNotifyProxy::GetDescriptor())) {
TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy write interface token failed");
return false;
}
return true;
}
int32_t NativeChildNotifyProxy::SendRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption& option)
{
sptr<IRemoteObject> remote = Remote();
if (!remote) {
TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy get remote object failed");
return ERR_NULL_OBJECT;
}
int32_t ret = remote->SendRequest(code, data, reply, option);
if (ret != NO_ERROR) {
TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy SendRequest failed(%{public}d)", ret);
return ret;
}
return NO_ERROR;
}
void NativeChildNotifyProxy::OnNativeChildStarted(const sptr<IRemoteObject> &nativeChild)
{
TAG_LOGD(AAFwkTag::APPMGR, "NativeChildNotifyProxy OnNativeChildStarted");
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_ASYNC);
if (!WriteInterfaceToken(data)) {
return;
}
if (!data.WriteRemoteObject(nativeChild)) {
TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy write native child ipc object failed.");
return;
}
SendRequest(INativeChildNotify::IPC_ID_ON_NATIVE_CHILD_STARTED, data, reply, option);
}
void NativeChildNotifyProxy::OnError(int32_t errCode)
{
TAG_LOGD(AAFwkTag::APPMGR, "NativeChildNotifyProxy OnError(%{public}d)", errCode);
MessageParcel data;
MessageParcel reply;
MessageOption option(MessageOption::TF_ASYNC);
if (!WriteInterfaceToken(data)) {
return;
}
if (!data.WriteInt32(errCode)) {
TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy write error code failed.");
return;
}
SendRequest(INativeChildNotify::IPC_ID_ON_ERROR, data, reply, option);
}
} // OHOS
} // AppExecFwk
@@ -0,0 +1,71 @@
/*
* 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_child_notify_stub.h"
#include "hilog_tag_wrapper.h"
#include "hilog_wrapper.h"
#include "ipc_types.h"
namespace OHOS {
namespace AppExecFwk {
int NativeChildNotifyStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
MessageParcel &reply, MessageOption &option)
{
TAG_LOGD(AAFwkTag::APPMGR, "NativeChildNotifyStub::OnRemoteRequest, code=%{public}u, flags=%{public}d.",
code, option.GetFlags());
std::u16string descriptor = NativeChildNotifyStub::GetDescriptor();
std::u16string remoteDesc = data.ReadInterfaceToken();
if (descriptor != remoteDesc) {
TAG_LOGE(AAFwkTag::APPMGR, "A local descriptor is not equivalent to a remote");
return ERR_INVALID_STATE;
}
int32_t ret;
switch (code) {
case INativeChildNotify::IPC_ID_ON_NATIVE_CHILD_STARTED:
ret = HandleOnNativeChildStarted(data, reply);
break;
case INativeChildNotify::IPC_ID_ON_ERROR:
ret = HandleOnError(data, reply);
break;
default:
TAG_LOGW(AAFwkTag::APPMGR, "NativeChildNotifyStub Unknow ipc call(%{public}u)", code);
ret = IPCObjectStub::OnRemoteRequest(code, data, reply, option);
break;
}
TAG_LOGD(AAFwkTag::APPMGR, "NativeChildNotifyStub::OnRemoteRequest end");
return ret;
}
int32_t NativeChildNotifyStub::HandleOnNativeChildStarted(MessageParcel &data, MessageParcel &reply)
{
sptr<IRemoteObject> cb = data.ReadRemoteObject();
OnNativeChildStarted(cb);
return ERR_NONE;
}
int32_t NativeChildNotifyStub::HandleOnError(MessageParcel &data, MessageParcel &reply)
{
int32_t err = data.ReadInt32();
OnError(err);
return ERR_NONE;
}
} // OHOS
} // AppExecFwk
@@ -32,6 +32,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_child_ipc_process.cpp",
]
deps = [
@@ -50,6 +51,7 @@ ohos_shared_library("child_process_manager") {
"eventhandler:libeventhandler",
"hilog:libhilog",
"init:libbegetutil",
"ipc:ipc_capi",
"ipc:ipc_core",
"napi:ace_napi",
"samgr:samgr_proxy",
@@ -25,6 +25,7 @@
#include "child_process_manager_error_utils.h"
#include "hap_module_info.h"
#include "runtime.h"
#include "iremote_object.h"
namespace OHOS {
namespace AbilityRuntime {
@@ -41,12 +42,15 @@ public:
bool IsChildProcess();
ChildProcessManagerErrorCode StartChildProcessBySelfFork(const std::string &srcEntry, pid_t &pid);
ChildProcessManagerErrorCode StartChildProcessByAppSpawnFork(const std::string &srcEntry, pid_t &pid);
ChildProcessManagerErrorCode StartNativeChildProcessByAppSpawnFork(
const std::string &libName, const sptr<IRemoteObject> &callbackStub);
bool GetBundleInfo(AppExecFwk::BundleInfo &bundleInfo);
bool GetHapModuleInfo(const AppExecFwk::BundleInfo &bundleInfo, AppExecFwk::HapModuleInfo &hapModuleInfo);
std::unique_ptr<AbilityRuntime::Runtime> CreateRuntime(const AppExecFwk::BundleInfo &bundleInfo,
const AppExecFwk::HapModuleInfo &hapModuleInfo, const bool fromAppSpawn, const bool jitEnabled);
bool LoadJsFile(const std::string &srcEntry, const AppExecFwk::HapModuleInfo &hapModuleInfo,
std::unique_ptr<AbilityRuntime::Runtime> &runtime);
bool LoadNativeLib(const std::string &libPath, const sptr<IRemoteObject> &mainProcessCb);
void SetForkProcessJITEnabled(bool jitEnabled);
void SetForkProcessDebugOption(const std::string bundleName, const bool isStartWithDebug, const bool isDebugApp,
const bool isStartWithNative);
@@ -55,6 +59,7 @@ private:
ChildProcessManager();
ChildProcessManagerErrorCode PreCheck();
ChildProcessManagerErrorCode PreCheckNativeProcess();
void RegisterSignal();
void HandleChildProcessBySelfFork(const std::string &srcEntry, const AppExecFwk::BundleInfo &bundleInfo);
bool hasChildProcessRecord();
@@ -31,6 +31,10 @@ enum class ChildProcessManagerErrorCode {
ERR_GET_BUNDLE_INFO_FAILED = 5,
ERR_GET_APP_MGR_FAILED = 6,
ERR_GET_APP_MGR_START_PROCESS_FAILED = 7,
ERR_UNSUPPORT_NATIVE_CHILD_PROCESS = 8,
ERR_MAX_NATIVE_CHILD_PROCESSES = 9,
ERR_NATIVE_CHILD_PROCESS_LOAD_LIB = 10,
ERR_NATIVE_CHILD_PROCESS_CONNECT = 11,
};
const std::map<ChildProcessManagerErrorCode, AbilityErrorCode> INTERNAL_ERR_CODE_MAP = {
@@ -17,6 +17,7 @@
#define OHOS_ABILITY_RUNTIME_CHILD_PROCESS_START_INFO_H
#include <string>
#include "iremote_object.h"
namespace OHOS {
namespace AbilityRuntime {
@@ -26,6 +27,7 @@ struct ChildProcessStartInfo {
std::string srcEntry;
std::string hapPath;
bool isEsModule = true;
sptr<IRemoteObject> ipcObj;
};
} // namespace AbilityRuntime
} // namespace OHOS
@@ -0,0 +1,53 @@
/*
* 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_CHILD_IPC_PROCESS_H
#define OHOS_ABILITY_RUNTIME_NATIVE_CHILD_IPC_PROCESS_H
#include <memory>
#include "child_process.h"
#include "native_child_notify_interface.h"
#include "ipc_inner_object.h"
namespace OHOS {
namespace AbilityRuntime {
class NativeChildIpcProcess : public ChildProcess {
public:
NativeChildIpcProcess() = default;
~NativeChildIpcProcess();
static std::shared_ptr<ChildProcess> Create();
bool Init(const std::shared_ptr<ChildProcessStartInfo> &info) override;
void OnStart() override;
private:
bool LoadNativeLib(const std::shared_ptr<ChildProcessStartInfo> &info);
void UnloadNativeLib();
typedef OHIPCRemoteStub* (*NativeChildProcess_OnConnect)();
typedef void (*NativeChildProcess_MainProc)();
sptr<OHOS::AppExecFwk::INativeChildNotify> mainProcessCb_;
void *nativeLibHandle_ = nullptr;
NativeChildProcess_OnConnect funcNativeLibOnConnect_ = nullptr;
NativeChildProcess_MainProc funcNativeLibMainProc_ = nullptr;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_NATIVE_CHILD_IPC_PROCESS_H
@@ -0,0 +1,144 @@
/*
* 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_C_ABILITY_RUNTIME_NATIVE_CHILD_PROCESS_H
#define OHOS_C_ABILITY_RUNTIME_NATIVE_CHILD_PROCESS_H
#include "ipc_cparcel.h"
/**
* @file native_child_process.h
*
* @brief Defines the functions for native child process management.
* @library libchild_process.so
* @syscap SystemCapability.Ability.AbilityRuntime.Core
* @since 12
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief native child process error code
* @since 12
*/
enum Ability_NativeChildProcess_ErrCode {
/**
* @error The operation completed successfully
*/
NCP_NOERROR = 0,
/**
* @error Invalid param
*/
NCP_ERR_INVALID_PARAM = 401,
/**
* @error Unsupport start native process
*/
NCP_ERR_NOT_SUPPORTED = 801,
/**
* @error Internal error
*/
NCP_ERR_INTERNAL = 16000050,
/**
* @error Can not start another during child process startup, try again after current child process started
*/
NCP_ERR_BUSY = 16010001,
/**
* @error Start native child time out
*/
NCP_ERR_TIMEOUT = 16010002,
/**
* @error Service process error
*/
NCP_ERR_SERVICE = 16010003,
/**
* @error Multi process disabled, can not start child process
*/
NCP_ERR_MULTI_PROCESS_DISABLED = 16010004,
/**
* @error Already in child process, only main process can start child
*/
NCP_ERR_ALREADY_IN_CHILD = 16010005,
/**
* @error Max native child processes reached, can not start another
*/
NCP_ERR_MAX_CHILD_PROCESSES_REACHED = 16010006,
/**
* @error Child process load library failed
*/
NCP_ERR_CHILD_PROCESS_LOAD_LIB = 16010007,
/**
* @error Faild to invoke OnConnect method in library
*/
NCP_ERR_CHILD_PROCESS_CONNECT = 16010008,
};
/**
* @brief callback function for notify the child process start result, see <b>OH_Ability_CreateNativeChildProcess</b>
*
* @param errCode Zero if successful, an error otherwise, see <v>Ability_NativeChildProcess_ErrCode</b> for detail
* @param remoteProxy IPC object implemented in the sharded lib loaded by child process; will be nullptr when failed
* @since 12
*/
typedef void (*OH_Ability_OnNativeChildProcessStarted)(int errCode, OHIPCRemoteProxy *remoteProxy);
/**
* @brief Create native child process for app and load shared library specified by param,
* process startup result is asynchronously notified via callback
* Lib file must be implemented and exported follow functions:
* 1. OHIPCRemoteStub* NativeChildProcess_OnConnect()
* 2. void NativeChildProcess_MainProc()
*
* Processing logic be like follows:
* Main Process:
* 1. Call OH_Ability_CreateNativeChildProcess(libName, onProcessStartedCallback)
* Child Process:
* 2. dlopen(libName)
* 3. dlsym("NativeChildProcess_OnConnect") & dlsym("NativeChildProcess_MainProc")
* 4. ipcRemote = NativeChildProcess_OnConnect()
* 5. NativeChildProcess_MainProc()
* Main Process:
* 6. onProcessStartedCallback(ipcRemote, errCode)
* Child Process:
* 7. Process exit after NativeChildProcess_MainProc() method returned
*
* @param libName Name of the library file loaded by child process, can not be nullptr
* @param onProcessStarted Callback for notify the child process start result
* @return Zero if successful, an error otherwise, see <b>Ability_NativeChildProcess_ErrCode</b> for detail
* @see OH_Ability_OnNativeChildProcessStarted
* @since 12
*/
int OH_Ability_CreateNativeChildProcess(const char* libName,
OH_Ability_OnNativeChildProcessStarted onProcessStarted);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OHOS_C_ABILITY_RUNTIME_NATIVE_CHILD_PROCESS_H
@@ -39,6 +39,7 @@ public:
static void Start(const ChildProcessInfo &processInfo);
bool ScheduleLoadJs() override;
bool ScheduleExitProcessSafely() override;
bool ScheduleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb) override;
private:
bool Init(const std::shared_ptr<EventRunner> &runner, const ChildProcessInfo &processInfo);
@@ -49,6 +50,8 @@ private:
void ExitProcessSafely();
void GetNativeLibPath(const BundleInfo &bundleInfo, AppLibPathMap &appLibPaths);
void GetHapSoPath(const HapModuleInfo &hapInfo, AppLibPathMap &appLibPaths, bool isPreInstallApp);
void HandleRunNativeProc(const sptr<IRemoteObject> &mainProcessCb);
void UpdateNativeChildLibPath(const AppLibPathMap &appLibPaths);
std::string GetLibPath(const std::string &hapPath, bool isPreInstallApp);
sptr<IAppMgr> appMgr_ = nullptr;
+11
View File
@@ -503,6 +503,17 @@ public:
int32_t NotifyMemorySizeStateChanged(bool isMemorySizeSufficent) override;
int32_t SetSupportedProcessCacheSelf(bool isSupport) override;
/**
* Start native child process, callde by ChildProcessManager.
* @param libName lib file name to be load in child process
* @param childProcessCount current started child process count
* @param callback callback for notify start result
* @return Returns ERR_OK on success, others on failure.
*/
int32_t StartNativeChildProcess(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback) override;
private:
/**
* Init, Initialize application services.
@@ -995,6 +995,17 @@ public:
*/
virtual void ExitChildProcessSafelyByChildPid(const pid_t pid);
/**
* Start native child process, callde by ChildProcessManager.
* @param hostPid Host process pid.
* @param childProcessCount current started child process count
* @param libName lib file name to be load in child process
* @param callback callback for notify start result
* @return Returns ERR_OK on success, others on failure.
*/
virtual int32_t StartNativeChildProcess(const pid_t hostPid,
const std::string &libName, int32_t childProcessCount, const sptr<IRemoteObject> &callback);
/**
* Whether the current application process is the last surviving process.
* @param bundleName To query the bundle name of a process.
@@ -22,6 +22,7 @@
#include "app_death_recipient.h"
#include "child_scheduler_interface.h"
#include "child_process_info.h"
namespace OHOS {
namespace AppExecFwk {
@@ -31,10 +32,15 @@ class ChildProcessRecord {
public:
ChildProcessRecord(pid_t hostPid, const std::string &srcEntry, const std::shared_ptr<AppRunningRecord> hostRecord,
int32_t childProcessCount, bool isStartWithDebug);
ChildProcessRecord(pid_t hostPid, const std::string &libName, const std::shared_ptr<AppRunningRecord> hostRecord,
const sptr<IRemoteObject> &mainProcessCb, int32_t childProcessCount, bool isStartWithDebug);
virtual ~ChildProcessRecord();
static std::shared_ptr<ChildProcessRecord> CreateChildProcessRecord(pid_t hostPid, const std::string &srcEntry,
const std::shared_ptr<AppRunningRecord> hostRecord, int32_t childProcessCount, bool isStartWithDebug);
static std::shared_ptr<ChildProcessRecord> CreateNativeChildProcessRecord(pid_t hostPid, const std::string &libName,
const std::shared_ptr<AppRunningRecord> hostRecord, const sptr<IRemoteObject> &mainProcessCb,
int32_t childProcessCount, bool isStartWithDebug);
void SetPid(pid_t pid);
pid_t GetPid() const;
@@ -51,6 +57,9 @@ public:
void RemoveDeathRecipient();
void ScheduleExitProcessSafely();
bool isStartWithDebug();
int32_t GetProcessType() const;
sptr<IRemoteObject> GetMainProcessCallback() const;
void ClearMainProcessCallback();
private:
void MakeProcessName(const std::shared_ptr<AppRunningRecord> hostRecord);
@@ -58,11 +67,13 @@ private:
pid_t hostPid_ = 0;
int32_t uid_ = 0;
int32_t childProcessCount_ = 0;
int32_t childProcessType_ = CHILD_PROCESS_TYPE_JS;
std::string processName_;
std::string srcEntry_;
std::weak_ptr<AppRunningRecord> hostRecord_;
sptr<IChildScheduler> scheduler_ = nullptr;
sptr<AppDeathRecipient> deathRecipient_ = nullptr;
sptr<IRemoteObject> mainProcessCb_ = nullptr;
bool isStartWithDebug_;
};
} // namespace AppExecFwk
+14
View File
@@ -1441,5 +1441,19 @@ int32_t AppMgrService::SetSupportedProcessCacheSelf(bool isSupport)
}
return appMgrServiceInner_->SetSupportedProcessCacheSelf(isSupport);
}
int32_t AppMgrService::StartNativeChildProcess(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback)
{
TAG_LOGI(AAFwkTag::APPMGR, "Called");
if (!IsReady()) {
TAG_LOGE(AAFwkTag::APPMGR, "Not ready.");
return ERR_INVALID_OPERATION;
}
return appMgrServiceInner_->StartNativeChildProcess(
IPCSkeleton::GetCallingPid(), libName, childProcessCount, callback);
}
} // namespace AppExecFwk
} // namespace OHOS
+51 -2
View File
@@ -5896,6 +5896,7 @@ int32_t AppMgrServiceInner::GetChildProcessInfo(const std::shared_ptr<ChildProce
info.pid = childProcessRecord->GetPid();
info.hostPid = childProcessRecord->GetHostPid();
info.uid = childProcessRecord->GetUid();
info.processType = childProcessRecord->GetProcessType();
info.bundleName = appRecord->GetBundleName();
info.processName = childProcessRecord->GetProcessName();
info.srcEntry = childProcessRecord->GetSrcEntry();
@@ -5944,7 +5945,12 @@ void AppMgrServiceInner::AttachChildProcess(const pid_t pid, const sptr<IChildSc
childRecord->SetDeathRecipient(appDeathRecipient);
childRecord->RegisterDeathRecipient();
childScheduler->ScheduleLoadJs();
if (childRecord->GetProcessType() != CHILD_PROCESS_TYPE_NATIVE) {
childScheduler->ScheduleLoadJs();
} else {
childScheduler->ScheduleRunNativeProc(childRecord->GetMainProcessCallback());
childRecord->ClearMainProcessCallback();
}
}
void AppMgrServiceInner::OnChildProcessRemoteDied(const wptr<IRemoteObject> &remote)
@@ -6539,5 +6545,48 @@ void AppMgrServiceInner::OnAppCacheStateChanged(const std::shared_ptr<AppRunning
DelayedSingleton<AppStateObserverManager>::GetInstance()->OnAppCacheStateChanged(appRecord);
}
int32_t AppMgrServiceInner::StartNativeChildProcess(const pid_t hostPid, const std::string &libName,
int32_t childProcessCount, const sptr<IRemoteObject> &callback)
{
TAG_LOGI(AAFwkTag::APPMGR, "StartNativeChildProcess, hostPid:%{public}d", hostPid);
if (hostPid <= 0 || libName.empty() || !callback) {
TAG_LOGE(AAFwkTag::APPMGR, "Invalid param: hostPid:%{public}d libName:%{private}s",
hostPid, libName.c_str());
return ERR_INVALID_VALUE;
}
if (!AAFwk::AppUtils::GetInstance().IsSupportNativeChildProcess()) {
TAG_LOGE(AAFwkTag::APPMGR, "Unsupport native child process");
return ERR_INVALID_OPERATION;
}
int32_t errCode = StartChildProcessPreCheck(hostPid);
if (errCode != ERR_OK) {
return errCode;
}
auto appRecord = GetAppRunningRecordByPid(hostPid);
if (!appRecord) {
TAG_LOGI(AAFwkTag::APPMGR, "Get app runnning record(hostPid:%{public}d) failed.", hostPid);
return ERR_INVALID_OPERATION;
}
auto childRecordMap = appRecord->GetChildProcessRecordMap();
auto itNativeChildInfo = find_if(childRecordMap.begin(), childRecordMap.end(), [] (const auto &pair) -> bool {
return pair.second->GetProcessType() == CHILD_PROCESS_TYPE_NATIVE;
});
if (itNativeChildInfo != childRecordMap.end()) {
TAG_LOGI(AAFwkTag::APPMGR, "Native child process still alive(hostPid:%{public}d childPid:%{public}d)",
hostPid, itNativeChildInfo->second->GetPid());
return ERR_OVERFLOW;
}
pid_t dummyChildPid = 0;
auto nativeChildRecord = ChildProcessRecord::CreateNativeChildProcessRecord(
hostPid, libName, appRecord, callback, childProcessCount, false);
return StartChildProcessImpl(nativeChildRecord, appRecord, dummyChildPid);
}
} // namespace AppExecFwk
} // namespace OHOS
} // namespace OHOS
@@ -29,6 +29,15 @@ ChildProcessRecord::ChildProcessRecord(pid_t hostPid, const std::string &srcEntr
MakeProcessName(hostRecord);
}
ChildProcessRecord::ChildProcessRecord(pid_t hostPid, const std::string &libName,
const std::shared_ptr<AppRunningRecord> hostRecord, const sptr<IRemoteObject> &mainProcessCb,
int32_t childProcessCount, bool isStartWithDebug)
: hostPid_(hostPid), childProcessCount_(childProcessCount), childProcessType_(CHILD_PROCESS_TYPE_NATIVE),
srcEntry_(libName), hostRecord_(hostRecord), mainProcessCb_(mainProcessCb), isStartWithDebug_(isStartWithDebug)
{
MakeProcessName(hostRecord);
}
ChildProcessRecord::~ChildProcessRecord()
{
TAG_LOGD(AAFwkTag::APPMGR, "Called.");
@@ -46,6 +55,19 @@ std::shared_ptr<ChildProcessRecord> ChildProcessRecord::CreateChildProcessRecord
return std::make_shared<ChildProcessRecord>(hostPid, srcEntry, hostRecord, childProcessCount, isStartWithDebug);
}
std::shared_ptr<ChildProcessRecord> ChildProcessRecord::CreateNativeChildProcessRecord(
pid_t hostPid, const std::string &libName, const std::shared_ptr<AppRunningRecord> hostRecord,
const sptr<IRemoteObject> &mainProcessCb, int32_t childProcessCount, bool isStartWithDebug)
{
TAG_LOGD(AAFwkTag::APPMGR, "hostPid: %{public}d, libName: %{public}s", hostPid, libName.c_str());
if (hostPid <= 0 || libName.empty() || !hostRecord || !mainProcessCb) {
TAG_LOGE(AAFwkTag::APPMGR, "Invalid parameter.");
return nullptr;
}
return std::make_shared<ChildProcessRecord>(hostPid, libName, hostRecord, mainProcessCb,
childProcessCount, isStartWithDebug);
}
void ChildProcessRecord::SetPid(pid_t pid)
{
pid_ = pid;
@@ -148,6 +170,10 @@ void ChildProcessRecord::MakeProcessName(const std::shared_ptr<AppRunningRecord>
std::string filename = std::filesystem::path(srcEntry_).stem();
if (!filename.empty()) {
processName_.append(":");
if (childProcessType_ == CHILD_PROCESS_TYPE_NATIVE) {
processName_.append("Native_");
}
processName_.append(filename);
}
processName_.append(std::to_string(childProcessCount_));
@@ -158,5 +184,21 @@ bool ChildProcessRecord::isStartWithDebug()
{
return isStartWithDebug_;
}
int32_t ChildProcessRecord::GetProcessType() const
{
return childProcessType_;
}
sptr<IRemoteObject> ChildProcessRecord::GetMainProcessCallback() const
{
return mainProcessCb_;
}
void ChildProcessRecord::ClearMainProcessCallback()
{
mainProcessCb_.clear();
}
} // namespace AppExecFwk
} // namespace OHOS
+1
View File
@@ -30,6 +30,7 @@ config("common_config") {
"${ability_runtime_innerkits_path}/*",
"${ability_runtime_napi_path}/*",
"${ability_runtime_native_path}/ability/native/*",
"${ability_runtime_native_path}/child_process/*",
"${ability_runtime_path}/frameworks/simulator/ability_simulator/*",
"${ability_runtime_path}/tools/aa/*",
"${ability_runtime_services_path}/common/*",
+2
View File
@@ -47,6 +47,7 @@ public:
bool IsStartOptionsWithProcessOptions();
bool EnableMoveUIAbilityToBackgroundApi();
bool IsLaunchEmbededUIAbility();
bool IsSupportNativeChildProcess();
private:
AppUtils();
@@ -65,6 +66,7 @@ private:
volatile DeviceConfiguration<bool> isStartOptionsWithProcessOptions_ = {false, false};
volatile DeviceConfiguration<bool> enableMoveUIAbilityToBackgroundApi_ = {false, true};
volatile DeviceConfiguration<bool> isLaunchEmbededUIAbility_ = {false, false};
volatile DeviceConfiguration<bool> isSupportNativeChildProcess_ = {false, false};
DISALLOW_COPY_AND_MOVE(AppUtils);
};
} // namespace AAFwk
+13
View File
@@ -41,7 +41,9 @@ const std::string START_OPTIONS_WITH_PROCESS_OPTION = "persist.sys.abilityms.sta
const std::string MOVE_UI_ABILITY_TO_BACKGROUND_API_ENABLE =
"persist.sys.abilityms.move_ui_ability_to_background_api_enable";
const std::string LAUNCH_EMBEDED_UI_ABILITY = "const.abilityms.launch_embeded_ui_ability";
const std::string SUPPROT_NATIVE_CHILD_PROCESS = "persist.sys.abilityms.start_native_child_process";
}
AppUtils::~AppUtils() {}
AppUtils::AppUtils()
@@ -207,5 +209,16 @@ bool AppUtils::IsLaunchEmbededUIAbility()
TAG_LOGI(AAFwkTag::DEFAULT, "isLaunchEmbededUIAbility_ is %{public}d", isLaunchEmbededUIAbility_.value);
return isLaunchEmbededUIAbility_.value;
}
bool AppUtils::IsSupportNativeChildProcess()
{
if (!isSupportNativeChildProcess_.isLoaded) {
isSupportNativeChildProcess_.value = system::GetBoolParameter(SUPPROT_NATIVE_CHILD_PROCESS, false);
isSupportNativeChildProcess_.isLoaded = true;
}
TAG_LOGI(AAFwkTag::DEFAULT, "isSupportNativeChildProcess_ is %{public}d", isSupportNativeChildProcess_.value);
return isSupportNativeChildProcess_.value;
}
} // namespace AAFwk
} // namespace OHOS
@@ -84,6 +84,8 @@ public:
MOCK_METHOD1(UnregisterRenderStateObserver, int32_t(const sptr<IRenderStateObserver> &observer));
MOCK_METHOD2(UpdateRenderState, int32_t(pid_t renderPid, int32_t state));
MOCK_METHOD1(SetSupportedProcessCacheSelf, int32_t(bool isSupported));
MOCK_METHOD3(StartNativeChildProcess, int32_t(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback));
void AttachApplication(const sptr<IRemoteObject>& app)
{
@@ -65,6 +65,8 @@ public:
int32_t childProcessCount, bool inStartWithDebug));
MOCK_METHOD1(GetChildProcessInfoForSelf, int32_t(ChildProcessInfo &info));
MOCK_METHOD4(PreloadApplication, int32_t(const std::string&, int32_t, AppExecFwk::PreloadMode, int32_t));
MOCK_METHOD4(StartNativeChildProcess, int32_t(const pid_t hostPid, const std::string &libName,
int32_t childProcessCount, const sptr<IRemoteObject> &callback));
void StartSpecifiedAbility(const AAFwk::Want&, const AppExecFwk::AbilityInfo&, int32_t)
{}
@@ -101,6 +101,8 @@ public:
MOCK_METHOD0(IsFinalAppProcess, bool());
MOCK_METHOD1(SetSupportedProcessCacheSelf, int32_t(bool isSupport));
MOCK_METHOD3(StartNativeChildProcess, int32_t(const std::string &libName, int32_t childProcessCount,
const sptr<IRemoteObject> &callback));
virtual int StartUserTestProcess(
const AAFwk::Want &want, const sptr<IRemoteObject> &observer, const BundleInfo &bundleInfo, int32_t userId)
{
@@ -71,6 +71,8 @@ public:
MOCK_METHOD1(IsWaitingDebugApp, bool(const std::string &bundleName));
MOCK_METHOD0(ClearNonPersistWaitingDebugFlag, void());
MOCK_METHOD0(IsMemorySizeSufficent, bool());
MOCK_METHOD4(StartNativeChildProcess, int32_t(const pid_t hostPid,
const std::string &libName, int32_t childProcessCount, const sptr<IRemoteObject> &callback));
void StartSpecifiedAbility(const AAFwk::Want&, const AppExecFwk::AbilityInfo&, int32_t)
{}
+3
View File
@@ -48,6 +48,8 @@ ohos_source_set("appmgr_test_source") {
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/app_state_callback_proxy.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/app_task_info.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/fault_data.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/native_child_notify_proxy.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/native_child_notify_stub.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/process_info.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/profile.cpp",
"${ability_runtime_innerkits_path}/app_manager/src/appmgr/render_scheduler_host.cpp",
@@ -417,6 +419,7 @@ group("unittest") {
"bundle_mgr_helper_test:unittest",
"cache_process_manager_test:unittest",
"call_record_test:unittest",
"child_process_capi_test:unittest",
"child_process_manager_test:unittest",
"completed_dispatcher_test:unittest",
"configuration_test:unittest",
@@ -1731,5 +1731,31 @@ HWTEST_F(AppMgrServiceTest, SetSupportedProcessCacheSelf_002, TestSize.Level0)
res = appMgrService->SetSupportedProcessCacheSelf(false);
EXPECT_EQ(res, AAFwk::ERR_SET_SUPPORTED_PROCESS_CACHE_AGAIN);
}
/**
* @tc.name: StartNativeChildProcess_0100
* @tc.desc: Start native child process.
* @tc.type: FUNC
*/
HWTEST_F(AppMgrServiceTest, StartNativeChildProcess_0100, TestSize.Level1)
{
TAG_LOGD(AAFwkTag::TEST, "StartNativeChildProcess_0100 called.");
sptr<AppMgrService> appMgrService = new (std::nothrow) AppMgrService();
ASSERT_NE(appMgrService, nullptr);
appMgrService->SetInnerService(mockAppMgrServiceInner_);
appMgrService->taskHandler_ = taskHandler_;
appMgrService->eventHandler_ = eventHandler_;
EXPECT_CALL(*mockAppMgrServiceInner_, StartNativeChildProcess(_, _, _, _))
.Times(1)
.WillOnce(Return(ERR_OK));
pid_t pid = 0;
sptr<IRemoteObject> callback;
int32_t res = appMgrService->StartNativeChildProcess("test.so", 1, callback);
EXPECT_EQ(res, ERR_OK);
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -170,5 +170,26 @@ HWTEST_F(ChildMainThreadTest, ScheduleExitProcessSafely_0100, TestSize.Level0)
auto ret = thread->ScheduleExitProcessSafely();
EXPECT_TRUE(ret);
}
/**
* @tc.number: ScheduleRunNativeProc_0100
* @tc.desc: Test ScheduleRunNativeProc works
* @tc.type: FUNC
*/
HWTEST_F(ChildMainThreadTest, ScheduleRunNativeProc_0100, TestSize.Level0)
{
TAG_LOGD(AAFwkTag::TEST, "ScheduleRunNativeProc_0100 called.");
sptr<ChildMainThread> thread = sptr<ChildMainThread>(new (std::nothrow) ChildMainThread());
ASSERT_NE(thread, nullptr);
std::shared_ptr<EventRunner> runner = EventRunner::GetMainEventRunner();
std::shared_ptr<EventHandler> handler = std::make_shared<EventHandler>(runner);
thread->mainHandler_ = handler;
sptr<IRemoteObject> mainPorcessCb = nullptr;
auto ret = thread->ScheduleRunNativeProc(mainPorcessCb);
EXPECT_FALSE(ret);
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -0,0 +1,52 @@
# 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.
import("//build/test.gni")
import("//foundation/ability/ability_runtime/ability_runtime.gni")
module_output_path = "ability_runtime/child_process_capi"
ohos_unittest("child_process_capi_test") {
module_out_path = module_output_path
configs = [ "${ability_runtime_services_path}/common:common_config" ]
if (target_cpu == "arm") {
cflags = [ "-DBINDER_IPC_32BIT" ]
}
include_dirs = [
"include",
"${ability_runtime_test_path}/mock/services_appmgr_test/include",
]
sources = [ "child_process_capi_test.cpp" ]
deps = [
"${ability_runtime_native_path}/child_process:child_process",
"${ability_runtime_services_path}/common:app_util",
"//third_party/googletest:gmock_main",
"//third_party/googletest:gtest_main",
]
external_deps = [
"c_utils:utils",
"hilog:libhilog",
"ipc:ipc_capi",
]
}
group("unittest") {
testonly = true
deps = [ ":child_process_capi_test" ]
}
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2023 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 <gtest/gtest.h>
#include <gmock/gmock.h>
#include "native_child_process.h"
#include "app_utils.h"
namespace OHOS {
namespace AbilityRuntime {
using namespace testing;
using namespace testing::ext;
class ChildProcessCapiTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy);
void SetUp();
void TearDown();
};
void ChildProcessCapiTest::SetUpTestCase(void)
{}
void ChildProcessCapiTest::TearDownTestCase(void)
{}
void ChildProcessCapiTest::SetUp(void)
{}
void ChildProcessCapiTest::TearDown(void)
{}
void ChildProcessCapiTest::OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy)
{
}
/**
* @tc.number: OH_Ability_CreateNativeChildProcess_001
* @tc.desc: Test API OH_Ability_CreateNativeChildProcess works
* @tc.type: FUNC
*/
HWTEST_F(ChildProcessCapiTest, OH_Ability_CreateNativeChildProcess_001, TestSize.Level0)
{
GTEST_LOG_(INFO) << "OH_Ability_CreateNativeChildProcess_001 begin";
int ret = OH_Ability_CreateNativeChildProcess(nullptr, ChildProcessCapiTest::OnNativeChildProcessStarted);
EXPECT_EQ(ret, NCP_ERR_INVALID_PARAM);
ret = OH_Ability_CreateNativeChildProcess("test.so", nullptr);
EXPECT_EQ(ret, NCP_ERR_INVALID_PARAM);
ret = OH_Ability_CreateNativeChildProcess("test.so", ChildProcessCapiTest::OnNativeChildProcessStarted);
if (!AAFwk::AppUtils::GetInstance().IsMultiProcessModel()) {
EXPECT_EQ(ret, NCP_ERR_MULTI_PROCESS_DISABLED);
return;
} else if (!AAFwk::AppUtils::GetInstance().IsSupportNativeChildProcess()) {
EXPECT_EQ(ret, NCP_ERR_NOT_SUPPORTED);
return;
}
GTEST_LOG_(INFO) << "OH_Ability_CreateNativeChildProcess return " << ret;
EXPECT_NE(ret, NCP_ERR_NOT_SUPPORTED);
}
} // namespace AbilityRuntime
} // namespace OHOS
@@ -45,6 +45,8 @@ void ChildProcessManagerTest::SetUpTestCase()
{
AAFwk::AppUtils::GetInstance().isMultiProcessModel_.isLoaded = true;
AAFwk::AppUtils::GetInstance().isMultiProcessModel_.value = true;
AAFwk::AppUtils::GetInstance().isSupportNativeChildProcess_.isLoaded = true;
AAFwk::AppUtils::GetInstance().isSupportNativeChildProcess_.value = true;
sptr<IRemoteObject> bundleMgrService = sptr<IRemoteObject>(new (std::nothrow) AppExecFwk::BundleMgrService());
sptr<IRemoteObject> mockAppMgrService = sptr<IRemoteObject>(new (std::nothrow) AppExecFwk::MockAppMgrService());
@@ -61,6 +63,8 @@ void ChildProcessManagerTest::TearDownTestCase()
{
AAFwk::AppUtils::GetInstance().isMultiProcessModel_.isLoaded = false;
AAFwk::AppUtils::GetInstance().isMultiProcessModel_.value = false;
AAFwk::AppUtils::GetInstance().isSupportNativeChildProcess_.isLoaded = false;
AAFwk::AppUtils::GetInstance().isSupportNativeChildProcess_.value = false;
}
void ChildProcessManagerTest::SetUp()
@@ -226,5 +230,19 @@ AbilityRuntime::Runtime::DebugOption debugOption;
ChildProcessManager::GetInstance().SetForkProcessDebugOption("test", false, false, false);
EXPECT_TRUE(true);
}
/**
* @tc.number: StartNativeChildProcessByAppSpawnFork_0100
* @tc.desc: Test StartNativeChildProcessByAppSpawnFork works.
* @tc.type: FUNC
*/
HWTEST_F(ChildProcessManagerTest, StartNativeChildProcessByAppSpawnFork_0100, TestSize.Level0)
{
TAG_LOGD(AAFwkTag::TEST, "StartNativeChildProcessByAppSpawnFork_0100 called.");
sptr<IRemoteObject> callback;
auto ret = ChildProcessManager::GetInstance().StartNativeChildProcessByAppSpawnFork("test.so", callback);
EXPECT_NE(ret, ChildProcessManagerErrorCode::ERR_FORK_FAILED);
}
} // namespace AbilityRuntime
} // namespace OHOS