1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci#include <ctype.h>
16d9f0492fSopenharmony_ci
17d9f0492fSopenharmony_ci#include "init_param.h"
18d9f0492fSopenharmony_ci#include "init_service_manager.h"
19d9f0492fSopenharmony_ci#include "init_utils.h"
20d9f0492fSopenharmony_ci#include "param_manager.h"
21d9f0492fSopenharmony_ci#include "param_message.h"
22d9f0492fSopenharmony_ci#include "param_utils.h"
23d9f0492fSopenharmony_ci#include "trigger_checker.h"
24d9f0492fSopenharmony_ci#include "trigger_manager.h"
25d9f0492fSopenharmony_ci#include "securec.h"
26d9f0492fSopenharmony_ci#include "hookmgr.h"
27d9f0492fSopenharmony_ci#include "bootstage.h"
28d9f0492fSopenharmony_ci
29d9f0492fSopenharmony_ci#define MAX_TRIGGER_COUNT_RUN_ONCE 20
30d9f0492fSopenharmony_ci#define MAX_TRIGGER_NAME_LENGTH 256
31d9f0492fSopenharmony_cistatic TriggerWorkSpace g_triggerWorkSpace = {};
32d9f0492fSopenharmony_ci
33d9f0492fSopenharmony_cistatic int DoTriggerExecute_(const TriggerNode *trigger, const char *content, uint32_t size)
34d9f0492fSopenharmony_ci{
35d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return -1, "Invalid trigger");
36d9f0492fSopenharmony_ci    PARAM_LOGV("Do execute trigger %s type: %d", GetTriggerName(trigger), trigger->type);
37d9f0492fSopenharmony_ci    PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return -1, "Invalid trigger type %d", trigger->type);
38d9f0492fSopenharmony_ci    CommandNode *cmd = GetNextCmdNode((JobNode *)trigger, NULL);
39d9f0492fSopenharmony_ci    while (cmd != NULL) {
40d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST
41d9f0492fSopenharmony_ci        DoCmdByIndex(cmd->cmdKeyIndex, cmd->content, &cmd->cfgContext);
42d9f0492fSopenharmony_ci#endif
43d9f0492fSopenharmony_ci        cmd = GetNextCmdNode((JobNode *)trigger, cmd);
44d9f0492fSopenharmony_ci    }
45d9f0492fSopenharmony_ci    return 0;
46d9f0492fSopenharmony_ci}
47d9f0492fSopenharmony_ci
48d9f0492fSopenharmony_cistatic int DoTriggerCheckResult(TriggerNode *trigger, const char *content, uint32_t size)
49d9f0492fSopenharmony_ci{
50d9f0492fSopenharmony_ci    UNUSED(content);
51d9f0492fSopenharmony_ci    UNUSED(size);
52d9f0492fSopenharmony_ci    if (TRIGGER_IN_QUEUE(trigger)) {
53d9f0492fSopenharmony_ci        PARAM_LOGI("DoTiggerExecute trigger %s has been waiting execute", GetTriggerName(trigger));
54d9f0492fSopenharmony_ci        return 0;
55d9f0492fSopenharmony_ci    }
56d9f0492fSopenharmony_ci    TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_QUEUE);
57d9f0492fSopenharmony_ci    PARAM_LOGV("Add trigger %s to execute queue", GetTriggerName(trigger));
58d9f0492fSopenharmony_ci    ExecuteQueuePush(&g_triggerWorkSpace, trigger);
59d9f0492fSopenharmony_ci    return 0;
60d9f0492fSopenharmony_ci}
61d9f0492fSopenharmony_ci
62d9f0492fSopenharmony_cistatic int ExecuteTriggerImmediately(TriggerNode *trigger, const char *content, uint32_t size)
63d9f0492fSopenharmony_ci{
64d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return -1, "Invalid trigger");
65d9f0492fSopenharmony_ci    PARAM_LOGV("ExecuteTriggerImmediately trigger %s", GetTriggerName(trigger));
66d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, trigger->type);
67d9f0492fSopenharmony_ci    if (triggerHead != NULL) {
68d9f0492fSopenharmony_ci        triggerHead->executeTrigger(trigger, content, size);
69d9f0492fSopenharmony_ci        TRIGGER_CLEAR_FLAG(trigger, TRIGGER_FLAGS_QUEUE);
70d9f0492fSopenharmony_ci
71d9f0492fSopenharmony_ci        if (TRIGGER_TEST_FLAG(trigger, TRIGGER_FLAGS_ONCE)) {
72d9f0492fSopenharmony_ci            FreeTrigger(&g_triggerWorkSpace, trigger);
73d9f0492fSopenharmony_ci        }
74d9f0492fSopenharmony_ci    }
75d9f0492fSopenharmony_ci    return 0;
76d9f0492fSopenharmony_ci}
77d9f0492fSopenharmony_ci
78d9f0492fSopenharmony_cistatic void StartTriggerExecute_(TriggerNode *trigger, const char *content, uint32_t size)
79d9f0492fSopenharmony_ci{
80d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, trigger->type);
81d9f0492fSopenharmony_ci    if (triggerHead != NULL) {
82d9f0492fSopenharmony_ci        PARAM_LOGV("StartTriggerExecute_ trigger %s flags:0x%04x",
83d9f0492fSopenharmony_ci            GetTriggerName(trigger), trigger->flags);
84d9f0492fSopenharmony_ci        triggerHead->executeTrigger(trigger, content, size);
85d9f0492fSopenharmony_ci        TRIGGER_CLEAR_FLAG(trigger, TRIGGER_FLAGS_QUEUE);
86d9f0492fSopenharmony_ci        if (TRIGGER_TEST_FLAG(trigger, TRIGGER_FLAGS_SUBTRIGGER)) { // boot && xxx=xxx trigger
87d9f0492fSopenharmony_ci            const char *condition = triggerHead->getCondition(trigger);
88d9f0492fSopenharmony_ci            CheckTrigger(&g_triggerWorkSpace, TRIGGER_UNKNOW, condition, strlen(condition), ExecuteTriggerImmediately);
89d9f0492fSopenharmony_ci        }
90d9f0492fSopenharmony_ci        if (TRIGGER_TEST_FLAG(trigger, TRIGGER_FLAGS_ONCE)) {
91d9f0492fSopenharmony_ci            FreeTrigger(&g_triggerWorkSpace, trigger);
92d9f0492fSopenharmony_ci        }
93d9f0492fSopenharmony_ci    }
94d9f0492fSopenharmony_ci}
95d9f0492fSopenharmony_ci
96d9f0492fSopenharmony_cistatic void ExecuteQueueWork(uint32_t maxCount, void (*bootStateChange)(int start, const char *))
97d9f0492fSopenharmony_ci{
98d9f0492fSopenharmony_ci    uint32_t executeCount = 0;
99d9f0492fSopenharmony_ci    TriggerNode *trigger = ExecuteQueuePop(&g_triggerWorkSpace);
100d9f0492fSopenharmony_ci    char triggerName[MAX_TRIGGER_NAME_LENGTH] = {0};
101d9f0492fSopenharmony_ci    while (trigger != NULL) {
102d9f0492fSopenharmony_ci        int ret = strcpy_s(triggerName, sizeof(triggerName), GetTriggerName(trigger));
103d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, return, "strcpy triggerName failed!");
104d9f0492fSopenharmony_ci        if (bootStateChange != NULL) {
105d9f0492fSopenharmony_ci            bootStateChange(0, triggerName);
106d9f0492fSopenharmony_ci        }
107d9f0492fSopenharmony_ci
108d9f0492fSopenharmony_ci        StartTriggerExecute_(trigger, NULL, 0);
109d9f0492fSopenharmony_ci        if (bootStateChange != NULL) {
110d9f0492fSopenharmony_ci            bootStateChange(1, triggerName);
111d9f0492fSopenharmony_ci        }
112d9f0492fSopenharmony_ci        executeCount++;
113d9f0492fSopenharmony_ci        if (executeCount > maxCount) {
114d9f0492fSopenharmony_ci            break;
115d9f0492fSopenharmony_ci        }
116d9f0492fSopenharmony_ci        trigger = ExecuteQueuePop(&g_triggerWorkSpace);
117d9f0492fSopenharmony_ci    }
118d9f0492fSopenharmony_ci}
119d9f0492fSopenharmony_ci
120d9f0492fSopenharmony_ciPARAM_STATIC void ProcessBeforeEvent(const ParamTaskPtr stream,
121d9f0492fSopenharmony_ci    uint64_t eventId, const uint8_t *content, uint32_t size)
122d9f0492fSopenharmony_ci{
123d9f0492fSopenharmony_ci    PARAM_LOGV("ProcessBeforeEvent %s ", (char *)content);
124d9f0492fSopenharmony_ci    switch (eventId) {
125d9f0492fSopenharmony_ci        case EVENT_TRIGGER_PARAM: {
126d9f0492fSopenharmony_ci            CheckTrigger(&g_triggerWorkSpace, TRIGGER_PARAM,
127d9f0492fSopenharmony_ci                (const char *)content, size, DoTriggerCheckResult);
128d9f0492fSopenharmony_ci            ExecuteQueueWork(MAX_TRIGGER_COUNT_RUN_ONCE, NULL);
129d9f0492fSopenharmony_ci            break;
130d9f0492fSopenharmony_ci        }
131d9f0492fSopenharmony_ci        case EVENT_TRIGGER_BOOT: {
132d9f0492fSopenharmony_ci            if (g_triggerWorkSpace.bootStateChange != NULL) {
133d9f0492fSopenharmony_ci                g_triggerWorkSpace.bootStateChange(0, (const char *)content);
134d9f0492fSopenharmony_ci            }
135d9f0492fSopenharmony_ci            CheckTrigger(&g_triggerWorkSpace, TRIGGER_BOOT,
136d9f0492fSopenharmony_ci                (const char *)content, size, DoTriggerCheckResult);
137d9f0492fSopenharmony_ci            ExecuteQueueWork(1, NULL);
138d9f0492fSopenharmony_ci            if (g_triggerWorkSpace.bootStateChange != NULL) {
139d9f0492fSopenharmony_ci                g_triggerWorkSpace.bootStateChange(1, (const char *)content);
140d9f0492fSopenharmony_ci            }
141d9f0492fSopenharmony_ci            ExecuteQueueWork(MAX_TRIGGER_COUNT_RUN_ONCE, g_triggerWorkSpace.bootStateChange);
142d9f0492fSopenharmony_ci            break;
143d9f0492fSopenharmony_ci        }
144d9f0492fSopenharmony_ci        case EVENT_TRIGGER_PARAM_WAIT: {
145d9f0492fSopenharmony_ci            CheckTrigger(&g_triggerWorkSpace, TRIGGER_PARAM_WAIT,
146d9f0492fSopenharmony_ci                (const char *)content, size, ExecuteTriggerImmediately);
147d9f0492fSopenharmony_ci            break;
148d9f0492fSopenharmony_ci        }
149d9f0492fSopenharmony_ci        case EVENT_TRIGGER_PARAM_WATCH: {
150d9f0492fSopenharmony_ci            CheckTrigger(&g_triggerWorkSpace, TRIGGER_PARAM_WATCH,
151d9f0492fSopenharmony_ci                (const char *)content, size, ExecuteTriggerImmediately);
152d9f0492fSopenharmony_ci            break;
153d9f0492fSopenharmony_ci        }
154d9f0492fSopenharmony_ci        default:
155d9f0492fSopenharmony_ci            break;
156d9f0492fSopenharmony_ci    }
157d9f0492fSopenharmony_ci}
158d9f0492fSopenharmony_ci
159d9f0492fSopenharmony_cistatic void SendTriggerEvent(int type, const char *content, uint32_t contentLen)
160d9f0492fSopenharmony_ci{
161d9f0492fSopenharmony_ci    PARAM_CHECK(content != NULL, return, "Invalid param");
162d9f0492fSopenharmony_ci    PARAM_LOGV("SendTriggerEvent type %d content %s", type, content);
163d9f0492fSopenharmony_ci    ParamEventSend(g_triggerWorkSpace.eventHandle, (uint64_t)type, content, contentLen);
164d9f0492fSopenharmony_ci}
165d9f0492fSopenharmony_ci
166d9f0492fSopenharmony_civoid PostParamTrigger(int type, const char *name, const char *value)
167d9f0492fSopenharmony_ci{
168d9f0492fSopenharmony_ci    PARAM_CHECK(name != NULL && value != NULL, return, "Invalid param");
169d9f0492fSopenharmony_ci    uint32_t bufferSize = strlen(name) + strlen(value) + 1 + 1 + 1;
170d9f0492fSopenharmony_ci    PARAM_CHECK(bufferSize < (PARAM_CONST_VALUE_LEN_MAX + PARAM_NAME_LEN_MAX + 1 + 1 + 1),
171d9f0492fSopenharmony_ci        return, "bufferSize is longest %d", bufferSize);
172d9f0492fSopenharmony_ci    char *buffer = (char *)calloc(1, bufferSize);
173d9f0492fSopenharmony_ci    PARAM_CHECK(buffer != NULL, return, "Failed to alloc memory for  param %s", name);
174d9f0492fSopenharmony_ci    int ret = sprintf_s(buffer, bufferSize - 1, "%s=%s", name, value);
175d9f0492fSopenharmony_ci    PARAM_CHECK(ret > EOK, free(buffer);
176d9f0492fSopenharmony_ci        return, "Failed to copy param");
177d9f0492fSopenharmony_ci    SendTriggerEvent(type, buffer, strlen(buffer));
178d9f0492fSopenharmony_ci    free(buffer);
179d9f0492fSopenharmony_ci}
180d9f0492fSopenharmony_ci
181d9f0492fSopenharmony_civoid PostTrigger(EventType type, const char *content, uint32_t contentLen)
182d9f0492fSopenharmony_ci{
183d9f0492fSopenharmony_ci    PARAM_CHECK(content != NULL && contentLen > 0, return, "Invalid param");
184d9f0492fSopenharmony_ci    SendTriggerEvent(type, content, contentLen);
185d9f0492fSopenharmony_ci}
186d9f0492fSopenharmony_ci
187d9f0492fSopenharmony_cistatic int GetTriggerType(const char *type)
188d9f0492fSopenharmony_ci{
189d9f0492fSopenharmony_ci    if (strncmp("param:", type, strlen("param:")) == 0) {
190d9f0492fSopenharmony_ci        return TRIGGER_PARAM;
191d9f0492fSopenharmony_ci    }
192d9f0492fSopenharmony_ci    if (strncmp("boot-service:", type, strlen("boot-service:")) == 0) {
193d9f0492fSopenharmony_ci        return TRIGGER_BOOT;
194d9f0492fSopenharmony_ci    }
195d9f0492fSopenharmony_ci    const char *triggerTypeStr[] = {
196d9f0492fSopenharmony_ci        "pre-init", "boot", "early-init", "init", "early-init", "late-init", "post-init",
197d9f0492fSopenharmony_ci        "fs", "early-fs", "post-fs", "late-fs", "early-boot", "post-fs-data", "reboot", "suspend"
198d9f0492fSopenharmony_ci    };
199d9f0492fSopenharmony_ci    for (size_t i = 0; i < ARRAY_LENGTH(triggerTypeStr); i++) {
200d9f0492fSopenharmony_ci        if (strcmp(triggerTypeStr[i], type) == 0) {
201d9f0492fSopenharmony_ci            return TRIGGER_BOOT;
202d9f0492fSopenharmony_ci        }
203d9f0492fSopenharmony_ci    }
204d9f0492fSopenharmony_ci    return TRIGGER_UNKNOW;
205d9f0492fSopenharmony_ci}
206d9f0492fSopenharmony_ci
207d9f0492fSopenharmony_cistatic int GetCommandInfo(const char *cmdLine, int *cmdKeyIndex, char **content)
208d9f0492fSopenharmony_ci{
209d9f0492fSopenharmony_ci    const char *matchCmd = GetMatchCmd(cmdLine, cmdKeyIndex);
210d9f0492fSopenharmony_ci    PARAM_CHECK(matchCmd != NULL, return -1, "Command not support %s", cmdLine);
211d9f0492fSopenharmony_ci    char *str = strstr(cmdLine, matchCmd);
212d9f0492fSopenharmony_ci    if (str != NULL) {
213d9f0492fSopenharmony_ci        str += strlen(matchCmd);
214d9f0492fSopenharmony_ci    }
215d9f0492fSopenharmony_ci    while (str != NULL && isspace(*str)) {
216d9f0492fSopenharmony_ci        str++;
217d9f0492fSopenharmony_ci    }
218d9f0492fSopenharmony_ci    *content = str;
219d9f0492fSopenharmony_ci    return 0;
220d9f0492fSopenharmony_ci}
221d9f0492fSopenharmony_ci
222d9f0492fSopenharmony_cistatic void ParseJobHookExecute(const char *name, const cJSON *jobNode)
223d9f0492fSopenharmony_ci{
224d9f0492fSopenharmony_ci    JOB_PARSE_CTX context;
225d9f0492fSopenharmony_ci
226d9f0492fSopenharmony_ci    context.jobName = name;
227d9f0492fSopenharmony_ci    context.jobNode = jobNode;
228d9f0492fSopenharmony_ci
229d9f0492fSopenharmony_ci    (void)HookMgrExecute(GetBootStageHookMgr(), INIT_JOB_PARSE, (void *)(&context), NULL);
230d9f0492fSopenharmony_ci}
231d9f0492fSopenharmony_ci
232d9f0492fSopenharmony_cistatic int ParseTrigger_(const TriggerWorkSpace *workSpace,
233d9f0492fSopenharmony_ci    const cJSON *triggerItem, int (*checkJobValid)(const char *jobName), const ConfigContext *cfgContext)
234d9f0492fSopenharmony_ci{
235d9f0492fSopenharmony_ci    PARAM_CHECK(triggerItem != NULL, return -1, "Invalid file");
236d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return -1, "Failed to create trigger list");
237d9f0492fSopenharmony_ci    char *name = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "name"));
238d9f0492fSopenharmony_ci    PARAM_CHECK(name != NULL, return -1, "Can not get name from cfg");
239d9f0492fSopenharmony_ci    char *condition = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "condition"));
240d9f0492fSopenharmony_ci    int type = GetTriggerType(name);
241d9f0492fSopenharmony_ci    PARAM_CHECK(type <= TRIGGER_UNKNOW, return -1, "Failed to get trigger index");
242d9f0492fSopenharmony_ci    if (type != TRIGGER_BOOT && checkJobValid != NULL && checkJobValid(name) != 0) {
243d9f0492fSopenharmony_ci        PARAM_LOGI("Trigger %s not exist in group", name);
244d9f0492fSopenharmony_ci        return 0;
245d9f0492fSopenharmony_ci    }
246d9f0492fSopenharmony_ci
247d9f0492fSopenharmony_ci    TriggerHeader *header = GetTriggerHeader(workSpace, type);
248d9f0492fSopenharmony_ci    PARAM_CHECK(header != NULL, return -1, "Failed to get header %d", type);
249d9f0492fSopenharmony_ci    JobNode *trigger = UpdateJobTrigger(workSpace, type, condition, name);
250d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return -1, "Failed to create trigger %s", name);
251d9f0492fSopenharmony_ci    PARAM_LOGV("ParseTrigger %s type %d count %d", name, type, header->triggerCount);
252d9f0492fSopenharmony_ci    cJSON *cmdItems = cJSON_GetObjectItem(triggerItem, CMDS_ARR_NAME_IN_JSON);
253d9f0492fSopenharmony_ci    if (cmdItems == NULL || !cJSON_IsArray(cmdItems)) {
254d9f0492fSopenharmony_ci        return 0;
255d9f0492fSopenharmony_ci    }
256d9f0492fSopenharmony_ci    int cmdLinesCnt = cJSON_GetArraySize(cmdItems);
257d9f0492fSopenharmony_ci    PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name);
258d9f0492fSopenharmony_ci
259d9f0492fSopenharmony_ci    int ret;
260d9f0492fSopenharmony_ci    int cmdKeyIndex = 0;
261d9f0492fSopenharmony_ci    for (int i = 0; (i < cmdLinesCnt) && (i < TRIGGER_MAX_CMD); ++i) {
262d9f0492fSopenharmony_ci        char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i));
263d9f0492fSopenharmony_ci        PARAM_CHECK(cmdLineStr != NULL, continue, "Command is null");
264d9f0492fSopenharmony_ci
265d9f0492fSopenharmony_ci        char *content = NULL;
266d9f0492fSopenharmony_ci        ret = GetCommandInfo(cmdLineStr, &cmdKeyIndex, &content);
267d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, continue, "Command not support %s", cmdLineStr);
268d9f0492fSopenharmony_ci        ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content, cfgContext);
269d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, continue, "Failed to add command %s", cmdLineStr);
270d9f0492fSopenharmony_ci        header->cmdNodeCount++;
271d9f0492fSopenharmony_ci    }
272d9f0492fSopenharmony_ci    return 0;
273d9f0492fSopenharmony_ci}
274d9f0492fSopenharmony_ci
275d9f0492fSopenharmony_ciint ParseTriggerConfig(const cJSON *fileRoot, int (*checkJobValid)(const char *jobName), void *context)
276d9f0492fSopenharmony_ci{
277d9f0492fSopenharmony_ci    PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Invalid trigger data");
278d9f0492fSopenharmony_ci    PARAM_CHECK(fileRoot != NULL, return -1, "Invalid file");
279d9f0492fSopenharmony_ci    ConfigContext *cfgContext = (ConfigContext *)context;
280d9f0492fSopenharmony_ci    cJSON *triggers = cJSON_GetObjectItemCaseSensitive(fileRoot, TRIGGER_ARR_NAME_IN_JSON);
281d9f0492fSopenharmony_ci    if (triggers == NULL || !cJSON_IsArray(triggers)) {
282d9f0492fSopenharmony_ci        return 0;
283d9f0492fSopenharmony_ci    }
284d9f0492fSopenharmony_ci    int size = cJSON_GetArraySize(triggers);
285d9f0492fSopenharmony_ci    PARAM_CHECK(size > 0, return -1, "Trigger array size must positive");
286d9f0492fSopenharmony_ci
287d9f0492fSopenharmony_ci    for (int i = 0; i < size && i < TRIGGER_MAX_CMD; ++i) {
288d9f0492fSopenharmony_ci        cJSON *item = cJSON_GetArrayItem(triggers, i);
289d9f0492fSopenharmony_ci        ParseTrigger_(&g_triggerWorkSpace, item, checkJobValid, cfgContext);
290d9f0492fSopenharmony_ci        /*
291d9f0492fSopenharmony_ci         * execute job parsing hooks
292d9f0492fSopenharmony_ci         */
293d9f0492fSopenharmony_ci        ParseJobHookExecute(cJSON_GetStringValue(cJSON_GetObjectItem(item, "name")), item);
294d9f0492fSopenharmony_ci    }
295d9f0492fSopenharmony_ci    return 0;
296d9f0492fSopenharmony_ci}
297d9f0492fSopenharmony_ci
298d9f0492fSopenharmony_ciint CheckAndMarkTrigger(int type, const char *name)
299d9f0492fSopenharmony_ci{
300d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, type);
301d9f0492fSopenharmony_ci    if (triggerHead) {
302d9f0492fSopenharmony_ci        return triggerHead->checkAndMarkTrigger(&g_triggerWorkSpace, type, name);
303d9f0492fSopenharmony_ci    }
304d9f0492fSopenharmony_ci    return 0;
305d9f0492fSopenharmony_ci}
306d9f0492fSopenharmony_ci
307d9f0492fSopenharmony_ciint InitTriggerWorkSpace(void)
308d9f0492fSopenharmony_ci{
309d9f0492fSopenharmony_ci    if (g_triggerWorkSpace.eventHandle != NULL) {
310d9f0492fSopenharmony_ci        return 0;
311d9f0492fSopenharmony_ci    }
312d9f0492fSopenharmony_ci    g_triggerWorkSpace.bootStateChange = NULL;
313d9f0492fSopenharmony_ci    ParamEventTaskCreate(&g_triggerWorkSpace.eventHandle, ProcessBeforeEvent);
314d9f0492fSopenharmony_ci    PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Failed to event handle");
315d9f0492fSopenharmony_ci
316d9f0492fSopenharmony_ci    // executeQueue
317d9f0492fSopenharmony_ci    g_triggerWorkSpace.executeQueue.executeQueue = calloc(1, TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
318d9f0492fSopenharmony_ci    PARAM_CHECK(g_triggerWorkSpace.executeQueue.executeQueue != NULL,
319d9f0492fSopenharmony_ci        return -1, "Failed to alloc memory for executeQueue");
320d9f0492fSopenharmony_ci    g_triggerWorkSpace.executeQueue.queueCount = TRIGGER_EXECUTE_QUEUE;
321d9f0492fSopenharmony_ci    g_triggerWorkSpace.executeQueue.startIndex = 0;
322d9f0492fSopenharmony_ci    g_triggerWorkSpace.executeQueue.endIndex = 0;
323d9f0492fSopenharmony_ci    InitTriggerHead(&g_triggerWorkSpace);
324d9f0492fSopenharmony_ci    RegisterTriggerExec(TRIGGER_BOOT, DoTriggerExecute_);
325d9f0492fSopenharmony_ci    RegisterTriggerExec(TRIGGER_PARAM, DoTriggerExecute_);
326d9f0492fSopenharmony_ci    RegisterTriggerExec(TRIGGER_UNKNOW, DoTriggerExecute_);
327d9f0492fSopenharmony_ci    PARAM_LOGV("InitTriggerWorkSpace success");
328d9f0492fSopenharmony_ci    return 0;
329d9f0492fSopenharmony_ci}
330d9f0492fSopenharmony_ci
331d9f0492fSopenharmony_civoid CloseTriggerWorkSpace(void)
332d9f0492fSopenharmony_ci{
333d9f0492fSopenharmony_ci    for (size_t i = 0; i < sizeof(g_triggerWorkSpace.triggerHead) / sizeof(g_triggerWorkSpace.triggerHead[0]); i++) {
334d9f0492fSopenharmony_ci        ClearTrigger(&g_triggerWorkSpace, i);
335d9f0492fSopenharmony_ci    }
336d9f0492fSopenharmony_ci    OH_HashMapDestory(g_triggerWorkSpace.hashMap, NULL);
337d9f0492fSopenharmony_ci    g_triggerWorkSpace.hashMap = NULL;
338d9f0492fSopenharmony_ci    free(g_triggerWorkSpace.executeQueue.executeQueue);
339d9f0492fSopenharmony_ci    g_triggerWorkSpace.executeQueue.executeQueue = NULL;
340d9f0492fSopenharmony_ci    ParamTaskClose(g_triggerWorkSpace.eventHandle);
341d9f0492fSopenharmony_ci    g_triggerWorkSpace.eventHandle = NULL;
342d9f0492fSopenharmony_ci}
343d9f0492fSopenharmony_ci
344d9f0492fSopenharmony_ciTriggerWorkSpace *GetTriggerWorkSpace(void)
345d9f0492fSopenharmony_ci{
346d9f0492fSopenharmony_ci    return &g_triggerWorkSpace;
347d9f0492fSopenharmony_ci}
348d9f0492fSopenharmony_ci
349d9f0492fSopenharmony_civoid RegisterTriggerExec(int type,
350d9f0492fSopenharmony_ci    int32_t (*executeTrigger)(const struct tagTriggerNode_ *, const char *, uint32_t))
351d9f0492fSopenharmony_ci{
352d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(&g_triggerWorkSpace, type);
353d9f0492fSopenharmony_ci    if (triggerHead != NULL) {
354d9f0492fSopenharmony_ci        triggerHead->executeTrigger = executeTrigger;
355d9f0492fSopenharmony_ci    }
356d9f0492fSopenharmony_ci}
357d9f0492fSopenharmony_ci
358d9f0492fSopenharmony_civoid DoTriggerExec(const char *triggerName)
359d9f0492fSopenharmony_ci{
360d9f0492fSopenharmony_ci    PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return, "Invalid trigger data");
361d9f0492fSopenharmony_ci    PARAM_CHECK(triggerName != NULL, return, "Invalid param");
362d9f0492fSopenharmony_ci    JobNode *trigger = GetTriggerByName(&g_triggerWorkSpace, triggerName);
363d9f0492fSopenharmony_ci    if (trigger != NULL && !TRIGGER_IN_QUEUE((TriggerNode *)trigger)) {
364d9f0492fSopenharmony_ci        PARAM_LOGV("Trigger job %s", trigger->name);
365d9f0492fSopenharmony_ci        TRIGGER_SET_FLAG((TriggerNode *)trigger, TRIGGER_FLAGS_QUEUE);
366d9f0492fSopenharmony_ci        ExecuteQueuePush(&g_triggerWorkSpace, (TriggerNode *)trigger);
367d9f0492fSopenharmony_ci    } else {
368d9f0492fSopenharmony_ci        PARAM_LOGW("Can not find trigger %s", triggerName);
369d9f0492fSopenharmony_ci    }
370d9f0492fSopenharmony_ci}
371d9f0492fSopenharmony_ci
372d9f0492fSopenharmony_civoid DoJobExecNow(const char *triggerName)
373d9f0492fSopenharmony_ci{
374d9f0492fSopenharmony_ci    PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return, "Invalid trigger data");
375d9f0492fSopenharmony_ci    PARAM_CHECK(triggerName != NULL, return, "Invalid param");
376d9f0492fSopenharmony_ci    JobNode *trigger = GetTriggerByName(&g_triggerWorkSpace, triggerName);
377d9f0492fSopenharmony_ci    if (trigger != NULL) {
378d9f0492fSopenharmony_ci        if (strncmp(triggerName, "reboot", strlen("reboot")) == 0) {
379d9f0492fSopenharmony_ci            HookMgrExecute(GetBootStageHookMgr(), INIT_SHUT_DETECTOR, NULL, NULL);
380d9f0492fSopenharmony_ci        }
381d9f0492fSopenharmony_ci        StartTriggerExecute_((TriggerNode *)trigger, NULL, 0);
382d9f0492fSopenharmony_ci    }
383d9f0492fSopenharmony_ci}
384d9f0492fSopenharmony_ci
385d9f0492fSopenharmony_ciint AddCompleteJob(const char *name, const char *condition, const char *cmdContent)
386d9f0492fSopenharmony_ci{
387d9f0492fSopenharmony_ci    PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Invalid trigger data");
388d9f0492fSopenharmony_ci    PARAM_CHECK(name != NULL, return -1, "Invalid name");
389d9f0492fSopenharmony_ci    PARAM_CHECK(cmdContent != NULL, return -1, "Invalid cmdContent");
390d9f0492fSopenharmony_ci    int type = GetTriggerType(name);
391d9f0492fSopenharmony_ci    PARAM_CHECK(type <= TRIGGER_UNKNOW, return -1, "Failed to get trigger index");
392d9f0492fSopenharmony_ci    TriggerHeader *header = GetTriggerHeader(&g_triggerWorkSpace, type);
393d9f0492fSopenharmony_ci    PARAM_CHECK(header != NULL, return -1, "Failed to get header %d", type);
394d9f0492fSopenharmony_ci
395d9f0492fSopenharmony_ci    JobNode *trigger = UpdateJobTrigger(&g_triggerWorkSpace, type, condition, name);
396d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return -1, "Failed to create trigger");
397d9f0492fSopenharmony_ci    char *content = NULL;
398d9f0492fSopenharmony_ci    int cmdKeyIndex = 0;
399d9f0492fSopenharmony_ci    int ret = GetCommandInfo(cmdContent, &cmdKeyIndex, &content);
400d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Command not support %s", cmdContent);
401d9f0492fSopenharmony_ci    ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, content, NULL); // use default context
402d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Failed to add command %s", cmdContent);
403d9f0492fSopenharmony_ci    header->cmdNodeCount++;
404d9f0492fSopenharmony_ci    PARAM_LOGV("AddCompleteJob %s type %d count %d", name, type, header->triggerCount);
405d9f0492fSopenharmony_ci    return 0;
406d9f0492fSopenharmony_ci}
407d9f0492fSopenharmony_ci
408d9f0492fSopenharmony_civoid RegisterBootStateChange(void (*bootStateChange)(int, const char *))
409d9f0492fSopenharmony_ci{
410d9f0492fSopenharmony_ci    if (bootStateChange != NULL) {
411d9f0492fSopenharmony_ci        g_triggerWorkSpace.bootStateChange = bootStateChange;
412d9f0492fSopenharmony_ci    }
413d9f0492fSopenharmony_ci}
414