Merge remote-tracking branch 'origin/master' into implement_api2
[platform/core/appfw/pkgmgr-info.git] / src / appinfo_internal.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <dlfcn.h>
9
10 #include <sqlite3.h>
11 #include <glib.h>
12
13 #include "pkgmgr-info.h"
14 #include "pkgmgrinfo_debug.h"
15 #include "pkgmgrinfo_private.h"
16 #include "pkgmgr_parser.h"
17 #include "pkgmgrinfo_internal.h"
18
19 static int __free_applications(gpointer key, gpointer value,
20                                gpointer user_data) {
21   pkgmgrinfo_basic_free_application((application_x *)value);
22 }
23
24 static void __parse_appcontrol(GList **appcontrol, char *appcontrol_str,
25                                char *visibility, char *id) {
26   char *dup;
27   char *token;
28   char *ptr = NULL;
29   appcontrol_x *ac;
30
31   if (appcontrol_str == NULL) return;
32
33   dup = strdup(appcontrol_str);
34   if (dup == NULL) {
35     _LOGE("out of memory");
36     return;
37   }
38
39   do {
40     ac = calloc(1, sizeof(appcontrol_x));
41     if (ac == NULL) {
42       _LOGE("out of memory");
43       break;
44     }
45     token = strtok_r(dup, "|", &ptr);
46     if (token && strcmp(token, "NULL")) ac->operation = strdup(token);
47     token = strtok_r(NULL, "|", &ptr);
48     if (token && strcmp(token, "NULL")) ac->uri = strdup(token);
49     token = strtok_r(NULL, "|", &ptr);
50     if (token && strcmp(token, "NULL")) ac->mime = strdup(token);
51     ac->visibility = strdup(visibility);
52     ac->id = strdup(id);
53     *appcontrol = g_list_prepend(*appcontrol, ac);
54   } while ((token = strtok_r(NULL, ";", &ptr)));
55
56   free(dup);
57 }
58
59 static int _appinfo_get_splashscreens(sqlite3 *db, const char *appid,
60                                       GList **splashscreens) {
61   static const char query_raw[] =
62       "SELECT src, type, orientation, indicatordisplay, operation, color_depth "
63       "FROM package_app_splash_screen WHERE app_id=%Q";
64   int ret;
65   char *query;
66   sqlite3_stmt *stmt;
67   int idx;
68   splashscreen_x *info;
69
70   query = sqlite3_mprintf(query_raw, appid);
71   if (query == NULL) {
72     LOGE("out of memory");
73     return PMINFO_R_ERROR;
74   }
75
76   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
77   sqlite3_free(query);
78   if (ret != SQLITE_OK) {
79     LOGE("prepare failed: %s", sqlite3_errmsg(db));
80     return PMINFO_R_ERROR;
81   }
82
83   while (sqlite3_step(stmt) == SQLITE_ROW) {
84     info = calloc(1, sizeof(splashscreen_x));
85     if (info == NULL) {
86       LOGE("out of memory");
87       sqlite3_finalize(stmt);
88       return PMINFO_R_ERROR;
89     }
90     idx = 0;
91     _save_column_str(stmt, idx++, &info->src);
92     _save_column_str(stmt, idx++, &info->type);
93     _save_column_str(stmt, idx++, &info->orientation);
94     _save_column_str(stmt, idx++, &info->indicatordisplay);
95     _save_column_str(stmt, idx++, &info->operation);
96     _save_column_str(stmt, idx++, &info->color_depth);
97     *splashscreens = g_list_prepend(*splashscreens, info);
98   }
99
100   sqlite3_finalize(stmt);
101
102   return PMINFO_R_OK;
103 }
104
105 static int _appinfo_get_metadata(sqlite3 *db, const char *appid,
106                                  GList **metadata) {
107   static const char query_raw[] =
108       "SELECT md_key, md_value "
109       "FROM package_app_app_metadata WHERE app_id=%Q";
110   int ret;
111   char *query;
112   sqlite3_stmt *stmt;
113   int idx;
114   metadata_x *info;
115
116   query = sqlite3_mprintf(query_raw, appid);
117   if (query == NULL) {
118     LOGE("out of memory");
119     return PMINFO_R_ERROR;
120   }
121
122   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
123   sqlite3_free(query);
124   if (ret != SQLITE_OK) {
125     LOGE("prepare failed: %s", sqlite3_errmsg(db));
126     return PMINFO_R_ERROR;
127   }
128
129   while (sqlite3_step(stmt) == SQLITE_ROW) {
130     info = calloc(1, sizeof(metadata_x));
131     if (info == NULL) {
132       LOGE("out of memory");
133       sqlite3_finalize(stmt);
134       return PMINFO_R_ERROR;
135     }
136     idx = 0;
137     _save_column_str(stmt, idx++, &info->key);
138     _save_column_str(stmt, idx++, &info->value);
139     *metadata = g_list_prepend(*metadata, info);
140   }
141
142   sqlite3_finalize(stmt);
143
144   return PMINFO_R_OK;
145 }
146
147 static int _appinfo_get_app_control(sqlite3 *db, const char *appid,
148                                     GList **appcontrol) {
149   static const char query_raw[] =
150       "SELECT app_control, visibility, app_control_id "
151       "FROM package_app_app_control WHERE app_id=%Q";
152   int ret;
153   int idx;
154   char *query;
155   sqlite3_stmt *stmt;
156   char *str;
157   char *visibility;
158   char *id;
159
160   query = sqlite3_mprintf(query_raw, appid);
161   if (query == NULL) {
162     LOGE("out of memory");
163     return PMINFO_R_ERROR;
164   }
165
166   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
167   sqlite3_free(query);
168   if (ret != SQLITE_OK) {
169     LOGE("prepare failed: %s", sqlite3_errmsg(db));
170     return PMINFO_R_ERROR;
171   }
172
173   while (sqlite3_step(stmt) == SQLITE_ROW) {
174     str = NULL;
175     visibility = NULL;
176     id = NULL;
177     idx = 0;
178     _save_column_str(stmt, idx++, &str);
179     _save_column_str(stmt, idx++, &visibility);
180     _save_column_str(stmt, idx++, &id);
181     /* TODO: revise */
182     __parse_appcontrol(appcontrol, str, visibility, id);
183     free(str);
184     free(visibility);
185     free(id);
186   }
187
188   sqlite3_finalize(stmt);
189
190   return PMINFO_R_OK;
191 }
192
193 static int _appinfo_get_category(sqlite3 *db, const char *appid,
194                                  GList **category) {
195   static const char query_raw[] =
196       "SELECT category FROM package_app_app_category WHERE app_id=%Q";
197   int ret;
198   char *query;
199   sqlite3_stmt *stmt;
200   char *val;
201
202   query = sqlite3_mprintf(query_raw, appid);
203   if (query == NULL) {
204     LOGE("out of memory");
205     return PMINFO_R_ERROR;
206   }
207
208   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
209   sqlite3_free(query);
210   if (ret != SQLITE_OK) {
211     LOGE("prepare failed: %s", sqlite3_errmsg(db));
212     return PMINFO_R_ERROR;
213   }
214
215   while (sqlite3_step(stmt) == SQLITE_ROW) {
216     val = NULL;
217     _save_column_str(stmt, 0, &val);
218     if (val) *category = g_list_prepend(*category, (gpointer)val);
219   }
220
221   sqlite3_finalize(stmt);
222
223   return PMINFO_R_OK;
224 }
225
226 static GList *__get_background_category(const char *value) {
227   GList *category_list = NULL;
228   int convert_value = 0;
229   if (!value || strlen(value) == 0) return NULL;
230
231   convert_value = atoi(value);
232   if (convert_value < 0) return NULL;
233
234   if (convert_value & APP_BG_CATEGORY_USER_DISABLE_TRUE_VAL)
235     category_list = g_list_prepend(
236         category_list, strdup(APP_BG_CATEGORY_USER_DISABLE_TRUE_STR));
237   else
238     category_list = g_list_prepend(
239         category_list, strdup(APP_BG_CATEGORY_USER_DISABLE_FALSE_STR));
240
241   if (convert_value & APP_BG_CATEGORY_MEDIA_VAL)
242     category_list =
243         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_MEDIA_STR));
244
245   if (convert_value & APP_BG_CATEGORY_DOWNLOAD_VAL)
246     category_list =
247         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_DOWNLOAD_STR));
248
249   if (convert_value & APP_BG_CATEGORY_BGNETWORK_VAL)
250     category_list =
251         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_BGNETWORK_STR));
252
253   if (convert_value & APP_BG_CATEGORY_LOCATION_VAL)
254     category_list =
255         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_LOCATION_STR));
256
257   if (convert_value & APP_BG_CATEGORY_SENSOR_VAL)
258     category_list =
259         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_SENSOR_STR));
260
261   if (convert_value & APP_BG_CATEGORY_IOTCOMM_VAL)
262     category_list =
263         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_IOTCOMM_STR));
264
265   if (convert_value & APP_BG_CATEGORY_SYSTEM_VAL)
266     category_list =
267         g_list_prepend(category_list, strdup(APP_BG_CATEGORY_SYSTEM));
268
269   return category_list;
270 }
271
272 static int __bind_params(sqlite3_stmt *stmt, GList *params) {
273   GList *tmp_list = NULL;
274   int idx = 0;
275   int ret;
276
277   if (stmt == NULL || params == NULL) return PMINFO_R_EINVAL;
278
279   tmp_list = params;
280   while (tmp_list) {
281     ret = sqlite3_bind_text(stmt, ++idx, (char *)tmp_list->data, -1,
282                             SQLITE_STATIC);
283     if (ret != SQLITE_OK) return PMINFO_R_ERROR;
284     tmp_list = tmp_list->next;
285   }
286
287   return PMINFO_R_OK;
288 }
289
290 static const char join_localized_info[] =
291     " LEFT OUTER JOIN package_app_localized_info"
292     "  ON ai.app_id=package_app_localized_info.app_id"
293     "  AND package_app_localized_info.app_locale=?";
294 static const char join_category[] =
295     " LEFT OUTER JOIN package_app_app_category"
296     " ON ai.app_id=package_app_app_category.app_id";
297 static const char join_app_control[] =
298     " LEFT OUTER JOIN package_app_app_control"
299     "  ON ai.app_id=package_app_app_control.app_id";
300 static const char join_metadata[] =
301     " LEFT OUTER JOIN package_app_app_metadata"
302     "  ON ai.app_id=package_app_app_metadata.app_id ";
303 static const char join_privilege[] =
304     " LEFT OUTER JOIN package_privilege_info"
305     " ON ai.package=package_privilege_info.package ";
306
307 static int _get_filtered_query(pkgmgrinfo_filter_x *filter, const char *locale,
308                                uid_t uid, char **query, GList **bind_params) {
309   int joined = 0;
310   int size;
311   char *condition = NULL;
312   char buf[MAX_QUERY_LEN] = {'\0'};
313   char tmp_query[MAX_QUERY_LEN] = {'\0'};
314   GSList *list;
315
316   if (!filter) return PMINFO_R_OK;
317   strncat(buf, " WHERE 1=1", sizeof(buf) - strlen(buf) - 1);
318
319   for (list = filter->list; list; list = list->next) {
320     joined |= __get_filter_condition(list->data, uid, &condition, bind_params);
321     if (condition == NULL) continue;
322
323     strncat(buf, " AND ", sizeof(buf) - strlen(buf) - 1);
324
325     strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
326     free(condition);
327     condition = NULL;
328   }
329
330   if (filter->list_metadata)
331     strncat(buf, " AND (", sizeof(buf) - strlen(buf) - 1);
332   for (list = filter->list_metadata; list; list = list->next) {
333     joined |=
334         __get_metadata_filter_condition(list->data, &condition, bind_params);
335     if (condition == NULL) continue;
336     strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
337     free(condition);
338     condition = NULL;
339
340     strncat(buf, " OR ", sizeof(buf) - strlen(buf) - 1);
341   }
342   if (filter->list_metadata)
343     strncat(buf, "1=0)", sizeof(buf) - strlen(buf) - 1);
344
345   if (joined & E_PMINFO_APPINFO_JOIN_LOCALIZED_INFO) {
346     strncat(tmp_query, join_localized_info,
347             sizeof(tmp_query) - strlen(tmp_query) - 1);
348     *bind_params = g_list_append(*bind_params, strdup(locale));
349   }
350   if (joined & E_PMINFO_APPINFO_JOIN_CATEGORY)
351     strncat(tmp_query, join_category,
352             sizeof(tmp_query) - strlen(tmp_query) - 1);
353   if (joined & E_PMINFO_APPINFO_JOIN_APP_CONTROL)
354     strncat(tmp_query, join_app_control,
355             sizeof(tmp_query) - strlen(tmp_query) - 1);
356   if (joined & E_PMINFO_APPINFO_JOIN_METADATA)
357     strncat(tmp_query, join_metadata,
358             sizeof(tmp_query) - strlen(tmp_query) - 1);
359   if (joined & E_PMINFO_APPINFO_JOIN_PRIVILEGE)
360     strncat(tmp_query, join_privilege,
361             sizeof(tmp_query) - strlen(tmp_query) - 1);
362
363   size = strlen(tmp_query) + strlen(buf) + 1;
364   *query = (char *)calloc(1, size);
365   if (*query == NULL) return PMINFO_R_ERROR;
366   snprintf(*query, size, "%s%s", tmp_query, buf);
367
368   return PMINFO_R_OK;
369 }
370
371 static bool __check_app_storage_status(pkgmgrinfo_filter_x *tmp_filter) {
372   GSList *tmp_list = NULL;
373   pkgmgrinfo_node_x *tmp_node = NULL;
374   int property = -1;
375
376   if (tmp_filter == NULL) return true;
377
378   property = _pminfo_appinfo_convert_to_prop_bool(
379       PMINFO_APPINFO_PROP_APP_CHECK_STORAGE);
380   for (tmp_list = tmp_filter->list; tmp_list != NULL;
381        tmp_list = g_slist_next(tmp_list)) {
382     tmp_node = (pkgmgrinfo_node_x *)tmp_list->data;
383     if (property == tmp_node->prop) {
384       if (strcmp(tmp_node->value, "true") == 0)
385         return true;
386       else
387         return false;
388     }
389   }
390
391   return true;
392 }
393
394 static int _appinfo_get_applications(sqlite3 *db, uid_t db_uid, uid_t uid,
395                                      const char *locale,
396                                      pkgmgrinfo_filter_x *filter, int flag,
397                                      GHashTable *applications) {
398   static const char query_raw[] =
399       "SELECT DISTINCT ai.app_id, ai.app_installed_storage, "
400       "ai.app_external_path";
401   static const char query_basic[] =
402       ", ai.app_component, ai.app_exec, "
403       "ai.app_nodisplay, ai.app_type, ai.app_onboot, "
404       "ai.app_multiple, ai.app_autorestart, ai.app_taskmanage, "
405       "ai.app_hwacceleration, ai.app_screenreader, "
406       "ai.app_mainapp, ai.app_recentimage, ai.app_launchcondition, "
407       "ai.app_indicatordisplay, ai.app_portraitimg, "
408       "ai.app_landscapeimg, ai.app_guestmodevisibility, "
409       "ai.app_permissiontype, ai.app_preload, ai.app_submode, "
410       "ai.app_submode_mainid, ai.app_launch_mode, ai.app_ui_gadget, "
411       "ai.app_support_disable, ai.app_process_pool, "
412       "ai.app_background_category, ai.app_package_type, "
413       "ai.app_root_path, ai.app_api_version, ai.app_effective_appid, "
414       "ai.app_disable, ai.app_splash_screen_display, ai.app_tep_name, "
415       "ai.app_zip_mount_file, ai.component_type, ai.package, "
416       "ai.app_package_system, ai.app_removable, "
417       "ai.app_package_installed_time, ai.app_support_mode, "
418       "ai.app_support_ambient, ai.app_setup_appid";
419   static const char query_uid_info[] =
420       ", ui.is_disabled, ui.is_splash_screen_enabled";
421   static const char query_label[] =
422       ", COALESCE("
423       "(SELECT app_label FROM package_app_localized_info WHERE "
424       "ai.app_id=app_id AND app_locale=?), "
425       "(SELECT app_label FROM package_app_localized_info WHERE "
426       "ai.app_id=app_id AND app_locale='No Locale'))";
427   static const char query_icon[] =
428       ", COALESCE("
429       "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
430       "AND app_locale=?), "
431       "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
432       "AND app_locale='No Locale'))";
433   static const char query_from_clause[] = " FROM package_app_info as ai";
434   static const char query_uid_info_clause[] =
435       " LEFT OUTER JOIN package_app_info_for_uid AS ui "
436       "ON (ai.app_id=ui.app_id AND ui.uid=?)";
437   int ret = PMINFO_R_ERROR;
438   int idx;
439   char *bg_category_str = NULL;
440   char *constraint = NULL;
441   char *tmp_record = NULL;
442   char query[MAX_QUERY_LEN] = {'\0'};
443   char buf[BUFSIZE] = {'\0'};
444   application_x *info = NULL;
445   GList *bind_params = NULL;
446   sqlite3_stmt *stmt = NULL;
447   bool is_check_storage = true;
448   const uid_t global_user_uid = GLOBAL_USER;
449
450   snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
451
452   if (flag & PMINFO_APPINFO_GET_BASICINFO) {
453     strncat(query, query_basic, sizeof(query) - strlen(query) - 1);
454     strncat(query, query_uid_info, sizeof(query) - strlen(query) - 1);
455   }
456   if (flag & PMINFO_APPINFO_GET_LABEL) {
457     strncat(query, query_label, sizeof(query) - strlen(query) - 1);
458     bind_params = g_list_append(bind_params, strdup(locale));
459   }
460   if (flag & PMINFO_APPINFO_GET_ICON) {
461     strncat(query, query_icon, sizeof(query) - strlen(query) - 1);
462     bind_params = g_list_append(bind_params, strdup(locale));
463   }
464
465   snprintf(buf, MAX_QUERY_LEN - 1, "%d", uid);
466   bind_params = g_list_append(bind_params, strdup(buf));
467
468   is_check_storage = __check_app_storage_status(filter);
469
470   ret = _get_filtered_query(filter, locale, uid, &constraint, &bind_params);
471   if (ret != PMINFO_R_OK) {
472     LOGE("Failed to get WHERE clause");
473     goto catch;
474   }
475   strncat(query, query_from_clause, sizeof(query) - strlen(query) - 1);
476
477   strncat(query, query_uid_info_clause, sizeof(query) - strlen(query) - 1);
478
479   if (constraint) strncat(query, constraint, sizeof(query) - strlen(query) - 1);
480
481   ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
482   if (ret != SQLITE_OK) {
483     LOGE("prepare failed: %s", sqlite3_errmsg(db));
484     ret = PMINFO_R_ERROR;
485     goto catch;
486   }
487
488   if (g_list_length(bind_params) != 0) {
489     ret = __bind_params(stmt, bind_params);
490     if (ret != SQLITE_OK) {
491       LOGE("Failed to bind parameters");
492       goto catch;
493     }
494   }
495
496   while (sqlite3_step(stmt) == SQLITE_ROW) {
497     info = calloc(1, sizeof(application_x));
498     if (info == NULL) {
499       LOGE("out of memory");
500       ret = PMINFO_R_ERROR;
501       goto catch;
502     }
503     idx = 0;
504     _save_column_str(stmt, idx++, &info->appid);
505     _save_column_str(stmt, idx++, &info->installed_storage);
506     _save_column_str(stmt, idx++, &info->external_path);
507
508     if (flag & PMINFO_APPINFO_GET_BASICINFO) {
509       _save_column_str(stmt, idx++, &info->component);
510       _save_column_str(stmt, idx++, &info->exec);
511       _save_column_str(stmt, idx++, &info->nodisplay);
512       _save_column_str(stmt, idx++, &info->type);
513       _save_column_str(stmt, idx++, &info->onboot);
514       _save_column_str(stmt, idx++, &info->multiple);
515       _save_column_str(stmt, idx++, &info->autorestart);
516       _save_column_str(stmt, idx++, &info->taskmanage);
517       _save_column_str(stmt, idx++, &info->hwacceleration);
518       _save_column_str(stmt, idx++, &info->screenreader);
519       _save_column_str(stmt, idx++, &info->mainapp);
520       _save_column_str(stmt, idx++, &info->recentimage);
521       _save_column_str(stmt, idx++, &info->launchcondition);
522       _save_column_str(stmt, idx++, &info->indicatordisplay);
523       _save_column_str(stmt, idx++, &info->portraitimg);
524       _save_column_str(stmt, idx++, &info->landscapeimg);
525       _save_column_str(stmt, idx++, &info->guestmode_visibility);
526       _save_column_str(stmt, idx++, &info->permission_type);
527       _save_column_str(stmt, idx++, &info->preload);
528       _save_column_str(stmt, idx++, &info->submode);
529       _save_column_str(stmt, idx++, &info->submode_mainid);
530       _save_column_str(stmt, idx++, &info->launch_mode);
531       _save_column_str(stmt, idx++, &info->ui_gadget);
532       _save_column_str(stmt, idx++, &info->support_disable);
533       _save_column_str(stmt, idx++, &info->process_pool);
534       _save_column_str(stmt, idx++, &bg_category_str);
535       _save_column_str(stmt, idx++, &info->package_type);
536       _save_column_str(stmt, idx++, &info->root_path);
537       _save_column_str(stmt, idx++, &info->api_version);
538       _save_column_str(stmt, idx++, &info->effective_appid);
539       _save_column_str(stmt, idx++, &info->is_disabled);
540       _save_column_str(stmt, idx++, &info->splash_screen_display);
541       _save_column_str(stmt, idx++, &info->tep_name);
542       _save_column_str(stmt, idx++, &info->zip_mount_file);
543       _save_column_str(stmt, idx++, &info->component_type);
544       _save_column_str(stmt, idx++, &info->package);
545       _save_column_str(stmt, idx++, &info->package_system);
546       _save_column_str(stmt, idx++, &info->removable);
547       _save_column_str(stmt, idx++, &info->package_installed_time);
548       _save_column_str(stmt, idx++, &info->support_mode);
549       _save_column_str(stmt, idx++, &info->support_ambient);
550       _save_column_str(stmt, idx++, &info->setup_appid);
551       info->background_category = __get_background_category(bg_category_str);
552       free(bg_category_str);
553       bg_category_str = NULL;
554     }
555
556     info->for_all_users =
557         strdup((db_uid != global_user_uid) ? "false" : "true");
558
559     if (db_uid != global_user_uid) {
560       idx = idx + 2;
561     } else {
562       tmp_record = NULL;
563       _save_column_str(stmt, idx++, &tmp_record);
564       if (tmp_record != NULL) {
565         if (strcasecmp(info->is_disabled, "false") == 0 &&
566             strcasecmp(tmp_record, "false") == 0) {
567           free(info->is_disabled);
568           info->is_disabled = tmp_record;
569         } else {
570           free(tmp_record);
571         }
572       }
573       tmp_record = NULL;
574       _save_column_str(stmt, idx++, &tmp_record);
575       if (tmp_record != NULL) {
576         if (strcasecmp(info->splash_screen_display, "false") == 0 &&
577             strcasecmp(tmp_record, "false") == 0) {
578           free(info->splash_screen_display);
579           info->splash_screen_display = tmp_record;
580         } else {
581           free(tmp_record);
582         }
583       }
584     }
585
586     if (flag & PMINFO_APPINFO_GET_LABEL) {
587       tmp_record = NULL;
588       _save_column_str(stmt, idx++, &tmp_record);
589       if (_add_label_info_into_list(locale, tmp_record, &info->label)) {
590         ret = PMINFO_R_ERROR;
591         goto catch;
592       }
593     }
594
595     if (flag & PMINFO_APPINFO_GET_ICON) {
596       tmp_record = NULL;
597       _save_column_str(stmt, idx++, &tmp_record);
598       if (_add_icon_info_into_list(locale, tmp_record, &info->icon)) {
599         ret = PMINFO_R_ERROR;
600         goto catch;
601       }
602     }
603
604     if (flag & PMINFO_APPINFO_GET_CATEGORY) {
605       if (_appinfo_get_category(db, info->appid, &info->category)) {
606         ret = PMINFO_R_ERROR;
607         goto catch;
608       }
609     }
610
611     if (flag & PMINFO_APPINFO_GET_APP_CONTROL) {
612       if (_appinfo_get_app_control(db, info->appid, &info->appcontrol)) {
613         ret = PMINFO_R_ERROR;
614         goto catch;
615       }
616     }
617
618     if (flag & PMINFO_APPINFO_GET_METADATA) {
619       if (_appinfo_get_metadata(db, info->appid, &info->metadata)) {
620         ret = PMINFO_R_ERROR;
621         goto catch;
622       }
623     }
624
625     if (flag & PMINFO_APPINFO_GET_SPLASH_SCREEN) {
626       if (_appinfo_get_splashscreens(db, info->appid, &info->splashscreens)) {
627         ret = PMINFO_R_ERROR;
628         goto catch;
629       }
630     }
631
632     if (is_check_storage &&
633         __appinfo_check_installed_storage(info) != PMINFO_R_OK) {
634       ret = PMINFO_R_ERROR;
635       pkgmgrinfo_basic_free_application(info);
636       info = NULL;
637       continue;
638     }
639
640     g_hash_table_insert(applications, (gpointer)info->appid, (gpointer)info);
641   }
642
643   ret = PMINFO_R_OK;
644
645   catch : sqlite3_finalize(stmt);
646
647   if (constraint) free(constraint);
648
649   if (ret != PMINFO_R_OK && info != NULL)
650     pkgmgrinfo_basic_free_application(info);
651
652   g_list_free_full(bind_params, free);
653
654   return ret;
655 }
656
657 API int appinfo_internal_filter_get_list(sqlite3 *db,
658                                          pkgmgrinfo_appinfo_filter_h filter,
659                                          uid_t uid, const char *locale,
660                                          GHashTable **appinfo_list) {
661   int ret;
662   GHashTable *list;
663
664   if (db == NULL || filter == NULL || appinfo_list == NULL) {
665     // TODO: add log
666     return PMINFO_R_EINVAL;
667   }
668
669   list = g_hash_table_new(g_str_hash, g_str_equal);
670   if (list == NULL) return PMINFO_R_ERROR;
671
672   ret = _appinfo_get_applications(db, uid, uid, locale, filter,
673                                   PMINFO_APPINFO_GET_ALL, list);
674   if (!g_hash_table_size(list) && uid != GLOBAL_USER)
675     ret = _appinfo_get_applications(db, GLOBAL_USER, uid, locale, filter,
676                                     PMINFO_APPINFO_GET_ALL, list);
677
678   if (ret != PMINFO_R_OK) {
679     g_hash_table_foreach_remove(list, __free_applications, NULL);
680     g_hash_table_destroy(list);
681     return ret;
682   }
683
684   if (!g_hash_table_size(list)) {
685     // TODO: add logs that failed to find appid
686     g_hash_table_destroy(list);
687     return PMINFO_R_ENOENT;
688   }
689
690   *appinfo_list = list;
691   return ret;
692 }