169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci
1669570cc8Sopenharmony_ci#include "appspawn_modulemgr.h"
1769570cc8Sopenharmony_ci
1869570cc8Sopenharmony_ci#include "appspawn_hook.h"
1969570cc8Sopenharmony_ci#include "appspawn_manager.h"
2069570cc8Sopenharmony_ci#include "appspawn_utils.h"
2169570cc8Sopenharmony_ci#include "hookmgr.h"
2269570cc8Sopenharmony_ci#include "modulemgr.h"
2369570cc8Sopenharmony_ci
2469570cc8Sopenharmony_citypedef struct {
2569570cc8Sopenharmony_ci    const AppSpawnContent *content;
2669570cc8Sopenharmony_ci    const AppSpawnedProcessInfo *appInfo;
2769570cc8Sopenharmony_ci} AppSpawnAppArg;
2869570cc8Sopenharmony_ci
2969570cc8Sopenharmony_cistatic struct {
3069570cc8Sopenharmony_ci    MODULE_MGR *moduleMgr;
3169570cc8Sopenharmony_ci    AppSpawnModuleType type;
3269570cc8Sopenharmony_ci    const char *moduleName;
3369570cc8Sopenharmony_ci} g_moduleMgr[MODULE_MAX] = {
3469570cc8Sopenharmony_ci    {NULL, MODULE_DEFAULT, "appspawn"},
3569570cc8Sopenharmony_ci    {NULL, MODULE_APPSPAWN, "appspawn/appspawn"},
3669570cc8Sopenharmony_ci    {NULL, MODULE_NWEBSPAWN, "appspawn/nwebspawn"},
3769570cc8Sopenharmony_ci    {NULL, MODULE_COMMON, "appspawn/common"},
3869570cc8Sopenharmony_ci    {NULL, MODULE_NATIVESPAWN, "appspawn/nativespawn"},
3969570cc8Sopenharmony_ci};
4069570cc8Sopenharmony_cistatic HOOK_MGR *g_appspawnHookMgr = NULL;
4169570cc8Sopenharmony_ci
4269570cc8Sopenharmony_ciint AppSpawnModuleMgrInstall(const char *moduleName)
4369570cc8Sopenharmony_ci{
4469570cc8Sopenharmony_ci    if (moduleName == NULL) {
4569570cc8Sopenharmony_ci        return -1;
4669570cc8Sopenharmony_ci    }
4769570cc8Sopenharmony_ci    int type = MODULE_DEFAULT;
4869570cc8Sopenharmony_ci    if (g_moduleMgr[type].moduleMgr == NULL) {
4969570cc8Sopenharmony_ci        g_moduleMgr[type].moduleMgr = ModuleMgrCreate(g_moduleMgr[type].moduleName);
5069570cc8Sopenharmony_ci    }
5169570cc8Sopenharmony_ci    if (g_moduleMgr[type].moduleMgr == NULL) {
5269570cc8Sopenharmony_ci        return -1;
5369570cc8Sopenharmony_ci    }
5469570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
5569570cc8Sopenharmony_ci    return ModuleMgrInstall(g_moduleMgr[type].moduleMgr, moduleName, 0, NULL);
5669570cc8Sopenharmony_ci#else
5769570cc8Sopenharmony_ci    return 0;
5869570cc8Sopenharmony_ci#endif
5969570cc8Sopenharmony_ci}
6069570cc8Sopenharmony_ci
6169570cc8Sopenharmony_civoid AppSpawnModuleMgrUnInstall(int type)
6269570cc8Sopenharmony_ci{
6369570cc8Sopenharmony_ci    if ((type < 0) || (type >= MODULE_MAX)) {
6469570cc8Sopenharmony_ci        return;
6569570cc8Sopenharmony_ci    }
6669570cc8Sopenharmony_ci    if (g_moduleMgr[type].moduleMgr == NULL) {
6769570cc8Sopenharmony_ci        return;
6869570cc8Sopenharmony_ci    }
6969570cc8Sopenharmony_ci    ModuleMgrDestroy(g_moduleMgr[type].moduleMgr);
7069570cc8Sopenharmony_ci    g_moduleMgr[type].moduleMgr = NULL;
7169570cc8Sopenharmony_ci}
7269570cc8Sopenharmony_ci
7369570cc8Sopenharmony_ciint AppSpawnLoadAutoRunModules(int type)
7469570cc8Sopenharmony_ci{
7569570cc8Sopenharmony_ci    if ((type < 0) || (type >= MODULE_MAX)) {
7669570cc8Sopenharmony_ci        return -1;
7769570cc8Sopenharmony_ci    }
7869570cc8Sopenharmony_ci    if (g_moduleMgr[type].moduleMgr != NULL) {
7969570cc8Sopenharmony_ci        return 0;
8069570cc8Sopenharmony_ci    }
8169570cc8Sopenharmony_ci    APPSPAWN_LOGI("AppSpawnLoadAutoRunModules: %{public}d moduleName: %{public}s", type, g_moduleMgr[type].moduleName);
8269570cc8Sopenharmony_ci#ifndef APPSPAWN_TEST
8369570cc8Sopenharmony_ci    g_moduleMgr[type].moduleMgr = ModuleMgrScan(g_moduleMgr[type].moduleName);
8469570cc8Sopenharmony_ci    return g_moduleMgr[type].moduleMgr == NULL ? -1 : 0;
8569570cc8Sopenharmony_ci#else
8669570cc8Sopenharmony_ci    return 0;
8769570cc8Sopenharmony_ci#endif
8869570cc8Sopenharmony_ci}
8969570cc8Sopenharmony_ci
9069570cc8Sopenharmony_ciHOOK_MGR *GetAppSpawnHookMgr(void)
9169570cc8Sopenharmony_ci{
9269570cc8Sopenharmony_ci    if (g_appspawnHookMgr != NULL) {
9369570cc8Sopenharmony_ci        return g_appspawnHookMgr;
9469570cc8Sopenharmony_ci    }
9569570cc8Sopenharmony_ci    g_appspawnHookMgr = HookMgrCreate("appspawn");
9669570cc8Sopenharmony_ci    return g_appspawnHookMgr;
9769570cc8Sopenharmony_ci}
9869570cc8Sopenharmony_ci
9969570cc8Sopenharmony_civoid DeleteAppSpawnHookMgr(void)
10069570cc8Sopenharmony_ci{
10169570cc8Sopenharmony_ci    HookMgrDestroy(g_appspawnHookMgr);
10269570cc8Sopenharmony_ci    g_appspawnHookMgr = NULL;
10369570cc8Sopenharmony_ci}
10469570cc8Sopenharmony_ci
10569570cc8Sopenharmony_cistatic void UpdateAppSpawnTime(int used)
10669570cc8Sopenharmony_ci{
10769570cc8Sopenharmony_ci    if (used < GetAppSpawnMgr()->spawnTime.minAppspawnTime) {
10869570cc8Sopenharmony_ci        GetAppSpawnMgr()->spawnTime.minAppspawnTime = used;
10969570cc8Sopenharmony_ci        APPSPAWN_LOGI("spawn min time: %{public}d", GetAppSpawnMgr()->spawnTime.minAppspawnTime);
11069570cc8Sopenharmony_ci    }
11169570cc8Sopenharmony_ci    if (used > GetAppSpawnMgr()->spawnTime.maxAppspawnTime) {
11269570cc8Sopenharmony_ci        GetAppSpawnMgr()->spawnTime.maxAppspawnTime = used;
11369570cc8Sopenharmony_ci        APPSPAWN_LOGI("spawn max time: %{public}d", GetAppSpawnMgr()->spawnTime.maxAppspawnTime);
11469570cc8Sopenharmony_ci    }
11569570cc8Sopenharmony_ci}
11669570cc8Sopenharmony_ci
11769570cc8Sopenharmony_cistatic int ServerStageHookRun(const HOOK_INFO *hookInfo, void *executionContext)
11869570cc8Sopenharmony_ci{
11969570cc8Sopenharmony_ci    AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
12069570cc8Sopenharmony_ci    ServerStageHook realHook = (ServerStageHook)hookInfo->hookCookie;
12169570cc8Sopenharmony_ci    return realHook((void *)arg->content);
12269570cc8Sopenharmony_ci}
12369570cc8Sopenharmony_ci
12469570cc8Sopenharmony_cistatic void PreHookExec(const HOOK_INFO *hookInfo, void *executionContext)
12569570cc8Sopenharmony_ci{
12669570cc8Sopenharmony_ci    AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
12769570cc8Sopenharmony_ci    AppSpawnMgr *spawnMgr = (AppSpawnMgr *)arg->content;
12869570cc8Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &spawnMgr->perLoadStart);
12969570cc8Sopenharmony_ci    APPSPAWN_LOGI("Hook stage: %{public}d prio: %{public}d start", hookInfo->stage, hookInfo->prio);
13069570cc8Sopenharmony_ci}
13169570cc8Sopenharmony_ci
13269570cc8Sopenharmony_cistatic void PostHookExec(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal)
13369570cc8Sopenharmony_ci{
13469570cc8Sopenharmony_ci    AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
13569570cc8Sopenharmony_ci    AppSpawnMgr *spawnMgr = (AppSpawnMgr *)arg->content;
13669570cc8Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &spawnMgr->perLoadEnd);
13769570cc8Sopenharmony_ci    uint64_t diff = DiffTime(&spawnMgr->perLoadStart, &spawnMgr->perLoadEnd);
13869570cc8Sopenharmony_ci    APPSPAWN_LOGI("Hook stage: %{public}d prio: %{public}d end time %{public}" PRId64 " ns result: %{public}d",
13969570cc8Sopenharmony_ci        hookInfo->stage, hookInfo->prio, diff, executionRetVal);
14069570cc8Sopenharmony_ci    UpdateAppSpawnTime(diff);
14169570cc8Sopenharmony_ci}
14269570cc8Sopenharmony_ci
14369570cc8Sopenharmony_ciint ServerStageHookExecute(AppSpawnHookStage stage, AppSpawnContent *content)
14469570cc8Sopenharmony_ci{
14569570cc8Sopenharmony_ci    APPSPAWN_CHECK(content != NULL, return APPSPAWN_ARG_INVALID, "Invalid content");
14669570cc8Sopenharmony_ci    APPSPAWN_CHECK((stage >= STAGE_SERVER_PRELOAD) && (stage <= STAGE_SERVER_EXIT),
14769570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
14869570cc8Sopenharmony_ci    AppSpawnHookArg arg;
14969570cc8Sopenharmony_ci    arg.content = content;
15069570cc8Sopenharmony_ci    arg.client = NULL;
15169570cc8Sopenharmony_ci    HOOK_EXEC_OPTIONS options;
15269570cc8Sopenharmony_ci    options.flags = TRAVERSE_STOP_WHEN_ERROR;
15369570cc8Sopenharmony_ci    options.preHook = PreHookExec;
15469570cc8Sopenharmony_ci    options.postHook = PostHookExec;
15569570cc8Sopenharmony_ci    int ret = HookMgrExecute(GetAppSpawnHookMgr(), stage, (void *)(&arg), &options);
15669570cc8Sopenharmony_ci    APPSPAWN_LOGV("Execute hook [%{public}d] result %{public}d", stage, ret);
15769570cc8Sopenharmony_ci    return ret == ERR_NO_HOOK_STAGE ? 0 : ret;
15869570cc8Sopenharmony_ci}
15969570cc8Sopenharmony_ci
16069570cc8Sopenharmony_ciint AddServerStageHook(AppSpawnHookStage stage, int prio, ServerStageHook hook)
16169570cc8Sopenharmony_ci{
16269570cc8Sopenharmony_ci    APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
16369570cc8Sopenharmony_ci    APPSPAWN_CHECK((stage >= STAGE_SERVER_PRELOAD) && (stage <= STAGE_SERVER_EXIT),
16469570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
16569570cc8Sopenharmony_ci    HOOK_INFO info;
16669570cc8Sopenharmony_ci    info.stage = stage;
16769570cc8Sopenharmony_ci    info.prio = prio;
16869570cc8Sopenharmony_ci    info.hook = ServerStageHookRun;
16969570cc8Sopenharmony_ci    info.hookCookie = (void *)hook;
17069570cc8Sopenharmony_ci    APPSPAWN_LOGI("AddServerStageHook prio: %{public}d", prio);
17169570cc8Sopenharmony_ci    return HookMgrAddEx(GetAppSpawnHookMgr(), &info);
17269570cc8Sopenharmony_ci}
17369570cc8Sopenharmony_ci
17469570cc8Sopenharmony_cistatic int AppSpawnHookRun(const HOOK_INFO *hookInfo, void *executionContext)
17569570cc8Sopenharmony_ci{
17669570cc8Sopenharmony_ci    AppSpawnForkArg *arg = (AppSpawnForkArg *)executionContext;
17769570cc8Sopenharmony_ci    AppSpawnHook realHook = (AppSpawnHook)hookInfo->hookCookie;
17869570cc8Sopenharmony_ci    return realHook((AppSpawnMgr *)arg->content, (AppSpawningCtx *)arg->client);
17969570cc8Sopenharmony_ci}
18069570cc8Sopenharmony_ci
18169570cc8Sopenharmony_cistatic void PreAppSpawnHookExec(const HOOK_INFO *hookInfo, void *executionContext)
18269570cc8Sopenharmony_ci{
18369570cc8Sopenharmony_ci    AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
18469570cc8Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &arg->tmStart);
18569570cc8Sopenharmony_ci    APPSPAWN_LOGV("Hook stage: %{public}d prio: %{public}d start", hookInfo->stage, hookInfo->prio);
18669570cc8Sopenharmony_ci}
18769570cc8Sopenharmony_ci
18869570cc8Sopenharmony_cistatic void PostAppSpawnHookExec(const HOOK_INFO *hookInfo, void *executionContext, int executionRetVal)
18969570cc8Sopenharmony_ci{
19069570cc8Sopenharmony_ci    AppSpawnHookArg *arg = (AppSpawnHookArg *)executionContext;
19169570cc8Sopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &arg->tmEnd);
19269570cc8Sopenharmony_ci    uint64_t diff = DiffTime(&arg->tmStart, &arg->tmEnd);
19369570cc8Sopenharmony_ci    APPSPAWN_LOGV("Hook stage: %{public}d prio: %{public}d end time %{public}" PRId64 " ns result: %{public}d",
19469570cc8Sopenharmony_ci        hookInfo->stage, hookInfo->prio, diff, executionRetVal);
19569570cc8Sopenharmony_ci}
19669570cc8Sopenharmony_ci
19769570cc8Sopenharmony_ciint AppSpawnHookExecute(AppSpawnHookStage stage, uint32_t flags, AppSpawnContent *content, AppSpawnClient *client)
19869570cc8Sopenharmony_ci{
19969570cc8Sopenharmony_ci    APPSPAWN_CHECK(content != NULL && client != NULL, return APPSPAWN_ARG_INVALID, "Invalid arg");
20069570cc8Sopenharmony_ci    APPSPAWN_LOGV("Execute hook [%{public}d] for app: %{public}s", stage, GetProcessName((AppSpawningCtx *)client));
20169570cc8Sopenharmony_ci    APPSPAWN_CHECK((stage >= STAGE_PARENT_PRE_FORK) && (stage <= STAGE_CHILD_PRE_RUN),
20269570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
20369570cc8Sopenharmony_ci    AppSpawnHookArg forkArg;
20469570cc8Sopenharmony_ci    forkArg.client = client;
20569570cc8Sopenharmony_ci    forkArg.content = content;
20669570cc8Sopenharmony_ci    HOOK_EXEC_OPTIONS options;
20769570cc8Sopenharmony_ci    options.flags = (int)flags;  // TRAVERSE_STOP_WHEN_ERROR : 0;
20869570cc8Sopenharmony_ci    options.preHook = PreAppSpawnHookExec;
20969570cc8Sopenharmony_ci    options.postHook = PostAppSpawnHookExec;
21069570cc8Sopenharmony_ci    int ret = HookMgrExecute(GetAppSpawnHookMgr(), stage, (void *)(&forkArg), &options);
21169570cc8Sopenharmony_ci    ret = (ret == ERR_NO_HOOK_STAGE) ? 0 : ret;
21269570cc8Sopenharmony_ci    if (ret != 0) {
21369570cc8Sopenharmony_ci        APPSPAWN_LOGE("Execute hook [%{public}d] result %{public}d", stage, ret);
21469570cc8Sopenharmony_ci    }
21569570cc8Sopenharmony_ci    return ret;
21669570cc8Sopenharmony_ci}
21769570cc8Sopenharmony_ci
21869570cc8Sopenharmony_ciint AppSpawnExecuteClearEnvHook(AppSpawnContent *content, AppSpawnClient *client)
21969570cc8Sopenharmony_ci{
22069570cc8Sopenharmony_ci    return AppSpawnHookExecute(STAGE_CHILD_PRE_COLDBOOT, HOOK_STOP_WHEN_ERROR, content, client);
22169570cc8Sopenharmony_ci}
22269570cc8Sopenharmony_ci
22369570cc8Sopenharmony_ciint AppSpawnExecuteSpawningHook(AppSpawnContent *content, AppSpawnClient *client)
22469570cc8Sopenharmony_ci{
22569570cc8Sopenharmony_ci    return AppSpawnHookExecute(STAGE_CHILD_EXECUTE, HOOK_STOP_WHEN_ERROR, content, client);
22669570cc8Sopenharmony_ci}
22769570cc8Sopenharmony_ci
22869570cc8Sopenharmony_ciint AppSpawnExecutePostReplyHook(AppSpawnContent *content, AppSpawnClient *client)
22969570cc8Sopenharmony_ci{
23069570cc8Sopenharmony_ci    return AppSpawnHookExecute(STAGE_CHILD_POST_RELY, HOOK_STOP_WHEN_ERROR, content, client);
23169570cc8Sopenharmony_ci}
23269570cc8Sopenharmony_ci
23369570cc8Sopenharmony_ciint AppSpawnExecutePreReplyHook(AppSpawnContent *content, AppSpawnClient *client)
23469570cc8Sopenharmony_ci{
23569570cc8Sopenharmony_ci    return AppSpawnHookExecute(STAGE_CHILD_PRE_RELY, HOOK_STOP_WHEN_ERROR, content, client);
23669570cc8Sopenharmony_ci}
23769570cc8Sopenharmony_ci
23869570cc8Sopenharmony_civoid AppSpawnEnvClear(AppSpawnContent *content, AppSpawnClient *client)
23969570cc8Sopenharmony_ci{
24069570cc8Sopenharmony_ci    (void)AppSpawnHookExecute(STAGE_CHILD_PRE_RUN, 0, content, client);
24169570cc8Sopenharmony_ci}
24269570cc8Sopenharmony_ci
24369570cc8Sopenharmony_ciint AddAppSpawnHook(AppSpawnHookStage stage, int prio, AppSpawnHook hook)
24469570cc8Sopenharmony_ci{
24569570cc8Sopenharmony_ci    APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
24669570cc8Sopenharmony_ci    APPSPAWN_CHECK((stage >= STAGE_PARENT_PRE_FORK) && (stage <= STAGE_CHILD_PRE_RUN),
24769570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
24869570cc8Sopenharmony_ci    HOOK_INFO info;
24969570cc8Sopenharmony_ci    info.stage = stage;
25069570cc8Sopenharmony_ci    info.prio = prio;
25169570cc8Sopenharmony_ci    info.hook = AppSpawnHookRun;
25269570cc8Sopenharmony_ci    info.hookCookie = (void *)hook;
25369570cc8Sopenharmony_ci    APPSPAWN_LOGI("AddAppSpawnHook stage: %{public}d prio: %{public}d", stage, prio);
25469570cc8Sopenharmony_ci    return HookMgrAddEx(GetAppSpawnHookMgr(), &info);
25569570cc8Sopenharmony_ci}
25669570cc8Sopenharmony_ci
25769570cc8Sopenharmony_ciint ProcessMgrHookExecute(AppSpawnHookStage stage, const AppSpawnContent *content,
25869570cc8Sopenharmony_ci    const AppSpawnedProcessInfo *appInfo)
25969570cc8Sopenharmony_ci{
26069570cc8Sopenharmony_ci    APPSPAWN_CHECK(content != NULL && appInfo != NULL,
26169570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid hook");
26269570cc8Sopenharmony_ci    APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED),
26369570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
26469570cc8Sopenharmony_ci
26569570cc8Sopenharmony_ci    AppSpawnAppArg arg;
26669570cc8Sopenharmony_ci    arg.appInfo = appInfo;
26769570cc8Sopenharmony_ci    arg.content = content;
26869570cc8Sopenharmony_ci    int ret = HookMgrExecute(GetAppSpawnHookMgr(), stage, (void *)(&arg), NULL);
26969570cc8Sopenharmony_ci    return ret == ERR_NO_HOOK_STAGE ? 0 : ret;
27069570cc8Sopenharmony_ci}
27169570cc8Sopenharmony_ci
27269570cc8Sopenharmony_cistatic int ProcessMgrHookRun(const HOOK_INFO *hookInfo, void *executionContext)
27369570cc8Sopenharmony_ci{
27469570cc8Sopenharmony_ci    AppSpawnAppArg *arg = (AppSpawnAppArg *)executionContext;
27569570cc8Sopenharmony_ci    ProcessChangeHook realHook = (ProcessChangeHook)hookInfo->hookCookie;
27669570cc8Sopenharmony_ci    return realHook((AppSpawnMgr *)arg->content, arg->appInfo);
27769570cc8Sopenharmony_ci}
27869570cc8Sopenharmony_ci
27969570cc8Sopenharmony_ciint AddProcessMgrHook(AppSpawnHookStage stage, int prio, ProcessChangeHook hook)
28069570cc8Sopenharmony_ci{
28169570cc8Sopenharmony_ci    APPSPAWN_CHECK(hook != NULL, return APPSPAWN_ARG_INVALID, "Invalid hook");
28269570cc8Sopenharmony_ci    APPSPAWN_CHECK((stage >= STAGE_SERVER_APP_ADD) && (stage <= STAGE_SERVER_APP_DIED),
28369570cc8Sopenharmony_ci        return APPSPAWN_ARG_INVALID, "Invalid stage %{public}d", (int)stage);
28469570cc8Sopenharmony_ci    HOOK_INFO info;
28569570cc8Sopenharmony_ci    info.stage = stage;
28669570cc8Sopenharmony_ci    info.prio = prio;
28769570cc8Sopenharmony_ci    info.hook = ProcessMgrHookRun;
28869570cc8Sopenharmony_ci    info.hookCookie = hook;
28969570cc8Sopenharmony_ci    return HookMgrAddEx(GetAppSpawnHookMgr(), &info);
29069570cc8Sopenharmony_ci}
29169570cc8Sopenharmony_ci
29269570cc8Sopenharmony_civoid RegChildLooper(struct AppSpawnContent *content, ChildLoop loop)
29369570cc8Sopenharmony_ci{
29469570cc8Sopenharmony_ci    APPSPAWN_CHECK(content != NULL && loop != NULL, return, "Invalid content for RegChildLooper");
29569570cc8Sopenharmony_ci    content->runChildProcessor = loop;
29669570cc8Sopenharmony_ci}
297