From a054ffeac0a4aceeabf09c11fda04efeca9b6058 Mon Sep 17 00:00:00 2001 From: yangyang706 Date: Fri, 16 May 2025 15:34:02 +0800 Subject: [PATCH] add native child exit Signed-off-by: yangyang706 Change-Id: I3d58b2274d5ba92092c145fed54004fa09210f78 --- .../include/native_child_callback.h | 9 + .../src/native_child_callback.cpp | 46 ++++ .../src/native_child_process.cpp | 86 +++++- .../include/appmgr/app_mgr_client.h | 14 + .../include/appmgr/app_mgr_interface.h | 21 ++ .../appmgr/app_mgr_ipc_interface_code.h | 2 + .../include/appmgr/app_mgr_proxy.h | 14 + .../app_manager/include/appmgr/app_mgr_stub.h | 2 + .../appmgr/native_child_notify_interface.h | 21 +- .../appmgr/native_child_notify_proxy.h | 1 + .../include/appmgr/native_child_notify_stub.h | 1 + .../app_manager/src/appmgr/app_mgr_client.cpp | 18 ++ .../app_manager/src/appmgr/app_mgr_proxy.cpp | 44 +++ .../app_manager/src/appmgr/app_mgr_stub.cpp | 36 +++ .../src/appmgr/native_child_notify_proxy.cpp | 23 ++ .../src/appmgr/native_child_notify_stub.cpp | 11 + .../child_process/native_child_process.h | 44 +++ services/appmgr/BUILD.gn | 1 + services/appmgr/include/app_mgr_service.h | 14 + .../appmgr/include/app_mgr_service_inner.h | 5 + .../appmgr/include/app_native_spawn_manager.h | 97 +++++++ .../appmgr/include/child_process_record.h | 1 + services/appmgr/src/app_mgr_service.cpp | 20 ++ services/appmgr/src/app_mgr_service_inner.cpp | 18 ++ .../appmgr/src/app_native_spawn_manager.cpp | 258 ++++++++++++++++++ services/appmgr/src/app_running_manager.cpp | 10 + services/appmgr/src/child_process_record.cpp | 5 + ...acesappmgrnativechildnotifystub_fuzzer.cpp | 1 + .../appmgrservicefirst_fuzzer.cpp | 3 + .../appmgrstub_fuzzer/appmgrstub_fuzzer.cpp | 2 + .../include/mock_app_mgr_service.h | 2 + .../include/mock_app_mgr_service.h | 2 + test/unittest/BUILD.gn | 1 + .../ams_ability_running_record_test/BUILD.gn | 2 + .../unittest/ams_app_life_cycle_test/BUILD.gn | 2 + test/unittest/ams_app_workflow_test/BUILD.gn | 2 + .../ams_ipc_appmgr_interface_test.cpp | 58 ++++ .../ams_recent_app_list_test/BUILD.gn | 2 + .../BUILD.gn | 2 + .../ams_service_event_drive_test/BUILD.gn | 2 + .../BUILD.gn | 3 + .../ams_service_startup_test/BUILD.gn | 3 + .../app_mgr_client_test.cpp | 30 ++ .../BUILD.gn | 3 + .../BUILD.gn | 2 + .../BUILD.gn | 2 + .../app_mgr_service_inner_test.cpp | 38 +++ .../app_mgr_service_test.cpp | 34 +++ .../app_mgr_stub_test/app_mgr_stub_test.cpp | 43 +++ .../app_native_spawn_manager_test/BUILD.gn | 90 ++++++ .../app_native_spawn_manager_test.cpp | 141 ++++++++++ .../BUILD.gn | 2 + .../child_process_capi_test.cpp | 37 +++ 53 files changed, 1324 insertions(+), 7 deletions(-) create mode 100644 services/appmgr/include/app_native_spawn_manager.h create mode 100644 services/appmgr/src/app_native_spawn_manager.cpp create mode 100644 test/unittest/app_native_spawn_manager_test/BUILD.gn create mode 100644 test/unittest/app_native_spawn_manager_test/app_native_spawn_manager_test.cpp diff --git a/frameworks/native/child_process/include/native_child_callback.h b/frameworks/native/child_process/include/native_child_callback.h index f4f3bbed56..128ef026e5 100644 --- a/frameworks/native/child_process/include/native_child_callback.h +++ b/frameworks/native/child_process/include/native_child_callback.h @@ -19,6 +19,7 @@ #include "native_child_notify_stub.h" #include "native_child_process.h" #include "child_callback_manager.h" +#include namespace OHOS { namespace AbilityRuntime { @@ -30,9 +31,17 @@ public: void OnNativeChildStarted(const sptr &nativeChild) override; void OnError(int32_t errCode) override; + int32_t OnNativeChildExit(int32_t pid, int32_t signal) override; + + bool IsCallbacksEmpty(); + void AddExitCallback(OH_Ability_OnNativeChildProcessExit callback); + int32_t RemoveExitCallback(OH_Ability_OnNativeChildProcessExit callback); + std::list GetExitCallbacks(); private: OH_Ability_OnNativeChildProcessStarted callback_ = nullptr; + std::mutex exitCallbackListMutex_; + std::list exitCallbacks_; }; } // namespace AbilityRuntime diff --git a/frameworks/native/child_process/src/native_child_callback.cpp b/frameworks/native/child_process/src/native_child_callback.cpp index 663f7cb440..86e4516434 100644 --- a/frameworks/native/child_process/src/native_child_callback.cpp +++ b/frameworks/native/child_process/src/native_child_callback.cpp @@ -67,5 +67,51 @@ void NativeChildCallback::OnError(int32_t errCode) ChildCallbackManager::GetInstance().RemoveRemoteObject(this); } +int32_t NativeChildCallback::OnNativeChildExit(int32_t pid, int32_t signal) +{ + auto exitCallbacks = GetExitCallbacks(); + for (const auto &exitCallback : exitCallbacks) { + TAG_LOGI(AAFwkTag::PROCESSMGR, + "native child process exit, pid:%{public}d, signal:%{public}d", pid, signal); + exitCallback(pid, signal); + } + return NCP_NO_ERROR; +} + +void NativeChildCallback::AddExitCallback(OH_Ability_OnNativeChildProcessExit callback) +{ + std::lock_guard lock(exitCallbackListMutex_); + for (const auto &cb : exitCallbacks_) { + if (cb == callback) { + TAG_LOGI(AAFwkTag::PROCESSMGR, "repeated add exit callback"); + return; + } + } + exitCallbacks_.emplace_back(callback); +} + +int32_t NativeChildCallback::RemoveExitCallback(OH_Ability_OnNativeChildProcessExit callback) +{ + std::lock_guard lock(exitCallbackListMutex_); + auto it = std::find(exitCallbacks_.begin(), exitCallbacks_.end(), callback); + if (it == exitCallbacks_.end()) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "native child exit callback not exist"); + return NCP_ERR_CALLBACK_NOT_EXIST; + } + exitCallbacks_.erase(it); + return NCP_NO_ERROR; +} + +bool NativeChildCallback::IsCallbacksEmpty() +{ + std::lock_guard lock(exitCallbackListMutex_); + return exitCallbacks_.empty(); +} + +std::list NativeChildCallback::GetExitCallbacks() +{ + std::lock_guard lock(exitCallbackListMutex_); + return exitCallbacks_; +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/child_process/src/native_child_process.cpp b/frameworks/native/child_process/src/native_child_process.cpp index 6e31c5b054..3f731c729a 100644 --- a/frameworks/native/child_process/src/native_child_process.cpp +++ b/frameworks/native/child_process/src/native_child_process.cpp @@ -16,6 +16,7 @@ #include "native_child_process.h" #include #include +#include "app_mgr_client.h" #include "hilog_tag_wrapper.h" #include "native_child_callback.h" #include "child_process_args_manager.h" @@ -27,11 +28,11 @@ using namespace OHOS; using namespace OHOS::AbilityRuntime; namespace { - -std::mutex g_mutexCallBackObj; constexpr size_t MAX_KEY_SIZE = 20; constexpr size_t MAX_FD_SIZE = 16; - +std::mutex g_callbackStubMutex; +std::mutex g_callbackSerialMutex; +sptr g_callbackStub = nullptr; } // Anonymous namespace int OH_Ability_CreateNativeChildProcess(const char* libName, OH_Ability_OnNativeChildProcessStarted onProcessStarted) @@ -124,4 +125,81 @@ NativeChildProcess_Args* OH_Ability_GetCurrentChildProcessArgs() TAG_LOGE(AAFwkTag::PROCESSMGR, "GetChildProcessArgs null"); } return result; -} \ No newline at end of file +} + +sptr GetGlobalNativeChildCallbackStub() +{ + std::lock_guard lock(g_callbackStubMutex); + return g_callbackStub; +} + +void SetGlobalNativeChildCallbackStub(sptr local) +{ + std::lock_guard lock(g_callbackStubMutex); + g_callbackStub = local; +} + +Ability_NativeChildProcess_ErrCode OH_Ability_RegisterNativeChildProcessExitCallback( + OH_Ability_OnNativeChildProcessExit onProcessExit) +{ + if (onProcessExit == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "null callback func pointer"); + return NCP_ERR_INVALID_PARAM; + } + + std::lock_guard lock(g_callbackSerialMutex); + auto localCallbackStub = GetGlobalNativeChildCallbackStub(); + if (localCallbackStub != nullptr) { + localCallbackStub->AddExitCallback(onProcessExit); + return NCP_NO_ERROR; + } + + localCallbackStub = sptr::MakeSptr(nullptr); + if (!localCallbackStub) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "null callbackStub"); + return NCP_ERR_INTERNAL; + } + SetGlobalNativeChildCallbackStub(localCallbackStub); + localCallbackStub->AddExitCallback(onProcessExit); + auto ret = DelayedSingleton::GetInstance()->RegisterNativeChildExitNotify( + localCallbackStub); + if (ret != NCP_NO_ERROR) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "register native child exit notify failed, %{public}d", ret); + SetGlobalNativeChildCallbackStub(nullptr); + return NCP_ERR_INTERNAL; + } + + return NCP_NO_ERROR; +} + +Ability_NativeChildProcess_ErrCode OH_Ability_UnregisterNativeChildProcessExitCallback( + OH_Ability_OnNativeChildProcessExit onProcessExit) +{ + if (onProcessExit == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "null callback func pointer"); + return NCP_ERR_INVALID_PARAM; + } + + std::lock_guard lock(g_callbackSerialMutex); + sptr localCallbackStub = GetGlobalNativeChildCallbackStub(); + if (localCallbackStub == nullptr) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "null callbackStub"); + return NCP_ERR_CALLBACK_NOT_EXIST; + } + + auto ret = localCallbackStub->RemoveExitCallback(onProcessExit); + if (ret == NCP_ERR_CALLBACK_NOT_EXIST) { + return static_cast(ret); + } + if (localCallbackStub->IsCallbacksEmpty()) { + auto ret = DelayedSingleton::GetInstance()->UnregisterNativeChildExitNotify( + localCallbackStub); + if (ret != NCP_NO_ERROR) { + TAG_LOGE(AAFwkTag::PROCESSMGR, "unregister native child exit notify failed, %{public}d", ret); + return NCP_ERR_INTERNAL; + } + SetGlobalNativeChildCallbackStub(nullptr); + } + + return NCP_NO_ERROR; +} diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_client.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_client.h index f376220b4e..64107d3c7e 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_client.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_client.h @@ -732,6 +732,20 @@ public: */ int32_t UnregisterApplicationStateObserver(const sptr &observer); + /** + * Register native child exit notify. + * @param notify, callback to notify. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t RegisterNativeChildExitNotify(sptr notify); + + /** + * Unregister native child exit notify. + * @param notify, callback to notify. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t UnregisterNativeChildExitNotify(sptr notify); + /** * @brief Notify AbilityManagerService the page show. * @param token Ability identify. diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h index f3b3919223..0fdeafecc0 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_interface.h @@ -48,6 +48,7 @@ #include "want.h" #include "app_jsheap_mem_info.h" #include "running_multi_info.h" +#include "native_child_notify_interface.h" namespace OHOS { namespace AppExecFwk { @@ -874,6 +875,26 @@ public: const sptr &callback) = 0; #endif // SUPPORT_CHILD_PROCESS + /** + * Register native child exit callback to notify. + * @param notify, Callback used to notify caller the info of native child exit. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t RegisterNativeChildExitNotify(const sptr notify) + { + return 0; + } + + /** + * Unregister native child exit callback to notify. + * @param notify, Callback used to notify caller the info of native child exit. + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t UnregisterNativeChildExitNotify(const sptr notify) + { + return 0; + } + /** * Notify that the process depends on web by itself. */ diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h index e47aec3892..e2cbf0decf 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_ipc_interface_code.h @@ -128,6 +128,8 @@ enum class AppMgrInterfaceCode { LAUNCH_ABILITY = 102, IS_PROCESS_CACHE_SUPPORTED = 103, SET_PROCESS_CACHE_ENABLE = 104, + REGISTER_NATIVE_CHILD_EXIT_NOTIFY = 105, + UNREGISTER_NATIVE_CHILD_EXIT_NOTIFY = 106, }; } // AppExecFwk } // OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h index 216eb28f18..3cca8c6082 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_proxy.h @@ -628,6 +628,20 @@ public: void ExitChildProcessSafely() override; #endif // SUPPORT_CHILD_PROCESS + /** + * Register native child exit callback to notify. + * @param notify, Callback used to notify caller the info of native child exit. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t RegisterNativeChildExitNotify(const sptr notify) override; + + /** + * Unregister native child exit callback to notify. + * @param notify, Callback used to notify caller the info of native child exit. + * @return Returns ERR_OK on success, others on failure. + */ + int32_t UnregisterNativeChildExitNotify(const sptr notify) override; + /** * Whether the current application process is the last surviving process. * diff --git a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h index ad229314ad..4bf481c7bb 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h +++ b/interfaces/inner_api/app_manager/include/appmgr/app_mgr_stub.h @@ -81,6 +81,8 @@ private: #ifdef SUPPORT_CHILD_PROCESS int32_t HandleGetAllChildrenProcesses(MessageParcel &data, MessageParcel &reply); #endif // SUPPORT_CHILD_PROCESS + int32_t HandleRegisterNativeChildExitNotify(MessageParcel &data, MessageParcel &reply); + int32_t HandleUnregisterNativeChildExitNotify(MessageParcel &data, MessageParcel &reply); int32_t HandleAddAbilityStageDone(MessageParcel &data, MessageParcel &reply); int32_t HandleNotifyMemoryLevel(MessageParcel &data, MessageParcel &reply); int32_t HandleNotifyProcMemoryLevel(MessageParcel &data, MessageParcel &reply); diff --git a/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_interface.h b/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_interface.h index b901b6c107..3eba849f17 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_interface.h +++ b/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_interface.h @@ -39,9 +39,24 @@ public: */ 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; + /** + * Notify native child process exit. + * + * @param pid child process pid + * @param signal child process exit signal + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t OnNativeChildExit(int32_t pid, int32_t signal) = 0; + + enum { + // ipc id for OnNativeChildStarted + IPC_ID_ON_NATIVE_CHILD_STARTED = 0, + + // ipc id for OnError + IPC_ID_ON_ERROR = 1, + + IPC_ID_ON_NATIVE_CHILD_EXIT = 2 + }; }; } // OHOS diff --git a/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_proxy.h b/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_proxy.h index fabd51a855..d843439fb1 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_proxy.h +++ b/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_proxy.h @@ -29,6 +29,7 @@ public: void OnNativeChildStarted(const sptr &nativeChild) override; void OnError(int32_t errCode) override; + int32_t OnNativeChildExit(int32_t pid, int32_t signal) override; private: bool WriteInterfaceToken(MessageParcel &data); diff --git a/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_stub.h b/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_stub.h index a77580f3a0..e81ad08281 100644 --- a/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_stub.h +++ b/interfaces/inner_api/app_manager/include/appmgr/native_child_notify_stub.h @@ -33,6 +33,7 @@ public: private: int32_t HandleOnNativeChildStarted(MessageParcel &data, MessageParcel &reply); int32_t HandleOnError(MessageParcel &data, MessageParcel &reply); + int32_t HandleOnNativeChildExit(MessageParcel &data, MessageParcel &reply); }; } // OHOS diff --git a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_client.cpp b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_client.cpp index 5ab69f2061..1f6b5e71dd 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_client.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_client.cpp @@ -1175,6 +1175,24 @@ int32_t AppMgrClient::UnregisterApplicationStateObserver(const sptrUnregisterApplicationStateObserver(observer); } +int32_t AppMgrClient::RegisterNativeChildExitNotify(sptr notify) +{ + sptr service = iface_cast(mgrHolder_->GetRemoteObject()); + if (service == nullptr) { + return AppMgrResultCode::ERROR_SERVICE_NOT_CONNECTED; + } + return service->RegisterNativeChildExitNotify(notify); +} + +int32_t AppMgrClient::UnregisterNativeChildExitNotify(sptr notify) +{ + sptr service = iface_cast(mgrHolder_->GetRemoteObject()); + if (service == nullptr) { + return AppMgrResultCode::ERROR_SERVICE_NOT_CONNECTED; + } + return service->UnregisterNativeChildExitNotify(notify); +} + int32_t AppMgrClient::NotifyPageShow(const sptr &token, const PageStateData &pageStateData) { sptr service = iface_cast(mgrHolder_->GetRemoteObject()); diff --git a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp index f7d82ebde5..8de3b0b5c2 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_proxy.cpp @@ -2057,6 +2057,50 @@ int32_t AppMgrProxy::StartNativeChildProcess(const std::string &libName, int32_t } #endif // SUPPORT_CHILD_PROCESS +int AppMgrProxy::RegisterNativeChildExitNotify(const sptr notify) +{ + if (!notify) { + TAG_LOGE(AAFwkTag::APPMGR, "notify null"); + return ERR_INVALID_VALUE; + } + TAG_LOGD(AAFwkTag::APPMGR, "RegisterNativeChildExitNotify start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return ERR_FLATTEN_OBJECT; + } + if (!data.WriteRemoteObject(notify->AsObject())) { + TAG_LOGE(AAFwkTag::APPMGR, "notify write failed."); + return ERR_FLATTEN_OBJECT; + } + + PARCEL_UTIL_SENDREQ_RET_INT(AppMgrInterfaceCode::REGISTER_NATIVE_CHILD_EXIT_NOTIFY, data, reply, option); + return reply.ReadInt32(); +} + +int AppMgrProxy::UnregisterNativeChildExitNotify(const sptr notify) +{ + if (!notify) { + TAG_LOGE(AAFwkTag::APPMGR, "notify null"); + return ERR_INVALID_VALUE; + } + TAG_LOGD(AAFwkTag::APPMGR, "UnregisterNativeChildExitNotify start"); + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!WriteInterfaceToken(data)) { + return ERR_FLATTEN_OBJECT; + } + if (!data.WriteRemoteObject(notify->AsObject())) { + TAG_LOGE(AAFwkTag::APPMGR, "notify write failed."); + return ERR_FLATTEN_OBJECT; + } + + PARCEL_UTIL_SENDREQ_RET_INT(AppMgrInterfaceCode::UNREGISTER_NATIVE_CHILD_EXIT_NOTIFY, data, reply, option); + return reply.ReadInt32(); +} + int32_t AppMgrProxy::CheckCallingIsUserTestMode(const pid_t pid, bool &isUserTest) { MessageParcel data; diff --git a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp index bcba893320..b0fd4f5a79 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/app_mgr_stub.cpp @@ -278,6 +278,10 @@ int32_t AppMgrStub::OnRemoteRequestInnerFifth(uint32_t code, MessageParcel &data case static_cast(AppMgrInterfaceCode::START_CHILD_PROCESS): return HandleStartChildProcess(data, reply); #endif // SUPPORT_CHILD_PROCESS + case static_cast(AppMgrInterfaceCode::REGISTER_NATIVE_CHILD_EXIT_NOTIFY): + return HandleRegisterNativeChildExitNotify(data, reply); + case static_cast(AppMgrInterfaceCode::UNREGISTER_NATIVE_CHILD_EXIT_NOTIFY): + return HandleUnregisterNativeChildExitNotify(data, reply); } return INVALID_FD; } @@ -1507,6 +1511,38 @@ int32_t AppMgrStub::HandleExitChildProcessSafely(MessageParcel &data, MessagePar } #endif // SUPPORT_CHILD_PROCESS +int32_t AppMgrStub::HandleRegisterNativeChildExitNotify(MessageParcel &data, MessageParcel &reply) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + auto callback = iface_cast(data.ReadRemoteObject()); + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "Callback is null."); + return ERR_INVALID_VALUE; + } + int32_t result = RegisterNativeChildExitNotify(callback); + if (!reply.WriteInt32(result)) { + TAG_LOGE(AAFwkTag::APPMGR, "Fail to write result."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + +int32_t AppMgrStub::HandleUnregisterNativeChildExitNotify(MessageParcel &data, MessageParcel &reply) +{ + TAG_LOGD(AAFwkTag::APPMGR, "called"); + auto callback = iface_cast(data.ReadRemoteObject()); + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "Callback is null."); + return ERR_INVALID_VALUE; + } + int32_t result = UnregisterNativeChildExitNotify(callback); + if (!reply.WriteInt32(result)) { + TAG_LOGE(AAFwkTag::APPMGR, "Fail to write result."); + return ERR_INVALID_VALUE; + } + return NO_ERROR; +} + int32_t AppMgrStub::HandleIsFinalAppProcess(MessageParcel &data, MessageParcel &reply) { TAG_LOGD(AAFwkTag::APPMGR, "called"); diff --git a/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_proxy.cpp b/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_proxy.cpp index 0bfd0770ee..533799eaa6 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_proxy.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_proxy.cpp @@ -89,5 +89,28 @@ void NativeChildNotifyProxy::OnError(int32_t errCode) SendRequest(INativeChildNotify::IPC_ID_ON_ERROR, data, reply, option); } +int32_t NativeChildNotifyProxy::OnNativeChildExit(int32_t pid, int32_t signal) +{ + TAG_LOGD(AAFwkTag::APPMGR, "NativeChildNotifyProxy OnNativeChildExit"); + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!WriteInterfaceToken(data)) { + return ERR_NULL_OBJECT; + } + + if (!data.WriteInt32(pid)) { + TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy write native child pid failed."); + return ERR_NULL_OBJECT; + } + + if (!data.WriteInt32(signal)) { + TAG_LOGE(AAFwkTag::APPMGR, "NativeChildNotifyProxy write native child signal failed."); + return ERR_NULL_OBJECT; + } + + return SendRequest(INativeChildNotify::IPC_ID_ON_NATIVE_CHILD_EXIT, data, reply, option); +} + } // OHOS } // AppExecFwk \ No newline at end of file diff --git a/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_stub.cpp b/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_stub.cpp index 87f5336068..7d1e492515 100644 --- a/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_stub.cpp +++ b/interfaces/inner_api/app_manager/src/appmgr/native_child_notify_stub.cpp @@ -38,6 +38,10 @@ int NativeChildNotifyStub::OnRemoteRequest(uint32_t code, MessageParcel &data, ret = HandleOnNativeChildStarted(data, reply); break; + case INativeChildNotify::IPC_ID_ON_NATIVE_CHILD_EXIT: + ret = HandleOnNativeChildExit(data, reply); + break; + case INativeChildNotify::IPC_ID_ON_ERROR: ret = HandleOnError(data, reply); break; @@ -59,6 +63,13 @@ int32_t NativeChildNotifyStub::HandleOnNativeChildStarted(MessageParcel &data, M return ERR_NONE; } +int32_t NativeChildNotifyStub::HandleOnNativeChildExit(MessageParcel &data, MessageParcel &reply) +{ + int pid = data.ReadInt32(); + int signal = data.ReadInt32(); + return OnNativeChildExit(pid, signal); +} + int32_t NativeChildNotifyStub::HandleOnError(MessageParcel &data, MessageParcel &reply) { int32_t err = data.ReadInt32(); diff --git a/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h b/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h index 66b2dd33a9..3a25cc7a45 100644 --- a/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h +++ b/interfaces/kits/c/ability/ability_runtime/child_process/native_child_process.h @@ -111,6 +111,11 @@ typedef enum Ability_NativeChildProcess_ErrCode { * An invalid IPC object pointer may be returned. */ NCP_ERR_CONNECTION_FAILED = 16010008, + + /** + * @error The callback does not exist; it may not have been registered or has already been unregistered. + */ + NCP_ERR_CALLBACK_NOT_EXIST = 16010009, } Ability_NativeChildProcess_ErrCode; @@ -288,6 +293,45 @@ Ability_NativeChildProcess_ErrCode OH_Ability_StartNativeChildProcess( */ NativeChildProcess_Args* OH_Ability_GetCurrentChildProcessArgs(); +/** + * @brief Define a callback function to handle the exit of a native child process. + * + * @param pid The pid of the exited native child process. + * @param signal The signal of the exited native child process. + * @since 20 + */ +typedef void (*OH_Ability_OnNativeChildProcessExit)(int32_t pid, int32_t signal); + +/** + * @brief Register a native child process exit callback. + * Registering the same callback repeatedly will only keep one. + * + * @param onProcessExit Pointer to the callback function to handle the exit of a native child process. + * For details, see {@link OH_Ability_OnNativeChildProcessExit}. + * @return Returns {@link NCP_NO_ERROR} if the call is successful. + * Returns {@link NCP_ERR_INVALID_PARAM} if the param is invalid. + * Returns {@link NCP_ERR_INTERNAL} if internal error occurs. + * For details, see {@link Ability_NativeChildProcess_ErrCode}. + * @since 20 + */ +Ability_NativeChildProcess_ErrCode OH_Ability_RegisterNativeChildProcessExitCallback( + OH_Ability_OnNativeChildProcessExit onProcessExit); + +/** + * @brief Unregister a native child process exit callback. + * + * @param onProcessExit Pointer to the callback function to handle the exit of a native child process. + * For details, see {@link OH_Ability_OnNativeChildProcessExit}. + * @return Returns {@link NCP_NO_ERROR} if the call is successful. + * Returns {@link NCP_ERR_INVALID_PARAM} if the param is invalid. + * Returns {@link NCP_ERR_INTERNAL} if internal error occurs. + * Returns {@link NCP_ERR_CALLBACK_NOT_EXIST} if the callback is not exist. + * For details, see {@link Ability_NativeChildProcess_ErrCode}. + * @since 20 + */ +Ability_NativeChildProcess_ErrCode OH_Ability_UnregisterNativeChildProcessExitCallback( + OH_Ability_OnNativeChildProcessExit onProcessExit); + #ifdef __cplusplus } // extern "C" #endif diff --git a/services/appmgr/BUILD.gn b/services/appmgr/BUILD.gn index 4581818329..ade83eb7a0 100644 --- a/services/appmgr/BUILD.gn +++ b/services/appmgr/BUILD.gn @@ -54,6 +54,7 @@ ohos_shared_library("libappms") { "src/app_mgr_event.cpp", "src/app_mgr_service.cpp", "src/app_mgr_service_event_handler.cpp", + "src/app_native_spawn_manager.cpp", "src/app_mgr_service_inner.cpp", "src/app_preloader.cpp", "src/app_running_manager.cpp", diff --git a/services/appmgr/include/app_mgr_service.h b/services/appmgr/include/app_mgr_service.h index 7364bd7287..5e3564b0fe 100644 --- a/services/appmgr/include/app_mgr_service.h +++ b/services/appmgr/include/app_mgr_service.h @@ -788,6 +788,20 @@ public: const sptr &callback) override; #endif // SUPPORT_CHILD_PROCESS + /** + * Register callback to notify native child exit. + * @param notify, callback to notify + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t RegisterNativeChildExitNotify(const sptr notify) override; + + /** + * Unregister callback to notify native child exit. + * @param notify, callback to notify + * @return Returns ERR_OK on success, others on failure. + */ + virtual int32_t UnregisterNativeChildExitNotify(const sptr notify) override; + /** * Notify that the process depends on web by itself. */ diff --git a/services/appmgr/include/app_mgr_service_inner.h b/services/appmgr/include/app_mgr_service_inner.h index 12b4417ff2..c002d7ab38 100644 --- a/services/appmgr/include/app_mgr_service_inner.h +++ b/services/appmgr/include/app_mgr_service_inner.h @@ -79,6 +79,7 @@ #include "running_multi_info.h" #include "multi_user_config_mgr.h" #include "user_callback.h" +#include "native_child_notify_interface.h" namespace OHOS { namespace AbilityRuntime { @@ -1258,6 +1259,10 @@ public: const std::string &libName, int32_t childProcessCount, const sptr &callback); #endif // SUPPORT_CHILD_PROCESS + virtual int32_t RegisterNativeChildExitNotify(const sptr &callback); + + virtual int32_t UnregisterNativeChildExitNotify(const sptr &callback); + /** * To clear the process by ability token. * diff --git a/services/appmgr/include/app_native_spawn_manager.h b/services/appmgr/include/app_native_spawn_manager.h new file mode 100644 index 0000000000..31f4a2793c --- /dev/null +++ b/services/appmgr/include/app_native_spawn_manager.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_APP_NATIVE_SPAWN_MANAGER_H +#define OHOS_APP_NATIVE_SPAWN_MANAGER_H + +#include +#include +#include "nocopyable.h" +#include "app_running_manager.h" +#include "native_child_notify_interface.h" + +namespace OHOS { +namespace AppExecFwk { + +/** + * @class AppNativeSpawnManager + * provides native spawn exit. + */ +class AppNativeSpawnManager { +public: + /** + * GetInstance, get an instance of AppNativeSpawnManager. + * + * @return An instance of AppNativeSpawnManager. + */ + static AppNativeSpawnManager &GetInstance(); + + /** + * AppNativeSpawnManager, destructor. + * + */ + ~AppNativeSpawnManager(); + + int32_t RegisterNativeChildExitNotify(const sptr &callback); + + int32_t UnregisterNativeChildExitNotify(const sptr &callback); + + // pid is parent pid + sptr GetNativeChildCallbackByPid(int32_t pid); + + // pid is parent pid + void RemoveNativeChildCallbackByPid(int32_t pid); + + void InitNativeSpawnMsgPipe(std::shared_ptr appRunningManager); + + int GetNRfd() const + { + return nrFd_; + } + + int GetNWfd() const + { + return nwFd_; + } + + void NotifyChildProcessExitTask(int32_t pid, int32_t signal, const std::string &bundleName); + + int32_t GetChildRelation(int32_t childPid); + + void AddChildRelation(int32_t childPid, int32_t parentPid); + + void RemoveChildRelation(int32_t childPid); +private: + /** + * AppUtils, private constructor. + * + */ + AppNativeSpawnManager(); + + //native spawn use + int nrFd_ = -1; + int nwFd_ = -1; + std::mutex nativeChildCallbackLock_; + std::map> nativeChildCallbackMap_; + + // child pid -> parent pid + std::mutex childRelationLock_; + std::map childRelationMap_; + std::shared_ptr appRunningManager_ = nullptr; + DISALLOW_COPY_AND_MOVE(AppNativeSpawnManager); +}; +} +} +#endif // OHOS_APP_NATIVE_SPAWN_MANAGER_H \ No newline at end of file diff --git a/services/appmgr/include/child_process_record.h b/services/appmgr/include/child_process_record.h index 9c35d37006..a36cb57f23 100644 --- a/services/appmgr/include/child_process_record.h +++ b/services/appmgr/include/child_process_record.h @@ -66,6 +66,7 @@ public: void SetEntryParams(const std::string &entryParams); std::string GetEntryParams() const; ProcessType GetProcessType() const; + bool IsNativeSpawnStarted() const; private: void MakeProcessName(const std::shared_ptr hostRecord); diff --git a/services/appmgr/src/app_mgr_service.cpp b/services/appmgr/src/app_mgr_service.cpp index 54b9fb931a..04b93ee3fe 100644 --- a/services/appmgr/src/app_mgr_service.cpp +++ b/services/appmgr/src/app_mgr_service.cpp @@ -601,6 +601,26 @@ int32_t AppMgrService::UnregisterApplicationStateObserver(const sptrUnregisterApplicationStateObserver(observer); } +int32_t AppMgrService::RegisterNativeChildExitNotify(const sptr notify) +{ + TAG_LOGD(AAFwkTag::APPMGR, "begin"); + if (!IsReady()) { + TAG_LOGE(AAFwkTag::APPMGR, "not ready"); + return ERR_INVALID_OPERATION; + } + return appMgrServiceInner_->RegisterNativeChildExitNotify(notify); +} + +int32_t AppMgrService::UnregisterNativeChildExitNotify(const sptr notify) +{ + TAG_LOGD(AAFwkTag::APPMGR, "begin"); + if (!IsReady()) { + TAG_LOGE(AAFwkTag::APPMGR, "not ready"); + return ERR_INVALID_OPERATION; + } + return appMgrServiceInner_->UnregisterNativeChildExitNotify(notify); +} + int32_t AppMgrService::RegisterAbilityForegroundStateObserver(const sptr &observer) { HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__); diff --git a/services/appmgr/src/app_mgr_service_inner.cpp b/services/appmgr/src/app_mgr_service_inner.cpp index 94dd8008ae..e805217b16 100644 --- a/services/appmgr/src/app_mgr_service_inner.cpp +++ b/services/appmgr/src/app_mgr_service_inner.cpp @@ -58,6 +58,7 @@ #include "killing_process_manager.h" #include "last_exit_detail_info.h" #include "os_account_manager.h" +#include "app_native_spawn_manager.h" #ifdef SUPPORT_SCREEN #include "locale_config.h" #endif @@ -295,6 +296,10 @@ constexpr int32_t NWEB_PRELOAD_DELAY = 3000; constexpr const char* APP_INSTANCE_KEY_0 = "app_instance_0"; +//listen fd use +constexpr int32_t PIPE_MSG_READ_BUFFER = 1024; +constexpr const char* NATIVESPAWN_STARTED = "startup.service.ctl.nativespawn.pid"; + // Max child process number limitation for pc device. constexpr int32_t PC_MAX_CHILD_PROCESS_NUM = 50; constexpr int32_t USER100 = 100; @@ -427,6 +432,7 @@ void AppMgrServiceInner::Init() otherTaskHandler_->SubmitTask([pThis = shared_from_this()]() { pThis->nwebPreloadSet_ = AAFwk::ResSchedUtil::GetInstance().GetNWebPreloadSet(); }, NWEB_PRELOAD_DELAY); + AppNativeSpawnManager::GetInstance().InitNativeSpawnMsgPipe(appRunningManager_); } AppMgrServiceInner::~AppMgrServiceInner() @@ -9076,6 +9082,18 @@ int32_t AppMgrServiceInner::StartNativeChildProcess(const pid_t hostPid, const s } #endif // SUPPORT_CHILD_PROCESS +int32_t AppMgrServiceInner::RegisterNativeChildExitNotify(const sptr &callback) +{ + HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); + return AppNativeSpawnManager::GetInstance().RegisterNativeChildExitNotify(callback); +} + +int32_t AppMgrServiceInner::UnregisterNativeChildExitNotify(const sptr &callback) +{ + HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); + return AppNativeSpawnManager::GetInstance().UnregisterNativeChildExitNotify(callback); +} + void AppMgrServiceInner::CacheLoadAbilityTask(const LoadAbilityTaskFunc&& func) { std::lock_guard lock(loadTaskListMutex_); diff --git a/services/appmgr/src/app_native_spawn_manager.cpp b/services/appmgr/src/app_native_spawn_manager.cpp new file mode 100644 index 0000000000..aafb5b1018 --- /dev/null +++ b/services/appmgr/src/app_native_spawn_manager.cpp @@ -0,0 +1,258 @@ +/* + * 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 "app_native_spawn_manager.h" + +#include +#include + +#include "ability_manager_errors.h" +#include "appspawn.h" +#include "c/executor_task.h" +#include "ffrt.h" +#include "ffrt_inner.h" +#include "hilog_tag_wrapper.h" +#include "ipc_skeleton.h" +#include "syspara/parameter.h" + +namespace OHOS { +namespace AppExecFwk { + +namespace { +//listen fd use +constexpr int32_t PIPE_MSG_READ_BUFFER = 1024; +constexpr const char* NATIVESPAWN_STARTED = "startup.service.ctl.nativespawn.pid"; +} + +AppNativeSpawnManager::~AppNativeSpawnManager() {} + +AppNativeSpawnManager::AppNativeSpawnManager() {} + +AppNativeSpawnManager &AppNativeSpawnManager::GetInstance() +{ + static AppNativeSpawnManager manager; + return manager; +} + +int32_t AppNativeSpawnManager::RegisterNativeChildExitNotify(const sptr &callback) +{ + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "register null callback"); + return ERR_INVALID_VALUE; + } + int32_t callingPid = IPCSkeleton::GetCallingPid(); + auto appRecord = appRunningManager_->GetAppRunningRecordByPid(callingPid); + if (!appRecord) { + TAG_LOGE(AAFwkTag::APPMGR, "no appRecord, parentPid:%{public}d", callingPid); + return OHOS::AAFwk::ERR_CALLER_NOT_EXISTS; + } + std::lock_guard lock(nativeChildCallbackLock_); + if (nativeChildCallbackMap_.find(callingPid) != nativeChildCallbackMap_.end()) { + TAG_LOGE(AAFwkTag::APPMGR, "register native child exit:%{public}d fail", callingPid); + return OHOS::AAFwk::ERR_INVALID_CALLER; + } + nativeChildCallbackMap_[callingPid] = callback; + TAG_LOGI(AAFwkTag::APPMGR, "register native child exit:%{public}d success", callingPid); + return ERR_OK; +} + +int32_t AppNativeSpawnManager::UnregisterNativeChildExitNotify(const sptr &callback) +{ + if (callback == nullptr) { + TAG_LOGE(AAFwkTag::APPMGR, "unregister null callback"); + return ERR_INVALID_VALUE; + } + int32_t callingPid = IPCSkeleton::GetCallingPid(); + std::lock_guard lock(nativeChildCallbackLock_); + auto iter = nativeChildCallbackMap_.find(callingPid); + if (iter == nativeChildCallbackMap_.end()) { + TAG_LOGE(AAFwkTag::APPMGR, "unregister callback not exist:%{public}d", callingPid); + return OHOS::AAFwk::ERR_INVALID_CALLER; + } + if (iter->second == nullptr || iter->second->AsObject() != callback->AsObject()) { + TAG_LOGE(AAFwkTag::APPMGR, "unregister callback not same:%{public}d", callingPid); + return OHOS::AAFwk::ERR_INVALID_CALLER; + } + + nativeChildCallbackMap_.erase(callingPid); + TAG_LOGI(AAFwkTag::APPMGR, "unregister native child exit:%{public}d success", callingPid); + return ERR_OK; +} + +static void AppNativeSpawnStartCallback(const char *key, const char *value, void *context) +{ + int nrFd = AppNativeSpawnManager::GetInstance().GetNRfd(); + int nwFd = AppNativeSpawnManager::GetInstance().GetNWfd(); + TAG_LOGI(AAFwkTag::APPMGR, "nrFd is: %{public}d, nwFd is: %{public}d", nrFd, nwFd); + // send fd + int ret = NativeSpawnListenFdSet(nwFd); + if (ret != 0) { + TAG_LOGE(AAFwkTag::APPMGR, "send fd to native spawn failed, ret: %{public}d", ret); + close(nrFd); + close(nwFd); + return; + } + // set flag + ret = NativeSpawnListenCloseSet(); + if (ret != 0) { + TAG_LOGI(AAFwkTag::APPMGR, "NativeSpawnListenCloseSet failed"); + } +} + +void AppNativeSpawnManager::NotifyChildProcessExitTask(int32_t pid, int32_t signal, const std::string &bundleName) +{ + if (!appRunningManager_) { + TAG_LOGE(AAFwkTag::APPMGR, "get appRunningManager fail"); + return; + } + + int32_t parentPid = 0; + auto appRecord = appRunningManager_->GetAppRunningRecordByChildProcessPid(pid); + if (!appRecord) { + parentPid = GetChildRelation(pid); + if (parentPid <= 0) { + TAG_LOGE(AAFwkTag::APPMGR, "not find parent, childPid:%{public}d", pid); + return; + } + RemoveChildRelation(pid); + } else { + parentPid = appRecord->GetPid(); + } + + auto nativeChildCallbacks = GetNativeChildCallbackByPid(parentPid); + if (!nativeChildCallbacks) { + TAG_LOGW(AAFwkTag::APPMGR, "not found native child process callback"); + return; + } + auto ret = nativeChildCallbacks->OnNativeChildExit(pid, signal); + if (ret != ERR_OK) { + TAG_LOGE(AAFwkTag::APPMGR, "OnNativeChildExit failed, pid: %{public}d", pid); + } +} + +static void ProcessSignalData(void *token, uint32_t event) +{ + int rFd = AppNativeSpawnManager::GetInstance().GetNRfd(); + if (rFd <= 0) { + TAG_LOGE(AAFwkTag::APPMGR, "rFd is invalid, %{public}d", rFd); + return; + } + + // read data from nativespawn + char buffer[PIPE_MSG_READ_BUFFER] = {0}; + std::string readResult = ""; + int count = read(rFd, buffer, PIPE_MSG_READ_BUFFER - 1); + if (count <= 0) { + TAG_LOGE(AAFwkTag::APPMGR, "read pipe failed"); + return; + } + + int32_t pid = -1; + int32_t signal = -1; + int32_t uid = 0; + std::string bundleName = ""; + std::string bufferStr = buffer; + TAG_LOGD(AAFwkTag::APPMGR, "buffer read: %{public}s", bufferStr.c_str()); + nlohmann::json jsonObject = nlohmann::json::parse(bufferStr, nullptr, false); + if (jsonObject.is_discarded()) { + TAG_LOGE(AAFwkTag::APPMGR, "parse json string failed"); + return; + } + if (!jsonObject.contains("pid") || !jsonObject.contains("signal") || !jsonObject.contains("uid") + || !jsonObject.contains("bundleName")) { + TAG_LOGE(AAFwkTag::APPMGR, "info lost!"); + return; + } + if (!jsonObject["pid"].is_number_integer() || !jsonObject["signal"].is_number_integer() || + !jsonObject["uid"].is_number_integer() || !jsonObject["bundleName"].is_string()) { + TAG_LOGE(AAFwkTag::APPMGR, "info type err!"); + return; + } + + pid = jsonObject["pid"]; + signal = jsonObject["signal"]; + uid = jsonObject["uid"]; + bundleName = jsonObject["bundleName"]; + if (signal == 0) { + TAG_LOGD(AAFwkTag::APPMGR, "ignore signal 0, pid: %{public}d", pid); + return; + } + TAG_LOGI(AAFwkTag::APPMGR, "pid:%{public}d, signal:%{public}d, uid:%{public}d, bundleName:%{public}s", + pid, signal, uid, bundleName.c_str()); + AppNativeSpawnManager::GetInstance().NotifyChildProcessExitTask(pid, signal, bundleName); +} + +sptr AppNativeSpawnManager::GetNativeChildCallbackByPid(int32_t pid) +{ + std::lock_guard lock(nativeChildCallbackLock_); + auto it = nativeChildCallbackMap_.find(pid); + return it != nativeChildCallbackMap_.end() ? it->second : nullptr; +} + +void AppNativeSpawnManager::RemoveNativeChildCallbackByPid(int32_t pid) +{ + TAG_LOGI(AAFwkTag::APPMGR, "remove native child callback, pid:%{public}d", pid); + std::lock_guard lock(nativeChildCallbackLock_); + nativeChildCallbackMap_.erase(pid); +} + +void AppNativeSpawnManager::InitNativeSpawnMsgPipe(std::shared_ptr appRunningManager) +{ + appRunningManager_ = appRunningManager; + int pipeFd[2]; + if (pipe(pipeFd) != 0) { + TAG_LOGE(AAFwkTag::APPMGR, "create native pipe failed"); + return; + } + nrFd_ = pipeFd[0]; + nwFd_ = pipeFd[1]; + int ret = WatchParameter(NATIVESPAWN_STARTED, AppNativeSpawnStartCallback, nullptr); + if (ret != 0) { + TAG_LOGE(AAFwkTag::APPMGR, "watch native parameter, ret :%{public}d", ret); + return; + } + ffrt_qos_t taskQos = 0; + ret = ffrt_epoll_ctl(taskQos, EPOLL_CTL_ADD, nrFd_, EPOLLIN, nullptr, ProcessSignalData); + if (ret != 0) { + TAG_LOGE(AAFwkTag::APPMGR, "ffrt_epoll_ctl failed, ret :%{public}d", ret); + close(nrFd_); + return; + } + TAG_LOGI(AAFwkTag::APPMGR, "Listen native signal msg ..."); +} + +int32_t AppNativeSpawnManager::GetChildRelation(int32_t childPid) +{ + std::lock_guard lock(childRelationLock_); + auto iter = childRelationMap_.find(childPid); + if (iter != childRelationMap_.end()) { + return iter->second; + } + return 0; +} + +void AppNativeSpawnManager::AddChildRelation(int32_t childPid, int32_t parentPid) +{ + std::lock_guard lock(childRelationLock_); + childRelationMap_[childPid] = parentPid; +} + +void AppNativeSpawnManager::RemoveChildRelation(int32_t childPid) +{ + std::lock_guard lock(childRelationLock_); + childRelationMap_.erase(childPid); +} +} // end AppExecFwk +} // end OHOS diff --git a/services/appmgr/src/app_running_manager.cpp b/services/appmgr/src/app_running_manager.cpp index 0be994d18c..75c7acdc94 100644 --- a/services/appmgr/src/app_running_manager.cpp +++ b/services/appmgr/src/app_running_manager.cpp @@ -44,6 +44,7 @@ #include "task_handler_wrap.h" #include "time_util.h" #include "ui_extension_utils.h" +#include "app_native_spawn_manager.h" namespace OHOS { namespace AppExecFwk { @@ -626,6 +627,11 @@ void AppRunningManager::RemoveAppRunningRecordById(const int32_t recordId) RemoveUIExtensionLauncherItem(appRecord->GetPid()); AbilityRuntime::FreezeUtil::GetInstance().DeleteAppLifecycleEvent(appRecord->GetPid()); } + + // unregister child process exit notify when parent exit + if (appRecord != nullptr) { + AppNativeSpawnManager::GetInstance().RemoveNativeChildCallbackByPid(appRecord->GetPid()); + } } void AppRunningManager::ClearAppRunningRecordMap() @@ -1547,6 +1553,10 @@ std::shared_ptr AppRunningManager::OnChildProcessRemoteDied( }); if (it != appRunningRecordMap_.end()) { auto appRecord = it->second; + if (childRecord->IsNativeSpawnStarted() && + AppNativeSpawnManager::GetInstance().GetNativeChildCallbackByPid(appRecord->GetPid()) != nullptr) { + AppNativeSpawnManager::GetInstance().AddChildRelation(childRecord->GetPid(), appRecord->GetPid()); + } appRecord->RemoveChildProcessRecord(childRecord); TAG_LOGI(AAFwkTag::APPMGR, "RemoveChildProcessRecord pid:%{public}d, uid:%{public}d", childRecord->GetPid(), childRecord->GetUid()); diff --git a/services/appmgr/src/child_process_record.cpp b/services/appmgr/src/child_process_record.cpp index ce537ae7b2..82c282875d 100644 --- a/services/appmgr/src/child_process_record.cpp +++ b/services/appmgr/src/child_process_record.cpp @@ -52,6 +52,11 @@ ChildProcessRecord::~ChildProcessRecord() TAG_LOGD(AAFwkTag::APPMGR, "called"); } +bool ChildProcessRecord::IsNativeSpawnStarted() const +{ + return childProcessType_ == CHILD_PROCESS_TYPE_NATIVE_ARGS; +} + std::shared_ptr ChildProcessRecord::CreateChildProcessRecord(pid_t hostPid, const ChildProcessRequest &request, const std::shared_ptr hostRecord) { diff --git a/test/fuzztest/abilityinterfacesappmgrnativechildnotifystub_fuzzer/abilityinterfacesappmgrnativechildnotifystub_fuzzer.cpp b/test/fuzztest/abilityinterfacesappmgrnativechildnotifystub_fuzzer/abilityinterfacesappmgrnativechildnotifystub_fuzzer.cpp index 118610b59c..ac67588a93 100644 --- a/test/fuzztest/abilityinterfacesappmgrnativechildnotifystub_fuzzer/abilityinterfacesappmgrnativechildnotifystub_fuzzer.cpp +++ b/test/fuzztest/abilityinterfacesappmgrnativechildnotifystub_fuzzer/abilityinterfacesappmgrnativechildnotifystub_fuzzer.cpp @@ -60,6 +60,7 @@ public: uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override{ return 0; }; void OnNativeChildStarted(const sptr &nativeChild) override{}; void OnError(int32_t errCode) override{}; + int32_t OnNativeChildExit(int32_t pid, int32_t signal) override{ return 0; }; }; sptr GetFuzzAbilityToken() diff --git a/test/fuzztest/appmgrservicefirst_fuzzer/appmgrservicefirst_fuzzer.cpp b/test/fuzztest/appmgrservicefirst_fuzzer/appmgrservicefirst_fuzzer.cpp index 7c359ff9fa..4dbfd06897 100644 --- a/test/fuzztest/appmgrservicefirst_fuzzer/appmgrservicefirst_fuzzer.cpp +++ b/test/fuzztest/appmgrservicefirst_fuzzer/appmgrservicefirst_fuzzer.cpp @@ -73,6 +73,9 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size) sptr applicationStateObserver; appMgrService->RegisterApplicationStateObserver(applicationStateObserver); appMgrService->UnregisterApplicationStateObserver(applicationStateObserver); + sptr nativeChildNotify; + appMgrService->RegisterNativeChildExitNotify(nativeChildNotify); + appMgrService->UnregisterNativeChildExitNotify(nativeChildNotify); pid_t pid = static_cast(GetU32Data(data)); appMgrService->AddAppDeathRecipient(pid); appMgrService->QueryServiceState(); diff --git a/test/fuzztest/appmgrstub_fuzzer/appmgrstub_fuzzer.cpp b/test/fuzztest/appmgrstub_fuzzer/appmgrstub_fuzzer.cpp index a7018e6e45..4015f95473 100644 --- a/test/fuzztest/appmgrstub_fuzzer/appmgrstub_fuzzer.cpp +++ b/test/fuzztest/appmgrstub_fuzzer/appmgrstub_fuzzer.cpp @@ -68,6 +68,8 @@ bool DoSomethingInterestingWithMyAPI(const char* data, size_t size) appMgrStub->HandleAttachRenderProcess(dataParcel, reply); appMgrStub->HandleJudgeSandboxByPid(dataParcel, reply); appMgrStub->HandleDumpHeapMemory(dataParcel, reply); + appMgrStub->HandleRegisterNativeChildExitNotify(dataParcel, reply); + appMgrStub->HandleUnregisterNativeChildExitNotify(dataParcel, reply); return true; } } diff --git a/test/mock/frameworks_kits_appkit_test/include/mock_app_mgr_service.h b/test/mock/frameworks_kits_appkit_test/include/mock_app_mgr_service.h index b6bdf21266..e1857def7e 100644 --- a/test/mock/frameworks_kits_appkit_test/include/mock_app_mgr_service.h +++ b/test/mock/frameworks_kits_appkit_test/include/mock_app_mgr_service.h @@ -81,6 +81,8 @@ public: #endif // SUPPORT_CHILD_PROCESS MOCK_METHOD1(RegisterRenderStateObserver, int32_t(const sptr &observer)); MOCK_METHOD1(UnregisterRenderStateObserver, int32_t(const sptr &observer)); + MOCK_METHOD1(RegisterNativeChildExitNotify, int32_t(const sptr notify)); + MOCK_METHOD1(UnregisterNativeChildExitNotify, int32_t(const sptr notify)); MOCK_METHOD2(UpdateRenderState, int32_t(pid_t renderPid, int32_t state)); MOCK_METHOD2(GetRunningMultiAppInfoByBundleName, int32_t(const std::string &bundleName, RunningMultiAppInfo &info)); diff --git a/test/mock/services_appmgr_test/include/mock_app_mgr_service.h b/test/mock/services_appmgr_test/include/mock_app_mgr_service.h index f70a299670..98a667f609 100644 --- a/test/mock/services_appmgr_test/include/mock_app_mgr_service.h +++ b/test/mock/services_appmgr_test/include/mock_app_mgr_service.h @@ -108,6 +108,8 @@ public: MOCK_METHOD1(AttachChildProcess, void(const sptr &childScheduler)); MOCK_METHOD0(ExitChildProcessSafely, void()); #endif // SUPPORT_CHILD_PROCESS + MOCK_METHOD1(RegisterNativeChildExitNotify, int32_t(const sptr notify)); + MOCK_METHOD1(UnregisterNativeChildExitNotify, int32_t(const sptr notify)); MOCK_METHOD1(RegisterRenderStateObserver, int32_t(const sptr &observer)); MOCK_METHOD1(UnregisterRenderStateObserver, int32_t(const sptr &observer)); MOCK_METHOD2(UpdateRenderState, int32_t(pid_t renderPid, int32_t state)); diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index c30405470b..3a2f392f1c 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -477,6 +477,7 @@ group("unittest") { "app_mgr_stub_test:unittest", "app_preloader_test:unittest", "app_recovery_test:unittest", + "app_native_spawn_manager_test:unittest", "app_running_manager_fourth_test:unittest", "app_running_manager_second_test:unittest", "app_running_manager_test:unittest", diff --git a/test/unittest/ams_ability_running_record_test/BUILD.gn b/test/unittest/ams_ability_running_record_test/BUILD.gn index ed3ed8ea08..1f8e223a3c 100644 --- a/test/unittest/ams_ability_running_record_test/BUILD.gn +++ b/test/unittest/ams_ability_running_record_test/BUILD.gn @@ -33,6 +33,7 @@ ohos_unittest("AmsAbilityRunningRecordTest") { "${ability_runtime_services_path}/appmgr/src/app_mgr_event.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", @@ -91,6 +92,7 @@ ohos_unittest("AmsAbilityRunningRecordTest") { "os_account:os_account_innerkits", "resource_schedule_service:ressched_client", "samgr:samgr_proxy", + "json:nlohmann_json_static", ] defines = [] diff --git a/test/unittest/ams_app_life_cycle_test/BUILD.gn b/test/unittest/ams_app_life_cycle_test/BUILD.gn index 29d0cd99ff..56b7902db5 100644 --- a/test/unittest/ams_app_life_cycle_test/BUILD.gn +++ b/test/unittest/ams_app_life_cycle_test/BUILD.gn @@ -29,6 +29,7 @@ ohos_unittest("AmsAppLifeCycleTest") { "${ability_runtime_services_path}/appmgr/src/app_lifecycle_deal.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", @@ -80,6 +81,7 @@ ohos_unittest("AmsAppLifeCycleTest") { "resource_schedule_service:ressched_client", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "json:nlohmann_json_static", ] if (ability_runtime_child_process) { diff --git a/test/unittest/ams_app_workflow_test/BUILD.gn b/test/unittest/ams_app_workflow_test/BUILD.gn index c10f4cc7c9..2807c90465 100644 --- a/test/unittest/ams_app_workflow_test/BUILD.gn +++ b/test/unittest/ams_app_workflow_test/BUILD.gn @@ -33,6 +33,7 @@ ohos_unittest("AmsWorkFlowTest") { "${ability_runtime_services_path}/appmgr/src/app_lifecycle_deal.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", @@ -80,6 +81,7 @@ ohos_unittest("AmsWorkFlowTest") { "memory_utils:libmeminfo", "os_account:os_account_innerkits", "resource_schedule_service:ressched_client", + "json:nlohmann_json_static", ] if (os_dlp_part_enabled) { diff --git a/test/unittest/ams_ipc_interface_test/ams_ipc_appmgr_interface_test.cpp b/test/unittest/ams_ipc_interface_test/ams_ipc_appmgr_interface_test.cpp index 0f5679613f..f12b91f70f 100644 --- a/test/unittest/ams_ipc_interface_test/ams_ipc_appmgr_interface_test.cpp +++ b/test/unittest/ams_ipc_interface_test/ams_ipc_appmgr_interface_test.cpp @@ -26,6 +26,7 @@ #include "mock_application.h" #include "mock_app_mgr_service.h" #include "mock_kia_interceptor.h" +#include "native_child_notify_stub.h" using namespace testing::ext; @@ -38,6 +39,17 @@ using testing::Return; namespace OHOS { namespace AppExecFwk { + +class NativeChildCallbackMock : public NativeChildNotifyStub { +public: + NativeChildCallbackMock() = default; + virtual ~NativeChildCallbackMock() = default; + + void OnNativeChildStarted(const sptr &nativeChild) {} + void OnError(int32_t errCode) {} + int32_t OnNativeChildExit(int32_t pid, int32_t signal) { return 0; } +}; + class AmsIpcAppMgrInterfaceTest : public testing::Test { public: static void SetUpTestCase(); @@ -238,6 +250,52 @@ HWTEST_F(AmsIpcAppMgrInterfaceTest, UnregisterApplicationStateObserver_001, Test TAG_LOGD(AAFwkTag::TEST, "UnregisterApplicationStateObserver_001 end"); } +/* + * @tc.name: RegisterNativeChildExitNotify_001 + * @tc.desc: Register native child exit notify test. + * @tc.type: FUNC + * @tc.require: issueI5822Q + */ +HWTEST_F(AmsIpcAppMgrInterfaceTest, RegisterNativeChildExitNotify_001, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "RegisterNativeChildExitNotify_001 start"); + + sptr notify = new NativeChildCallbackMock(); + sptr mockAppMgr(new MockAppMgrService()); + sptr appMgrClient = iface_cast(mockAppMgr); + + EXPECT_CALL(*mockAppMgr, RegisterNativeChildExitNotify(_)).Times(1).WillOnce(Return(OHOS::NO_ERROR)); + + int32_t err = appMgrClient->RegisterNativeChildExitNotify(notify); + + EXPECT_EQ(OHOS::NO_ERROR, err); + + TAG_LOGD(AAFwkTag::TEST, "RegisterNativeChildExitNotify_001 end"); +} + +/* + * @tc.name: UnregisterNativeChildExitNotify_001 + * @tc.desc: Unregister native child exit notify test. + * @tc.type: FUNC + * @tc.require: issueI5822Q + */ +HWTEST_F(AmsIpcAppMgrInterfaceTest, UnregisterNativeChildExitNotify_001, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "UnregisterNativeChildExitNotify_001 start"); + + sptr notify = new NativeChildCallbackMock(); + sptr mockAppMgr(new MockAppMgrService()); + sptr appMgrClient = iface_cast(mockAppMgr); + + EXPECT_CALL(*mockAppMgr, UnregisterNativeChildExitNotify(_)).Times(1).WillOnce(Return(OHOS::NO_ERROR)); + + int32_t err = appMgrClient->UnregisterNativeChildExitNotify(notify); + + EXPECT_EQ(OHOS::NO_ERROR, err); + + TAG_LOGD(AAFwkTag::TEST, "UnregisterNativeChildExitNotify_001 end"); +} + /* * @tc.name: RegisterKiaInterceptor_001 * @tc.desc: Register kia interceptor test. diff --git a/test/unittest/ams_recent_app_list_test/BUILD.gn b/test/unittest/ams_recent_app_list_test/BUILD.gn index 53397fb919..bd1c5f7524 100644 --- a/test/unittest/ams_recent_app_list_test/BUILD.gn +++ b/test/unittest/ams_recent_app_list_test/BUILD.gn @@ -32,6 +32,7 @@ ohos_unittest("AmsRecentAppListTest") { "${ability_runtime_services_path}/appmgr/src/app_lifecycle_deal.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", @@ -96,6 +97,7 @@ ohos_unittest("AmsRecentAppListTest") { "resource_schedule_service:ressched_client", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "json:nlohmann_json_static", ] if (os_dlp_part_enabled) { diff --git a/test/unittest/ams_service_app_spawn_client_test/BUILD.gn b/test/unittest/ams_service_app_spawn_client_test/BUILD.gn index b611e952ef..4cdd33dfbb 100644 --- a/test/unittest/ams_service_app_spawn_client_test/BUILD.gn +++ b/test/unittest/ams_service_app_spawn_client_test/BUILD.gn @@ -38,6 +38,7 @@ ohos_unittest("AmsServiceAppSpawnClientTest") { "${ability_runtime_services_path}/appmgr/src/app_mgr_service.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", @@ -93,6 +94,7 @@ ohos_unittest("AmsServiceAppSpawnClientTest") { "memory_utils:libmeminfo", "os_account:os_account_innerkits", "resource_schedule_service:ressched_client", + "json:nlohmann_json_static", ] if (ability_runtime_child_process) { diff --git a/test/unittest/ams_service_event_drive_test/BUILD.gn b/test/unittest/ams_service_event_drive_test/BUILD.gn index d3535ca31f..e9239bb4a9 100644 --- a/test/unittest/ams_service_event_drive_test/BUILD.gn +++ b/test/unittest/ams_service_event_drive_test/BUILD.gn @@ -39,6 +39,7 @@ ohos_unittest("AmsServiceEventDriveTest") { "${ability_runtime_services_path}/appmgr/src/app_mgr_service.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", @@ -97,6 +98,7 @@ ohos_unittest("AmsServiceEventDriveTest") { "memory_utils:libmeminfo", "os_account:os_account_innerkits", "resource_schedule_service:ressched_client", + "json:nlohmann_json_static", ] if (ability_runtime_child_process) { diff --git a/test/unittest/ams_service_load_ability_process_test/BUILD.gn b/test/unittest/ams_service_load_ability_process_test/BUILD.gn index b317b9afab..003b5330e7 100644 --- a/test/unittest/ams_service_load_ability_process_test/BUILD.gn +++ b/test/unittest/ams_service_load_ability_process_test/BUILD.gn @@ -36,6 +36,7 @@ ohos_unittest("AmsServiceLoadAbilityProcessTest") { "${ability_runtime_services_path}/appmgr/src/app_mgr_event.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", @@ -105,6 +106,8 @@ ohos_unittest("AmsServiceLoadAbilityProcessTest") { "resource_schedule_service:ressched_client", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "json:nlohmann_json_static", + "jsoncpp:jsoncpp", ] defines = [] diff --git a/test/unittest/ams_service_startup_test/BUILD.gn b/test/unittest/ams_service_startup_test/BUILD.gn index 83e691c331..df4aa68b99 100644 --- a/test/unittest/ams_service_startup_test/BUILD.gn +++ b/test/unittest/ams_service_startup_test/BUILD.gn @@ -34,6 +34,7 @@ ohos_unittest("AmsServiceStartupTest") { "${ability_runtime_services_path}/appmgr/src/app_mgr_service.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", @@ -94,6 +95,8 @@ ohos_unittest("AmsServiceStartupTest") { "safwk:api_cache_manager", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "json:nlohmann_json_static", + "jsoncpp:jsoncpp", ] defines = [] diff --git a/test/unittest/app_mgr_client_test/app_mgr_client_test.cpp b/test/unittest/app_mgr_client_test/app_mgr_client_test.cpp index 93cffd0a9b..8ab5b228eb 100644 --- a/test/unittest/app_mgr_client_test/app_mgr_client_test.cpp +++ b/test/unittest/app_mgr_client_test/app_mgr_client_test.cpp @@ -961,6 +961,36 @@ HWTEST_F(AppMgrClientTest, AppMgrClient_UnregisterApplicationStateObserver_001, EXPECT_EQ(result, ERR_INVALID_VALUE); } +/** + * @tc.name: AppMgrClient_RegisterNativeChildExitNotify_001 + * @tc.desc: RegisterNativeChildExitNotify. + * @tc.type: FUNC + */ +HWTEST_F(AppMgrClientTest, AppMgrClient_RegisterNativeChildExitNotify_001, TestSize.Level1) +{ + auto appMgrClient = std::make_unique(); + EXPECT_NE(appMgrClient, nullptr); + + sptr notify = nullptr; + auto result = appMgrClient->RegisterNativeChildExitNotify(notify); + EXPECT_EQ(result, ERR_INVALID_VALUE); +} + +/** + * @tc.name: AppMgrClient_UnregisterNativeChildExitNotify_001 + * @tc.desc: UnregisterNativeChildExitNotify. + * @tc.type: FUNC + */ +HWTEST_F(AppMgrClientTest, AppMgrClient_UnregisterNativeChildExitNotify_001, TestSize.Level1) +{ + auto appMgrClient = std::make_unique(); + EXPECT_NE(appMgrClient, nullptr); + + sptr notify = nullptr; + auto result = appMgrClient->UnregisterNativeChildExitNotify(notify); + EXPECT_EQ(result, ERR_INVALID_VALUE); +} + /** * @tc.name: AppMgrClient_NotifyPageShow_001 * @tc.desc: NotifyPageShow. diff --git a/test/unittest/app_mgr_service_event_handler_test/BUILD.gn b/test/unittest/app_mgr_service_event_handler_test/BUILD.gn index c22b950499..05d3b33bda 100644 --- a/test/unittest/app_mgr_service_event_handler_test/BUILD.gn +++ b/test/unittest/app_mgr_service_event_handler_test/BUILD.gn @@ -32,6 +32,7 @@ ohos_unittest("AMSEventHandlerTest") { "${ability_runtime_services_path}/appmgr/src/app_mgr_event.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_record.cpp", @@ -99,6 +100,8 @@ ohos_unittest("AMSEventHandlerTest") { "resource_schedule_service:ressched_client", "safwk:system_ability_fwk", "samgr:samgr_proxy", + "json:nlohmann_json_static", + "jsoncpp:jsoncpp", ] if (os_dlp_part_enabled) { cflags_cc += [ "-DWITH_DLP" ] diff --git a/test/unittest/app_mgr_service_inner_eighth_test/BUILD.gn b/test/unittest/app_mgr_service_inner_eighth_test/BUILD.gn index b7dc6a9077..0fa9f8b42e 100644 --- a/test/unittest/app_mgr_service_inner_eighth_test/BUILD.gn +++ b/test/unittest/app_mgr_service_inner_eighth_test/BUILD.gn @@ -55,6 +55,7 @@ ohos_unittest("app_mgr_service_inner_eighth_test") { "${ability_runtime_services_path}/appmgr/src/app_mgr_service.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", "${ability_runtime_services_path}/appmgr/src/app_state_observer_manager.cpp", @@ -126,6 +127,7 @@ ohos_unittest("app_mgr_service_inner_eighth_test") { "init:libbeget_proxy", "init:libbegetutil", "ipc:ipc_core", + "json:nlohmann_json_static", "jsoncpp:jsoncpp", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", diff --git a/test/unittest/app_mgr_service_inner_seventh_test/BUILD.gn b/test/unittest/app_mgr_service_inner_seventh_test/BUILD.gn index 73ed75de1b..300608c243 100644 --- a/test/unittest/app_mgr_service_inner_seventh_test/BUILD.gn +++ b/test/unittest/app_mgr_service_inner_seventh_test/BUILD.gn @@ -55,6 +55,7 @@ ohos_unittest("app_mgr_service_inner_seventh_test") { "${ability_runtime_services_path}/appmgr/src/app_mgr_service.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", "${ability_runtime_services_path}/appmgr/src/app_state_observer_manager.cpp", @@ -125,6 +126,7 @@ ohos_unittest("app_mgr_service_inner_seventh_test") { "init:libbeget_proxy", "init:libbegetutil", "ipc:ipc_core", + "json:nlohmann_json_static", "jsoncpp:jsoncpp", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", diff --git a/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp b/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp index d87c2334d1..50f730421f 100644 --- a/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp +++ b/test/unittest/app_mgr_service_inner_test/app_mgr_service_inner_test.cpp @@ -2330,6 +2330,44 @@ HWTEST_F(AppMgrServiceInnerTest, UnregisterApplicationStateObserver_001, TestSiz TAG_LOGI(AAFwkTag::TEST, "UnregisterApplicationStateObserver_001 end"); } +/** + * @tc.name: RegisterNativeChildExitNotify_001 + * @tc.desc: register native chlid exit notify. + * @tc.type: FUNC + * @tc.require: issueI5W4S7 + */ +HWTEST_F(AppMgrServiceInnerTest, RegisterNativeChildExitNotify_001, TestSize.Level0) +{ + TAG_LOGI(AAFwkTag::TEST, "RegisterNativeChildExitNotify_001 start"); + auto appMgrServiceInner = std::make_shared(); + EXPECT_NE(appMgrServiceInner, nullptr); + + sptr notify; + auto ret = appMgrServiceInner->RegisterNativeChildExitNotify(notify); + EXPECT_EQ(ret, ERR_OK); + + TAG_LOGI(AAFwkTag::TEST, "RegisterNativeChildExitNotify_001 end"); +} + +/** + * @tc.name: UnregisterNativeChildExitNotify_001 + * @tc.desc: unregister native chlid exit notify. + * @tc.type: FUNC + * @tc.require: issueI5W4S7 + */ +HWTEST_F(AppMgrServiceInnerTest, UnregisterNativeChildExitNotify_001, TestSize.Level0) +{ + TAG_LOGI(AAFwkTag::TEST, "UnregisterNativeChildExitNotify_001 start"); + auto appMgrServiceInner = std::make_shared(); + EXPECT_NE(appMgrServiceInner, nullptr); + + sptr notify; + auto ret = appMgrServiceInner->UnregisterNativeChildExitNotify(notify); + EXPECT_NE(ret, ERR_OK); + + TAG_LOGI(AAFwkTag::TEST, "UnregisterNativeChildExitNotify_001 end"); +} + /** * @tc.name: GetForegroundApplications_001 * @tc.desc: get foreground applications. diff --git a/test/unittest/app_mgr_service_test/app_mgr_service_test.cpp b/test/unittest/app_mgr_service_test/app_mgr_service_test.cpp index 2e252f5ec8..57ab7647f8 100644 --- a/test/unittest/app_mgr_service_test/app_mgr_service_test.cpp +++ b/test/unittest/app_mgr_service_test/app_mgr_service_test.cpp @@ -513,6 +513,40 @@ HWTEST_F(AppMgrServiceTest, UnregisterApplicationStateObserver_001, TestSize.Lev EXPECT_EQ(res, ERR_INVALID_OPERATION); } +/* + * Feature: AppMgrService + * Function: RegisterNativeChildExitNotify + * SubFunction: NA + * FunctionPoints: AppMgrService RegisterNativeChildExitNotify + * EnvConditions: NA + * CaseDescription: Verify RegisterNativeChildExitNotify + */ +HWTEST_F(AppMgrServiceTest, RegisterNativeChildExitNotify_001, TestSize.Level0) +{ + auto appMgrService = std::make_shared(); + sptr notify = nullptr; + appMgrService->SetInnerService(nullptr); + int32_t res = appMgrService->RegisterNativeChildExitNotify(notify); + EXPECT_EQ(res, ERR_INVALID_OPERATION); +} + +/* + * Feature: AppMgrService + * Function: UnregisterNativeChildExitNotify + * SubFunction: NA + * FunctionPoints: AppMgrService UnregisterNativeChildExitNotify + * EnvConditions: NA + * CaseDescription: Verify UnregisterNativeChildExitNotify + */ +HWTEST_F(AppMgrServiceTest, UnregisterNativeChildExitNotify_001, TestSize.Level0) +{ + auto appMgrService = std::make_shared(); + sptr notify = nullptr; + appMgrService->SetInnerService(nullptr); + int32_t res = appMgrService->UnregisterNativeChildExitNotify(notify); + EXPECT_EQ(res, ERR_INVALID_OPERATION); +} + /* * Feature: AppMgrService * Function: GetForegroundApplications diff --git a/test/unittest/app_mgr_stub_test/app_mgr_stub_test.cpp b/test/unittest/app_mgr_stub_test/app_mgr_stub_test.cpp index aa3e3c3d12..0912354bca 100644 --- a/test/unittest/app_mgr_stub_test/app_mgr_stub_test.cpp +++ b/test/unittest/app_mgr_stub_test/app_mgr_stub_test.cpp @@ -26,6 +26,7 @@ #include "ipc_types.h" #include "mock_app_mgr_service.h" #include "render_state_observer_stub.h" +#include "native_child_notify_stub.h" using namespace testing; using namespace testing::ext; @@ -52,6 +53,16 @@ public: {} }; +class NativeChildCallbackMock : public NativeChildNotifyStub { +public: + NativeChildCallbackMock() = default; + virtual ~NativeChildCallbackMock() = default; + + void OnNativeChildStarted(const sptr &nativeChild) {} + void OnError(int32_t errCode) {} + int32_t OnNativeChildExit(int32_t pid, int32_t signal) { return 0; } +}; + class AppMgrStubTest : public testing::Test { public: static void SetUpTestCase(); @@ -480,6 +491,38 @@ HWTEST_F(AppMgrStubTest, HandleUnregisterAppForegroundStateObserver_0100, TestSi EXPECT_EQ(res, NO_ERROR); } +/** + * @tc.name: HandleRegisterNativeChildExitNotify_0100 + * @tc.desc: Test when callback is not nullptr the return of writeInt32 is true. + * @tc.type: FUNC + */ +HWTEST_F(AppMgrStubTest, HandleRegisterNativeChildExitNotify_0100, TestSize.Level1) +{ + MessageParcel data; + MessageParcel reply; + sptr object = new (std::nothrow) NativeChildCallbackMock(); + data.WriteRemoteObject(object); + reply.WriteInt32(0); + auto res = mockAppMgrService_->HandleRegisterNativeChildExitNotify(data, reply); + EXPECT_EQ(res, NO_ERROR); +} + +/** + * @tc.name: HandleUnregisterNativeChildExitNotify_0100 + * @tc.desc: Test when callback is not nullptr the return of writeInt32 is true. + * @tc.type: FUNC + */ +HWTEST_F(AppMgrStubTest, HandleUnregisterNativeChildExitNotify_0100, TestSize.Level1) +{ + MessageParcel data; + MessageParcel reply; + sptr object = new (std::nothrow) NativeChildCallbackMock(); + data.WriteRemoteObject(object); + reply.WriteInt32(0); + auto res = mockAppMgrService_->HandleUnregisterNativeChildExitNotify(data, reply); + EXPECT_EQ(res, NO_ERROR); +} + /** * @tc.name: HandleRegisterRenderStateObserver_0100 * @tc.desc: Test register observer success. diff --git a/test/unittest/app_native_spawn_manager_test/BUILD.gn b/test/unittest/app_native_spawn_manager_test/BUILD.gn new file mode 100644 index 0000000000..42099f9b68 --- /dev/null +++ b/test/unittest/app_native_spawn_manager_test/BUILD.gn @@ -0,0 +1,90 @@ +# 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/ability_runtime/appmgrservice" + +ohos_unittest("app_native_spawn_manager_test") { + module_out_path = module_output_path + + configs = [ "${ability_runtime_services_path}/common:common_config" ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } + + include_dirs = [ + "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", + "${ability_runtime_utils_path}/global/constant", + "${ability_runtime_innerkits_path}/ability_manager/include", + "${ability_runtime_innerkits_path}/app_manager/include/appmgr", + "${ability_runtime_services_path}/appmgr/include", + ] + + sources = [ + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", + "app_native_spawn_manager_test.cpp", + ] + + deps = [ + "${ability_runtime_services_path}/appmgr:libappms", + "${ability_runtime_innerkits_path}/app_manager:app_manager", + ] + + external_deps = [ + "ability_base:base", + "ability_base:session_info", + "ability_base:configuration", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "appspawn:appspawn_client", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "init:libbeget_proxy", + "init:libbegetutil", + "ipc:ipc_core", + "kv_store:distributeddata_mgr", + "memory_utils:libmeminfo", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + "window_manager:libwm", + "window_manager:libwsutils", + "json:nlohmann_json_static", + "jsoncpp:jsoncpp", + ] + + if (ability_runtime_child_process) { + defines = [ "SUPPORT_CHILD_PROCESS" ] + } + +} + + +group("unittest") { + testonly = true + + deps = [ ":app_native_spawn_manager_test" ] +} + diff --git a/test/unittest/app_native_spawn_manager_test/app_native_spawn_manager_test.cpp b/test/unittest/app_native_spawn_manager_test/app_native_spawn_manager_test.cpp new file mode 100644 index 0000000000..13071e0e80 --- /dev/null +++ b/test/unittest/app_native_spawn_manager_test/app_native_spawn_manager_test.cpp @@ -0,0 +1,141 @@ +/* +* 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 +#include "ability_manager_errors.h" +#include "app_native_spawn_manager.h" +#include "native_child_notify_proxy.h" +#include "hilog_tag_wrapper.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace AppExecFwk { +class AppNativeSpawnManagerTest : public testing::Test { +public: + void SetUp(); + void TearDown(); + +protected: + std::shared_ptr appRunningManager_ = nullptr; +}; + +void AppNativeSpawnManagerTest::SetUp() +{ + appRunningManager_ = std::make_shared(); + AppNativeSpawnManager::GetInstance().InitNativeSpawnMsgPipe(appRunningManager_); +} + +void AppNativeSpawnManagerTest::TearDown() +{ +} + +/** + * @tc.number: AppNativeSpawnManagerTest_RegisterNativeChildExitNotify_0100 + * @tc.desc: Test RegisterNativeChildExitNotify works + * @tc.type: FUNC + * @tc.Function: RegisterNativeChildExitNotify + * @tc.SubFunction: NA + * @tc.EnvConditions: NA + */ +HWTEST_F(AppNativeSpawnManagerTest, AppNativeSpawnManagerTest_RegisterNativeChildExitNotify_0100, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "AppNativeSpawnManagerTest_RegisterNativeChildExitNotify_0100 start."); + sptr notify; + auto ret = AppNativeSpawnManager::GetInstance().RegisterNativeChildExitNotify(notify); + EXPECT_EQ(ret, ERR_INVALID_VALUE); + notify = sptr::MakeSptr(nullptr); + ret = AppNativeSpawnManager::GetInstance().RegisterNativeChildExitNotify(notify); + EXPECT_EQ(ret, OHOS::AAFwk::ERR_CALLER_NOT_EXISTS); +} + +/** + * @tc.number: AppNativeSpawnManagerTest_UnregisterNativeChildExitNotify_0200 + * @tc.desc: Test UnregisterNativeChildExitNotify works + * @tc.type: FUNC + * @tc.Function: UnregisterNativeChildExitNotify + * @tc.SubFunction: NA + * @tc.EnvConditions: NA + */ +HWTEST_F(AppNativeSpawnManagerTest, AppNativeSpawnManagerTest_UnregisterNativeChildExitNotify_0200, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "AppNativeSpawnManagerTest_UnregisterNativeChildExitNotify_0200 start."); + sptr notify; + auto ret = AppNativeSpawnManager::GetInstance().UnregisterNativeChildExitNotify(notify); + EXPECT_EQ(ret, ERR_INVALID_VALUE); + notify = sptr::MakeSptr(nullptr); + ret = AppNativeSpawnManager::GetInstance().UnregisterNativeChildExitNotify(notify); + EXPECT_EQ(ret, OHOS::AAFwk::ERR_INVALID_CALLER); +} + +/** + * @tc.number: AppNativeSpawnManagerTest_GetNativeChildCallbackByPid_0300 + * @tc.desc: Test UnregisterNativeChildExitNotify works + * @tc.type: FUNC + * @tc.Function: UnregisterNativeChildExitNotify + * @tc.SubFunction: NA + * @tc.EnvConditions: NA + */ +HWTEST_F(AppNativeSpawnManagerTest, AppNativeSpawnManagerTest_GetNativeChildCallbackByPid_0300, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "AppNativeSpawnManagerTest_GetNativeChildCallbackByPid_0300 start."); + int32_t pid = 1; + auto notify = AppNativeSpawnManager::GetInstance().GetNativeChildCallbackByPid(pid); + EXPECT_EQ(notify, nullptr); +} + + +/** + * @tc.number: AppNativeSpawnManagerTest_RemoveNativeChildCallbackByPid_0400 + * @tc.desc: Test RemoveNativeChildCallbackByPid works + * @tc.type: FUNC + * @tc.Function: RemoveNativeChildCallbackByPid + * @tc.SubFunction: NA + * @tc.EnvConditions: NA + */ +HWTEST_F(AppNativeSpawnManagerTest, AppNativeSpawnManagerTest_RemoveNativeChildCallbackByPid_0400, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "AppNativeSpawnManagerTest_RemoveNativeChildCallbackByPid_0400 start."); + int32_t pid = 1; + AppNativeSpawnManager::GetInstance().RemoveNativeChildCallbackByPid(pid); + auto notify = AppNativeSpawnManager::GetInstance().GetNativeChildCallbackByPid(pid); + EXPECT_EQ(notify, nullptr); +} + +/** + * @tc.number: AppNativeSpawnManagerTest_ChildRelation_0500 + * @tc.desc: Test ChildRelation works + * @tc.type: FUNC + * @tc.Function: ChildRelation + * @tc.SubFunction: NA + * @tc.EnvConditions: NA + */ +HWTEST_F(AppNativeSpawnManagerTest, AppNativeSpawnManagerTest_ChildRelation_0500, TestSize.Level0) +{ + TAG_LOGD(AAFwkTag::TEST, "AppNativeSpawnManagerTest_ChildRelation_0500 start."); + int32_t childPid = 1; + int32_t parentPid = 2; + AppNativeSpawnManager::GetInstance().AddChildRelation(childPid, parentPid); + auto parent = AppNativeSpawnManager::GetInstance().GetChildRelation(childPid); + EXPECT_EQ(parent, 2); + AppNativeSpawnManager::GetInstance().RemoveChildRelation(childPid); + parent = AppNativeSpawnManager::GetInstance().GetChildRelation(childPid); + EXPECT_EQ(parent, 0); +} + + +} // namespace AppExecFwk +} // namespace OHOS diff --git a/test/unittest/cache_process_manager_second_test/BUILD.gn b/test/unittest/cache_process_manager_second_test/BUILD.gn index c0fd123550..265643796c 100644 --- a/test/unittest/cache_process_manager_second_test/BUILD.gn +++ b/test/unittest/cache_process_manager_second_test/BUILD.gn @@ -52,6 +52,7 @@ ohos_unittest("cache_process_manager_second_test") { "${ability_runtime_services_path}/appmgr/src/app_mgr_service.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_event_handler.cpp", "${ability_runtime_services_path}/appmgr/src/app_mgr_service_inner.cpp", + "${ability_runtime_services_path}/appmgr/src/app_native_spawn_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_preloader.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_manager.cpp", "${ability_runtime_services_path}/appmgr/src/app_running_status_module.cpp", @@ -142,6 +143,7 @@ ohos_unittest("cache_process_manager_second_test") { "init:libbegetutil", "ipc:ipc_core", "json:nlohmann_json_static", + "jsoncpp:jsoncpp", "kv_store:distributeddata_inner", "memmgr:memmgrclient", "memory_utils:libmeminfo", diff --git a/test/unittest/child_process_capi_test/child_process_capi_test.cpp b/test/unittest/child_process_capi_test/child_process_capi_test.cpp index cfcb3fc904..5992898787 100644 --- a/test/unittest/child_process_capi_test/child_process_capi_test.cpp +++ b/test/unittest/child_process_capi_test/child_process_capi_test.cpp @@ -30,6 +30,7 @@ public: static void TearDownTestCase(void); static void OnNativeChildProcessStarted(int errCode, OHIPCRemoteProxy *remoteProxy); + static void OnNativeChildProcessExit(int32_t pid, int32_t signal); void SetUp(); void TearDown(); @@ -51,6 +52,10 @@ void ChildProcessCapiTest::OnNativeChildProcessStarted(int errCode, OHIPCRemoteP { } +void ChildProcessCapiTest::OnNativeChildProcessExit(int32_t pid, int32_t signal) +{ +} + /** * @tc.number: OH_Ability_CreateNativeChildProcess_001 * @tc.desc: Test API OH_Ability_CreateNativeChildProcess works @@ -94,6 +99,38 @@ HWTEST_F(ChildProcessCapiTest, OH_Ability_StartNativeChildProcess_001, TestSize. GTEST_LOG_(INFO) << "OH_Ability_StartNativeChildProcess_001 begin"; } +/** + * @tc.number: OH_Ability_RegisterNativeChildProcessExitCallback_001 + * @tc.desc: Test API OH_Ability_RegisterNativeChildProcessExitCallback_001 works + * @tc.type: FUNC + */ +HWTEST_F(ChildProcessCapiTest, OH_Ability_RegisterNativeChildProcessExitCallback_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "OH_Ability_RegisterNativeChildProcessExitCallback_001 begin"; + auto ret = OH_Ability_RegisterNativeChildProcessExitCallback(nullptr); + EXPECT_EQ(ret, NCP_ERR_INVALID_PARAM); + ret = OH_Ability_RegisterNativeChildProcessExitCallback(ChildProcessCapiTest::OnNativeChildProcessExit); + EXPECT_EQ(ret, NCP_ERR_INTERNAL); + ret = OH_Ability_UnregisterNativeChildProcessExitCallback(ChildProcessCapiTest::OnNativeChildProcessExit); + EXPECT_EQ(ret, NCP_ERR_INTERNAL); + GTEST_LOG_(INFO) << "OH_Ability_RegisterNativeChildProcessExitCallback_001 end"; +} + +/** + * @tc.number: OH_Ability_UnregisterNativeChildProcessExitCallback_001 + * @tc.desc: Test API OH_Ability_UnregisterNativeChildProcessExitCallback_001 works + * @tc.type: FUNC + */ +HWTEST_F(ChildProcessCapiTest, OH_Ability_UnregisterNativeChildProcessExitCallback_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "OH_Ability_UnregisterNativeChildProcessExitCallback_001 begin"; + auto ret = OH_Ability_UnregisterNativeChildProcessExitCallback(nullptr); + EXPECT_EQ(ret, NCP_ERR_INVALID_PARAM); + ret = OH_Ability_UnregisterNativeChildProcessExitCallback(ChildProcessCapiTest::OnNativeChildProcessExit); + EXPECT_EQ(ret, NCP_ERR_CALLBACK_NOT_EXIST); + GTEST_LOG_(INFO) << "OH_Ability_UnregisterNativeChildProcessExitCallback_001 end"; +} + /** * @tc.number: OH_Ability_GetCurrentChildProcessArgs_001 * @tc.desc: Test API OH_Ability_GetCurrentChildProcessArgs_001 works