• 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     node = NULL;
207 
208     return 0;
209 }
210 
211 /*
212  * 删除钩子函数
213  * hook为NULL,表示删除该stage上的所有hooks
214  */
HookMgrDel(HOOK_MGR * hookMgr,int stage,OhosHook hook)215 void HookMgrDel(HOOK_MGR *hookMgr, int stage, OhosHook hook)
216 {
217     HOOK_STAGE *stageItem;
218 
219     // Get HOOK_MGR
220     hookMgr = getHookMgr(hookMgr, 0);
221     BEGET_CHECK(hookMgr != NULL, return);
222 
223     // Get HOOK_STAGE list
224     stageItem = getHookStage(hookMgr, stage, false);
225     BEGET_CHECK(stageItem != NULL, return);
226 
227     if (hook != NULL) {
228         OH_ListTraversal(&(stageItem->hooks), hook, hookTraversalDelProc, 0);
229         return;
230     }
231 
232     // Remove from list
233     OH_ListRemove((ListNode *)stageItem);
234 
235     // Destroy stage item
236     hookStageDestroy((ListNode *)stageItem);
237 }
238 
239 typedef struct tagHOOK_EXECUTION_ARGS {
240     void *executionContext;
241     const HOOK_EXEC_OPTIONS *options;
242 } HOOK_EXECUTION_ARGS;
243 
hookExecutionProc(ListNode * node,void * cookie)244 static int hookExecutionProc(ListNode *node, void *cookie)
245 {
246     int ret;
247     HOOK_ITEM *hookItem = (HOOK_ITEM *)node;
248     HOOK_EXECUTION_ARGS *args = (HOOK_EXECUTION_ARGS *)cookie;
249 
250     if ((args->options != NULL) && (args->options->preHook != NULL)) {
251         args->options->preHook(&hookItem->info, args->executionContext);
252     }
253     ret = hookItem->info.hook(&hookItem->info, args->executionContext);
254     if ((args->options != NULL) && (args->options->postHook != NULL)) {
255         args->options->postHook(&hookItem->info, args->executionContext, ret);
256     }
257 
258     return ret;
259 }
260 
261 /*
262  * 执行钩子函数
263  */
HookMgrExecute(HOOK_MGR * hookMgr,int stage,void * executionContext,const HOOK_EXEC_OPTIONS * options)264 int HookMgrExecute(HOOK_MGR *hookMgr, int stage, void *executionContext, const HOOK_EXEC_OPTIONS *options)
265 {
266     unsigned int flags;
267     HOOK_STAGE *stageItem;
268     HOOK_EXECUTION_ARGS args;
269 
270     // Get HOOK_MGR
271     hookMgr = getHookMgr(hookMgr, 0);
272     BEGET_CHECK(hookMgr != NULL, return -1)
273 
274     // Get HOOK_STAGE list
275     stageItem = getHookStage(hookMgr, stage, false);
276     BEGET_CHECK(stageItem != NULL, return ERR_NO_HOOK_STAGE);
277 
278     flags = 0;
279     if (options != NULL) {
280         flags = (unsigned int)(options->flags);
281     }
282 
283     args.executionContext = executionContext;
284     args.options = options;
285 
286     // Traversal all hooks in the specified stage
287     return OH_ListTraversal(&(stageItem->hooks), (void *)(&args), hookExecutionProc, flags);
288 }
289 
HookMgrCreate(const char * name)290 HOOK_MGR *HookMgrCreate(const char *name)
291 {
292     HOOK_MGR *ret;
293 
294     BEGET_CHECK(name != NULL, return NULL);
295     ret = (HOOK_MGR *)malloc(sizeof(HOOK_MGR));
296     BEGET_CHECK(ret != NULL, return NULL);
297 
298     ret->name = strdup(name);
299     if (ret->name == NULL) {
300         free((void *)ret);
301         return NULL;
302     }
303     OH_ListInit(&(ret->stages));
304     return ret;
305 }
306 
HookMgrDestroy(HOOK_MGR * hookMgr)307 void HookMgrDestroy(HOOK_MGR *hookMgr)
308 {
309     hookMgr = getHookMgr(hookMgr, 0);
310     BEGET_CHECK(hookMgr != NULL, return);
311 
312     OH_ListRemoveAll(&(hookMgr->stages), hookStageDestroy);
313 
314     if (hookMgr == defaultHookMgr) {
315         defaultHookMgr = NULL;
316     }
317     if (hookMgr->name != NULL) {
318         free((void *)hookMgr->name);
319     }
320     free((void *)hookMgr);
321 }
322 
323 typedef struct tagHOOK_TRAVERSAL_ARGS {
324     void *traversalCookie;
325     OhosHookTraversal traversal;
326 } HOOK_TRAVERSAL_ARGS;
327 
hookItemTraversal(ListNode * node,void * data)328 static int hookItemTraversal(ListNode *node, void *data)
329 {
330     HOOK_ITEM *hookItem;
331     HOOK_TRAVERSAL_ARGS *stageArgs;
332 
333     hookItem = (HOOK_ITEM *)node;
334     stageArgs = (HOOK_TRAVERSAL_ARGS *)data;
335 
336     stageArgs->traversal(&(hookItem->info), stageArgs->traversalCookie);
337     return 0;
338 }
339 
hookStageTraversal(ListNode * node,void * data)340 static int hookStageTraversal(ListNode *node, void *data)
341 {
342     HOOK_STAGE *stageItem = (HOOK_STAGE *)node;
343     OH_ListTraversal(&(stageItem->hooks), data, hookItemTraversal, 0);
344     return 0;
345 }
346 
347 /*
348  * 遍历所有的hooks
349  */
HookMgrTraversal(HOOK_MGR * hookMgr,void * traversalCookie,OhosHookTraversal traversal)350 void HookMgrTraversal(HOOK_MGR *hookMgr, void *traversalCookie, OhosHookTraversal traversal)
351 {
352     HOOK_TRAVERSAL_ARGS stageArgs;
353 
354     BEGET_CHECK(traversal != NULL, return);
355 
356     hookMgr = getHookMgr(hookMgr, 0);
357     BEGET_CHECK(hookMgr != NULL, return);
358 
359     // Prepare common args
360     stageArgs.traversalCookie = traversalCookie;
361     stageArgs.traversal = traversal;
362     OH_ListTraversal(&(hookMgr->stages), (void *)(&stageArgs), hookStageTraversal, 0);
363 }
364 
365 /*
366  * 获取指定stage中hooks的个数
367  */
HookMgrGetHooksCnt(HOOK_MGR * hookMgr,int stage)368 int HookMgrGetHooksCnt(HOOK_MGR *hookMgr, int stage)
369 {
370     HOOK_STAGE *stageItem;
371 
372     hookMgr = getHookMgr(hookMgr, 0);
373     BEGET_CHECK(hookMgr != NULL, return 0);
374 
375     // Get HOOK_STAGE list
376     stageItem = getHookStage(hookMgr, stage, false);
377     BEGET_CHECK(stageItem != NULL, return 0);
378 
379     return OH_ListGetCnt(&(stageItem->hooks));
380 }
381 
382 /*
383  * 获取指定stage中hooks的个数
384  */
HookMgrGetStagesCnt(HOOK_MGR * hookMgr)385 int HookMgrGetStagesCnt(HOOK_MGR *hookMgr)
386 {
387     hookMgr = getHookMgr(hookMgr, 0);
388     BEGET_CHECK(hookMgr != NULL, return 0);
389 
390     return OH_ListGetCnt(&(hookMgr->stages));
391 }
392