mirror of
https://github.com/openharmony/ability_ability_runtime.git
synced 2026-08-24 22:21:36 -04:00
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/*",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user