Improve query performance
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_appinfo.c
index cc47899..de7afaf 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
                                "LEFT OUTER JOIN package_app_app_category " \
                                "ON package_app_info.app_id=package_app_app_category.app_id where "
 
+static bool _get_bool_value(const char *str)
+{
+       if (str == NULL)
+               return false;
+       else if (!strcasecmp(str, "true"))
+               return true;
+       else
+               return false;
+}
+
 static void __cleanup_appinfo(pkgmgr_appinfo_x *data)
 {
        pkgmgr_appinfo_x *info = data;
@@ -77,53 +88,135 @@ static char *_get_filtered_query(const char *query_raw,
        return strdup(buf);
 }
 
-static GSList *_appinfo_get_filtered_list(const char *locale,
-               pkgmgrinfo_filter_x *filter)
+static gint __list_strcmp(gconstpointer a, gconstpointer b)
+{
+       return strcmp((char *)a, (char *)b);
+}
+
+static gint _appinfo_get_list(sqlite3 *db, const char *locale,
+               pkgmgrinfo_filter_x *filter, GList **list)
 {
        static const char query_raw[] =
-               "SELECT package_app_info.app_id FROM package_app_info"
+               "SELECT DISTINCT package_app_info.app_id FROM package_app_info"
                " LEFT OUTER JOIN package_app_localized_info"
                "  ON package_app_info.app_id=package_app_localized_info.app_id"
                "  AND package_app_localized_info.app_locale=%Q"
                " LEFT OUTER JOIN package_app_app_category"
                "  ON package_app_info.app_id=package_app_app_category.app_id"
                " LEFT OUTER JOIN package_app_app_svc"
-               "  ON package_app_info.app_id=package_app_app_svc.app_id ";
+               "  ON package_app_info.app_id=package_app_app_svc.app_id "
+               " LEFT OUTER JOIN package_app_app_metadata"
+               "  ON package_app_info.app_id=package_app_app_metadata.app_id ";
        int ret;
        char *query;
        char *query_localized;
        sqlite3_stmt *stmt;
-       GSList *list = NULL;
-       char *appid;
+       char *appid = NULL;
 
        query = _get_filtered_query(query_raw, filter);
        if (query == NULL)
-               return NULL;
+               return PMINFO_R_ERROR;
        query_localized = sqlite3_mprintf(query, locale);
        free(query);
        if (query_localized == NULL)
-               return NULL;
+               return PMINFO_R_ERROR;
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query_localized,
+       ret = sqlite3_prepare_v2(db, query_localized,
                        strlen(query_localized), &stmt, NULL);
        sqlite3_free(query_localized);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
-               return NULL;
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
+               return PMINFO_R_ERROR;
        }
 
        while (sqlite3_step(stmt) == SQLITE_ROW) {
                _save_column_str(stmt, 0, (const char **)&appid);
-               list = g_slist_append(list, appid);
+               if (appid != NULL)
+                       *list = g_list_insert_sorted(*list, appid,
+                                       __list_strcmp);
        }
 
        sqlite3_finalize(stmt);
 
-       return list;
+       return PMINFO_R_OK;
+}
+
+static int _appinfo_get_filtered_list(pkgmgrinfo_filter_x *filter, uid_t uid,
+               GList **list)
+{
+       int ret;
+       sqlite3 *db;
+       const char *dbpath;
+       char *locale;
+       GList *tmp;
+
+       locale = _get_system_locale();
+       if (locale == NULL)
+               return PMINFO_R_ERROR;
+
+       dbpath = getUserPkgParserDBPathUID(uid);
+       if (dbpath == NULL) {
+               free(locale);
+               return PMINFO_R_ERROR;
+       }
+
+       ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
+       if (ret != SQLITE_OK) {
+               _LOGE("failed to open db: %d", ret);
+               free(locale);
+               return PMINFO_R_ERROR;
+       }
+
+       if (_appinfo_get_list(db, locale, filter, list)) {
+               free(locale);
+               sqlite3_close_v2(db);
+               return PMINFO_R_ERROR;
+       }
+       sqlite3_close_v2(db);
+
+       if (uid == GLOBAL_USER) {
+               free(locale);
+               return PMINFO_R_OK;
+       }
+
+       /* search again from global */
+       dbpath = getUserPkgParserDBPathUID(GLOBAL_USER);
+       if (dbpath == NULL) {
+               free(locale);
+               return PMINFO_R_ERROR;
+       }
+
+       ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
+       if (ret != SQLITE_OK) {
+               _LOGE("failed to open db: %d", ret);
+               free(locale);
+               return PMINFO_R_ERROR;
+       }
+
+       if (_appinfo_get_list(db, locale, filter, list)) {
+               free(locale);
+               sqlite3_close_v2(db);
+               return PMINFO_R_ERROR;
+       }
+       sqlite3_close_v2(db);
+
+       /* remove duplicate element:
+        * since the list is sorted, we can remove duplicates in linear time
+        */
+       for (tmp = *list; tmp; tmp = tmp->next) {
+               if (tmp->prev == NULL || tmp->data == NULL)
+                       continue;
+               if (strcmp((const char *)tmp->prev->data,
+                                       (const char *)tmp->data) == 0)
+                       *list = g_list_delete_link(*list, tmp);
+       }
+
+       return PMINFO_R_OK;
+
 }
 
