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