Add pkgmgrinfo_pkginfo_foreach_depends_on_by_pkgid
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_pkginfo.c
index 439a59e..2c9bfb5 100644 (file)
 #include <ctype.h>
 #include <sys/smack.h>
 #include <linux/limits.h>
-#include <libgen.h>
 #include <sys/stat.h>
 
-#include <sqlite3.h>
 #include <glib.h>
 
 #include "pkgmgrinfo_basic.h"
 #include "pkgmgrinfo_private.h"
 #include "pkgmgrinfo_debug.h"
 #include "pkgmgr-info.h"
+#include "manager/pkginfo_manager.h"
 
 static bool _get_bool_value(const char *str)
 {
@@ -70,22 +69,6 @@ static gint __pkg_disable_chk_func(gconstpointer data1, gconstpointer data2)
                return 1;
 }
 
-static void __destroy_each_node(gpointer data, gpointer user_data)
-{
-       ret_if(data == NULL);
-       pkgmgrinfo_node_x *node = (pkgmgrinfo_node_x *)data;
-       if (node->value) {
-               free(node->value);
-               node->value = NULL;
-       }
-       if (node->key) {
-               free(node->key);
-               node->key = NULL;
-       }
-       free(node);
-       node = NULL;
-}
-
 static void __destroy_metadata_node(gpointer data)
 {
        pkgmgrinfo_metadata_node_x *node = (pkgmgrinfo_metadata_node_x *)data;
@@ -151,19 +134,22 @@ static int _pkginfo_get_filtered_foreach_pkginfo(uid_t uid,
                if (ret != PMINFO_R_OK) {
                        _LOGE("Failed to add filter");
                        g_hash_table_destroy(list);
-                       if (filter == NULL)
-                               pkgmgrinfo_pkginfo_filter_destroy(filter);
                        return PMINFO_R_ERROR;
                }
        }
 
-       // TODO: use pkginfo-client APIs.
+       ret = _pkginfo_get_packages(uid, filter, flag, list);
+       if (ret == PMINFO_R_ERROR) {
+               g_hash_table_destroy(list);
+               return ret;
+       }
+
        g_hash_table_iter_init(&iter, list);
        while (g_hash_table_iter_next(&iter, NULL, &value)) {
                pkg = (package_x *)value;
                info.uid = uid;
                info.pkg_info = pkg;
-               //info.locale = locale;
+               info.locale = pkg->locale;
                if (pkg_list_cb(&info, user_data) < 0)
                        break;
        }
@@ -173,17 +159,16 @@ static int _pkginfo_get_filtered_foreach_pkginfo(uid_t uid,
        return PMINFO_R_OK;
 }
 
-API int pkgmgrinfo_pkginfo_get_usr_pkginfo(const char *pkgid, uid_t uid,
-               pkgmgrinfo_pkginfo_h *handle)
+static int _pkgmgrinfo_get_pkginfo(const char *pkgid, uid_t uid,
+       pkgmgrinfo_pkginfo_filter_h filter, pkgmgrinfo_pkginfo_h *handle)
 {
        int ret;
-       pkgmgrinfo_pkginfo_filter_h filter;
        GHashTable *list;
        pkgmgr_pkginfo_x *info;
 
-       if (pkgid == NULL || handle == NULL) {
-               LOGE("invalid parameter");
-               return PMINFO_R_EINVAL;
+       if (pkgid == NULL || filter == NULL || handle == NULL) {
+                       LOGE("invalid parameter");
+                       return PMINFO_R_EINVAL;
        }
 
        list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
@@ -191,31 +176,19 @@ API int pkgmgrinfo_pkginfo_get_usr_pkginfo(const char *pkgid, uid_t uid,
        if (list == NULL)
                return PMINFO_R_ERROR;
 
-       ret = pkgmgrinfo_pkginfo_filter_create(&filter);
-       if (ret != PMINFO_R_OK)
-               return ret;
-
-       ret = pkgmgrinfo_pkginfo_filter_add_string(filter,
-                       PMINFO_PKGINFO_PROP_PACKAGE_ID, pkgid);
+       ret = _pkginfo_get_packages(uid, filter, PMINFO_PKGINFO_GET_ALL, list);
        if (ret != PMINFO_R_OK) {
-               pkgmgrinfo_pkginfo_filter_destroy(filter);
-               return PMINFO_R_ERROR;
+               g_hash_table_destroy(list);
+               return ret;
        }
 
-       ret = pkgmgrinfo_pkginfo_filter_add_bool(filter,
-                       PMINFO_PKGINFO_PROP_PACKAGE_DISABLE, false);
-       if (ret != PMINFO_R_OK) {
-               pkgmgrinfo_pkginfo_filter_destroy(filter);
-               return PMINFO_R_ERROR;
+       if (!g_hash_table_size(list) || !g_hash_table_lookup(list, pkgid)) {
+               _LOGD("pkginfo for [%s] is not existed for user [%d]",
+                               pkgid, uid);
+               g_hash_table_destroy(list);
+               return PMINFO_R_ENOENT;
        }
 
-       /* TODO: use pkginfo-client APIs to get pkginfo using filter. */
-
-
-
-
-       pkgmgrinfo_pkginfo_filter_destroy(filter);
-
        info = calloc(1, sizeof(pkgmgr_pkginfo_x));
        if (info == NULL) {
                _LOGE("out of memory");
@@ -225,9 +198,13 @@ API int pkgmgrinfo_pkginfo_get_usr_pkginfo(const char *pkgid, uid_t uid,
 
        info->uid = uid;
        info->pkg_info = (package_x *)g_hash_table_lookup(list, pkgid);
-
-       // TODO: Each parcel will have locale. Use pkginfo-client APIs to get it.
-       //info->locale = locale;
+       info->locale = strdup(info->pkg_info->locale);
+       if (info->locale == NULL) {
+               _LOGE("Out of memory");
+               g_hash_table_destroy(list);
+               free(info);
+               return PMINFO_R_ERROR;
+       }
 
        /* just free list only */
        g_hash_table_steal(list, (gconstpointer)pkgid);
@@ -238,6 +215,40 @@ API int pkgmgrinfo_pkginfo_get_usr_pkginfo(const char *pkgid, uid_t uid,
        return ret;
 }
 
+API int pkgmgrinfo_pkginfo_get_usr_pkginfo(const char *pkgid, uid_t uid,
+               pkgmgrinfo_pkginfo_h *handle)
+{
+       int ret;
+       pkgmgrinfo_pkginfo_filter_h filter;
+
+       if (pkgid == NULL || handle == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       ret = pkgmgrinfo_pkginfo_filter_create(&filter);
+       if (ret != PMINFO_R_OK)
+               return ret;
+
+       ret = pkgmgrinfo_pkginfo_filter_add_string(filter,
+                       PMINFO_PKGINFO_PROP_PACKAGE_ID, pkgid);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_pkginfo_filter_destroy(filter);
+               return PMINFO_R_ERROR;
+       }
+
+       ret = pkgmgrinfo_pkginfo_filter_add_bool(filter,
+                       PMINFO_PKGINFO_PROP_PACKAGE_DISABLE, false);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_pkginfo_filter_destroy(filter);
+               return PMINFO_R_ERROR;
+       }
+       ret = _pkgmgrinfo_get_pkginfo(pkgid, uid, filter, handle);
+       pkgmgrinfo_pkginfo_filter_destroy(filter);
+
+       return ret;
+}
+
 API int pkgmgrinfo_pkginfo_get_pkginfo(const char *pkgid,
                pkgmgrinfo_pkginfo_h *handle)
 {
@@ -248,9 +259,7 @@ API int pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(const char *pkgid,
                uid_t uid, pkgmgrinfo_pkginfo_h *handle)
 {
        int ret;
-       GHashTable *list;
        pkgmgrinfo_pkginfo_filter_h filter;
-       pkgmgr_pkginfo_x *info;
 
        if (pkgid == NULL || handle == NULL) {
                LOGE("invalid parameter");
@@ -276,40 +285,11 @@ API int pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(const char *pkgid,
                return PMINFO_R_ERROR;
        }
 
-       list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-                       __free_packages);
-       if (list == NULL) {
-               pkgmgrinfo_pkginfo_filter_destroy(filter);
-               return PMINFO_R_ERROR;
-       }
-
-       // TODO: use pkginfo-client APIs.
-
-       pkgmgrinfo_pkginfo_filter_destroy(filter);
-       if (!g_hash_table_size(list)) {
-               _LOGD("disabled pkginfo for [%s] is not existed for user [%d]",
+       ret = _pkgmgrinfo_get_pkginfo(pkgid, uid, filter, handle);
+       if (ret == PMINFO_R_ENOENT)
+               LOGE("disabled pkginfo for [%s] is not existed for user [%d]",
                                pkgid, uid);
-               g_hash_table_destroy(list);
-               return PMINFO_R_ENOENT;
-       }
-
-       info = calloc(1, sizeof(pkgmgr_pkginfo_x));
-       if (info == NULL) {
-               _LOGE("out of memory");
-               g_hash_table_destroy(list);
-               return PMINFO_R_ERROR;
-       }
-
-       info->uid = uid;
-       info->pkg_info = (package_x *)g_hash_table_lookup(list, pkgid);
-       //info->locale = locale;
-
-       /* just free list only */
-       g_hash_table_steal(list, (gconstpointer)pkgid);
-       g_hash_table_destroy(list);
-
-       *handle = info;
-
+       pkgmgrinfo_pkginfo_filter_destroy(filter);
        return ret;
 }
 
@@ -342,7 +322,7 @@ API int pkgmgrinfo_pkginfo_get_usr_all_pkginfo(const char *pkgid, uid_t uid,
                return PMINFO_R_ERROR;
        }
 
-       // TODO: use pkginfo-client APIs.
+       ret = _pkgmgrinfo_get_pkginfo(pkgid, uid, filter, handle);
        pkgmgrinfo_pkginfo_filter_destroy(filter);
 
        return ret;
@@ -904,6 +884,65 @@ API int pkgmgrinfo_pkginfo_get_csc_path(pkgmgrinfo_pkginfo_h handle, char **path
        return PMINFO_R_OK;
 }
 
+API int pkgmgrinfo_pkginfo_get_res_type(pkgmgrinfo_pkginfo_h handle,
+               char **res_type)
+{
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+
+       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
+       retvm_if(res_type == NULL, PMINFO_R_EINVAL,
+                       "Argument supplied to hold return value is NULL\n");
+
+       if (info->pkg_info == NULL)
+               return PMINFO_R_ERROR;
+
+       if (info->pkg_info->res_type == NULL)
+               return PMINFO_R_ENOENT;
+
+       *res_type = (char *)info->pkg_info->res_type;
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_pkginfo_get_res_version(pkgmgrinfo_pkginfo_h handle,
+               char **res_version)
+{
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+
+       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
+       retvm_if(res_version == NULL, PMINFO_R_EINVAL,
+                       "Argument supplied to hold return value is NULL\n");
+
+       if (info->pkg_info == NULL)
+               return PMINFO_R_ERROR;
+
+       if (info->pkg_info->res_version == NULL)
+               return PMINFO_R_ENOENT;
+
+       *res_version = (char *)info->pkg_info->res_version;
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_pkginfo_get_light_user_switch_mode(pkgmgrinfo_pkginfo_h handle, char **mode)
+{
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+
+       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
+       retvm_if(mode == NULL, PMINFO_R_EINVAL,
+                       "Argument supplied to hold return value is NULL\n");
+
+       if (info->pkg_info == NULL)
+               return PMINFO_R_ERROR;
+
+       if (info->pkg_info->light_user_switch_mode == NULL)
+               return PMINFO_R_ERROR;
+
+       *mode = (char *)info->pkg_info->light_user_switch_mode;
+
+       return PMINFO_R_OK;
+}
+
 API int pkgmgrinfo_pkginfo_get_support_mode(pkgmgrinfo_pkginfo_h handle, int *support_mode)
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
@@ -1144,12 +1183,16 @@ API int pkgmgrinfo_pkginfo_filter_destroy(pkgmgrinfo_pkginfo_filter_h handle)
 
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "Filter handle input parameter is NULL\n");
 
-       if (filter->list) {
-               g_slist_foreach(filter->list, __destroy_each_node, NULL);
-               g_slist_free(filter->list);
-       }
+       if (filter->list)
+               g_slist_free_full(filter->list,
+                               (GDestroyNotify)_pkgmgrinfo_node_destroy);
 
-       g_slist_free_full(filter->list_metadata, __destroy_metadata_node);
+       if (filter->list_metadata)
+               g_slist_free_full(filter->list_metadata,
+                               __destroy_metadata_node);
+       if (filter->list_pkg_metadata)
+               g_slist_free_full(filter->list_pkg_metadata,
+                               __destroy_metadata_node);
 
        free(filter);
 
@@ -1192,8 +1235,10 @@ API int pkgmgrinfo_pkginfo_filter_add_int(pkgmgrinfo_pkginfo_filter_h handle,
        /*If API is called multiple times for same property, we should override the previous values.
        Last value set will be used for filtering.*/
        link = g_slist_find_custom(filter->list, (gconstpointer)node, __compare_func);
-       if (link)
+       if (link) {
+               _pkgmgrinfo_node_destroy(link->data);
                filter->list = g_slist_delete_link(filter->list, link);
+       }
        filter->list = g_slist_append(filter->list, (gpointer)node);
        return PMINFO_R_OK;
 
@@ -1236,8 +1281,10 @@ API int pkgmgrinfo_pkginfo_filter_add_bool(pkgmgrinfo_pkginfo_filter_h handle,
        /*If API is called multiple times for same property, we should override the previous values.
        Last value set will be used for filtering.*/
        link = g_slist_find_custom(filter->list, (gconstpointer)node, __compare_func);
-       if (link)
+       if (link) {
+               _pkgmgrinfo_node_destroy(link->data);
                filter->list = g_slist_delete_link(filter->list, link);
+       }
        filter->list = g_slist_append(filter->list, (gpointer)node);
        return PMINFO_R_OK;
 
@@ -1289,8 +1336,10 @@ API int pkgmgrinfo_pkginfo_filter_add_string(pkgmgrinfo_pkginfo_filter_h handle,
        /*If API is called multiple times for same property, we should override the previous values.
        Last value set will be used for filtering.*/
        link = g_slist_find_custom(filter->list, (gconstpointer)node, __compare_func);
-       if (link)
+       if (link) {
+               _pkgmgrinfo_node_destroy(link->data);
                filter->list = g_slist_delete_link(filter->list, link);
+       }
        filter->list = g_slist_append(filter->list, (gpointer)node);
        return PMINFO_R_OK;
 
@@ -1299,6 +1348,7 @@ API int pkgmgrinfo_pkginfo_filter_add_string(pkgmgrinfo_pkginfo_filter_h handle,
 API int pkgmgrinfo_pkginfo_usr_filter_count(pkgmgrinfo_pkginfo_filter_h handle, int *count, uid_t uid)
 {
        int ret;
+       int query_count;
        GHashTable *list = NULL;
 
        if (handle == NULL || count == NULL) {
@@ -1320,11 +1370,12 @@ API int pkgmgrinfo_pkginfo_usr_filter_count(pkgmgrinfo_pkginfo_filter_h handle,
                }
        }
 
-       // TODO: use pkginfo-client APIs to get pkginfo list
-       *count = g_hash_table_size(list);
-
+       ret = _pkginfo_get_packages(uid, handle, PMINFO_PKGINFO_GET_BASICINFO, list);
+       query_count = g_hash_table_size(list);
        g_hash_table_destroy(list);
-
+       if (ret == PMINFO_R_ERROR)
+               return ret;
+       *count = query_count;
        return PMINFO_R_OK;
 }
 
@@ -1474,161 +1525,113 @@ API int pkgmgrinfo_pkginfo_foreach_dependency(pkgmgrinfo_pkginfo_h handle,
        return PMINFO_R_OK;
 }
 
-struct depends_on {
-       char *from;
-       char *to;
-       char *type;
-       char *version;
-};
+static void __free_depends_on(gpointer data)
+{
+       dependency_x *dep = (dependency_x *)data;
+       pkgmgrinfo_basic_free_dependency(dep);
+}
 
-static int _get_depends_on(sqlite3 *db, const char *pkgid, GQueue **queue,
-               GHashTable **table, GList **pkg_list)
+/* This API is not exported at the header file */
+API int pkgmgrinfo_pkginfo_foreach_depends_on_by_pkgid(const char *pkgid,
+               pkgmgrinfo_pkg_dependency_list_cb dependency_cb,
+               void *user_data, uid_t uid)
 {
-       static const char query[] =
-               "SELECT package, depends_on, type, required_version "
-               "FROM package_dependency_info WHERE depends_on=?";
        int ret;
-       sqlite3_stmt *stmt;
-       struct depends_on *req;
-
-       /* already checked */
-       if (!g_hash_table_insert(*table, strdup(pkgid), GINT_TO_POINTER(1)))
-               return PMINFO_R_OK;
+       GList *pkg_list = NULL;
+       GList *l;
+       dependency_x *dep;
 
-       ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
-       if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(db));
-               return PMINFO_R_ERROR;
+       if (pkgid == NULL || dependency_cb == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
        }
 
-       ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC);
-       if (ret != SQLITE_OK) {
-               LOGE("bind failed: %s", sqlite3_errmsg(db));
-               sqlite3_finalize(stmt);
+       ret = _pkginfo_get_depends_on(uid, pkgid, &pkg_list);
+       if (ret != PMINFO_R_OK)
                return PMINFO_R_ERROR;
+
+       for (l = pkg_list; l != NULL; l = g_list_next(l)) {
+               dep = (dependency_x *)l->data;
+               ret = dependency_cb(dep->pkgid, dep->depends_on,
+                               dep->type, dep->required_version, user_data);
+               if (ret < 0)
+                       break;
        }
+       g_list_free_full(pkg_list, __free_depends_on);
 
-       while (sqlite3_step(stmt) == SQLITE_ROW) {
-               req = calloc(1, sizeof(struct depends_on));
-               if (req == NULL) {
-                       LOGE("out of memory");
-                       sqlite3_finalize(stmt);
-                       return PMINFO_R_ERROR;
-               }
-               _save_column_str(stmt, 0, &req->from);
-               _save_column_str(stmt, 1, &req->to);
-               _save_column_str(stmt, 2, &req->type);
-               _save_column_str(stmt, 3, &req->version);
+       return PMINFO_R_OK;
+}
 
-               *pkg_list = g_list_prepend(*pkg_list, req);
-               g_queue_push_tail(*queue, strdup(req->from));
-       }
+API int pkgmgrinfo_pkginfo_foreach_depends_on(pkgmgrinfo_pkginfo_h handle,
+               pkgmgrinfo_pkg_dependency_list_cb dependency_cb,
+               void *user_data)
+{
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
 
-       sqlite3_finalize(stmt);
+       if (handle == NULL || dependency_cb == NULL || info->pkg_info == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
 
-       return PMINFO_R_OK;
+       return pkgmgrinfo_pkginfo_foreach_depends_on_by_pkgid(
+                        info->pkg_info->package, dependency_cb, user_data,
+                        info->uid);
 }
 
-static int _pkginfo_foreach_depends_on(uid_t uid, const char *pkgid,
-               GList **pkg_list)
+API int pkgmgrinfo_pkginfo_foreach_res_allowed_package(
+               pkgmgrinfo_pkginfo_h handle,
+               pkgmgrinfo_res_allowed_package_list_cb res_allowed_package_cb,
+               void *user_data)
 {
        int ret;
-       char *dbpath;
-       sqlite3 *db;
-       GQueue *queue;
-       GHashTable *table;
-       char *item;
-
-       dbpath = getUserPkgParserDBPathUID(uid);
-       if (dbpath == NULL)
-               return PMINFO_R_ERROR;
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+       GList *res_pkgs;
+       res_allowed_package_x *res_allowed_package;
 
-       ret = __open_db(dbpath, &db, SQLITE_OPEN_READONLY);
-       if (ret != SQLITE_OK) {
-               LOGD("failed to open db(%s): %d", dbpath, ret);
-               free(dbpath);
-               return PMINFO_R_ERROR;
+       if (handle == NULL || res_allowed_package_cb == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
        }
-       free(dbpath);
 
-       queue = g_queue_new();
-       if (queue == NULL) {
-               LOGE("out of memory");
-               sqlite3_close_v2(db);
+       if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       }
 
-       table = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+       for (res_pkgs = info->pkg_info->res_allowed_packages; res_pkgs;
+                       res_pkgs = res_pkgs->next) {
+               res_allowed_package = (res_allowed_package_x *)res_pkgs->data;
+               if (res_allowed_package == NULL)
+                       continue;
 
-       g_queue_push_tail(queue, strdup(pkgid));
-       while (!g_queue_is_empty(queue)) {
-               item = g_queue_pop_head(queue);
-               ret = _get_depends_on(db, item, &queue, &table, pkg_list);
-               free(item);
-               if (ret != PMINFO_R_OK) {
-                       LOGE("failed to get pkgs depends on %s", pkgid);
-                       g_hash_table_destroy(table);
-                       g_queue_free_full(queue, free);
-                       sqlite3_close_v2(db);
-                       return PMINFO_R_ERROR;
-               }
+               ret = res_allowed_package_cb(
+                               res_allowed_package->allowed_package,
+                               res_allowed_package->required_privileges,
+                               user_data);
+               if (ret < 0)
+                       return PMINFO_R_OK;
        }
 
-       g_hash_table_destroy(table);
-       g_queue_free_full(queue, free);
-       sqlite3_close_v2(db);
-
        return PMINFO_R_OK;
 }
 
-static void __free_depends_on(gpointer data)
-{
-       struct depends_on *dep = (struct depends_on *)data;
-
-       free(dep->from);
-       free(dep->to);
-       free(dep->type);
-       free(dep->version);
-       free(dep);
-}
-
-// TODO: need to change this
-API int pkgmgrinfo_pkginfo_foreach_depends_on(pkgmgrinfo_pkginfo_h handle,
-               pkgmgrinfo_pkg_dependency_list_cb dependency_cb,
+API int pkgmgrinfo_pkginfo_foreach_required_privilege(
+               required_privilege_h handle,
+               pkgmgrinfo_pkg_privilege_list_cb privilege_func,
                void *user_data)
 {
        int ret;
-       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
-       GList *pkg_list = NULL;
-       GList *l;
-       struct depends_on *dep;
+       GList *privs;
 
-       if (handle == NULL || dependency_cb == NULL || info->pkg_info == NULL) {
+       if (privilege_func == NULL) {
                LOGE("invalid parameter");
                return PMINFO_R_EINVAL;
        }
 
-       ret = _pkginfo_foreach_depends_on(info->uid, info->pkg_info->package,
-                       &pkg_list);
-       if (ret == PMINFO_R_OK && info->uid != GLOBAL_USER)
-               ret = _pkginfo_foreach_depends_on(GLOBAL_USER,
-                               info->pkg_info->package, &pkg_list);
-
-       if (ret != PMINFO_R_OK) {
-               g_list_free_full(pkg_list, __free_depends_on);
-               return ret;
-       }
-
-       for (l = pkg_list; l != NULL; l = l->next) {
-               dep = (struct depends_on *)l->data;
-               ret = dependency_cb(dep->from, dep->to, dep->type, dep->version,
-                               user_data);
+       for (privs = (GList *)handle; privs; privs = privs->next) {
+               ret = privilege_func((char *)privs->data, user_data);
                if (ret < 0)
-                       break;
+                       return PMINFO_R_OK;
        }
 
-       g_list_free_full(pkg_list, __free_depends_on);
-
        return PMINFO_R_OK;
 }
 
@@ -1754,3 +1757,102 @@ API int pkgmgrinfo_compare_package_version(const char *current_version,
 
        return PMINFO_R_OK;
 }
+
+API int pkgmgrinfo_pkginfo_foreach_metadata(pkgmgrinfo_pkginfo_h handle,
+               pkgmgrinfo_pkg_metadata_list_cb metadata_func, void *user_data)
+{
+       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL");
+       retvm_if(metadata_func == NULL, PMINFO_R_EINVAL,
+                       "Callback function is NULL");
+       int ret = -1;
+       metadata_x *ptr;
+       GList *tmp;
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+
+       if (info->pkg_info == NULL)
+               return PMINFO_R_ERROR;
+
+       for (tmp = info->pkg_info->metadata; tmp; tmp = tmp->next) {
+               ptr = (metadata_x *)tmp->data;
+               if (ptr == NULL)
+                       continue;
+               if (ptr->key) {
+                       ret = metadata_func(ptr->key, ptr->value ?
+                                       ptr->value : "", user_data);
+                       if (ret < 0)
+                               break;
+               }
+       }
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_pkginfo_metadata_filter_create(
+               pkgmgrinfo_pkginfo_metadata_filter_h *handle)
+{
+       return pkgmgrinfo_pkginfo_filter_create(handle);
+}
+
+API int pkgmgrinfo_pkginfo_metadata_filter_destroy(
+               pkgmgrinfo_pkginfo_metadata_filter_h handle)
+{
+       return pkgmgrinfo_pkginfo_filter_destroy(handle);
+}
+
+API int pkgmgrinfo_pkginfo_metadata_filter_add(
+               pkgmgrinfo_pkginfo_metadata_filter_h handle,
+               const char *key, const char *value)
+{
+       pkgmgrinfo_filter_x *filter = (pkgmgrinfo_filter_x *)handle;
+       pkgmgrinfo_metadata_node_x *node;
+
+       /* value can be NULL.
+        * In that case all pkgs with specified key should be displayed
+        */
+       if (handle == NULL || key == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       node = calloc(1, sizeof(pkgmgrinfo_metadata_node_x));
+       if (node == NULL) {
+               LOGE("out of memory");
+               return PMINFO_R_ERROR;
+       }
+
+       node->key = strdup(key);
+       if (value && strlen(value))
+               node->value = strdup(value);
+
+       filter->list_pkg_metadata = g_slist_append(filter->list_pkg_metadata,
+                       (gpointer)node);
+
+       return PMINFO_R_OK;
+}
+
+API int pkgmgrinfo_pkginfo_usr_metadata_filter_foreach(
+               pkgmgrinfo_pkginfo_metadata_filter_h handle,
+               pkgmgrinfo_pkg_list_cb pkg_cb, void *user_data, uid_t uid)
+{
+       if (handle == NULL || pkg_cb == NULL) {
+               LOGE("invalid parameter");
+               return PMINFO_R_EINVAL;
+       }
+
+       pkgmgrinfo_filter_x *filter = (pkgmgrinfo_filter_x *)handle;
+
+       if (pkgmgrinfo_pkginfo_filter_add_bool(filter,
+                       PMINFO_PKGINFO_PROP_PACKAGE_DISABLE, false))
+               return PMINFO_R_ERROR;
+
+       return _pkginfo_get_filtered_foreach_pkginfo(uid, handle,
+                       PMINFO_PKGINFO_GET_ALL, pkg_cb,
+                       user_data);
+}
+
+API int pkgmgrinfo_pkginfo_metadata_filter_foreach(
+               pkgmgrinfo_pkginfo_metadata_filter_h handle,
+               pkgmgrinfo_pkg_list_cb pkg_cb, void *user_data)
+{
+       return pkgmgrinfo_pkginfo_usr_metadata_filter_foreach(handle, pkg_cb,
+                       user_data, _getuid());
+}