-static int _appinfo_get_label(const char *appid, const char *locale,
-               label_x **label)
+static int _appinfo_get_label(sqlite3 *db, const char *appid,
+               const char *locale, label_x **label)
 {
        static const char query_raw[] =
                "SELECT app_label, app_locale "
@@ -141,11 +234,10 @@ static int _appinfo_get_label(const char *appid, const char *locale,
                return PMINFO_R_ERROR;
        }
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
-                       &stmt, NULL);
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        sqlite3_free(query);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
                return PMINFO_R_ERROR;
        }
 
@@ -176,7 +268,7 @@ static int _appinfo_get_label(const char *appid, const char *locale,
        return PMINFO_R_OK;
 }
 
-static int _appinfo_get_icon(const char *appid, const char *locale,
+static int _appinfo_get_icon(sqlite3 *db, const char *appid, const char *locale,
                icon_x **icon)
 {
        static const char query_raw[] =
@@ -195,11 +287,11 @@ static int _appinfo_get_icon(const char *appid, const char *locale,
                return PMINFO_R_ERROR;
        }
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
+       ret = sqlite3_prepare_v2(db, query, strlen(query),
                        &stmt, NULL);
        sqlite3_free(query);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
                return PMINFO_R_ERROR;
        }
 
@@ -230,7 +322,8 @@ static int _appinfo_get_icon(const char *appid, const char *locale,
        return PMINFO_R_OK;
 }
 
-static int _appinfo_get_category(const char *appid, category_x **category)
+static int _appinfo_get_category(sqlite3 *db, const char *appid,
+               category_x **category)
 {
        static const char query_raw[] =
                "SELECT category FROM package_app_app_category WHERE app_id=%Q";
@@ -245,11 +338,10 @@ static int _appinfo_get_category(const char *appid, category_x **category)
                return PMINFO_R_ERROR;
        }
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
-                       &stmt, NULL);
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        sqlite3_free(query);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
                return PMINFO_R_ERROR;
        }
 
@@ -314,7 +406,7 @@ static void __parse_appcontrol(appcontrol_x **appcontrol, char *appcontrol_str)
        free(dup);
 }
 
-static int _appinfo_get_app_control(const char *appid,
+static int _appinfo_get_app_control(sqlite3 *db, const char *appid,
                appcontrol_x **appcontrol)
 {
        static const char query_raw[] =
@@ -332,11 +424,10 @@ static int _appinfo_get_app_control(const char *appid,
                return PMINFO_R_ERROR;
        }
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
-                       &stmt, NULL);
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        sqlite3_free(query);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
                return PMINFO_R_ERROR;
        }
 
@@ -355,7 +446,7 @@ static int _appinfo_get_app_control(const char *appid,
        return PMINFO_R_OK;
 }
 
-static int _appinfo_get_data_control(const char *appid,
+static int _appinfo_get_data_control(sqlite3 *db, const char *appid,
                datacontrol_x **datacontrol)
 {
        static const char query_raw[] =
@@ -373,11 +464,10 @@ static int _appinfo_get_data_control(const char *appid,
                return PMINFO_R_ERROR;
        }
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
-                       &stmt, NULL);
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        sqlite3_free(query);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
                return PMINFO_R_ERROR;
        }
 
@@ -409,8 +499,61 @@ static int _appinfo_get_data_control(const char *appid,
        return PMINFO_R_OK;
 }
 
