Bump up efl module version.
[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_ACTIVATION_METHOD           "ACTIVATION_METHOD"
33 #define TAG_DEACTIVATION_METHOD         "DEACTIVATION_METHOD"
34 #define TAG_TTL                         "TTL"
35 #define TAG_TIMEOUT                     "TIMEOUT"
36 #define TAG_EXTRA                       "EXTRA"
37 #define TAG_EXTRA_ARRAY                 "EXTRA_ARRAY"
38 #define TAG_EXTRA_ARRAY_VAL             "EXTRA_ARRAY_VAL"
39 #define TAG_ALTERNATIVE_LOADER          "ALTERNATIVE_LOADER"
40 #define TAG_HW_ACC                      "HW_ACC"
41 #define TAG_CPU_THRESHOLD_MAX           "CPU_THRESHOLD_MAX"
42 #define TAG_CPU_THRESHOLD_MIN           "CPU_THRESHOLD_MIN"
43 #define TAG_ON_BOOT                     "ON_BOOT"
44
45 #define VAL_ON                          "ON"
46 #define VAL_OFF                         "OFF"
47 #define VAL_METHOD_TIMEOUT              "TIMEOUT"
48 #define VAL_METHOD_DEMAND               "DEMAND"
49 #define VAL_METHOD_VISIBILITY           "VISIBILITY"
50 #define VAL_METHOD_REQUEST              "REQUEST"
51 #define VAL_METHOD_AVAILABLE_MEMORY     "AVAILABLE_MEMORY"
52 #define VAL_METHOD_TTL                  "TTL"
53 #define VAL_METHOD_OUT_OF_MEMORY        "OUT_OF_MEMORY"
54
55 static loader_info_t *__create_loader_info()
56 {
57         loader_info_t *info;
58
59         info = malloc(sizeof(loader_info_t));
60         if (info == NULL) {
61                 _E("Out of memory");
62                 return NULL;
63         }
64
65         info->type = 0;
66         info->name = NULL;
67         info->exe = NULL;
68         info->app_types = NULL;
69         info->hw_acc = NULL;
70         info->alternative_loaders = NULL;
71         info->detection_method = METHOD_TIMEOUT | METHOD_VISIBILITY |
72                 METHOD_INSTALL;
73         info->timeout_val = 5000;
74         info->extra = bundle_create();
75         info->cpu_threshold_max = DEFAULT_CPU_THRESHOLD_MAX;
76         info->cpu_threshold_min = DEFAULT_CPU_THRESHOLD_MIN;
77         info->on_boot = true;
78         info->app_exists = false;
79         info->activation_method = 0;
80         info->deactivation_method = 0;
81         info->ttl = 600; /* 10 minutes */
82
83         return info;
84 }
85
86 static void __parse_detection_method(loader_info_t *info, char *line)
87 {
88         char *token;
89         char *savedptr;
90
91         token = strtok_r(line, " |\t\r\n", &savedptr);
92         info->detection_method = 0;
93         while (token) {
94                 if (!strcmp(token, VAL_METHOD_TIMEOUT))
95                         info->detection_method |= METHOD_TIMEOUT;
96                 else if (!strcmp(token, VAL_METHOD_VISIBILITY))
97                         info->detection_method |= METHOD_VISIBILITY;
98                 else if (!strcmp(token, VAL_METHOD_DEMAND))
99                         info->detection_method |= METHOD_DEMAND;
100
101                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
102         }
103
104         info->detection_method |= METHOD_INSTALL;
105         _D("detection_method:%d", info->detection_method);
106 }
107
108 static void __parse_activation_method(loader_info_t *info, char *line)
109 {
110         char *token;
111         char *savedptr;
112
113         token = strtok_r(line, " |\t\r\n", &savedptr);
114         info->activation_method = 0;
115         while (token) {
116                 if (!strcmp(token, VAL_METHOD_REQUEST))
117                         info->activation_method |= METHOD_REQUEST;
118                 else if (!strcmp(token, VAL_METHOD_AVAILABLE_MEMORY))
119                         info->activation_method |= METHOD_AVAILABLE_MEMORY;
120
121                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
122         }
123
124         _D("activation_method:%d", info->activation_method);
125 }
126
127 static void __parse_deactivation_method(loader_info_t *info, char *line)
128 {
129         char *token;
130         char *savedptr;
131
132         token = strtok_r(line, " |\t\r\n", &savedptr);
133         info->deactivation_method = 0;
134         while (token) {
135                 if (!strcmp(token, VAL_METHOD_TTL))
136                         info->deactivation_method |= METHOD_TTL;
137                 else if (!strcmp(token, VAL_METHOD_OUT_OF_MEMORY))
138                         info->deactivation_method |= METHOD_OUT_OF_MEMORY;
139
140                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
141         }
142
143         _D("deactivation_method:%d", info->deactivation_method);
144 }
145
146 static void __parse_app_types(loader_info_t *info, char *line)
147 {
148         char *token;
149         char *savedptr;
150
151         token = strtok_r(line, " |\t\r\n", &savedptr);
152         while (token) {
153                 info->app_types = g_list_append(info->app_types, strdup(token));
154                 token = strtok_r(NULL, " |\t\r\n", &savedptr);
155         }
156 }
157
158 static void __parse_extra(loader_info_t *info, char *line)
159 {
160         char *tok1 = NULL;
161         char *tok2 = NULL;
162         char *tok3 = NULL;
163
164         if (info->extra == NULL)
165                 return;
166
167         sscanf(line, "%ms %ms %ms", &tok1, &tok2, &tok3);
168
169         if (!tok1 || !tok2 || !tok3)
170                 goto end;
171
172         if (strlen(tok2) == 0 || strlen(tok3) == 0)
173                 goto end;
174
175         bundle_add_str(info->extra, tok2, tok3);
176
177 end:
178         if (tok1)
179                 free(tok1);
180         if (tok2)
181                 free(tok2);
182         if (tok3)
183                 free(tok3);
184 }
185
186 static void __add_extra_array_from_list(bundle *b, const char *key, GList *list)
187 {
188         const char **array;
189         int len;
190         int i;
191         GList *cur;
192
193         if (b == NULL || key == NULL || list == NULL)
194                 return;
195
196         len = g_list_length(list);
197         array = malloc(sizeof(const char *) * len);
198         if (array == NULL)
199                 return;
200
201         cur = list;
202         for (i = 0; i < len; i++) {
203                 array[i] = cur->data;
204                 cur = g_list_next(cur);
205         }
206
207         bundle_add_str_array(b, key, array, len);
208         free(array);
209 }
210
211 static void __flush_extra_array(bundle *b, char *key, GList *list)
212 {
213         if (list) {
214                 __add_extra_array_from_list(b, key, list);
215                 g_list_free_full(list, free);
216         }
217
218         free(key);
219 }
220
221 static GList *__parse_file(GList *list, const char *path)
222 {
223         FILE *fp;
224         char buf[LINE_MAX];
225         char *tok1 = NULL;
226         char *tok2 = NULL;
227         loader_info_t *cur_info = NULL;
228         char *key = NULL;
229         GList *extra_array = NULL;
230
231         fp = fopen(path, "rt");
232         if (fp == NULL)
233                 return list;
234
235         while (fgets(buf, sizeof(buf), fp) != NULL) {
236                 FREE_AND_NULL(tok1);
237                 FREE_AND_NULL(tok2);
238                 sscanf(buf, "%ms %ms", &tok1, &tok2);
239                 if (tok1 && strcasecmp(TAG_LOADER, tok1) == 0) {
240                         if (cur_info != NULL) {
241                                 __flush_extra_array(cur_info->extra, key,
242                                                 extra_array);
243                                 extra_array = NULL;
244                                 key = NULL;
245                                 list = g_list_append(list, cur_info);
246                         }
247                         cur_info = __create_loader_info();
248                         if (!cur_info)
249                                 break;
250                         continue;
251                 }
252
253                 if (!tok1 || !tok2 || !cur_info)
254                         continue;
255                 if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#')
256                         continue;
257
258                 if (strcasecmp(TAG_NAME, tok1) == 0) {
259                         cur_info->name = strdup(tok2);
260                 } else if (strcasecmp(TAG_EXE, tok1) == 0) {
261                         cur_info->exe = strdup(tok2);
262                 } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) {
263                         __parse_app_types(cur_info, &buf[strlen(tok1)]);
264                 } else if (strcasecmp(TAG_DETECTION_METHOD, tok1) == 0) {
265                         __parse_detection_method(cur_info, &buf[strlen(tok1)]);
266                 } else if (strcasecmp(TAG_ACTIVATION_METHOD, tok1) == 0) {
267                         __parse_activation_method(cur_info,
268                                         &buf[strlen(tok1)]);
269                 } else if (strcasecmp(TAG_DEACTIVATION_METHOD, tok1) == 0) {
270                         __parse_deactivation_method(cur_info,
271                                         &buf[strlen(tok1)]);
272                 } else if (strcasecmp(TAG_TTL, tok1) == 0) {
273                         cur_info->ttl = strtoul(tok2, NULL, 10);
274                 } else if (strcasecmp(TAG_TIMEOUT, tok1) == 0) {
275                         cur_info->timeout_val = atoi(tok2);
276                 } else if (strcasecmp(TAG_EXTRA, tok1) == 0) {
277                         __parse_extra(cur_info, buf);
278                 } else if (strcasecmp(TAG_EXTRA_ARRAY, tok1) == 0) {
279                         __flush_extra_array(cur_info->extra, key, extra_array);
280                         extra_array = NULL;
281                         key = strdup(tok2);
282                 } else if (strcasecmp(TAG_EXTRA_ARRAY_VAL, tok1) == 0) {
283                         extra_array = g_list_append(extra_array, strdup(tok2));
284                 } else if (strcasecmp(TAG_HW_ACC, tok1) == 0) {
285                         cur_info->hw_acc = strdup(tok2);
286                 } else if (strcasecmp(TAG_ALTERNATIVE_LOADER, tok1) == 0) {
287                         cur_info->alternative_loaders =
288                                 g_list_append(cur_info->alternative_loaders,
289                                                 strdup(tok2));
290                 } else if (strcasecmp(TAG_CPU_THRESHOLD_MAX, tok1) == 0) {
291                         cur_info->cpu_threshold_max = atoi(tok2);
292                 } else if (strcasecmp(TAG_CPU_THRESHOLD_MIN, tok1) == 0) {
293                         cur_info->cpu_threshold_min = atoi(tok2);
294                 } else if (strcasecmp(TAG_ON_BOOT, tok1) == 0) {
295                         if (tok2 && strcasecmp(VAL_OFF, tok2) == 0)
296                                 cur_info->on_boot = false;
297                 }
298         }
299
300         if (cur_info != NULL) {
301                 __flush_extra_array(cur_info->extra, key, extra_array);
302                 list = g_list_append(list, cur_info);
303         }
304
305         if (tok1)
306                 free(tok1);
307         if (tok2)
308                 free(tok2);
309
310         fclose(fp);
311
312         return list;
313 }
314
315 GList *_loader_info_load(const char *path)
316 {
317         DIR *dir_info;
318         struct dirent *entry = NULL;
319         GList *list = NULL;
320         char buf[PATH_MAX];
321         char *ext;
322
323         dir_info = opendir(path);
324         if (dir_info == NULL)
325                 return  NULL;
326
327         while ((entry = readdir(dir_info)) != NULL) {
328                 if (entry->d_name[0] == '.')
329                         continue;
330                 ext = strrchr(entry->d_name, '.');
331                 if (ext && !strcmp(ext, ".loader")) {
332                         snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name);
333                         list = __parse_file(list, buf);
334                 }
335         }
336         closedir(dir_info);
337
338         return list;
339 }
340
341 static void __free_info(gpointer data)
342 {
343         loader_info_t *info;
344
345         if (data == NULL)
346                 return;
347
348         info = (loader_info_t *)data;
349
350         free(info->name);
351         free(info->exe);
352         if (info->app_types)
353                 g_list_free_full(info->app_types, free);
354         free(info->hw_acc);
355         if (info->extra)
356                 bundle_free(info->extra);
357         if (info->alternative_loaders)
358                 g_list_free_full(info->alternative_loaders, free);
359
360         free(info);
361 }
362
363 void _loader_info_dispose(GList *info)
364 {
365         g_list_free_full(info, __free_info);
366 }
367
368 static int __comp_str(gconstpointer a, gconstpointer b)
369 {
370         if (!a || !b)
371                 return -1;
372         return strcmp(a, b);
373 }
374
375 static int __comp_app_type_with_hw_acc(gconstpointer a, gconstpointer b)
376 {
377         loader_info_t *info = (loader_info_t *)a;
378
379         if (info == NULL || info->app_types == NULL || b == NULL)
380                 return -1;
381
382         if (g_list_find_custom(info->app_types, b, __comp_str) &&
383                 (info->hw_acc == NULL || !strcasecmp(VAL_ON, info->hw_acc)))
384                 return 0;
385
386         return -1;
387 }
388
389 static int __comp_app_type_with_sw_acc(gconstpointer a, gconstpointer b)
390 {
391         loader_info_t *info = (loader_info_t *)a;
392
393         if (info == NULL || info->app_types == NULL || b == NULL)
394                 return -1;
395
396         if (g_list_find_custom(info->app_types, b, __comp_str) &&
397                 (info->hw_acc == NULL || !strcasecmp(VAL_OFF, info->hw_acc)))
398                 return 0;
399
400         return -1;
401 }
402
403 static int __comp_name(gconstpointer a, gconstpointer b)
404 {
405         loader_info_t *info = (loader_info_t *)a;
406
407         if (info == NULL || info->name == NULL || b == NULL)
408                 return -1;
409
410         return strcmp(info->name, b);
411 }
412
413 int _loader_info_find_type(GList *info,  const char *app_type, bool hwacc)
414 {
415         GList *cur;
416
417         if (hwacc) {
418                 cur = g_list_find_custom(info, app_type,
419                                 __comp_app_type_with_hw_acc);
420         } else {
421                 cur = g_list_find_custom(info, app_type,
422                                 __comp_app_type_with_sw_acc);
423         }
424
425         if (cur == NULL)
426                 return -1;
427
428         loader_info_t *cur_info = (loader_info_t *)cur->data;
429
430         return cur_info->type;
431 }
432
433 int _loader_info_find_type_by_loader_name(GList *info,  const char *loader_name)
434 {
435         GList *cur = NULL;
436
437         cur = g_list_find_custom(info, loader_name, __comp_name);
438         if (cur == NULL)
439                 return -1;
440
441         loader_info_t *cur_info = (loader_info_t *)cur->data;
442
443         return cur_info->type;
444 }
445
446 static int *__make_type_array(GList *info, GList *loaders, int *len)
447 {
448         int l;
449         int *t;
450         loader_info_t *i;
451         GList *c;
452         GList *cur;
453         int j = 0;
454
455         l = g_list_length(loaders);
456
457         if (l <= 0)
458                 return NULL;
459
460         t = malloc(sizeof(int) * l);
461         if (!t)
462                 return NULL;
463
464         *len = l;
465
466         cur = loaders;
467         while (cur) {
468                 c = g_list_find_custom(info, cur->data, __comp_name);
469
470                 if (c) {
471                         i = (loader_info_t *)c->data;
472                         t[j] = i->type;
473                         j++;
474                 }
475
476                 cur = g_list_next(cur);
477         }
478
479         return t;
480 }
481
482 int *_loader_get_alternative_types(GList *info, int type, int *len)
483 {
484         GList *cur;
485         loader_info_t *i;
486
487         if (!info)
488                 return NULL;
489
490         cur = info;
491         while (cur) {
492                 i = (loader_info_t *)cur->data;
493                 if (i->type == type) {
494                         if (!i->alternative_loaders)
495                                 return NULL;
496
497                         return __make_type_array(info, i->alternative_loaders,
498                                         len);
499                 }
500                 cur = g_list_next(cur);
501         }
502
503         return NULL;
504 }
505
506 int _loader_info_foreach(GList *info, loader_info_foreach_cb callback,
507                 void *data)
508 {
509         GList *cur;
510         loader_info_t *i;
511
512         if (!info || !callback)
513                 return -1;
514
515         cur = info;
516         while (cur) {
517                 i = (loader_info_t *)cur->data;
518                 callback(i, data);
519                 cur = g_list_next(cur);
520         }
521
522         return 0;
523 }
524
525 bool _loader_info_exist_app_type(loader_info_t *info, const char *app_type)
526 {
527         GList *list;
528
529         list = g_list_find_custom(info->app_types, app_type, __comp_str);
530         if (list)
531                 return true;
532
533         return false;
534 }