• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdbool.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include "list.h"
22 #include "beget_ext.h"
23 #include "hookmgr.h"
24 
25 // Forward declaration
26 typedef struct tagHOOK_STAGE HOOK_STAGE;
27 
28 /*
29  * Internal HOOK Item with priorities
30  */
31 typedef struct tagHOOK_ITEM {
32     ListNode node;
33     HOOK_INFO info;
34     HOOK_STAGE *stage;
35 } HOOK_ITEM;
36 
37 /*
38  * Internal HOOK Stage in the same stage
39  */
40 struct tagHOOK_STAGE {
41     ListNode node;
42     int stage;
43     ListNode hooks;
44 };
45 
46 /*
47  * HookManager is consist of different hook stages
48  */
49 struct tagHOOK_MGR {
50     const char *name;
51     ListNode stages;
52 };
53 
54 /*
55  * Default HookManager is created automatically for HookMgrAddHook
56  */
57 static HOOK_MGR *defaultHookMgr = NULL;
58 
getHookMgr(HOOK_MGR * hookMgr,int autoCreate)59 static HOOK_MGR *getHookMgr(HOOK_MGR *hookMgr, int autoCreate)
60 {
61     BEGET_CHECK(hookMgr == NULL, return hookMgr);
62     // Use default HOOK_MGR if possible
63     BEGET_CHECK(defaultHookMgr == NULL, return defaultHookMgr);
64 
65     BEGET_CHECK(autoCreate, return NULL);
66 
67     // Create default HOOK_MGR if not created
68     defaultHookMgr = HookMgrCreate("default");
69     return defaultHookMgr;
70 }
71 
hookStageCompare(ListNode * node,void * data)72 static int hookStageCompare(ListNode *node, void *data)
73 {
74     const HOOK_STAGE *stage;
75     int compareStage = *((int *)data);
76 
77     stage = (const HOOK_STAGE *)node;
78     return (stage->stage - compareStage);
79 }
80 
hookStageDestroy(ListNode * node)81 static void hookStageDestroy(ListNode *node)
82 {
83     HOOK_STAGE *stage;
84 
85     BEGET_CHECK(node != NULL, return);
86 
87     stage = (HOOK_STAGE *)node;
88     OH_ListRemoveAll(&(stage->hooks), NULL);
89     free((void *)stage);
90 }
91 
92 // Get HOOK_STAGE if found, otherwise create it
getHookStage(HOOK_MGR * hookMgr,int stage,int createIfNotFound)93 static HOOK_STAGE *getHookStage(HOOK_MGR *hookMgr, int stage, int createIfNotFound)
94 {
95     HOOK_STAGE *stageItem;
96 
97     stageItem = (HOOK_STAGE *)OH_ListFind(&(hookMgr->stages), (void *)(&stage), hookStageCompare);
98     BEGET_CHECK(stageItem == NULL, return stageItem);
99 
100     BEGET_CHECK(createIfNotFound, return NULL);
101 
102     // Not found, create it
103     stageItem = (HOOK_STAGE *)malloc(sizeof(HOOK_STAGE));
104     BEGET_CHECK(stageItem != NULL, return NULL);
105     stageItem->stage = stage;
106     OH_ListInit(&(stageItem->hooks));
107     OH_ListAddTail(&(hookMgr->stages), (ListNode *)stageItem);
108     return stageItem;
109 }
110 
hookItemCompare(ListNode * node,ListNode * newNode)111 static int hookItemCompare(ListNode *node, ListNode *newNode)
112 {
113     const HOOK_ITEM *hookItem;
114     const HOOK_ITEM *newItem;
115 
116     hookItem = (const HOOK_ITEM *)node;
117     newItem = (const HOOK_ITEM *)newNode;
118     return (hookItem->info.prio - newItem->info.prio);
119 }
120 
121 struct HOOKITEM_COMPARE_VAL {
122     int prio;
123     OhosHook hook;
124     void *hookCookie;
125 };
126 
hookItemCompareValue(ListNode * node,void * data)127 static int hookItemCompareValue(ListNode *node, void *data)
128 {
129     const HOOK_ITEM *hookItem;
130     struct HOOKITEM_COMPARE_VAL *compareVal = (struct HOOKITEM_COMPARE_VAL *)data;
131 
132     hookItem = (const HOOK_ITEM *)node;
133     BEGET_CHECK(hookItem->info.prio == compareVal->prio, return (hookItem->info.prio - compareVal->prio));
134     if (hookItem->info.hook == compareVal->hook && hookItem->info.hookCookie == compareVal->hookCookie) {
135         return 0;
136     }
137     return -1;
138 }
139 
140 // Add hook to stage list with prio ordered
addHookToStage(HOOK_STAGE * hookStage,int prio,OhosHook hook,void * hookCookie)141 static int addHookToStage(HOOK_STAGE *hookStage, int prio, OhosHook hook, void *hookCookie)
142 {
143     HOOK_ITEM *hookItem;
144     struct HOOKITEM_COMPARE_VAL compareVal;
145 
146     // Check if exists
147     compareVal.prio = prio;
148     compareVal.hook = hook;
149     compareVal.hookCookie = hookCookie;
150     hookItem = (HOOK_ITEM *)OH_ListFind(&(hookStage->hooks), (void *)(&compareVal), hookItemCompareValue);
151     BEGET_CHECK(hookItem == NULL, return 0);
152 
153     // Create new item
154     hookItem = (HOOK_ITEM *)malloc(sizeof(HOOK_ITEM));
155     BEGET_CHECK(hookItem != NULL, return -1);
156     hookItem->info.stage = hookStage->stage;
157     hookItem->info.prio = prio;
158     hookItem->info.hook = hook;
159     hookItem->info.hookCookie = hookCookie;
160     hookItem->stage = hookStage;
161 
162     // Insert with order
163     OH_ListAddWithOrder(&(hookStage->hooks), (ListNode *)hookItem, hookItemCompare);
164     return 0;
165 }
166 
HookMgrAddEx(HOOK_MGR * hookMgr,const HOOK_INFO * hookInfo)167 int HookMgrAddEx(HOOK_MGR *hookMgr, const HOOK_INFO *hookInfo)
168 {
169     HOOK_STAGE *stageItem;
170     BEGET_CHECK(hookInfo != NULL, return -1);
171     BEGET_CHECK(hookInfo->hook != NULL, return -1);
172 
173     // Get HOOK_MGR
174     hookMgr = getHookMgr(hookMgr, true);
175     BEGET_CHECK(hookMgr != NULL, return -1);
176 
177     // Get HOOK_STAGE list
178     stageItem = getHookStage(hookMgr, hookInfo->stage, true);
179     BEGET_CHECK(stageItem != NULL, return -1);
180 
181     // Add hook to stage
182     return addHookToStage(stageItem, hookInfo->prio, hookInfo->hook, hookInfo->hookCookie);
183 }
184 
HookMgrAdd(HOOK_MGR * hookMgr,int stage,int prio,OhosHook hook)185 int HookMgrAdd(HOOK_MGR *hookMgr, int stage, int prio, OhosHook hook)
186 {
187     HOOK_INFO info;
188     info.stage = stage;
189     info.prio = prio;
190     info.hook = hook;
191     info.hookCookie = NULL;
192     return HookMgrAddEx(hookMgr, &info);
193 }
194 
hookTraversalDelProc(ListNode * node,void * cookie)195 static int hookTraversalDelProc(ListNode *node, void *cookie)
196 {
197     HOOK_ITEM *hookItem = (HOOK_ITEM *)node;
198 
199     // Not equal, just return
200     BEGET_CHECK((void *)hookItem->info.hook == cookie, return 0);
201 
202     // Remove from the list
203     OH_ListRemove(node);
204     // Destroy myself
205     free((void *)node);
206 
207     return 0;
208 }
209 
210 /*
211  * 删除钩子函数
212  * hook为NULL,表示删除该stage上的所有hooks
213  */
HookMgrDel(HOOK_MGR * hookMgr,int stage,OhosHook hook)214 void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook)
215 {
216     HOOK_STAGE *stageItem;
217 
218     // Get HOOK_MGR
219     hookMgr = getHookMgr(hookMgr, 0);
220     BEGET_CHECK(hookMgr != NULL, return);
221 
222     // Get HOOK_STAGE list
223     stageItem = getHookStage(hookMgr, stage, false);
224     BEGET_CHECK(stageItem != NULL, return);
225 
226     if (hook != NULL) {
227         OH_ListTraversal(&(stageItem->hooks), hook, hookTraversalDelProc, 0);
228         return;
229     }
230 
231     // Remove from list
232     OH_ListRemove((ListNode *)stageItem);
233 
234     // Destroy stage item
235     hookStageDestroy((ListNode *)stageItem);
236 }
237 
238 typedef struct tagHOOK_EXECUTION_ARGS {
239     void *executionContext;
240     const HOOK_EXEC_OPTIONS *options;
241 } HOOK_EXECUTION_ARGS;
242 
hookExecutionProc(ListNode * node,void * cookie)243 static int hookExecutionProc(ListNode *node, void *cookie)
244 {
245     int ret;
246     HOOK_ITEM *hookItem = (HOOK_ITEM *)node;
247     HOOK_EXECUTION_ARGS *args = (HOOK_EXECUTION_ARGS *)cookie;
248 
249     if ((args->options != NULL) && (args->options->preHook != NULL)) {
250         args->options->preHook(&hookItem->info, args->executionContext);
251     }
252     ret = hookItem->info.hook(&hookItem->info, args->executionContext);
253     if ((args->options != NULL) && (args->options->postHook != NULL)) {
254         args->options->postHook(&hookItem->info, args->executionContext, ret);
255     }
256 
257     return ret;
258 }
259 
260 /*
261  * 执行钩子函数
262  */
HookMgrExecute(HOOK_MGR * hookMgr,int stage,void * executionContext,const HOOK_EXEC_OPTIONS * options)263 int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *options)
264 {
265     unsigned int flags;
266     HOOK_STAGE *stageItem;
267     HOOK_EXECUTION_ARGS args;
268 
269     // Get HOOK_MGR
270     hookMgr = getHookMgr(hookMgr, 0);
271     BEGET_CHECK(hookMgr != NULL, return -1)
272 
273     // Get HOOK_STAGE list
274     stageItem = getHookStage(hookMgr, stage, false);
275     BEGET_CHECK(stageItem != NULL, return -1);
276 
277     flags = 0;
278     if (options != NULL) {
279         flags = (unsigned int)(options->flags);
280     }
281 
282     args.executionContext = executionContext;
283     args.options = options;
284 
285     // Traversal all hooks in the specified stage
286     return OH_ListTraversal(&(stageItem->hooks), (void *)(&args), hookExecutionProc, flags);
287 }
288 
HookMgrCreate(const char * name)289 HOOK_MGR *HookMgrCreate(const char *name)
290 {
291     HOOK_MGR *ret;
292 
293     BEGET_CHECK(name != NULL, return NULL);
294     ret = (HOOK_MGR *)malloc(sizeof(HOOK_MGR));
295     BEGET_CHECK(ret != NULL, return NULL);
296 
297     ret->name = strdup(name);
298     if (ret->name == NULL) {
299         free((void *)ret);
300         return NULL;
301     }
302     OH_ListInit(&(ret->stages));
303     return ret;
304 }
305 
HookMgrDestroy(HOOK_MGR * hookMgr)306 void HookMgrDestroy(HOOK_MGR *hookMgr)
307 {
308     hookMgr = getHookMgr(hookMgr, 0);
309     BEGET_CHECK(hookMgr != NULL, return);
310 
311     OH_ListRemoveAll(&(hookMgr->stages), hookStageDestroy);
312 
313     if (hookMgr == defaultHookMgr) {
314         defaultHookMgr = NULL;
315     }
316     if (hookMgr->name != NULL) {
317         free((void *)hookMgr->name);
318     }
319     free((void *)hookMgr);
320 }
321 
322 typedef struct tagHOOK_TRAVERSAL_ARGS {
323     void *traversalCookie;
324     OhosHookTraversal traversal;
325 } HOOK_TRAVERSAL_ARGS;
326 
hookItemTraversal(ListNode * node,void * data)327 static int hookItemTraversal(ListNode *node, void *data)
328 {
329     HOOK_ITEM *hookItem;
330     HOOK_TRAVERSAL_ARGS *stageArgs;
331 
332     hookItem = (HOOK_ITEM *)node;
333     stageArgs = (HOOK_TRAVERSAL_ARGS *)data;
334 
335     stageArgs->traversal(&(hookItem->info), stageArgs->traversalCookie);
336     return 0;
337 }
338 
hookStageTraversal(ListNode * node,void * data)339 static int hookStageTraversal(ListNode *node, void *data)
340 {
341     HOOK_STAGE *stageItem = (HOOK_STAGE *)node;
342     OH_ListTraversal(&(stageItem->hooks), data, hookItemTraversal, 0);
343     return 0;
344 }
345 
346 /*
347  * 遍历所有的hooks
348  */
HookMgrTraversal(HOOK_MGR * hookMgr,void * traversalCookie,OhosHookTraversal traversal)349 void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal)
350 {
351     HOOK_TRAVERSAL_ARGS stageArgs;
352 
353     BEGET_CHECK(traversal != NULL, return);
354 
355     hookMgr = getHookMgr(hookMgr, 0);
356     BEGET_CHECK(hookMgr != NULL, return);
357 
358     // Prepare common args
359     stageArgs.traversalCookie = traversalCookie;
360     stageArgs.traversal = traversal;
361     OH_ListTraversal(&(hookMgr->stages), (void *)(&stageArgs), hookStageTraversal, 0);
362 }
363 
364 /*
365  * 获取指定stage中hooks的个数
366  */
HookMgrGetHooksCnt(HOOK_MGR * hookMgr,int stage)367 int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage)
368 {
369     HOOK_STAGE *stageItem;
370 
371     hookMgr = getHookMgr(hookMgr, 0);
372     BEGET_CHECK(hookMgr != NULL, return 0);
373 
374     // Get HOOK_STAGE list
375     stageItem = getHookStage(hookMgr, stage, false);
376     BEGET_CHECK(stageItem != NULL, return 0);
377 
378     return OH_ListGetCnt(&(stageItem->hooks));
379 }
380 
381 /*
382  * 获取指定stage中hooks的个数
383  */
HookMgrGetStagesCnt(HOOK_MGR * hookMgr)384 int HookMgrGetStagesCnt(HOOK_MGR *hookMgr)
385 {
386     hookMgr = getHookMgr(hookMgr, 0);
387     BEGET_CHECK(hookMgr != NULL, return 0);
388 
389     return OH_ListGetCnt(&(hookMgr->stages));
390 }
391