-static int _appinfo_get_app(const char *appid, const char *locale,
-               pkgmgr_appinfo_x **appinfo)
+static int _appinfo_get_metadata(sqlite3 *db, const char *appid,
+               metadata_x **metadata)
+{
+       static const char query_raw[] =
+               "SELECT md_key, md_value "
+               "FROM package_app_app_metadata WHERE app_id=%Q";
+       int ret;
+       char *query;
+       sqlite3_stmt *stmt;
+       int idx;
+       metadata_x *info;
+
+       query = sqlite3_mprintf(query_raw, appid);
+       if (query == NULL) {
+               LOGE("out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+       sqlite3_free(query);
+       if (ret != SQLITE_OK) {
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
+               return PMINFO_R_ERROR;
+       }
+
+       while (sqlite3_step(stmt) == SQLITE_ROW) {
+               info = calloc(1, sizeof(metadata_x));
+               if (info == NULL) {
+                       LOGE("out of memory");
+                       sqlite3_finalize(stmt);
+                       if (*metadata) {
+                               LISTHEAD(*metadata, info);
+                               *metadata = info;
+                       }
+                       return PMINFO_R_ERROR;
+               }
+               idx = 0;
+               _save_column_str(stmt, idx++, &info->key);
+               _save_column_str(stmt, idx++, &info->value);
+               LISTADD(*metadata, info);
+       }
+
+       if (*metadata) {
+               LISTHEAD(*metadata, info);
+               *metadata = info;
+       }
+
+       sqlite3_finalize(stmt);
+
+       return PMINFO_R_OK;
+
+}
+
+static int _appinfo_get_application(sqlite3 *db, const char *appid,
+               const char *locale, application_x **application)
 {
        static const char query_raw[] =
                "SELECT app_id, app_component, app_exec, app_nodisplay, "
@@ -420,14 +563,14 @@ static int _appinfo_get_app(const char *appid, const char *locale,
                "app_launchcondition, app_indicatordisplay, app_portraitimg, "
                "app_landscapeimg, app_guestmodevisibility, "
                "app_permissiontype, app_preload, app_submode, "
-               "app_submode_mainid, app_launch_mode, component_type, package "
+               "app_submode_mainid, app_launch_mode, app_ui_gadget, "
+               "component_type, package "
                "FROM package_app_info WHERE app_id=%Q";
        int ret;
        char *query;
        sqlite3_stmt *stmt;
        int idx;
-       pkgmgr_appinfo_x *info;
-       application_x *app;
+       application_x *info;
 
        query = sqlite3_mprintf(query_raw, appid);
        if (query == NULL) {
@@ -435,139 +578,166 @@ static int _appinfo_get_app(const char *appid, const char *locale,
                return PMINFO_R_ERROR;
        }
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
-                       &stmt, NULL);
+       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        sqlite3_free(query);
        if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("prepare failed: %s", sqlite3_errmsg(db));
                return PMINFO_R_ERROR;
        }
 
        ret = sqlite3_step(stmt);
        if (ret == SQLITE_DONE) {
-               LOGE("cannot find app");
                sqlite3_finalize(stmt);
                return PMINFO_R_ENOENT;
        } else if (ret != SQLITE_ROW) {
-               LOGE("step failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
+               LOGE("step failed: %s", sqlite3_errmsg(db));
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       app = calloc(1, sizeof(application_x));
-       if (app == NULL) {
+       info = calloc(1, sizeof(application_x));
+       if (info == NULL) {
                LOGE("out of memory");
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
        idx = 0;
-       _save_column_str(stmt, idx++, &app->appid);
-       _save_column_str(stmt, idx++, &app->component);
-       _save_column_str(stmt, idx++, &app->exec);
-       _save_column_str(stmt, idx++, &app->nodisplay);
-       _save_column_str(stmt, idx++, &app->type);
-       _save_column_str(stmt, idx++, &app->onboot);
-       _save_column_str(stmt, idx++, &app->multiple);
-       _save_column_str(stmt, idx++, &app->autorestart);
-       _save_column_str(stmt, idx++, &app->taskmanage);
-       _save_column_str(stmt, idx++, &app->enabled);
-       _save_column_str(stmt, idx++, &app->hwacceleration);
-       _save_column_str(stmt, idx++, &app->screenreader);
-       _save_column_str(stmt, idx++, &app->mainapp);
-       _save_column_str(stmt, idx++, &app->recentimage);
-       _save_column_str(stmt, idx++, &app->launchcondition);
-       _save_column_str(stmt, idx++, &app->indicatordisplay);
-       _save_column_str(stmt, idx++, &app->portraitimg);
-       _save_column_str(stmt, idx++, &app->landscapeimg);
-       _save_column_str(stmt, idx++, &app->guestmode_visibility);
-       _save_column_str(stmt, idx++, &app->permission_type);
-       _save_column_str(stmt, idx++, &app->preload);
-       _save_column_str(stmt, idx++, &app->submode);
-       _save_column_str(stmt, idx++, &app->submode_mainid);
-       _save_column_str(stmt, idx++, &app->launch_mode);
-       _save_column_str(stmt, idx++, &app->component_type);
-       _save_column_str(stmt, idx++, &app->package);
-
-       if (_appinfo_get_label(app->appid, locale, &app->label)) {
-               pkgmgrinfo_basic_free_application(app);
+       _save_column_str(stmt, idx++, &info->appid);
+       _save_column_str(stmt, idx++, &info->component);
+       _save_column_str(stmt, idx++, &info->exec);
+       _save_column_str(stmt, idx++, &info->nodisplay);
+       _save_column_str(stmt, idx++, &info->type);
+       _save_column_str(stmt, idx++, &info->onboot);
+       _save_column_str(stmt, idx++, &info->multiple);
+       _save_column_str(stmt, idx++, &info->autorestart);
+       _save_column_str(stmt, idx++, &info->taskmanage);
+       _save_column_str(stmt, idx++, &info->enabled);
+       _save_column_str(stmt, idx++, &info->hwacceleration);
+       _save_column_str(stmt, idx++, &info->screenreader);
+       _save_column_str(stmt, idx++, &info->mainapp);
+       _save_column_str(stmt, idx++, &info->recentimage);
+       _save_column_str(stmt, idx++, &info->launchcondition);
+       _save_column_str(stmt, idx++, &info->indicatordisplay);
+       _save_column_str(stmt, idx++, &info->portraitimg);
+       _save_column_str(stmt, idx++, &info->landscapeimg);
+       _save_column_str(stmt, idx++, &info->guestmode_visibility);
+       _save_column_str(stmt, idx++, &info->permission_type);
+       _save_column_str(stmt, idx++, &info->preload);
+       _save_column_str(stmt, idx++, &info->submode);
+       _save_column_str(stmt, idx++, &info->submode_mainid);
+       _save_column_str(stmt, idx++, &info->launch_mode);
+       _save_column_str(stmt, idx++, &info->ui_gadget);
+       _save_column_str(stmt, idx++, &info->component_type);
+       _save_column_str(stmt, idx++, &info->package);
+
+       if (_appinfo_get_label(db, info->appid, locale, &info->label)) {
+               pkgmgrinfo_basic_free_application(info);
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       if (_appinfo_get_icon(app->appid, locale, &app->icon)) {
-               pkgmgrinfo_basic_free_application(app);
+       if (_appinfo_get_icon(db, info->appid, locale, &info->icon)) {
+               pkgmgrinfo_basic_free_application(info);
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       if (_appinfo_get_category(app->appid, &app->category)) {
-               pkgmgrinfo_basic_free_application(app);
+       if (_appinfo_get_category(db, info->appid, &info->category)) {
+               pkgmgrinfo_basic_free_application(info);
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       if (_appinfo_get_app_control(app->appid, &app->appcontrol)) {
-               pkgmgrinfo_basic_free_application(app);
+       if (_appinfo_get_app_control(db, info->appid, &info->appcontrol)) {
+               pkgmgrinfo_basic_free_application(info);
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       if (_appinfo_get_data_control(app->appid, &app->datacontrol)) {
-               pkgmgrinfo_basic_free_application(app);
+       if (_appinfo_get_data_control(db, info->appid, &info->datacontrol)) {
+               pkgmgrinfo_basic_free_application(info);
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       info = calloc(1, sizeof(pkgmgr_appinfo_x));
-       if (info == NULL) {
-               LOGE("out of memory");
-               pkgmgrinfo_basic_free_application(app);
+       if (_appinfo_get_metadata(db, info->appid, &info->metadata)) {
+               pkgmgrinfo_basic_free_application(info);
                sqlite3_finalize(stmt);
                return PMINFO_R_ERROR;
        }
 
-       info->package = strdup(app->package);
-       info->app_info = app;
-       info->locale = strdup(locale);
-       *appinfo = info;
+       *application = info;
 
        sqlite3_finalize(stmt);
 
        return PMINFO_R_OK;
 }
 
-API int pkgmgrinfo_appinfo_get_usr_appinfo(const char *appid, uid_t uid,
-               pkgmgrinfo_appinfo_h *handle)
+static int _appinfo_get_appinfo(const char *appid, uid_t uid,
+               pkgmgr_appinfo_x **appinfo)
 {
-       pkgmgr_appinfo_x *appinfo = NULL;
+       int ret;
+       sqlite3 *db;
+       const char *dbpath;
        char *locale;
+       pkgmgr_appinfo_x *info;
 
-       if (appid == NULL || handle == NULL) {
-               LOGE("invalid parameter");
-               return PMINFO_R_EINVAL;
-       }
-
-       if (__open_manifest_db(uid) < 0)
+       dbpath = getUserPkgParserDBPathUID(uid);
+       if (dbpath == NULL)
                return PMINFO_R_ERROR;
 
        locale = _get_system_locale();
-       if (locale == NULL) {
-               __close_manifest_db();
+       if (locale == NULL)
+               return PMINFO_R_ERROR;
+
+       ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
+       if (ret != SQLITE_OK) {
+               _LOGE("failed to open db: %d", ret);
+               free(locale);
                return PMINFO_R_ERROR;
        }
 
-       if (_appinfo_get_app(appid, locale, &appinfo)) {
+       info = calloc(1, sizeof(pkgmgr_appinfo_x));
+       if (info == NULL) {
+               _LOGE("out of memory");
                free(locale);
-               __close_manifest_db();
+               sqlite3_close_v2(db);
                return PMINFO_R_ERROR;
        }
 
-       *handle = appinfo;
+       ret = _appinfo_get_application(db, appid, locale, &info->app_info);
+       if (ret == PMINFO_R_OK) {
+               info->locale = strdup(locale);
+               info->package = strdup(info->app_info->package);
+       }
+
+       *appinfo = info;
 
        free(locale);
-       __close_manifest_db();
+       sqlite3_close_v2(db);
 
-       return PMINFO_R_OK;
+       return ret;
+}
+
+API int pkgmgrinfo_appinfo_get_usr_appinfo(const char *appid, uid_t uid,
+               pkgmgrinfo_appinfo_h *handle)
+{
+       int ret;
+
+       if (appid == NULL || handle == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       ret = _appinfo_get_appinfo(appid, uid, (pkgmgr_appinfo_x **)handle);
+       if (ret == PMINFO_R_ENOENT && uid != GLOBAL_USER)
+               ret = _appinfo_get_appinfo(appid, GLOBAL_USER,
+                               (pkgmgr_appinfo_x **)handle);
+
+       if (ret != PMINFO_R_OK)
+               _LOGE("failed to get appinfo of %s for user %d", appid, uid);
+
+       return ret;
 }
 
 API int pkgmgrinfo_appinfo_get_appinfo(const char *appid, pkgmgrinfo_appinfo_h *handle)
@@ -579,33 +749,25 @@ static int _appinfo_get_filtered_foreach_appinfo(uid_t uid,
                pkgmgrinfo_filter_x *filter, pkgmgrinfo_app_list_cb app_list_cb,
                void *user_data)
 {
+       int ret;
        pkgmgr_appinfo_x *info;
-       GSList *list;
-       GSList *tmp;
+       GList *list = NULL;
+       GList *tmp;
        char *appid;
-       char *locale;
        int stop = 0;
 
-       if (__open_manifest_db(uid) < 0)
+       ret = _appinfo_get_filtered_list(filter, uid, &list);
+       if (ret != PMINFO_R_OK)
                return PMINFO_R_ERROR;
 
-       locale = _get_system_locale();
-       if (locale == NULL) {
-               __close_manifest_db();
-               return PMINFO_R_ERROR;
-       }
-
-       list = _appinfo_get_filtered_list(locale, filter);
-       if (list == NULL) {
-               free(locale);
-               __close_manifest_db();
-               return PMINFO_R_OK;
-       }
-
        for (tmp = list; tmp; tmp = tmp->next) {
                appid = (char *)tmp->data;
                if (stop == 0) {
-                       if (_appinfo_get_app(appid, locale, &info)) {
+                       ret = _appinfo_get_appinfo(appid, uid, &info);
+                       if (ret == PMINFO_R_ENOENT && uid != GLOBAL_USER)
+                               ret = _appinfo_get_appinfo(appid, GLOBAL_USER,
+                                               &info);
+                       if (ret != PMINFO_R_OK) {
                                free(appid);
                                continue;
                        }
@@ -616,9 +778,7 @@ static int _appinfo_get_filtered_foreach_appinfo(uid_t uid,
                free(appid);
        }
 
-       free(locale);
-       g_slist_free(list);
-       __close_manifest_db();
+       g_list_free(list);
 
        return PMINFO_R_OK;
 }
@@ -1241,7 +1401,7 @@ API int pkgmgrinfo_appinfo_usr_get_datacontrol_info(const char *providerid, cons
        sqlite3_stmt *stmt = NULL;
 
        /*open db*/
-       ret = __open_manifest_db(uid);
+       ret = __open_manifest_db(uid, true);
        retvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "connect db [%s] failed!", MANIFEST_DB);
 
        /*Start constructing query*/
@@ -1282,7 +1442,7 @@ API int pkgmgrinfo_appinfo_usr_get_datacontrol_appid(const char *providerid, uid
        sqlite3_stmt *stmt = NULL;
 
        /*open db*/
-       ret = __open_manifest_db(uid);
+       ret = __open_manifest_db(uid, true);
        retvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "connect db [%s] failed!", MANIFEST_DB);
 
        /*Start constructing query*/
@@ -1403,21 +1563,12 @@ API int pkgmgrinfo_appinfo_is_nodisplay(pkgmgrinfo_appinfo_h handle, bool *nodis
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(nodisplay == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->nodisplay;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *nodisplay = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *nodisplay = 0;
-               else
-                       *nodisplay = 0;
-       }
+       *nodisplay = _get_bool_value(info->app_info->nodisplay);
        return PMINFO_R_OK;
 }
 
@@ -1425,21 +1576,12 @@ API int pkgmgrinfo_appinfo_is_multiple(pkgmgrinfo_appinfo_h handle, bool *multip
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(multiple == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->multiple;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *multiple = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *multiple = 0;
-               else
-                       *multiple = 0;
-       }
+       *multiple = _get_bool_value(info->app_info->multiple);
        return PMINFO_R_OK;
 }
 
@@ -1447,22 +1589,12 @@ API int pkgmgrinfo_appinfo_is_indicator_display_allowed(pkgmgrinfo_appinfo_h han
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(indicator_disp == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->indicatordisplay;
-       if (val) {
-               if (strcasecmp(val, "true") == 0){
-                       *indicator_disp = 1;
-               }else if (strcasecmp(val, "false") == 0){
-                       *indicator_disp = 0;
-               }else{
-                       *indicator_disp = 0;
-               }
-       }
+       *indicator_disp = _get_bool_value(info->app_info->indicatordisplay);
        return PMINFO_R_OK;
 }
 
@@ -1470,21 +1602,12 @@ API int pkgmgrinfo_appinfo_is_taskmanage(pkgmgrinfo_appinfo_h  handle, bool *tas
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(taskmanage == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->taskmanage;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *taskmanage = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *taskmanage = 0;
-               else
-                       *taskmanage = 0;
-       }
+       *taskmanage = _get_bool_value(info->app_info->taskmanage);
        return PMINFO_R_OK;
 }
 
@@ -1492,21 +1615,12 @@ API int pkgmgrinfo_appinfo_is_enabled(pkgmgrinfo_appinfo_h  handle, bool *enable
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(enabled == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->enabled;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *enabled = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *enabled = 0;
-               else
-                       *enabled = 1;
-       }
+       *enabled = _get_bool_value(info->app_info->enabled);
        return PMINFO_R_OK;
 
 }
@@ -1515,21 +1629,12 @@ API int pkgmgrinfo_appinfo_is_onboot(pkgmgrinfo_appinfo_h  handle, bool *onboot)
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(onboot == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->onboot;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *onboot = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *onboot = 0;
-               else
-                       *onboot = 0;
-       }
+       *onboot = _get_bool_value(info->app_info->onboot);
        return PMINFO_R_OK;
 }
 
@@ -1537,21 +1642,12 @@ API int pkgmgrinfo_appinfo_is_autorestart(pkgmgrinfo_appinfo_h  handle, bool *au
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(autorestart == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->autorestart;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *autorestart = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *autorestart = 0;
-               else
-                       *autorestart = 0;
-       }
+       *autorestart = _get_bool_value(info->app_info->autorestart);
        return PMINFO_R_OK;
 }
 
@@ -1559,21 +1655,12 @@ API int pkgmgrinfo_appinfo_is_mainapp(pkgmgrinfo_appinfo_h  handle, bool *mainap
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        retvm_if(mainapp == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->mainapp;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *mainapp = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *mainapp = 0;
-               else
-                       *mainapp = 0;
-       }
+       *mainapp = _get_bool_value(info->app_info->mainapp);
        return PMINFO_R_OK;
 }
 
@@ -1581,21 +1668,12 @@ API int pkgmgrinfo_appinfo_is_preload(pkgmgrinfo_appinfo_h handle, bool *preload
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL\n");
        retvm_if(preload == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->preload;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *preload = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *preload = 0;
-               else
-                       *preload = 0;
-       }
+       *preload = _get_bool_value(info->app_info->preload);
        return PMINFO_R_OK;
 }
 
@@ -1603,21 +1681,12 @@ API int pkgmgrinfo_appinfo_is_submode(pkgmgrinfo_appinfo_h handle, bool *submode
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL\n");
        retvm_if(submode == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
-       char *val = NULL;
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
 
        if (info->app_info == NULL)
                return PMINFO_R_ERROR;
 
-       val = (char *)info->app_info->submode;
-       if (val) {
-               if (strcasecmp(val, "true") == 0)
-                       *submode = 1;
-               else if (strcasecmp(val, "false") == 0)
-                       *submode = 0;
-               else
-                       *submode = 0;
-       }
+       *submode = _get_bool_value(info->app_info->submode);
        return PMINFO_R_OK;
 }
 
@@ -1646,7 +1715,22 @@ API int pkgmgrinfo_appinfo_is_category_exist(pkgmgrinfo_appinfo_h handle, const
        return PMINFO_R_OK;
 }
 
-API int pkgmgrinfo_appinfo_destroy_appinfo(pkgmgrinfo_appinfo_h  handle)
+API int pkgmgrinfo_appinfo_is_ui_gadget(pkgmgrinfo_appinfo_h handle,
+               bool *ui_gadget)
+{
+       pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
+
+       if (info == NULL || info->app_info == NULL || ui_gadget == NULL) {
+               _LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       *ui_gadget = _get_bool_value(info->app_info->ui_gadget);
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_appinfo_destroy_appinfo(pkgmgrinfo_appinfo_h handle)
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "appinfo handle is NULL");
        pkgmgr_appinfo_x *info = (pkgmgr_appinfo_x *)handle;
@@ -1867,7 +1951,7 @@ API int pkgmgrinfo_appinfo_usr_filter_count(pkgmgrinfo_appinfo_filter_h handle,
                return PMINFO_R_ERROR;
        }
 
-       ret = __open_manifest_db(uid);
+       ret = __open_manifest_db(uid, true);
        if (ret == -1) {
                _LOGE("Fail to open manifest DB\n");
                free(locale);
@@ -1950,183 +2034,49 @@ API int pkgmgrinfo_appinfo_metadata_filter_destroy(pkgmgrinfo_appinfo_metadata_f
        return (pkgmgrinfo_pkginfo_filter_destroy(handle));
 }
 
-API int pkgmgrinfo_appinfo_metadata_filter_add(pkgmgrinfo_appinfo_metadata_filter_h handle,
+API int pkgmgrinfo_appinfo_metadata_filter_add(
+               pkgmgrinfo_appinfo_metadata_filter_h handle,
                const char *key, const char *value)
 {
-       retvm_if(handle == NULL, PMINFO_R_EINVAL, "filter handle is NULL\n");
-       retvm_if(key == NULL, PMINFO_R_EINVAL, "metadata key supplied is NULL\n");
-       /*value can be NULL. In that case all apps with specified key should be displayed*/
-       int ret = 0;
-       char *k = NULL;
-       char *v = NULL;
-       pkgmgrinfo_filter_x *filter = (pkgmgrinfo_filter_x*)handle;
-       pkgmgrinfo_node_x *node = (pkgmgrinfo_node_x*)calloc(1, sizeof(pkgmgrinfo_node_x));
-       retvm_if(node == NULL, PMINFO_R_ERROR, "Out of Memory!!!\n");
-       k = strdup(key);
-       tryvm_if(k == NULL, ret = PMINFO_R_ERROR, "Out of Memory!!!\n");
-       node->key = k;
-       if (value) {
-               v = strdup(value);
-               tryvm_if(v == NULL, ret = PMINFO_R_ERROR, "Out of Memory!!!\n");
-       }
-       node->value = v;
-       /*If API is called multiple times, we should OR all conditions.*/
-       filter->list = g_slist_append(filter->list, (gpointer)node);
-       /*All memory will be freed in destroy API*/
-       return PMINFO_R_OK;
-catch:
-       if (node) {
-               if (node->key) {
-                       free(node->key);
-                       node->key = NULL;
-               }
-               if (node->value) {
-                       free(node->value);
-                       node->value = NULL;
-               }
-               free(node);
-               node = NULL;
-       }
-       return ret;
-}
-
-static void __get_metadata_filter_condition(gpointer data, char **condition)
-{
-       pkgmgrinfo_node_x *node = (pkgmgrinfo_node_x*)data;
-       char key[MAX_QUERY_LEN] = {'\0'};
-       char value[MAX_QUERY_LEN] = {'\0'};
-       if (node->key) {
-               snprintf(key, MAX_QUERY_LEN, "(package_app_app_metadata.md_key='%s'", node->key);
-       }
-       if (node->value) {
-               snprintf(value, MAX_QUERY_LEN, " AND package_app_app_metadata.md_value='%s')", node->value);
-               strcat(key, value);
-       } else {
-               strcat(key, ")");
-       }
-       *condition = strdup(key);
-       return;
-}
-
-static char *_get_metadata_filtered_query(const char *query_raw,
-               pkgmgrinfo_filter_x *filter)
-{
-       char buf[MAX_QUERY_LEN] = { 0, };
-       char *condition;
-       size_t len;
-       GSList *list;
-       GSList *head = NULL;
-
-       if (filter)
-               head = filter->list;
-
-       strncat(buf, query_raw, MAX_QUERY_LEN - 1);
-       len = strlen(buf);
-       for (list = head; list; list = list->next) {
-               /* TODO: revise condition getter function */
-               __get_metadata_filter_condition(list->data, &condition);
-               if (condition == NULL)
-                       continue;
-               if (buf[strlen(query_raw)] == '\0') {
-                       len += strlen(" WHERE ");
-                       strncat(buf, " WHERE ", MAX_QUERY_LEN - len - 1);
-               } else {
-                       len += strlen(" AND ");
-                       strncat(buf, " AND ", MAX_QUERY_LEN -len - 1);
-               }
-               len += strlen(condition);
-               strncat(buf, condition, sizeof(buf) - len - 1);
-               free(condition);
-               condition = NULL;
-       }
-
-       return strdup(buf);
-}
-
-static GSList *_appinfo_get_metadata_filtered_list(pkgmgrinfo_filter_x *filter)
-{
-       static const char query_raw[] =
-               "SELECT app_id FROM package_app_app_metadata";
        int ret;
-       char *query;
-       sqlite3_stmt *stmt;
-       GSList *list = NULL;
-       char *appid;
 
-       query = _get_metadata_filtered_query(query_raw, filter);
-       if (query == NULL) {
-               LOGE("out of memory");
-               return NULL;
-       }
+       ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+                       PMINFO_APPINFO_PROP_APP_METADATA_KEY, key);
+       if (ret != PMINFO_R_OK)
+               return ret;
 
-       ret = sqlite3_prepare_v2(GET_DB(manifest_db), query, strlen(query),
-                       &stmt, NULL);
-       free(query);
-       if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(GET_DB(manifest_db)));
-               return NULL;
-       }
-
-       while (sqlite3_step(stmt) == SQLITE_ROW) {
-               _save_column_str(stmt, 0, (const char **)&appid);
-               list = g_slist_append(list, appid);
+       /* value can be NULL.
+        * In that case all apps with specified key should be displayed
+        */
+       if (value) {
+               ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+                               PMINFO_APPINFO_PROP_APP_METADATA_VALUE, value);
+               if (ret != PMINFO_R_OK)
+                       return ret;
        }
 
-       sqlite3_finalize(stmt);
-
-       return list;
+       return PMINFO_R_OK;
 }
 
 API int pkgmgrinfo_appinfo_usr_metadata_filter_foreach(
                pkgmgrinfo_appinfo_metadata_filter_h handle,
                pkgmgrinfo_app_list_cb app_cb, void *user_data, uid_t uid)
 {
-       GSList *list;
-       GSList *tmp;
-       char *appid;
-       pkgmgrinfo_appinfo_h info;
-       int stop = 0;
-
        if (handle == NULL || app_cb == NULL) {
                LOGE("invalid parameter");
                return PMINFO_R_EINVAL;
        }
 
-       if (__open_manifest_db(uid) < 0)
-               return PMINFO_R_ERROR;
-
-       list = _appinfo_get_metadata_filtered_list(handle);
-       if (list == NULL) {
-               LOGE("no result");
-               __close_manifest_db();
-               return PMINFO_R_OK;
-       }
-
-       for (tmp = list; tmp; tmp = tmp->next) {
-               appid = (char *)tmp->data;
-               if (stop == 0) {
-                       if (pkgmgrinfo_appinfo_get_usr_appinfo(appid, uid,
-                                               &info)) {
-                               free(appid);
-                               continue;
-                       }
-                       if (app_cb(info, user_data) < 0)
-                               stop = 1;
-                       pkgmgrinfo_appinfo_destroy_appinfo(info);
-               }
-               free(appid);
-       }
-
-       g_slist_free(list);
-       __close_manifest_db();
-
-       return PMINFO_R_OK;
+       return _appinfo_get_filtered_foreach_appinfo(uid, handle, app_cb,
+                       user_data);
 }
 
-API int pkgmgrinfo_appinfo_metadata_filter_foreach(pkgmgrinfo_appinfo_metadata_filter_h handle,
+API int pkgmgrinfo_appinfo_metadata_filter_foreach(
+               pkgmgrinfo_appinfo_metadata_filter_h handle,
                pkgmgrinfo_app_list_cb app_cb, void *user_data)
 {
-       return pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle, app_cb, user_data, GLOBAL_USER);
+       return pkgmgrinfo_appinfo_usr_metadata_filter_foreach(handle, app_cb,
+                       user_data, GLOBAL_USER);
 }
 
 API int pkgmgrinfo_appinfo_is_guestmode_visibility(pkgmgrinfo_appinfo_h handle, bool *status)
@@ -2138,14 +2088,6 @@ API int pkgmgrinfo_appinfo_is_guestmode_visibility(pkgmgrinfo_appinfo_h handle,
        retvm_if(status == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
 
        val = info->uiapp_info->guestmode_visibility;
-       if (val) {
-               if (strcasecmp(val, "true") == 0){
-                       *status = 1;
-               }else if (strcasecmp(val, "false") == 0){
-                       *status = 0;
-               }else{
-                       *status = 1;
-               }
-       }
+       *status = _get_bool_value(val);
        return PMINFO_R_OK;
 }