Add grammar for setting cpu threadhold
[platform/core/appfw/launchpad.git] / src / loader_info.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define _GNU_SOURCE
17
18 #include <stdio.h>
19 #include <malloc.h>
20 #include <stdlib.h>
21 #include <dirent.h>
22 #include <string.h>
23
24 #include "loader_info.h"
25 #include "launchpad_common.h"
26
27 #define TAG_LOADER      "[LOADER]"
28 #define TAG_NAME        "NAME"
29 #define TAG_EXE         "EXE"
30 #define TAG_APP_TYPE    "APP_TYPE"
31 #define TAG_DETECTION_METHOD    "DETECTION_METHOD"
32 #define TAG_TIMEOUT     "TIMEOUT"
33 #define TAG_EXTRA       "EXTRA"
34 #define TAG_EXTRA_ARRAY         "EXTRA_ARRAY"
35 #define TAG_EXTRA_ARRAY_VAL     "EXTRA_ARRAY_VAL"
36 #define TAG_ALTERNATIVE_LOADER  "ALTERNATIVE_LOADER"
37 #define TAG_HW_ACC              "HW_ACC"
38 #define TAG_CPU_THRESHOLD_MAX   "CPU_THRESHOLD_MAX"
39 #define TAG_CPU_THRESHOLD_MIN   "CPU_THRESHOLD_MIN"
40 #define VAL_ON                  "ON"
41 #define VAL_OFF                 "OFF"
42 #define VAL_METHOD_TIMEOUT      "TIMEOUT"
43 #define VAL_METHOD_DEMAND       "DEMAND"
44 #define VAL_METHOD_VISIBILITY   "VISIBILITY"
45
46
47 static loader_info_t *__create_loader_info()
48 {
49         loader_info_t *info = malloc(sizeof(loader_info_t));
50
51         if (!info)
52                 return NULL;
53
54         info->type = 0;
55         info->name = NULL;
56         info->exe = NULL;
57         info->app_types = NULL;
58         info->hw_acc = NULL;
59         info->alternative_loaders = NULL;
60         info->detection_method = METHOD_TIMEOUT | METHOD_VISIBILITY;
61         info->timeout_val = 5000;
62         info->extra = bundle_create();
63         info->cpu_threshold_max = DEFAULT_CPU_THRESHOLD_MAX;
64         info->cpu_threshold_min = DEFAULT_CPU_THRESHOLD_MIN;
65
66         return info;
67 }
68
69 static void __parse_detection_method(loader_info_t *info, char *line)
70 {
71         char *token;
72         char *savedptr;
73
74         token = strtok_r(line, " |\t\r\n", &savedptr);
75         info->detection_method = 0;
76         while (token) {
77                 if (!strcmp(token, VAL_METHOD_TIMEOUT))
78                         info->detection_method |= METHOD_TIMEOUT;
79                 else if (!strcmp(token, VAL_METHOD_VISIBILITY))
80                         info->detection_method |= METHOD_VISIBILITY;
81                 else if (!strcmp(token, VAL_METHOD_DEMAND))
82                         info->detection_method |= METHOD_DEMAND;
83
84                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
85         }
86
87         _D("detection_method:%d", info->detection_method);
88 }
89
90 static void __parse_app_types(loader_info_t *info, char *line)
91 {
92         char *token;
93         char *savedptr;
94
95         token = strtok_r(line, " |\t\r\n", &savedptr);
96         while (token) {
97                 info->app_types = g_list_append(info->app_types, strdup(token));
98                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
99         }
100 }
101
102 static void __parse_extra(loader_info_t *info, char *line)
103 {
104         char *tok1 = NULL;
105         char *tok2 = NULL;
106         char *tok3 = NULL;
107
108         if (info->extra == NULL)
109                 return;
110
111         sscanf(line, "%ms %ms %ms", &tok1, &tok2, &tok3);
112
113         if (!tok1 || !tok2 || !tok3)
114                 goto end;
115
116         if (strlen(tok2) == 0 || strlen(tok3) == 0)
117                 goto end;
118
119         bundle_add_str(info->extra, tok2, tok3);
120
121 end:
122         if (tok1)
123                 free(tok1);
124         if (tok2)
125                 free(tok2);
126         if (tok3)
127                 free(tok3);
128 }
129
130 static void __add_extra_array_from_list(bundle *b, const char *key, GList *list)
131 {
132         const char **array;
133         int len;
134         int i;
135         GList *cur;
136
137         if (b == NULL || key == NULL || list == NULL)
138                 return;
139
140         len = g_list_length(list);
141         array = malloc(sizeof(const char *) * len);
142
143         cur = list;
144         for (i = 0; i < len; i++) {
145                 array[i] = cur->data;
146                 cur = g_list_next(cur);
147         }
148
149         bundle_add_str_array(b, key, array, len);
150         free(array);
151 }
152
153 static void __flush_extra_array(bundle *b, char *key, GList *list)
154 {
155         if (list) {
156                 __add_extra_array_from_list(b, key, list);
157                 g_list_free_full(list, free);
158         }
159
160         free(key);
161 }
162
163 static GList *__parse_file(GList *list, const char *path)
164 {
165         FILE *fp;
166         char buf[LINE_MAX];
167         char *tok1 = NULL;
168         char *tok2 = NULL;
169         loader_info_t *cur_info = NULL;
170         char *key = NULL;
171         GList *extra_array = NULL;
172
173         fp = fopen(path, "rt");
174         if (fp == NULL)
175                 return list;
176
177         while (fgets(buf, sizeof(buf), fp) != NULL) {
178                 FREE_AND_NULL(tok1);
179                 FREE_AND_NULL(tok2);
180                 sscanf(buf, "%ms %ms", &tok1, &tok2);
181                 if (tok1 && strcasecmp(TAG_LOADER, tok1) == 0) {
182                         if (cur_info != NULL) {
183                                 __flush_extra_array(cur_info->extra, key,
184                                                 extra_array);
185                                 extra_array = NULL;
186                                 key = NULL;
187                                 list = g_list_append(list, cur_info);
188                         }
189                         cur_info = __create_loader_info();
190                         continue;
191                 }
192
193                 if (!tok1 || !tok2 || !cur_info)
194                         continue;
195                 if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#')
196                         continue;
197
198                 if (strcasecmp(TAG_NAME, tok1) == 0) {
199                         cur_info->name = strdup(tok2);
200                 } else if (strcasecmp(TAG_EXE, tok1) == 0) {
201                         cur_info->exe = strdup(tok2);
202                 } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) {
203                         __parse_app_types(cur_info, &buf[strlen(tok1)]);
204                 } else if (strcasecmp(TAG_DETECTION_METHOD, tok1) == 0) {
205                         __parse_detection_method(cur_info, &buf[strlen(tok1)]);
206                 } else if (strcasecmp(TAG_TIMEOUT, tok1) == 0) {
207                         cur_info->timeout_val = atoi(tok2);
208                 } else if (strcasecmp(TAG_EXTRA, tok1) == 0) {
209                         __parse_extra(cur_info, buf);
210                 } else if (strcasecmp(TAG_EXTRA_ARRAY, tok1) == 0) {
211                         __flush_extra_array(cur_info->extra, key, extra_array);
212                         extra_array = NULL;
213                         key = strdup(tok2);
214                 } else if (strcasecmp(TAG_EXTRA_ARRAY_VAL, tok1) == 0) {
215                         extra_array = g_list_append(extra_array, strdup(tok2));
216                 } else if (strcasecmp(TAG_HW_ACC, tok1) == 0) {
217                         cur_info->hw_acc = strdup(tok2);
218                 } else if (strcasecmp(TAG_ALTERNATIVE_LOADER, tok1) == 0) {
219                         cur_info->alternative_loaders =
220                                 g_list_append(cur_info->alternative_loaders,
221                                                 strdup(tok2));
222                 } else if (strcasecmp(TAG_CPU_THRESHOLD_MAX, tok1) == 0) {
223                         cur_info->cpu_threshold_max = atoi(tok2);
224                 } else if (strcasecmp(TAG_CPU_THRESHOLD_MIN, tok1) == 0) {
225                         cur_info->cpu_threshold_min = atoi(tok2);
226                 }
227         }
228
229         if (cur_info != NULL) {
230                 __flush_extra_array(cur_info->extra, key, extra_array);
231                 list = g_list_append(list, cur_info);
232         }
233
234         if (tok1)
235                 free(tok1);
236         if (tok2)
237                 free(tok2);
238
239         fclose(fp);
240
241         return list;
242 }
243
244 GList *_loader_info_load(const char *path)
245 {
246         DIR *dir_info;
247         struct dirent *entry = NULL;
248         GList *list = NULL;
249         char buf[PATH_MAX];
250         char *ext;
251
252         dir_info = opendir(path);
253         if (dir_info == NULL)
254                 return  NULL;
255
256         while ((entry = readdir(dir_info)) != NULL) {
257                 if (entry->d_name[0] == '.')
258                         continue;
259                 ext = strrchr(entry->d_name, '.');
260                 if (ext && !strcmp(ext, ".loader")) {
261                         snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name);
262                         list = __parse_file(list, buf);
263                 }
264         }
265         closedir(dir_info);
266
267         return list;
268 }
269
270 static void __free_info(gpointer data)
271 {
272         loader_info_t *info;
273
274         if (data == NULL)
275                 return;
276
277         info = (loader_info_t *)data;
278
279         free(info->name);
280         free(info->exe);
281         if (info->app_types)
282                 g_list_free_full(info->app_types, free);
283         free(info->hw_acc);
284         if (info->extra)
285                 bundle_free(info->extra);
286         if (info->alternative_loaders)
287                 g_list_free_full(info->alternative_loaders, free);
288
289         free(info);
290 }
291
292 void _loader_info_dispose(GList *info)
293 {
294         g_list_free_full(info, __free_info);
295 }
296
297 static int __comp_str(gconstpointer a, gconstpointer b)
298 {
299         if (!a || !b)
300                 return -1;
301         return strcmp(a, b);
302 }
303
304 static int __comp_app_type_with_hw_acc(gconstpointer a, gconstpointer b)
305 {
306         loader_info_t *info = (loader_info_t *)a;
307
308         if (info == NULL || info->app_types == NULL || b == NULL)
309                 return -1;
310
311         if (g_list_find_custom(info->app_types, b, __comp_str) &&
312                 (info->hw_acc == NULL || !strcasecmp(VAL_ON, info->hw_acc)))
313                 return 0;
314
315         return -1;
316 }
317
318 static int __comp_app_type_with_sw_acc(gconstpointer a, gconstpointer b)
319 {
320         loader_info_t *info = (loader_info_t *)a;
321
322         if (info == NULL || info->app_types == NULL || b == NULL)
323                 return -1;
324
325         if (g_list_find_custom(info->app_types, b, __comp_str) &&
326                 (info->hw_acc == NULL || !strcasecmp(VAL_OFF, info->hw_acc)))
327                 return 0;
328
329         return -1;
330 }
331
332 static int __comp_name(gconstpointer a, gconstpointer b)
333 {
334         loader_info_t *info = (loader_info_t *)a;
335
336         if (info == NULL || info->name == NULL || b == NULL)
337                 return -1;
338
339         return strcmp(info->name, b);
340 }
341
342 int _loader_info_find_type(GList *info,  const char *app_type, bool hwacc)
343 {
344         GList *cur;
345
346         if (hwacc) {
347                 cur = g_list_find_custom(info, app_type,
348                                 __comp_app_type_with_hw_acc);
349         } else {
350                 cur = g_list_find_custom(info, app_type,
351                                 __comp_app_type_with_sw_acc);
352         }
353
354         if (cur == NULL)
355                 return -1;
356
357         loader_info_t *cur_info = (loader_info_t *)cur->data;
358
359         return cur_info->type;
360 }
361
362 int _loader_info_find_type_by_loader_name(GList *info,  const char *loader_name)
363 {
364         GList *cur = NULL;
365
366         cur = g_list_find_custom(info, loader_name, __comp_name);
367         if (cur == NULL)
368                 return -1;
369
370         loader_info_t *cur_info = (loader_info_t *)cur->data;
371
372         return cur_info->type;
373 }
374
375 static int *__make_type_array(GList *info, GList *loaders, int *len)
376 {
377         int l;
378         int *t;
379         loader_info_t *i;
380         GList *c;
381         GList *cur;
382         int j = 0;
383
384         l = g_list_length(loaders);
385
386         if (l <= 0)
387                 return NULL;
388
389         t = malloc(sizeof(int) * l);
390         if (!t)
391                 return NULL;
392
393         *len = l;
394
395         cur = loaders;
396         while (cur) {
397                 c = g_list_find_custom(info, cur->data, __comp_name);
398
399                 if (c) {
400                         i = (loader_info_t *)c->data;
401                         t[j] = i->type;
402                         j++;
403                 }
404
405                 cur = g_list_next(cur);
406         }
407
408         return t;
409 }
410
411 int *_loader_get_alternative_types(GList *info, int type, int *len)
412 {
413         GList *cur;
414         loader_info_t *i;
415
416         if (!info)
417                 return NULL;
418
419         cur = info;
420         while (cur) {
421                 i = (loader_info_t *)cur->data;
422                 if (i->type == type) {
423                         if (!i->alternative_loaders)
424                                 return NULL;
425
426                         return __make_type_array(info, i->alternative_loaders,
427                                         len);
428                 }
429                 cur = g_list_next(cur);
430         }
431
432         return NULL;
433 }
434
435
436