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
16d9f0492fSopenharmony_ci#include "trigger_manager.h"
17d9f0492fSopenharmony_ci
18d9f0492fSopenharmony_ci#include <string.h>
19d9f0492fSopenharmony_ci#include <sys/types.h>
20d9f0492fSopenharmony_ci
21d9f0492fSopenharmony_ci#include "init_cmds.h"
22d9f0492fSopenharmony_ci#include "param_manager.h"
23d9f0492fSopenharmony_ci#include "trigger_checker.h"
24d9f0492fSopenharmony_ci#include "securec.h"
25d9f0492fSopenharmony_ci
26d9f0492fSopenharmony_cistatic DUMP_PRINTF g_printf = printf;
27d9f0492fSopenharmony_ci
28d9f0492fSopenharmony_ciint AddCommand(JobNode *trigger, uint32_t cmdKeyIndex, const char *content, const ConfigContext *cfgContext)
29d9f0492fSopenharmony_ci{
30d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return -1, "trigger is null");
31d9f0492fSopenharmony_ci    uint32_t size = sizeof(CommandNode);
32d9f0492fSopenharmony_ci    size += (content == NULL) ? 1 : (strlen(content) + 1);
33d9f0492fSopenharmony_ci    size = PARAM_ALIGN(size);
34d9f0492fSopenharmony_ci
35d9f0492fSopenharmony_ci    CommandNode *node = (CommandNode *)calloc(1, size);
36d9f0492fSopenharmony_ci    PARAM_CHECK(node != NULL, return -1, "Failed to alloc memory for command");
37d9f0492fSopenharmony_ci    node->cmdKeyIndex = cmdKeyIndex;
38d9f0492fSopenharmony_ci    node->next = NULL;
39d9f0492fSopenharmony_ci    node->content[0] = '\0';
40d9f0492fSopenharmony_ci    if (content != NULL && strlen(content) != 0) {
41d9f0492fSopenharmony_ci        int ret = memcpy_s(node->content, size, content, strlen(content));
42d9f0492fSopenharmony_ci        node->content[strlen(content)] = '\0';
43d9f0492fSopenharmony_ci        PARAM_CHECK(ret == EOK, free(node);
44d9f0492fSopenharmony_ci            return 0, "Failed to copy command");
45d9f0492fSopenharmony_ci    }
46d9f0492fSopenharmony_ci    node->cfgContext.type = INIT_CONTEXT_MAIN;
47d9f0492fSopenharmony_ci    if (cfgContext != NULL) {
48d9f0492fSopenharmony_ci        node->cfgContext.type = cfgContext->type;
49d9f0492fSopenharmony_ci    }
50d9f0492fSopenharmony_ci    if (trigger->firstCmd == NULL) {
51d9f0492fSopenharmony_ci        trigger->firstCmd = node;
52d9f0492fSopenharmony_ci        trigger->lastCmd = node;
53d9f0492fSopenharmony_ci    } else {
54d9f0492fSopenharmony_ci        PARAM_CHECK(trigger->lastCmd != NULL, free(node);
55d9f0492fSopenharmony_ci            return 0, "Invalid last cmd");
56d9f0492fSopenharmony_ci        trigger->lastCmd->next = node;
57d9f0492fSopenharmony_ci        trigger->lastCmd = node;
58d9f0492fSopenharmony_ci    }
59d9f0492fSopenharmony_ci    return 0;
60d9f0492fSopenharmony_ci}
61d9f0492fSopenharmony_ci
62d9f0492fSopenharmony_ciCommandNode *GetNextCmdNode(const JobNode *trigger, const CommandNode *curr)
63d9f0492fSopenharmony_ci{
64d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return NULL, "trigger is null");
65d9f0492fSopenharmony_ci    if (curr == NULL) {
66d9f0492fSopenharmony_ci        return trigger->firstCmd;
67d9f0492fSopenharmony_ci    }
68d9f0492fSopenharmony_ci    return curr->next;
69d9f0492fSopenharmony_ci}
70d9f0492fSopenharmony_ci
71d9f0492fSopenharmony_cistatic int CopyCondition(TriggerNode *node, const char *condition)
72d9f0492fSopenharmony_ci{
73d9f0492fSopenharmony_ci    if (condition == NULL || strlen(condition) == 0) {
74d9f0492fSopenharmony_ci        return 0;
75d9f0492fSopenharmony_ci    }
76d9f0492fSopenharmony_ci    uint32_t buffSize = 0;
77d9f0492fSopenharmony_ci    char *cond = GetTriggerCache(&buffSize);
78d9f0492fSopenharmony_ci    int ret = ConvertInfixToPrefix(condition, cond, buffSize);
79d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Failed to convert condition for trigger");
80d9f0492fSopenharmony_ci    node->condition = strdup(cond);
81d9f0492fSopenharmony_ci    PARAM_CHECK(node->condition != NULL, return -1, "Failed to dup conditition");
82d9f0492fSopenharmony_ci    return 0;
83d9f0492fSopenharmony_ci}
84d9f0492fSopenharmony_ci
85d9f0492fSopenharmony_cistatic TriggerNode *AddTriggerNode_(TriggerHeader *triggerHead,
86d9f0492fSopenharmony_ci    uint32_t type, const char *condition, uint32_t dataSize)
87d9f0492fSopenharmony_ci{
88d9f0492fSopenharmony_ci    TriggerNode *node = (TriggerNode *)calloc(1, dataSize);
89d9f0492fSopenharmony_ci    PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
90d9f0492fSopenharmony_ci    node->condition = NULL;
91d9f0492fSopenharmony_ci    int ret = CopyCondition(node, condition);
92d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, free(node);
93d9f0492fSopenharmony_ci            return NULL, "Failed to copy conditition");
94d9f0492fSopenharmony_ci    node->type = type;
95d9f0492fSopenharmony_ci    node->flags = 0;
96d9f0492fSopenharmony_ci    OH_ListInit(&node->node);
97d9f0492fSopenharmony_ci    OH_ListAddTail(&triggerHead->triggerList, &node->node);
98d9f0492fSopenharmony_ci    triggerHead->triggerCount++;
99d9f0492fSopenharmony_ci    return node;
100d9f0492fSopenharmony_ci}
101d9f0492fSopenharmony_ci
102d9f0492fSopenharmony_cistatic int32_t AddJobNode_(TriggerNode *trigger, const TriggerExtInfo *extInfo)
103d9f0492fSopenharmony_ci{
104d9f0492fSopenharmony_ci    JobNode *node = (JobNode *)trigger;
105d9f0492fSopenharmony_ci    int ret = strcpy_s(node->name, strlen(extInfo->info.name) + 1, extInfo->info.name);
106d9f0492fSopenharmony_ci    PARAM_CHECK(ret == EOK, return -1, "Failed to copy name for trigger");
107d9f0492fSopenharmony_ci    node->firstCmd = NULL;
108d9f0492fSopenharmony_ci    node->lastCmd = NULL;
109d9f0492fSopenharmony_ci    ret = OH_HashMapAdd(GetTriggerWorkSpace()->hashMap, &node->hashNode);
110d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Failed to add hash node");
111d9f0492fSopenharmony_ci    return 0;
112d9f0492fSopenharmony_ci}
113d9f0492fSopenharmony_ci
114d9f0492fSopenharmony_cistatic TriggerNode *AddJobTrigger_(const TriggerWorkSpace *workSpace,
115d9f0492fSopenharmony_ci    const char *condition, const TriggerExtInfo *extInfo)
116d9f0492fSopenharmony_ci{
117d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
118d9f0492fSopenharmony_ci    PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
119d9f0492fSopenharmony_ci    PARAM_CHECK(extInfo->type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
120d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
121d9f0492fSopenharmony_ci    PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
122d9f0492fSopenharmony_ci    uint32_t nameLen = strlen(extInfo->info.name);
123d9f0492fSopenharmony_ci    uint32_t triggerNodeLen = PARAM_ALIGN(nameLen + 1) + sizeof(JobNode);
124d9f0492fSopenharmony_ci    TriggerNode *node = (TriggerNode *)AddTriggerNode_(triggerHead, extInfo->type, condition, triggerNodeLen);
125d9f0492fSopenharmony_ci    PARAM_CHECK(node != NULL, return NULL, "Failed to alloc jobnode");
126d9f0492fSopenharmony_ci    int ret = extInfo->addNode(node, extInfo);
127d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
128d9f0492fSopenharmony_ci        return NULL, "Failed to add hash node");
129d9f0492fSopenharmony_ci    if (extInfo->type == TRIGGER_BOOT) {
130d9f0492fSopenharmony_ci        TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
131d9f0492fSopenharmony_ci        if (strncmp("boot-service:", extInfo->info.name, strlen("boot-service:")) != 0) {
132d9f0492fSopenharmony_ci            TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_SUBTRIGGER);
133d9f0492fSopenharmony_ci        }
134d9f0492fSopenharmony_ci    }
135d9f0492fSopenharmony_ci    return node;
136d9f0492fSopenharmony_ci}
137d9f0492fSopenharmony_ci
138d9f0492fSopenharmony_cistatic void DelJobTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
139d9f0492fSopenharmony_ci{
140d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return, "Param is null");
141d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return, "Trigger is null");
142d9f0492fSopenharmony_ci    JobNode *jobNode = (JobNode *)trigger;
143d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type);
144d9f0492fSopenharmony_ci    PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type);
145d9f0492fSopenharmony_ci    CommandNode *cmd = jobNode->firstCmd;
146d9f0492fSopenharmony_ci    while (cmd != NULL) {
147d9f0492fSopenharmony_ci        CommandNode *next = cmd->next;
148d9f0492fSopenharmony_ci        free(cmd);
149d9f0492fSopenharmony_ci        triggerHead->cmdNodeCount--;
150d9f0492fSopenharmony_ci        cmd = next;
151d9f0492fSopenharmony_ci    }
152d9f0492fSopenharmony_ci    if (jobNode->condition != NULL) {
153d9f0492fSopenharmony_ci        free(jobNode->condition);
154d9f0492fSopenharmony_ci        jobNode->condition = NULL;
155d9f0492fSopenharmony_ci    }
156d9f0492fSopenharmony_ci    jobNode->lastCmd = NULL;
157d9f0492fSopenharmony_ci    jobNode->firstCmd = NULL;
158d9f0492fSopenharmony_ci    OH_ListRemove(&trigger->node);
159d9f0492fSopenharmony_ci    triggerHead->triggerCount--;
160d9f0492fSopenharmony_ci    OH_HashMapRemove(workSpace->hashMap, jobNode->name);
161d9f0492fSopenharmony_ci
162d9f0492fSopenharmony_ci    if (!TRIGGER_IN_QUEUE(trigger)) {
163d9f0492fSopenharmony_ci        free(jobNode);
164d9f0492fSopenharmony_ci        return;
165d9f0492fSopenharmony_ci    }
166d9f0492fSopenharmony_ci    TriggerExecuteQueue *executeQueue = (TriggerExecuteQueue *)&workSpace->executeQueue;
167d9f0492fSopenharmony_ci    for (uint32_t i = executeQueue->startIndex; i < executeQueue->endIndex; i++) {
168d9f0492fSopenharmony_ci        if (executeQueue->executeQueue[i] == trigger) {
169d9f0492fSopenharmony_ci            executeQueue->executeQueue[i] = NULL;
170d9f0492fSopenharmony_ci            break;
171d9f0492fSopenharmony_ci        }
172d9f0492fSopenharmony_ci    }
173d9f0492fSopenharmony_ci    free(jobNode);
174d9f0492fSopenharmony_ci}
175d9f0492fSopenharmony_ci
176d9f0492fSopenharmony_cistatic TriggerNode *AddWatchTrigger_(const TriggerWorkSpace *workSpace,
177d9f0492fSopenharmony_ci    const char *condition, const TriggerExtInfo *extInfo)
178d9f0492fSopenharmony_ci{
179d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return NULL, "workSpace is null");
180d9f0492fSopenharmony_ci    PARAM_CHECK(extInfo != NULL && extInfo->addNode != NULL, return NULL, "extInfo is null");
181d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, extInfo->type);
182d9f0492fSopenharmony_ci    PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", extInfo->type);
183d9f0492fSopenharmony_ci    uint32_t size = 0;
184d9f0492fSopenharmony_ci    if (extInfo->type == TRIGGER_PARAM_WATCH) {
185d9f0492fSopenharmony_ci        size = sizeof(WatchNode);
186d9f0492fSopenharmony_ci    } else if (extInfo->type == TRIGGER_PARAM_WAIT) {
187d9f0492fSopenharmony_ci        size = sizeof(WaitNode);
188d9f0492fSopenharmony_ci    } else {
189d9f0492fSopenharmony_ci        PARAM_LOGE("Invalid trigger type %d", extInfo->type);
190d9f0492fSopenharmony_ci        return NULL;
191d9f0492fSopenharmony_ci    }
192d9f0492fSopenharmony_ci    TriggerNode *node = AddTriggerNode_(triggerHead, extInfo->type, condition, size);
193d9f0492fSopenharmony_ci    PARAM_CHECK(node != NULL, return NULL, "Failed to alloc memory for trigger");
194d9f0492fSopenharmony_ci    int ret = extInfo->addNode(node, extInfo);
195d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, FreeTrigger(workSpace, node);
196d9f0492fSopenharmony_ci        return NULL, "Failed to add node");
197d9f0492fSopenharmony_ci    if (extInfo->type == TRIGGER_PARAM_WAIT) {
198d9f0492fSopenharmony_ci        TRIGGER_SET_FLAG(node, TRIGGER_FLAGS_ONCE);
199d9f0492fSopenharmony_ci    }
200d9f0492fSopenharmony_ci    return node;
201d9f0492fSopenharmony_ci}
202d9f0492fSopenharmony_ci
203d9f0492fSopenharmony_cistatic void DelWatchTrigger_(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
204d9f0492fSopenharmony_ci{
205d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && trigger != NULL, return, "Param is null");
206d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, trigger->type);
207d9f0492fSopenharmony_ci    PARAM_CHECK(triggerHead != NULL, return, "Failed to get header %d", trigger->type);
208d9f0492fSopenharmony_ci    OH_ListRemove(&trigger->node);
209d9f0492fSopenharmony_ci    if (trigger->type == TRIGGER_PARAM_WAIT) {
210d9f0492fSopenharmony_ci        WaitNode *node = (WaitNode *)trigger;
211d9f0492fSopenharmony_ci        OH_ListRemove(&node->item);
212d9f0492fSopenharmony_ci    } else if (trigger->type == TRIGGER_PARAM_WATCH) {
213d9f0492fSopenharmony_ci        WatchNode *node = (WatchNode *)trigger;
214d9f0492fSopenharmony_ci        OH_ListRemove(&node->item);
215d9f0492fSopenharmony_ci    }
216d9f0492fSopenharmony_ci    PARAM_LOGV("DelWatchTrigger_ %s count %d", GetTriggerName(trigger), triggerHead->triggerCount);
217d9f0492fSopenharmony_ci    triggerHead->triggerCount--;
218d9f0492fSopenharmony_ci    if (trigger->condition != NULL) {
219d9f0492fSopenharmony_ci        free(trigger->condition);
220d9f0492fSopenharmony_ci        trigger->condition = NULL;
221d9f0492fSopenharmony_ci    }
222d9f0492fSopenharmony_ci    free(trigger);
223d9f0492fSopenharmony_ci}
224d9f0492fSopenharmony_ci
225d9f0492fSopenharmony_cistatic TriggerNode *GetNextTrigger_(const TriggerHeader *triggerHead, const TriggerNode *curr)
226d9f0492fSopenharmony_ci{
227d9f0492fSopenharmony_ci    PARAM_CHECK(triggerHead != NULL, return NULL, "Invalid triggerHead");
228d9f0492fSopenharmony_ci    ListNode *node = NULL;
229d9f0492fSopenharmony_ci    if (curr != NULL) {
230d9f0492fSopenharmony_ci        node = curr->node.next;
231d9f0492fSopenharmony_ci    } else {
232d9f0492fSopenharmony_ci        node = triggerHead->triggerList.next;
233d9f0492fSopenharmony_ci    }
234d9f0492fSopenharmony_ci    if (node != &triggerHead->triggerList) {
235d9f0492fSopenharmony_ci        return ListEntry(node, TriggerNode, node);
236d9f0492fSopenharmony_ci    }
237d9f0492fSopenharmony_ci    return NULL;
238d9f0492fSopenharmony_ci}
239d9f0492fSopenharmony_ci
240d9f0492fSopenharmony_cistatic const char *GetTriggerCondition_(const TriggerNode *trigger)
241d9f0492fSopenharmony_ci{
242d9f0492fSopenharmony_ci    return (trigger == NULL || trigger->condition == NULL) ? "" : trigger->condition;
243d9f0492fSopenharmony_ci}
244d9f0492fSopenharmony_ci
245d9f0492fSopenharmony_cistatic const char *GetBootCondition_(const TriggerNode *trigger)
246d9f0492fSopenharmony_ci{
247d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
248d9f0492fSopenharmony_ci    PARAM_CHECK(trigger->type == TRIGGER_BOOT, return "", "Invalid type");
249d9f0492fSopenharmony_ci    const JobNode *node = (const JobNode *)trigger;
250d9f0492fSopenharmony_ci    return node->name;
251d9f0492fSopenharmony_ci}
252d9f0492fSopenharmony_ci
253d9f0492fSopenharmony_cistatic const char *GetJobName_(const TriggerNode *trigger)
254d9f0492fSopenharmony_ci{
255d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
256d9f0492fSopenharmony_ci    PARAM_CHECK(trigger->type <= TRIGGER_UNKNOW, return "", "Invalid type");
257d9f0492fSopenharmony_ci    const JobNode *node = (const JobNode *)trigger;
258d9f0492fSopenharmony_ci    return node->name;
259d9f0492fSopenharmony_ci}
260d9f0492fSopenharmony_ci
261d9f0492fSopenharmony_cistatic const char *GetWatchName_(const TriggerNode *trigger)
262d9f0492fSopenharmony_ci{
263d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
264d9f0492fSopenharmony_ci    PARAM_CHECK(trigger->type < TRIGGER_MAX && trigger->type > TRIGGER_UNKNOW,
265d9f0492fSopenharmony_ci        return "", "Invalid type");
266d9f0492fSopenharmony_ci    return trigger->condition;
267d9f0492fSopenharmony_ci}
268d9f0492fSopenharmony_ci
269d9f0492fSopenharmony_ciJobNode *UpdateJobTrigger(const TriggerWorkSpace *workSpace,
270d9f0492fSopenharmony_ci    int type, const char *condition, const char *name)
271d9f0492fSopenharmony_ci{
272d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && name != NULL, return NULL, "name is null");
273d9f0492fSopenharmony_ci    PARAM_CHECK(type <= TRIGGER_UNKNOW, return NULL, "Invalid type");
274d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type);
275d9f0492fSopenharmony_ci    PARAM_CHECK(triggerHead != NULL, return NULL, "Failed to get header %d", type);
276d9f0492fSopenharmony_ci    JobNode *jobNode = GetTriggerByName(workSpace, name);
277d9f0492fSopenharmony_ci    if (jobNode == NULL) {
278d9f0492fSopenharmony_ci        TriggerExtInfo extInfo = {};
279d9f0492fSopenharmony_ci        extInfo.info.name = (char *)name;
280d9f0492fSopenharmony_ci        extInfo.type = type;
281d9f0492fSopenharmony_ci        extInfo.addNode = AddJobNode_;
282d9f0492fSopenharmony_ci        return (JobNode *)triggerHead->addTrigger(workSpace, condition, &extInfo);
283d9f0492fSopenharmony_ci    } else if (jobNode->condition == NULL && condition != NULL) {
284d9f0492fSopenharmony_ci        int ret = CopyCondition((TriggerNode *)jobNode, condition);
285d9f0492fSopenharmony_ci        PARAM_CHECK(ret == 0, FreeTrigger(workSpace, (TriggerNode*)jobNode);
286d9f0492fSopenharmony_ci            return NULL, "Failed to copy conditition");
287d9f0492fSopenharmony_ci    }
288d9f0492fSopenharmony_ci    return jobNode;
289d9f0492fSopenharmony_ci}
290d9f0492fSopenharmony_ci
291d9f0492fSopenharmony_ciJobNode *GetTriggerByName(const TriggerWorkSpace *workSpace, const char *triggerName)
292d9f0492fSopenharmony_ci{
293d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && triggerName != NULL, return NULL, "Invalid param");
294d9f0492fSopenharmony_ci    HashNode *node = OH_HashMapGet(workSpace->hashMap, triggerName);
295d9f0492fSopenharmony_ci    if (node == NULL) {
296d9f0492fSopenharmony_ci        return NULL;
297d9f0492fSopenharmony_ci    }
298d9f0492fSopenharmony_ci    JobNode *trigger = HASHMAP_ENTRY(node, JobNode, hashNode);
299d9f0492fSopenharmony_ci    return trigger;
300d9f0492fSopenharmony_ci}
301d9f0492fSopenharmony_ci
302d9f0492fSopenharmony_civoid FreeTrigger(const TriggerWorkSpace *workSpace, TriggerNode *trigger)
303d9f0492fSopenharmony_ci{
304d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && trigger != NULL, return, "Invalid param");
305d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(workSpace, trigger->type);
306d9f0492fSopenharmony_ci    if (head != NULL) {
307d9f0492fSopenharmony_ci        head->delTrigger(workSpace, trigger);
308d9f0492fSopenharmony_ci    }
309d9f0492fSopenharmony_ci}
310d9f0492fSopenharmony_ci
311d9f0492fSopenharmony_civoid ClearTrigger(const TriggerWorkSpace *workSpace, int8_t type)
312d9f0492fSopenharmony_ci{
313d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return, "head is null");
314d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(workSpace, type);
315d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
316d9f0492fSopenharmony_ci    TriggerNode *trigger = head->nextTrigger(head, NULL);
317d9f0492fSopenharmony_ci    while (trigger != NULL) {
318d9f0492fSopenharmony_ci        TriggerNode *next = head->nextTrigger(head, trigger);
319d9f0492fSopenharmony_ci        FreeTrigger(workSpace, trigger);
320d9f0492fSopenharmony_ci        trigger = next;
321d9f0492fSopenharmony_ci    }
322d9f0492fSopenharmony_ci    OH_ListInit(&head->triggerList);
323d9f0492fSopenharmony_ci}
324d9f0492fSopenharmony_ci
325d9f0492fSopenharmony_ciint ExecuteQueuePush(TriggerWorkSpace *workSpace, const TriggerNode *trigger)
326d9f0492fSopenharmony_ci{
327d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return -1, "Invalid workSpace");
328d9f0492fSopenharmony_ci    uint32_t index = workSpace->executeQueue.endIndex++ % workSpace->executeQueue.queueCount;
329d9f0492fSopenharmony_ci    workSpace->executeQueue.executeQueue[index] = (TriggerNode *)trigger;
330d9f0492fSopenharmony_ci    return 0;
331d9f0492fSopenharmony_ci}
332d9f0492fSopenharmony_ci
333d9f0492fSopenharmony_ciTriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace)
334d9f0492fSopenharmony_ci{
335d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return NULL, "Invalid workSpace");
336d9f0492fSopenharmony_ci    TriggerNode *trigger = NULL;
337d9f0492fSopenharmony_ci    do {
338d9f0492fSopenharmony_ci        if (workSpace->executeQueue.endIndex <= workSpace->executeQueue.startIndex) {
339d9f0492fSopenharmony_ci            return NULL;
340d9f0492fSopenharmony_ci        }
341d9f0492fSopenharmony_ci        uint32_t currIndex = workSpace->executeQueue.startIndex % workSpace->executeQueue.queueCount;
342d9f0492fSopenharmony_ci        trigger = workSpace->executeQueue.executeQueue[currIndex];
343d9f0492fSopenharmony_ci        workSpace->executeQueue.executeQueue[currIndex] = NULL;
344d9f0492fSopenharmony_ci        workSpace->executeQueue.startIndex++;
345d9f0492fSopenharmony_ci    } while (trigger == NULL);
346d9f0492fSopenharmony_ci    return trigger;
347d9f0492fSopenharmony_ci}
348d9f0492fSopenharmony_ci
349d9f0492fSopenharmony_cistatic int CheckBootCondition_(LogicCalculator *calculator,
350d9f0492fSopenharmony_ci    const char *condition, const char *content, uint32_t contentSize)
351d9f0492fSopenharmony_ci{
352d9f0492fSopenharmony_ci    UNUSED(calculator);
353d9f0492fSopenharmony_ci    if (strncmp(condition, content, contentSize) == 0) {
354d9f0492fSopenharmony_ci        return 1;
355d9f0492fSopenharmony_ci    }
356d9f0492fSopenharmony_ci    return 0;
357d9f0492fSopenharmony_ci}
358d9f0492fSopenharmony_ci
359d9f0492fSopenharmony_cistatic int CheckWatchCondition_(LogicCalculator *calculator,
360d9f0492fSopenharmony_ci    const char *condition, const char *content, uint32_t contentSize)
361d9f0492fSopenharmony_ci{
362d9f0492fSopenharmony_ci    UNUSED(calculator);
363d9f0492fSopenharmony_ci    UNUSED(contentSize);
364d9f0492fSopenharmony_ci    if (strncmp(condition, content, strlen(condition)) == 0) {
365d9f0492fSopenharmony_ci        return 1;
366d9f0492fSopenharmony_ci    }
367d9f0492fSopenharmony_ci    return 0;
368d9f0492fSopenharmony_ci}
369d9f0492fSopenharmony_ci
370d9f0492fSopenharmony_cistatic int CheckParamCondition_(LogicCalculator *calculator,
371d9f0492fSopenharmony_ci    const char *condition, const char *content, uint32_t contentSize)
372d9f0492fSopenharmony_ci{
373d9f0492fSopenharmony_ci    UNUSED(content);
374d9f0492fSopenharmony_ci    UNUSED(contentSize);
375d9f0492fSopenharmony_ci    if (calculator->inputName != NULL) {
376d9f0492fSopenharmony_ci        if (!CheckMatchSubCondition(condition, calculator->inputName, strlen(calculator->inputName))) {
377d9f0492fSopenharmony_ci            return 0;
378d9f0492fSopenharmony_ci        }
379d9f0492fSopenharmony_ci    }
380d9f0492fSopenharmony_ci    return ComputeCondition(calculator, condition);
381d9f0492fSopenharmony_ci}
382d9f0492fSopenharmony_ci
383d9f0492fSopenharmony_cistatic int CheckUnknowCondition_(LogicCalculator *calculator,
384d9f0492fSopenharmony_ci    const char *condition, const char *content, uint32_t contentSize)
385d9f0492fSopenharmony_ci{
386d9f0492fSopenharmony_ci    if (condition != NULL && content != NULL && strcmp(content, condition) == 0) {
387d9f0492fSopenharmony_ci        return 1;
388d9f0492fSopenharmony_ci    }
389d9f0492fSopenharmony_ci    return ComputeCondition(calculator, condition);
390d9f0492fSopenharmony_ci}
391d9f0492fSopenharmony_ci
392d9f0492fSopenharmony_cistatic int ExecTriggerMatch_(const TriggerWorkSpace *workSpace,
393d9f0492fSopenharmony_ci    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
394d9f0492fSopenharmony_ci{
395d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(workSpace, type);
396d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
397d9f0492fSopenharmony_ci    TriggerNode *trigger = head->nextTrigger(head, NULL);
398d9f0492fSopenharmony_ci    while (trigger != NULL) {
399d9f0492fSopenharmony_ci        TriggerNode *next = head->nextTrigger(head, trigger);
400d9f0492fSopenharmony_ci        const char *condition = head->getCondition(trigger);
401d9f0492fSopenharmony_ci        if (head->checkCondition(calculator, condition, content, contentSize) == 1) {
402d9f0492fSopenharmony_ci            calculator->triggerCheckDone(trigger, content, contentSize);
403d9f0492fSopenharmony_ci        }
404d9f0492fSopenharmony_ci        trigger = next;
405d9f0492fSopenharmony_ci    }
406d9f0492fSopenharmony_ci    return 0;
407d9f0492fSopenharmony_ci}
408d9f0492fSopenharmony_ci
409d9f0492fSopenharmony_cistatic int CheckBootMatch_(const TriggerWorkSpace *workSpace,
410d9f0492fSopenharmony_ci    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
411d9f0492fSopenharmony_ci{
412d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return -1, "Invalid space");
413d9f0492fSopenharmony_ci    PARAM_CHECK((type == TRIGGER_BOOT) || (type == TRIGGER_PARAM_WATCH), return -1, "Invalid type");
414d9f0492fSopenharmony_ci    return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
415d9f0492fSopenharmony_ci}
416d9f0492fSopenharmony_ci
417d9f0492fSopenharmony_cistatic int CheckParamMatch_(const TriggerWorkSpace *workSpace,
418d9f0492fSopenharmony_ci    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
419d9f0492fSopenharmony_ci{
420d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return -1, "Invalid space");
421d9f0492fSopenharmony_ci    PARAM_CHECK((type == TRIGGER_PARAM) || (type == TRIGGER_PARAM_WAIT), return -1, "Invalid type");
422d9f0492fSopenharmony_ci
423d9f0492fSopenharmony_ci    CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
424d9f0492fSopenharmony_ci    int ret = GetValueFromContent(content, contentSize, 0, calculator->inputName, SUPPORT_DATA_BUFFER_MAX);
425d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Failed parse content name");
426d9f0492fSopenharmony_ci    ret = GetValueFromContent(content, contentSize,
427d9f0492fSopenharmony_ci        strlen(calculator->inputName) + 1, calculator->inputContent, SUPPORT_DATA_BUFFER_MAX);
428d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return -1, "Failed parse content value");
429d9f0492fSopenharmony_ci    return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
430d9f0492fSopenharmony_ci}
431d9f0492fSopenharmony_ci
432d9f0492fSopenharmony_cistatic int CheckUnknowMatch_(const TriggerWorkSpace *workSpace,
433d9f0492fSopenharmony_ci    int type, LogicCalculator *calculator, const char *content, uint32_t contentSize)
434d9f0492fSopenharmony_ci{
435d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && content != NULL, return -1, "Failed arg for trigger");
436d9f0492fSopenharmony_ci    PARAM_CHECK(type == TRIGGER_UNKNOW, return -1, "Invalid type");
437d9f0492fSopenharmony_ci
438d9f0492fSopenharmony_ci    CalculatorInit(calculator, MAX_CONDITION_NUMBER, sizeof(LogicData), 1);
439d9f0492fSopenharmony_ci    int ret = memcpy_s(calculator->triggerContent, sizeof(calculator->triggerContent), content, contentSize);
440d9f0492fSopenharmony_ci    PARAM_CHECK(ret == EOK, return -1, "Failed to memcpy");
441d9f0492fSopenharmony_ci    calculator->inputName = NULL;
442d9f0492fSopenharmony_ci    calculator->inputContent = NULL;
443d9f0492fSopenharmony_ci    return ExecTriggerMatch_(workSpace, type, calculator, content, contentSize);
444d9f0492fSopenharmony_ci}
445d9f0492fSopenharmony_ci
446d9f0492fSopenharmony_ciint32_t CheckAndMarkTrigger_(const TriggerWorkSpace *workSpace, int type, const char *name)
447d9f0492fSopenharmony_ci{
448d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "Failed arg for trigger");
449d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(workSpace, type);
450d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL, return 0, "Failed to get header %d", type);
451d9f0492fSopenharmony_ci    int ret = 0;
452d9f0492fSopenharmony_ci    TriggerNode *trigger = head->nextTrigger(head, NULL);
453d9f0492fSopenharmony_ci    while (trigger != NULL) {
454d9f0492fSopenharmony_ci        if (head->getCondition(trigger) == NULL) {
455d9f0492fSopenharmony_ci            trigger = head->nextTrigger(head, trigger);
456d9f0492fSopenharmony_ci            continue;
457d9f0492fSopenharmony_ci        }
458d9f0492fSopenharmony_ci        if (CheckMatchSubCondition(head->getCondition(trigger), name, strlen(name)) == 1) {
459d9f0492fSopenharmony_ci            TRIGGER_SET_FLAG(trigger, TRIGGER_FLAGS_RELATED);
460d9f0492fSopenharmony_ci            ret = 1;
461d9f0492fSopenharmony_ci        }
462d9f0492fSopenharmony_ci        trigger = head->nextTrigger(head, trigger);
463d9f0492fSopenharmony_ci    }
464d9f0492fSopenharmony_ci    return ret;
465d9f0492fSopenharmony_ci}
466d9f0492fSopenharmony_ci
467d9f0492fSopenharmony_ciint CheckTrigger(TriggerWorkSpace *workSpace, int type,
468d9f0492fSopenharmony_ci    const char *content, uint32_t contentSize, PARAM_CHECK_DONE triggerCheckDone)
469d9f0492fSopenharmony_ci{
470d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL && content != NULL && triggerCheckDone != NULL,
471d9f0492fSopenharmony_ci        return -1, "Failed arg for trigger");
472d9f0492fSopenharmony_ci    PARAM_LOGV("CheckTrigger_ type: %d content: %s ", type, content);
473d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(workSpace, type);
474d9f0492fSopenharmony_ci    if (triggerHead != NULL) {
475d9f0492fSopenharmony_ci        LogicCalculator calculator = {{0}};
476d9f0492fSopenharmony_ci        calculator.triggerCheckDone = triggerCheckDone;
477d9f0492fSopenharmony_ci        int ret = triggerHead->checkTriggerMatch(workSpace, type, &calculator, content, contentSize);
478d9f0492fSopenharmony_ci        CalculatorFree(&calculator);
479d9f0492fSopenharmony_ci        return ret;
480d9f0492fSopenharmony_ci    }
481d9f0492fSopenharmony_ci    return 0;
482d9f0492fSopenharmony_ci}
483d9f0492fSopenharmony_ci
484d9f0492fSopenharmony_cistatic void DumpJobTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
485d9f0492fSopenharmony_ci{
486d9f0492fSopenharmony_ci    const JobNode *node = (const JobNode *)trigger;
487d9f0492fSopenharmony_ci    PARAM_DUMP("trigger     flags: 0x%08x \n", trigger->flags);
488d9f0492fSopenharmony_ci    PARAM_DUMP("trigger      name: %s \n", node->name);
489d9f0492fSopenharmony_ci    PARAM_DUMP("trigger condition: %s \n", node->condition);
490d9f0492fSopenharmony_ci    const int maxCmd = 1024;
491d9f0492fSopenharmony_ci    int count = 0;
492d9f0492fSopenharmony_ci    CommandNode *cmd = GetNextCmdNode(node, NULL);
493d9f0492fSopenharmony_ci    while (cmd != NULL && count < maxCmd) {
494d9f0492fSopenharmony_ci        PARAM_DUMP("    command name: %s (%s) \n", GetCmdKey(cmd->cmdKeyIndex),
495d9f0492fSopenharmony_ci            (cmd->cfgContext.type == INIT_CONTEXT_CHIPSET) ? "chipset" : "system");
496d9f0492fSopenharmony_ci        PARAM_DUMP("    command args    : %s \n", cmd->content);
497d9f0492fSopenharmony_ci        cmd = GetNextCmdNode(node, cmd);
498d9f0492fSopenharmony_ci        count++;
499d9f0492fSopenharmony_ci    }
500d9f0492fSopenharmony_ci}
501d9f0492fSopenharmony_ci
502d9f0492fSopenharmony_cistatic void DumpWatchTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
503d9f0492fSopenharmony_ci{
504d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return, "Empty trigger");
505d9f0492fSopenharmony_ci    const WatchNode *node = (const WatchNode *)trigger;
506d9f0492fSopenharmony_ci    PARAM_DUMP("trigger     flags: 0x%08x \n", trigger->flags);
507d9f0492fSopenharmony_ci    PARAM_DUMP("trigger condition: %s \n", trigger->condition);
508d9f0492fSopenharmony_ci    PARAM_DUMP("trigger   watchId: %d \n", node->watchId);
509d9f0492fSopenharmony_ci}
510d9f0492fSopenharmony_ci
511d9f0492fSopenharmony_cistatic void DumpWaitTrigger_(const TriggerWorkSpace *workSpace, const TriggerNode *trigger)
512d9f0492fSopenharmony_ci{
513d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return, "Empty trigger");
514d9f0492fSopenharmony_ci    const WaitNode *node = (const WaitNode *)trigger;
515d9f0492fSopenharmony_ci    PARAM_DUMP("trigger     flags: 0x%08x \n", trigger->flags);
516d9f0492fSopenharmony_ci    PARAM_DUMP("trigger      name: %s \n", GetTriggerName(trigger));
517d9f0492fSopenharmony_ci    PARAM_DUMP("trigger condition: %s \n", trigger->condition);
518d9f0492fSopenharmony_ci    PARAM_DUMP("trigger    waitId: %d \n", node->waitId);
519d9f0492fSopenharmony_ci    PARAM_DUMP("trigger   timeout: %d \n", node->timeout);
520d9f0492fSopenharmony_ci}
521d9f0492fSopenharmony_ci
522d9f0492fSopenharmony_cistatic void DumpTrigger_(const TriggerWorkSpace *workSpace, int type)
523d9f0492fSopenharmony_ci{
524d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
525d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(workSpace, type);
526d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
527d9f0492fSopenharmony_ci    TriggerNode *trigger = head->nextTrigger(head, NULL);
528d9f0492fSopenharmony_ci    while (trigger != NULL) {
529d9f0492fSopenharmony_ci        head->dumpTrigger(workSpace, trigger);
530d9f0492fSopenharmony_ci        trigger = head->nextTrigger(head, trigger);
531d9f0492fSopenharmony_ci    }
532d9f0492fSopenharmony_ci}
533d9f0492fSopenharmony_ci
534d9f0492fSopenharmony_civoid SystemDumpTriggers(int verbose, int (*dump)(const char *fmt, ...))
535d9f0492fSopenharmony_ci{
536d9f0492fSopenharmony_ci    if (dump != NULL) {
537d9f0492fSopenharmony_ci        g_printf = dump;
538d9f0492fSopenharmony_ci    } else {
539d9f0492fSopenharmony_ci        g_printf = printf;
540d9f0492fSopenharmony_ci    }
541d9f0492fSopenharmony_ci    TriggerWorkSpace *workSpace = GetTriggerWorkSpace();
542d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace ");
543d9f0492fSopenharmony_ci    PARAM_DUMP("workspace queue BOOT info:\n");
544d9f0492fSopenharmony_ci    DumpTrigger_(workSpace, TRIGGER_BOOT);
545d9f0492fSopenharmony_ci    PARAM_DUMP("workspace queue parameter info:\n");
546d9f0492fSopenharmony_ci    DumpTrigger_(workSpace, TRIGGER_PARAM);
547d9f0492fSopenharmony_ci    PARAM_DUMP("workspace queue other info:\n");
548d9f0492fSopenharmony_ci    DumpTrigger_(workSpace, TRIGGER_UNKNOW);
549d9f0492fSopenharmony_ci    PARAM_DUMP("workspace queue watch info:\n");
550d9f0492fSopenharmony_ci    DumpTrigger_(workSpace, TRIGGER_PARAM_WATCH);
551d9f0492fSopenharmony_ci    PARAM_DUMP("workspace queue wait info:\n");
552d9f0492fSopenharmony_ci    DumpTrigger_(workSpace, TRIGGER_PARAM_WAIT);
553d9f0492fSopenharmony_ci
554d9f0492fSopenharmony_ci    PARAM_DUMP("workspace queue execute info:\n");
555d9f0492fSopenharmony_ci    PARAM_DUMP("queue info count: %u start: %u end: %u\n",
556d9f0492fSopenharmony_ci        workSpace->executeQueue.queueCount, workSpace->executeQueue.startIndex, workSpace->executeQueue.endIndex);
557d9f0492fSopenharmony_ci    for (uint32_t index = workSpace->executeQueue.startIndex; index < workSpace->executeQueue.endIndex; index++) {
558d9f0492fSopenharmony_ci        TriggerNode *trigger = workSpace->executeQueue.executeQueue[index % workSpace->executeQueue.queueCount];
559d9f0492fSopenharmony_ci        if (trigger != 0) {
560d9f0492fSopenharmony_ci            PARAM_DUMP("    queue node trigger name: %s \n", GetTriggerName(trigger));
561d9f0492fSopenharmony_ci        }
562d9f0492fSopenharmony_ci    }
563d9f0492fSopenharmony_ci}
564d9f0492fSopenharmony_ci
565d9f0492fSopenharmony_cistatic int32_t CompareData_(const struct tagTriggerNode_ *trigger, const void *data)
566d9f0492fSopenharmony_ci{
567d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL && data != NULL, return -1, "Invalid trigger");
568d9f0492fSopenharmony_ci    if (trigger->type == TRIGGER_PARAM_WAIT) {
569d9f0492fSopenharmony_ci        WaitNode *node = (WaitNode *)trigger;
570d9f0492fSopenharmony_ci        return node->waitId - *(uint32_t *)data;
571d9f0492fSopenharmony_ci    } else if (trigger->type == TRIGGER_PARAM_WATCH) {
572d9f0492fSopenharmony_ci        WatchNode *node = (WatchNode *)trigger;
573d9f0492fSopenharmony_ci        return node->watchId - *(uint32_t *)data;
574d9f0492fSopenharmony_ci    }
575d9f0492fSopenharmony_ci    return -1;
576d9f0492fSopenharmony_ci}
577d9f0492fSopenharmony_ci
578d9f0492fSopenharmony_cistatic void TriggerHeadSetDefault(TriggerHeader *head)
579d9f0492fSopenharmony_ci{
580d9f0492fSopenharmony_ci    OH_ListInit(&head->triggerList);
581d9f0492fSopenharmony_ci    head->triggerCount = 0;
582d9f0492fSopenharmony_ci    head->cmdNodeCount = 0;
583d9f0492fSopenharmony_ci    head->addTrigger = AddJobTrigger_;
584d9f0492fSopenharmony_ci    head->nextTrigger = GetNextTrigger_;
585d9f0492fSopenharmony_ci    head->delTrigger = DelJobTrigger_;
586d9f0492fSopenharmony_ci    head->executeTrigger = NULL;
587d9f0492fSopenharmony_ci    head->checkAndMarkTrigger = CheckAndMarkTrigger_;
588d9f0492fSopenharmony_ci    head->checkTriggerMatch = CheckBootMatch_;
589d9f0492fSopenharmony_ci    head->checkCondition = CheckBootCondition_;
590d9f0492fSopenharmony_ci    head->getCondition = GetBootCondition_;
591d9f0492fSopenharmony_ci    head->getTriggerName = GetJobName_;
592d9f0492fSopenharmony_ci    head->dumpTrigger = DumpJobTrigger_;
593d9f0492fSopenharmony_ci    head->compareData = CompareData_;
594d9f0492fSopenharmony_ci}
595d9f0492fSopenharmony_ci
596d9f0492fSopenharmony_cistatic int JobNodeNodeCompare(const HashNode *node1, const HashNode *node2)
597d9f0492fSopenharmony_ci{
598d9f0492fSopenharmony_ci    JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
599d9f0492fSopenharmony_ci    JobNode *jobNode2 = HASHMAP_ENTRY(node2, JobNode, hashNode);
600d9f0492fSopenharmony_ci    return strcmp(jobNode1->name, jobNode2->name);
601d9f0492fSopenharmony_ci}
602d9f0492fSopenharmony_ci
603d9f0492fSopenharmony_cistatic int JobNodeKeyCompare(const HashNode *node1, const void *key)
604d9f0492fSopenharmony_ci{
605d9f0492fSopenharmony_ci    JobNode *jobNode1 = HASHMAP_ENTRY(node1, JobNode, hashNode);
606d9f0492fSopenharmony_ci    return strcmp(jobNode1->name, (char *)key);
607d9f0492fSopenharmony_ci}
608d9f0492fSopenharmony_ci
609d9f0492fSopenharmony_cistatic int JobNodeGetNodeHasCode(const HashNode *node)
610d9f0492fSopenharmony_ci{
611d9f0492fSopenharmony_ci    JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
612d9f0492fSopenharmony_ci    int code = 0;
613d9f0492fSopenharmony_ci    size_t nameLen = strlen(jobNode->name);
614d9f0492fSopenharmony_ci    for (size_t i = 0; i < nameLen; i++) {
615d9f0492fSopenharmony_ci        code += jobNode->name[i] - 'A';
616d9f0492fSopenharmony_ci    }
617d9f0492fSopenharmony_ci    return code;
618d9f0492fSopenharmony_ci}
619d9f0492fSopenharmony_ci
620d9f0492fSopenharmony_cistatic int JobNodeGetKeyHasCode(const void *key)
621d9f0492fSopenharmony_ci{
622d9f0492fSopenharmony_ci    int code = 0;
623d9f0492fSopenharmony_ci    const char *buff = (char *)key;
624d9f0492fSopenharmony_ci    size_t buffLen = strlen(buff);
625d9f0492fSopenharmony_ci    for (size_t i = 0; i < buffLen; i++) {
626d9f0492fSopenharmony_ci        code += buff[i] - 'A';
627d9f0492fSopenharmony_ci    }
628d9f0492fSopenharmony_ci    return code;
629d9f0492fSopenharmony_ci}
630d9f0492fSopenharmony_ci
631d9f0492fSopenharmony_cistatic void JobNodeFree(const HashNode *node, void *context)
632d9f0492fSopenharmony_ci{
633d9f0492fSopenharmony_ci    JobNode *jobNode = HASHMAP_ENTRY(node, JobNode, hashNode);
634d9f0492fSopenharmony_ci    FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)jobNode);
635d9f0492fSopenharmony_ci}
636d9f0492fSopenharmony_ci
637d9f0492fSopenharmony_civoid InitTriggerHead(const TriggerWorkSpace *workSpace)
638d9f0492fSopenharmony_ci{
639d9f0492fSopenharmony_ci    HashInfo info = {
640d9f0492fSopenharmony_ci        JobNodeNodeCompare,
641d9f0492fSopenharmony_ci        JobNodeKeyCompare,
642d9f0492fSopenharmony_ci        JobNodeGetNodeHasCode,
643d9f0492fSopenharmony_ci        JobNodeGetKeyHasCode,
644d9f0492fSopenharmony_ci        JobNodeFree,
645d9f0492fSopenharmony_ci        64
646d9f0492fSopenharmony_ci    };
647d9f0492fSopenharmony_ci    PARAM_CHECK(workSpace != NULL, return, "Invalid workSpace");
648d9f0492fSopenharmony_ci    int ret = OH_HashMapCreate((HashMapHandle *)&workSpace->hashMap, &info);
649d9f0492fSopenharmony_ci    PARAM_CHECK(ret == 0, return, "Failed to create hash map");
650d9f0492fSopenharmony_ci
651d9f0492fSopenharmony_ci    TriggerHeader *head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_BOOT];
652d9f0492fSopenharmony_ci    TriggerHeadSetDefault(head);
653d9f0492fSopenharmony_ci    // param trigger
654d9f0492fSopenharmony_ci    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM];
655d9f0492fSopenharmony_ci    TriggerHeadSetDefault(head);
656d9f0492fSopenharmony_ci    head->checkTriggerMatch = CheckParamMatch_;
657d9f0492fSopenharmony_ci    head->checkCondition = CheckParamCondition_;
658d9f0492fSopenharmony_ci    head->getCondition = GetTriggerCondition_;
659d9f0492fSopenharmony_ci    // unknown trigger
660d9f0492fSopenharmony_ci    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_UNKNOW];
661d9f0492fSopenharmony_ci    TriggerHeadSetDefault(head);
662d9f0492fSopenharmony_ci    head->checkTriggerMatch = CheckUnknowMatch_;
663d9f0492fSopenharmony_ci    head->checkCondition = CheckUnknowCondition_;
664d9f0492fSopenharmony_ci    head->getCondition = GetTriggerCondition_;
665d9f0492fSopenharmony_ci    // wait trigger
666d9f0492fSopenharmony_ci    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WAIT];
667d9f0492fSopenharmony_ci    TriggerHeadSetDefault(head);
668d9f0492fSopenharmony_ci    head->addTrigger = AddWatchTrigger_;
669d9f0492fSopenharmony_ci    head->delTrigger = DelWatchTrigger_;
670d9f0492fSopenharmony_ci    head->checkTriggerMatch = CheckParamMatch_;
671d9f0492fSopenharmony_ci    head->checkCondition = CheckParamCondition_;
672d9f0492fSopenharmony_ci    head->getCondition = GetTriggerCondition_;
673d9f0492fSopenharmony_ci    head->dumpTrigger = DumpWaitTrigger_;
674d9f0492fSopenharmony_ci    head->getTriggerName = GetWatchName_;
675d9f0492fSopenharmony_ci    // watch trigger
676d9f0492fSopenharmony_ci    head = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM_WATCH];
677d9f0492fSopenharmony_ci    TriggerHeadSetDefault(head);
678d9f0492fSopenharmony_ci    head->addTrigger = AddWatchTrigger_;
679d9f0492fSopenharmony_ci    head->delTrigger = DelWatchTrigger_;
680d9f0492fSopenharmony_ci    head->checkTriggerMatch = CheckBootMatch_;
681d9f0492fSopenharmony_ci    head->checkCondition = CheckWatchCondition_;
682d9f0492fSopenharmony_ci    head->getCondition = GetTriggerCondition_;
683d9f0492fSopenharmony_ci    head->dumpTrigger = DumpWatchTrigger_;
684d9f0492fSopenharmony_ci    head->getTriggerName = GetWatchName_;
685d9f0492fSopenharmony_ci}
686d9f0492fSopenharmony_ci
687d9f0492fSopenharmony_civoid DelWatchTrigger(int type, const void *data)
688d9f0492fSopenharmony_ci{
689d9f0492fSopenharmony_ci    PARAM_CHECK(data != NULL, return, "Invalid data");
690d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
691d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
692d9f0492fSopenharmony_ci    PARAM_CHECK(head->compareData != NULL, return, "Invalid compareData");
693d9f0492fSopenharmony_ci    TriggerNode *trigger = head->nextTrigger(head, NULL);
694d9f0492fSopenharmony_ci    while (trigger != NULL) {
695d9f0492fSopenharmony_ci        if (head->compareData(trigger, data) == 0) {
696d9f0492fSopenharmony_ci            head->delTrigger(GetTriggerWorkSpace(), trigger);
697d9f0492fSopenharmony_ci            return;
698d9f0492fSopenharmony_ci        }
699d9f0492fSopenharmony_ci        trigger = head->nextTrigger(head, trigger);
700d9f0492fSopenharmony_ci    }
701d9f0492fSopenharmony_ci}
702d9f0492fSopenharmony_ci
703d9f0492fSopenharmony_civoid ClearWatchTrigger(ParamWatcher *watcher, int type)
704d9f0492fSopenharmony_ci{
705d9f0492fSopenharmony_ci    PARAM_CHECK(watcher != NULL, return, "Invalid watcher");
706d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), type);
707d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL, return, "Failed to get header %d", type);
708d9f0492fSopenharmony_ci    ListNode *node = watcher->triggerHead.next;
709d9f0492fSopenharmony_ci    while (node != &watcher->triggerHead) {
710d9f0492fSopenharmony_ci        TriggerNode *trigger = NULL;
711d9f0492fSopenharmony_ci        if (type == TRIGGER_PARAM_WAIT) {
712d9f0492fSopenharmony_ci            trigger = (TriggerNode *)ListEntry(node, WaitNode, item);
713d9f0492fSopenharmony_ci        } else if (type == TRIGGER_PARAM_WATCH) {
714d9f0492fSopenharmony_ci            trigger = (TriggerNode *)ListEntry(node, WatchNode, item);
715d9f0492fSopenharmony_ci        }
716d9f0492fSopenharmony_ci        if (trigger == NULL || type != trigger->type) {
717d9f0492fSopenharmony_ci            PARAM_LOGE("ClearWatchTrigger %s error type %d", GetTriggerName(trigger), type);
718d9f0492fSopenharmony_ci            return;
719d9f0492fSopenharmony_ci        }
720d9f0492fSopenharmony_ci        PARAM_LOGV("ClearWatchTrigger %s", GetTriggerName(trigger));
721d9f0492fSopenharmony_ci        ListNode *next = node->next;
722d9f0492fSopenharmony_ci        FreeTrigger(GetTriggerWorkSpace(), trigger);
723d9f0492fSopenharmony_ci        node = next;
724d9f0492fSopenharmony_ci    }
725d9f0492fSopenharmony_ci}
726d9f0492fSopenharmony_ci
727d9f0492fSopenharmony_ciint CheckWatchTriggerTimeout(void)
728d9f0492fSopenharmony_ci{
729d9f0492fSopenharmony_ci    TriggerHeader *head = GetTriggerHeader(GetTriggerWorkSpace(), TRIGGER_PARAM_WAIT);
730d9f0492fSopenharmony_ci    PARAM_CHECK(head != NULL && head->nextTrigger != NULL, return 0, "Invalid header");
731d9f0492fSopenharmony_ci    int hasNode = 0;
732d9f0492fSopenharmony_ci    WaitNode *node = (WaitNode *)head->nextTrigger(head, NULL);
733d9f0492fSopenharmony_ci    while (node != NULL) {
734d9f0492fSopenharmony_ci        WaitNode *next = (WaitNode *)head->nextTrigger(head, (TriggerNode *)node);
735d9f0492fSopenharmony_ci        if (node->timeout > 0) {
736d9f0492fSopenharmony_ci            node->timeout--;
737d9f0492fSopenharmony_ci        } else {
738d9f0492fSopenharmony_ci            head->executeTrigger((TriggerNode*)node, NULL, 0);
739d9f0492fSopenharmony_ci            FreeTrigger(GetTriggerWorkSpace(), (TriggerNode *)node);
740d9f0492fSopenharmony_ci        }
741d9f0492fSopenharmony_ci        hasNode = 1;
742d9f0492fSopenharmony_ci        node = next;
743d9f0492fSopenharmony_ci    }
744d9f0492fSopenharmony_ci    return hasNode;
745d9f0492fSopenharmony_ci}
746d9f0492fSopenharmony_ci
747d9f0492fSopenharmony_ciTriggerHeader *GetTriggerHeader(const TriggerWorkSpace *workSpace, int type)
748d9f0492fSopenharmony_ci{
749d9f0492fSopenharmony_ci    if (workSpace == NULL || type >= TRIGGER_MAX) {
750d9f0492fSopenharmony_ci        return NULL;
751d9f0492fSopenharmony_ci    }
752d9f0492fSopenharmony_ci    return (TriggerHeader *)&workSpace->triggerHead[type];
753d9f0492fSopenharmony_ci}
754d9f0492fSopenharmony_ci
755d9f0492fSopenharmony_cichar *GetTriggerCache(uint32_t *size)
756d9f0492fSopenharmony_ci{
757d9f0492fSopenharmony_ci    TriggerWorkSpace *space = GetTriggerWorkSpace();
758d9f0492fSopenharmony_ci    if (space == NULL) {
759d9f0492fSopenharmony_ci        return NULL;
760d9f0492fSopenharmony_ci    }
761d9f0492fSopenharmony_ci    if (size != NULL) {
762d9f0492fSopenharmony_ci        *size = sizeof(space->cache) / sizeof(space->cache[0]);
763d9f0492fSopenharmony_ci    }
764d9f0492fSopenharmony_ci    return space->cache;
765d9f0492fSopenharmony_ci}
766d9f0492fSopenharmony_ci
767d9f0492fSopenharmony_ciconst char *GetTriggerName(const TriggerNode *trigger)
768d9f0492fSopenharmony_ci{
769d9f0492fSopenharmony_ci    PARAM_CHECK(trigger != NULL, return "", "Invalid trigger");
770d9f0492fSopenharmony_ci    TriggerHeader *triggerHead = GetTriggerHeader(GetTriggerWorkSpace(), trigger->type);
771d9f0492fSopenharmony_ci    if (triggerHead) {
772d9f0492fSopenharmony_ci        return triggerHead->getTriggerName(trigger);
773d9f0492fSopenharmony_ci    }
774d9f0492fSopenharmony_ci    return "";
775d9f0492fSopenharmony_ci}
776