Release version 0.15.0
[platform/core/appfw/slp-pkgmgr.git] / client / src / pkgmgr.c
index c594e1f..3887f55 100644 (file)
@@ -29,6 +29,8 @@
 #include <fcntl.h>
 #include <sys/wait.h>
 #include <sys/time.h>
+#include <unzip.h>
+#include <pthread.h>
 
 #include <glib.h>
 
@@ -38,6 +40,7 @@
 #include <tzplatform_config.h>
 
 #include "package-manager.h"
+#include "package-manager-types.h"
 #include "pkgmgr_client_debug.h"
 #include "pkgmgr_client_internal.h"
 
@@ -52,6 +55,9 @@
 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 #define REGULAR_USER 5000
 
+static GList *jobs_to_free;
+static pthread_mutex_t __mutex = PTHREAD_MUTEX_INITIALIZER;
+
 static inline uid_t _getuid(void)
 {
        uid_t uid = getuid();
@@ -62,13 +68,27 @@ static inline uid_t _getuid(void)
                return uid;
 }
 
-static int _get_request_id()
+static int _get_internal_request_id()
 {
        static int internal_req_id = 1;
 
        return internal_req_id++;
 }
 
+static char *_generate_request_id(void)
+{
+       struct timeval tv;
+       long curtime;
+       char buf[BUFMAX];
+
+       gettimeofday(&tv, NULL);
+       curtime = tv.tv_sec * 1000000 + tv.tv_usec;
+
+       snprintf(buf, sizeof(buf), "%d_%ld", getpid(), curtime);
+
+       return strdup(buf);
+}
+
 static struct cb_info *__create_event_cb_info(struct pkgmgr_client_t *client,
                pkgmgr_handler event_cb, void *data, const char *req_key)
 {
@@ -82,7 +102,7 @@ static struct cb_info *__create_event_cb_info(struct pkgmgr_client_t *client,
        cb_info->client = client;
        cb_info->event_cb = event_cb;
        cb_info->data = data;
-       cb_info->req_id = _get_request_id();
+       cb_info->req_id = _get_internal_request_id();
        if (req_key != NULL) {
                cb_info->req_key = strdup(req_key);
                if (cb_info->req_key == NULL) {
@@ -109,7 +129,7 @@ static struct cb_info *__create_app_event_cb_info(
        cb_info->client = client;
        cb_info->app_event_cb = app_event_cb;
        cb_info->data = data;
-       cb_info->req_id = _get_request_id();
+       cb_info->req_id = _get_internal_request_id();
        if (req_key != NULL) {
                cb_info->req_key = strdup(req_key);
                if (cb_info->req_key == NULL) {
@@ -122,6 +142,66 @@ static struct cb_info *__create_app_event_cb_info(
        return cb_info;
 }
 
+static struct cb_info *__create_res_event_cb_info(
+               struct pkgmgr_client_t *client,
+               pkgmgr_res_handler res_event_cb,
+               void *data, const char *req_key)
+{
+       struct cb_info *cb_info;
+
+       cb_info = calloc(1, sizeof(struct cb_info));
+       if (cb_info == NULL) {
+               ERR("out of memory");
+               return NULL;
+       }
+
+       cb_info->client = client;
+       cb_info->res_event_cb = res_event_cb;
+       cb_info->data = data;
+       cb_info->req_id = _get_internal_request_id();
+       if (req_key == NULL)
+               return cb_info;
+
+       cb_info->req_key = strdup(req_key);
+       if (cb_info->req_key == NULL) {
+               ERR("out of memory");
+               free(cb_info);
+               return NULL;
+       }
+
+       return cb_info;
+}
+
+static struct cb_info *__create_upgrade_event_cb_info(
+               struct pkgmgr_client_t *client,
+               pkgmgr_pkg_upgrade_handler upgrade_event_cb,
+               void *data, const char *req_key)
+{
+       struct cb_info *cb_info;
+
+       cb_info = calloc(1, sizeof(struct cb_info));
+       if (cb_info == NULL) {
+               ERR("out of memory");
+               return NULL;
+       }
+
+       cb_info->client = client;
+       cb_info->upgrade_event_cb = upgrade_event_cb;
+       cb_info->data = data;
+       cb_info->req_id = _get_internal_request_id();
+       if (req_key == NULL)
+               return cb_info;
+
+       cb_info->req_key = strdup(req_key);
+       if (cb_info->req_key == NULL) {
+               ERR("out of memory");
+               free(cb_info);
+               return NULL;
+       }
+
+       return cb_info;
+}
+
 static struct cb_info *__create_size_info_cb_info(
                struct pkgmgr_client_t *client,
                pkgmgr_pkg_size_info_receive_cb size_info_cb,
@@ -137,7 +217,7 @@ static struct cb_info *__create_size_info_cb_info(
        cb_info->client = client;
        cb_info->size_info_cb = size_info_cb;
        cb_info->data = data;
-       cb_info->req_id = _get_request_id();
+       cb_info->req_id = _get_internal_request_id();
        if (req_key != NULL) {
                cb_info->req_key = strdup(req_key);
                if (cb_info->req_key == NULL) {
@@ -150,12 +230,64 @@ static struct cb_info *__create_size_info_cb_info(
        return cb_info;
 }
 
-static void __free_cb_info(struct cb_info *cb_info)
+static int __jobs_to_free_add(gpointer data)
+{
+       pthread_mutex_lock(&__mutex);
+       if (g_list_find(jobs_to_free, data)) {
+               pthread_mutex_unlock(&__mutex);
+               return -1;
+       }
+
+       jobs_to_free = g_list_append(jobs_to_free, data);
+       pthread_mutex_unlock(&__mutex);
+       return 0;
+}
+
+static void __jobs_to_free_remove(gpointer data)
+{
+       pthread_mutex_lock(&__mutex);
+       jobs_to_free = g_list_remove(jobs_to_free, data);
+       pthread_mutex_unlock(&__mutex);
+}
+
+static void __do_free_cb_info(gpointer data)
 {
+       struct cb_info *cb_info = (struct cb_info *)data;
+
+       g_list_free(cb_info->sid_list);
        free(cb_info->req_key);
        free(cb_info);
 }
 
+static void __free_cb_info_cb(gpointer data)
+{
+       g_idle_remove_by_data(data);
+       __do_free_cb_info(data);
+}
+
+__attribute__((destructor)) static void __free_cb_info_at_destructor(void)
+{
+       pthread_mutex_lock(&__mutex);
+       g_list_free_full(jobs_to_free, __free_cb_info_cb);
+       pthread_mutex_unlock(&__mutex);
+}
+
+static gboolean __free_cb_info_at_idle(gpointer data)
+{
+       __jobs_to_free_remove(data);
+       __do_free_cb_info(data);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void __free_cb_info(struct cb_info *cb_info)
+{
+       if (__jobs_to_free_add(cb_info) < 0)
+               return;
+
+       g_idle_add(__free_cb_info_at_idle, cb_info);
+}
+
 static int __get_size_process(pkgmgr_client *pc, const char *pkgid, uid_t uid,
                pkgmgr_getsize_type get_type, pkgmgr_handler event_cb,
                void *data)
@@ -190,7 +322,7 @@ static int __get_size_process(pkgmgr_client *pc, const char *pkgid, uid_t uid,
        }
 
        if (size_info < 0) {
-               ERR("invalid size_info=(%d)", size_info);
+               ERR("invalid size_info=(%lld)", size_info);
                ret = -1;
        } else {
                ret = (int)size_info;
@@ -228,20 +360,27 @@ static int __check_app_process(pkgmgr_request_service_type service_type,
 
        retvm_if(client->pc_type != PC_REQUEST, PKGMGR_R_EINVAL, "client->pc_type is not PC_REQUEST\n");
 
-       if (uid != GLOBAL_USER)
-               ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
-       else
-               ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
-       retvm_if(ret < 0, PKGMGR_R_ERROR, "pkgmgrinfo_pkginfo_get_pkginfo failed");
+       ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
+       if (ret != PMINFO_R_OK) {
+               ERR("pkgmgrinfo_pkginfo_get_pkginfo failed");
+               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+               return PKGMGR_R_ERROR;
+       }
 
-       if (service_type == PM_REQUEST_KILL_APP)
+       if (service_type == PM_REQUEST_KILL_APP) {
                ret = pkgmgr_client_connection_send_request(client, "kill",
                                g_variant_new("(us)", uid, pkgid), &result);
-       else if (service_type == PM_REQUEST_CHECK_APP)
+       } else if (service_type == PM_REQUEST_CHECK_APP) {
                ret = pkgmgr_client_connection_send_request(client, "check",
                                g_variant_new("(us)", uid, pkgid), &result);
+       } else {
+               ERR("unexpected service type: %d", service_type);
+               ret = PKGMGR_R_ERROR;
+       }
+
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
+               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
                return ret;
        }
 
@@ -249,6 +388,7 @@ static int __check_app_process(pkgmgr_request_service_type service_type,
        g_variant_unref(result);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed, ret=%d", ret);
+               pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
                return ret;
        }
 
@@ -260,44 +400,6 @@ static int __check_app_process(pkgmgr_request_service_type service_type,
 
 }
 
-static int __request_size_info(pkgmgr_client *pc, uid_t uid)
-{
-       GVariant *result;
-       int ret = PKGMGR_R_ECOMM;
-//     char *req_key = NULL;
-       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
-
-       if (pc == NULL) {
-               ERR("invalid parameter");
-               return PKGMGR_R_EINVAL;
-       }
-
-       if (client->pc_type != PC_REQUEST) {
-               ERR("client->pc_type is not PC_REQUEST");
-               return PKGMGR_R_EINVAL;
-       }
-
-       ret = pkgmgr_client_connection_send_request(client, "getsize",
-                       g_variant_new("(usi)", uid, "size_info",
-                               PM_GET_SIZE_INFO), &result);
-       if (ret != PKGMGR_R_OK) {
-               ERR("request failed: %d", ret);
-               return ret;
-       }
-
-/*
-       g_variant_get(result, "(i&s)", &ret, &req_key);
-       if (req_key == NULL) {
-               g_variant_unref(result);
-               return PKGMGR_R_ECOMM;
-       }
-*/
-
-       g_variant_unref(result);
-
-       return ret;
-}
-
 API pkgmgr_client *pkgmgr_client_new(pkgmgr_client_type pc_type)
 {
        struct pkgmgr_client_t *client;
@@ -321,8 +423,10 @@ API pkgmgr_client *pkgmgr_client_new(pkgmgr_client_type pc_type)
        client->pc_type = pc_type;
        client->status_type = PKGMGR_CLIENT_STATUS_ALL;
 
-       if (pkgmgr_client_connection_connect(client))
+       if (pkgmgr_client_connection_connect(client) != PKGMGR_R_OK) {
+               free(client);
                return NULL;
+       }
 
        return (pkgmgr_client *)client;
 }
@@ -340,38 +444,46 @@ API int pkgmgr_client_free(pkgmgr_client *pc)
        pkgmgr_client_connection_disconnect(client);
        if (client->tep_path)
                free(client->tep_path);
+       if (client->res_copy_builder)
+               g_variant_builder_unref(client->res_copy_builder);
+       if (client->res_remove_builder)
+               g_variant_builder_unref(client->res_remove_builder);
+       if (client->res_create_dir_builder)
+               g_variant_builder_unref(client->res_create_dir_builder);
        free(client);
 
        return PKGMGR_R_OK;
 }
 
+struct manifest_and_type type_map[] = {
+               { "res/wgt/config.xml", "wgt" },
+               { "config.xml", "wgt" },
+               { "tizen-manifest.xml", "tpk" },
+               { NULL, NULL }
+};
+
 static char *__get_type_from_path(const char *pkg_path)
 {
-       int ret;
-       char mimetype[255] = { '\0', };
-       char extlist[256] = { '\0', };
-       char *pkg_type;
+       const char *type = NULL;
+       unzFile uf;
+       int i;
 
-       ret = _get_mime_from_file(pkg_path, mimetype, sizeof(mimetype));
-       if (ret) {
-               ERR("_get_mime_from_file() failed - error code[%d]\n", ret);
+       uf = unzOpen(pkg_path);
+       if (uf == NULL) {
+               ERR("failed to open zip file %s", pkg_path);
                return NULL;
        }
 
-       ret = _get_mime_extension(mimetype, extlist, sizeof(extlist));
-       if (ret) {
-               ERR("_get_mime_extension() failed - error code[%d]\n", ret);
-               return NULL;
+       for (i = 0; type_map[i].manifest != NULL; i++) {
+               if (unzLocateFile(uf, type_map[i].manifest, 0) == UNZ_OK) {
+                       DBG("pkgtype of %s: [%s]", pkg_path, type_map[i].type);
+                       type = type_map[i].type;
+                       break;
+               }
        }
+       unzClose(uf);
 
-       if (strlen(extlist) == 0)
-               return NULL;
-
-       if (strchr(extlist, ','))
-               extlist[strlen(extlist) - strlen(strchr(extlist, ','))] = '\0';
-
-       pkg_type = strchr(extlist, '.') + 1;
-       return strdup(pkg_type);
+       return type ? strdup(type) : NULL;
 }
 
 API int pkgmgr_client_set_tep_path(pkgmgr_client *pc, const char *tep_path,
@@ -393,6 +505,98 @@ API int pkgmgr_client_set_tep_path(pkgmgr_client *pc, const char *tep_path,
        return PKGMGR_R_OK;
 }
 
+API int pkgmgr_client_usr_install_packages(pkgmgr_client *pc,
+               const char **pkg_paths, int n_pkgs, pkgmgr_handler event_cb,
+               void *data, uid_t uid)
+{
+       GVariant *result;
+       GVariantBuilder *pkgs_builder;
+       GVariant *pkgs;
+       GVariantBuilder *args_builder;
+       GVariant *args;
+       int ret;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+       int i;
+       char *request_id = NULL;
+
+       if (pc == NULL || pkg_paths == NULL || n_pkgs < 1) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       for (i = 0; i < n_pkgs; i++) {
+               if (access(pkg_paths[i], F_OK) != 0) {
+                       ERR("failed to access: %s", pkg_paths[i]);
+                       return PKGMGR_R_EINVAL;
+               }
+       }
+
+       pkgs_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < n_pkgs; i++)
+               g_variant_builder_add(pkgs_builder, "s", pkg_paths[i]);
+       pkgs = g_variant_new("as", pkgs_builder);
+       g_variant_builder_unref(pkgs_builder);
+
+       args_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       if (client->debug_mode)
+               g_variant_builder_add(args_builder, "s", "-G");
+       if (client->skip_optimization)
+               g_variant_builder_add(args_builder, "s", "-S");
+       args = g_variant_new("as", args_builder);
+       g_variant_builder_unref(args_builder);
+
+       request_id = _generate_request_id();
+       ret = pkgmgr_client_connection_send_request(client, "install_pkgs",
+                       g_variant_new("(u@as@ass)", uid, pkgs, args,
+                                       request_id),
+                       &result);
+       free(request_id);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_event_cb_info(client, event_cb, data, req_key);
+       if (cb_info == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ERROR;
+       }
+       g_variant_unref(result);
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_install_packages(pkgmgr_client *pc,
+               const char **pkg_paths, int n_pkgs, pkgmgr_handler event_cb,
+               void *data)
+{
+       return pkgmgr_client_usr_install_packages(pc, pkg_paths, n_pkgs,
+                       event_cb, data, _getuid());
+}
+
 API int pkgmgr_client_usr_install(pkgmgr_client *pc, const char *pkg_type,
                const char *descriptor_path, const char *pkg_path,
                const char *optional_data, pkgmgr_mode mode,
@@ -404,8 +608,8 @@ API int pkgmgr_client_usr_install(pkgmgr_client *pc, const char *pkg_type,
        GVariantBuilder *builder = NULL;
        GVariant *args = NULL;
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
-       char *pkgtype = NULL;
        struct cb_info *cb_info;
+       char *request_id = NULL;
 
        if (pc == NULL || pkg_path == NULL) {
                ERR("invalid parameter");
@@ -427,9 +631,6 @@ API int pkgmgr_client_usr_install(pkgmgr_client *pc, const char *pkg_type,
                return PKGMGR_R_EINVAL;
        }
 
-       if (pkg_type)
-               pkgtype = strdup(pkg_type);
-
        /* build arguments */
        builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
        if (client->tep_path) {
@@ -442,14 +643,18 @@ API int pkgmgr_client_usr_install(pkgmgr_client *pc, const char *pkg_type,
        }
        if (client->debug_mode)
                g_variant_builder_add(builder, "s", "-G");
+       if (client->skip_optimization)
+               g_variant_builder_add(builder, "s", "-S");
 
        args = g_variant_new("as", builder);
        g_variant_builder_unref(builder);
 
+       request_id = _generate_request_id();
        ret = pkgmgr_client_connection_send_request(client, "install",
-                       g_variant_new("(uss@as)", uid, pkgtype ? pkgtype : "",
-                               pkg_path, args),
+                       g_variant_new("(uss@ass)", uid, pkg_type ? pkg_type : "",
+                               pkg_path, args, request_id),
                        &result);
+       free(request_id);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
                return ret;
@@ -477,7 +682,6 @@ API int pkgmgr_client_usr_install(pkgmgr_client *pc, const char *pkg_type,
                return ret;
        }
        client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
-
        return cb_info->req_id;
 }
 
@@ -552,6 +756,88 @@ API int pkgmgr_client_usr_reinstall(pkgmgr_client *pc, const char *pkg_type,
        return cb_info->req_id;
 }
 
+API int pkgmgr_client_usr_mount_install_packages(pkgmgr_client *pc,
+               const char **pkg_paths, int n_pkgs, pkgmgr_handler event_cb,
+               void *data, uid_t uid)
+{
+       GVariant *result;
+       GVariantBuilder *pkgs_builder;
+       GVariant *pkgs;
+       int ret = PKGMGR_R_ECOMM;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+       int i;
+       char *request_id = NULL;
+
+       if (pc == NULL || pkg_paths == NULL || n_pkgs < 1) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       for (i = 0; i < n_pkgs; i++) {
+               if (access(pkg_paths[i], F_OK) != 0) {
+                       ERR("failed to access: %s", pkg_paths[i]);
+                       return PKGMGR_R_EINVAL;
+               }
+       }
+
+       pkgs_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < n_pkgs; i++)
+               g_variant_builder_add(pkgs_builder, "s", pkg_paths[i]);
+       pkgs = g_variant_new("as", pkgs_builder);
+       g_variant_builder_unref(pkgs_builder);
+
+       request_id = _generate_request_id();
+       ret = pkgmgr_client_connection_send_request(client,
+                       "mount_install_pkgs",
+                       g_variant_new("(u@ass)", uid, pkgs, request_id),
+                       &result);
+       free(request_id);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_event_cb_info(client, event_cb, data, req_key);
+       if (cb_info == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ENOMEM;
+       }
+       g_variant_unref(result);
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_mount_install_packages(pkgmgr_client *pc,
+               const char **pkg_paths, int n_pkgs, pkgmgr_handler event_cb,
+               void *data)
+{
+       return pkgmgr_client_usr_mount_install_packages(pc, pkg_paths, n_pkgs,
+                       event_cb, data, _getuid());
+}
+
 API int pkgmgr_client_usr_mount_install(pkgmgr_client *pc, const char *pkg_type,
                const char *descriptor_path, const char *pkg_path,
                const char *optional_data, pkgmgr_mode mode,
@@ -563,8 +849,8 @@ API int pkgmgr_client_usr_mount_install(pkgmgr_client *pc, const char *pkg_type,
        GVariantBuilder *builder = NULL;
        GVariant *args = NULL;
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
-       char *pkgtype = NULL;
        struct cb_info *cb_info;
+       char *request_id = NULL;
 
        if (pc == NULL || pkg_path == NULL) {
                ERR("invalid parameter");
@@ -586,9 +872,6 @@ API int pkgmgr_client_usr_mount_install(pkgmgr_client *pc, const char *pkg_type,
                return PKGMGR_R_EINVAL;
        }
 
-       if (pkg_type)
-               pkgtype = strdup(pkg_type);
-
        /* build arguments */
        builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
        if (client->tep_path) {
@@ -603,10 +886,13 @@ API int pkgmgr_client_usr_mount_install(pkgmgr_client *pc, const char *pkg_type,
        args = g_variant_new("as", builder);
        g_variant_builder_unref(builder);
 
+       request_id = _generate_request_id();
        ret = pkgmgr_client_connection_send_request(client, "mount_install",
-                       g_variant_new("(uss@as)", uid, pkgtype ? pkgtype : "",
-                               pkg_path, args),
+                       g_variant_new("(uss@ass)", uid,
+                                       pkg_type ? pkg_type : "", pkg_path,
+                                       args, request_id),
                        &result);
+       free(request_id);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
                return ret;
@@ -648,12 +934,82 @@ API int pkgmgr_client_mount_install(pkgmgr_client *pc, const char *pkg_type,
                        _getuid());
 }
 
-API int pkgmgr_client_uninstall(pkgmgr_client *pc, const char *pkg_type,
-               const char *pkgid, pkgmgr_mode mode, pkgmgr_handler event_cb,
-               void *data)
+API int pkgmgr_client_usr_uninstall_packages(pkgmgr_client *pc,
+               const char **pkgids, int n_pkgs, pkgmgr_handler event_cb,
+               void *data, uid_t uid)
 {
-       return pkgmgr_client_usr_uninstall(pc, pkg_type, pkgid, mode, event_cb,
-                       data, _getuid());
+       GVariant *result;
+       GVariantBuilder *pkgs_builder;
+       GVariant *pkgs;
+       int ret = PKGMGR_R_ECOMM;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+       int i;
+
+       if (pc == NULL || pkgids == NULL || n_pkgs < 1) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       pkgs_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < n_pkgs; i++)
+               g_variant_builder_add(pkgs_builder, "s", pkgids[i]);
+       pkgs = g_variant_new("as", pkgs_builder);
+       g_variant_builder_unref(pkgs_builder);
+
+       ret = pkgmgr_client_connection_send_request(client, "uninstall_pkgs",
+                       g_variant_new("(u@as)", uid, pkgs), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_event_cb_info(client, event_cb, data, req_key);
+       if (cb_info == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ENOMEM;
+       }
+       g_variant_unref(result);
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_uninstall_packages(pkgmgr_client *pc,
+               const char **pkgids, int n_pkgs, pkgmgr_handler event_cb,
+               void *data)
+{
+       return pkgmgr_client_usr_uninstall_packages(pc, pkgids, n_pkgs,
+                       event_cb, data, _getuid());
+}
+
+API int pkgmgr_client_uninstall(pkgmgr_client *pc, const char *pkg_type,
+               const char *pkgid, pkgmgr_mode mode, pkgmgr_handler event_cb,
+               void *data)
+{
+       return pkgmgr_client_usr_uninstall(pc, pkg_type, pkgid, mode, event_cb,
+                       data, _getuid());
 }
 
 API int pkgmgr_client_usr_uninstall(pkgmgr_client *pc, const char *pkg_type,
@@ -732,7 +1088,7 @@ API int pkgmgr_client_usr_move(pkgmgr_client *pc, const char *pkg_type,
        }
 
        if ((move_type < PM_MOVE_TO_INTERNAL) ||
-                       (move_type > PM_MOVE_TO_SDCARD))
+                       (move_type > PM_MOVE_TO_EXTENDED))
                return PKGMGR_R_EINVAL;
 
        if (client->pc_type != PC_REQUEST) {
@@ -773,6 +1129,129 @@ API int pkgmgr_client_usr_move(pkgmgr_client *pc, const char *pkg_type,
        return cb_info->req_id;
 }
 
+API int pkgmgr_client_usr_register_pkg_update_info(pkgmgr_client *pc,
+               pkg_update_info_t *update_info, uid_t uid)
+{
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       GVariant *result;
+
+       if (pc == NULL || update_info == NULL || update_info->pkgid == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client, "register_pkg_update_info",
+                       g_variant_new("(ussi)", uid, update_info->pkgid, update_info->version,
+                       update_info->type), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+       g_variant_unref(result);
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_register_pkg_update_info(pkgmgr_client *pc,
+               pkg_update_info_t *update_info)
+{
+       return pkgmgr_client_usr_register_pkg_update_info(pc, update_info,
+                       _getuid());
+}
+
+API int pkgmgr_client_usr_unregister_pkg_update_info(pkgmgr_client *pc,
+               const char *pkgid, uid_t uid)
+{
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       GVariant *result;
+
+       if (pc == NULL || pkgid == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "unregister_pkg_update_info",
+                       g_variant_new("(us)", uid, pkgid), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+       g_variant_unref(result);
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_unregister_pkg_update_info(pkgmgr_client *pc,
+               const char *pkgid)
+{
+       return pkgmgr_client_usr_unregister_pkg_update_info(pc, pkgid, _getuid());
+}
+
+API int pkgmgr_client_usr_unregister_all_pkg_update_info(pkgmgr_client *pc,
+               uid_t uid)
+{
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       GVariant *result;
+
+       if (pc == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "unregister_all_pkg_update_info",
+                       g_variant_new("(u)", uid), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+       g_variant_unref(result);
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_unregister_all_pkg_update_info(pkgmgr_client *pc)
+{
+       return pkgmgr_client_usr_unregister_all_pkg_update_info(pc, _getuid());
+}
+
 API int pkgmgr_client_usr_activate(pkgmgr_client *pc, const char *pkg_type,
                const char *pkgid, uid_t uid)
 {
@@ -982,7 +1461,7 @@ API int pkgmgr_client_deactivate_packages(pkgmgr_client *pc,
 }
 
 API int pkgmgr_client_usr_activate_app(pkgmgr_client *pc, const char *appid,
-               pkgmgr_app_handler app_event_cb, uid_t uid)
+               pkgmgr_app_handler app_event_cb, void *data, uid_t uid)
 {
        GVariant *result;
        int ret = PKGMGR_R_ECOMM;
@@ -1012,7 +1491,7 @@ API int pkgmgr_client_usr_activate_app(pkgmgr_client *pc, const char *appid,
                return ret;
        }
 
-       cb_info = __create_app_event_cb_info(client, app_event_cb, NULL,
+       cb_info = __create_app_event_cb_info(client, app_event_cb, data,
                        req_key);
        if (cb_info == NULL) {
                g_variant_unref(result);
@@ -1026,33 +1505,44 @@ API int pkgmgr_client_usr_activate_app(pkgmgr_client *pc, const char *appid,
        }
        client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
 
-       return PKGMGR_R_OK;
+       return cb_info->req_id;
 }
 
 API int pkgmgr_client_activate_app(pkgmgr_client *pc, const char *appid,
-               pkgmgr_app_handler app_event_cb)
+               pkgmgr_app_handler app_event_cb, void *data)
 {
        return pkgmgr_client_usr_activate_app(pc, appid, app_event_cb,
-                       _getuid());
+                       data, _getuid());
 }
 
-API int pkgmgr_client_activate_global_app_for_uid(pkgmgr_client *pc,
-               const char *appid, pkgmgr_app_handler app_event_cb, uid_t uid)
+API int pkgmgr_client_usr_activate_apps(pkgmgr_client *pc, const char **appids,
+               int n_apps, pkgmgr_app_handler app_event_cb, void *data, uid_t uid)
 {
        GVariant *result;
+       GVariantBuilder *builder;
        int ret = PKGMGR_R_ECOMM;
        char *req_key = NULL;
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
        struct cb_info *cb_info;
+       int i;
 
-       if (pc == NULL || appid == NULL) {
+       if (pc == NULL || appids == NULL || n_apps < 1) {
                ERR("invalid parameter");
                return PKGMGR_R_EINVAL;
        }
 
-       ret = pkgmgr_client_connection_send_request(client,
-                       "enable_global_app_for_uid",
-                       g_variant_new("(us)", uid, appid), &result);
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < n_apps; i++)
+               g_variant_builder_add(builder, "s", appids[i]);
+
+       ret = pkgmgr_client_connection_send_request(client, "enable_apps",
+               g_variant_new("(uas)", uid, builder), &result);
+       g_variant_builder_unref(builder);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
                return ret;
@@ -1068,11 +1558,10 @@ API int pkgmgr_client_activate_global_app_for_uid(pkgmgr_client *pc,
                return ret;
        }
 
-       cb_info = __create_app_event_cb_info(client, app_event_cb, NULL,
-                       req_key);
+       cb_info = __create_app_event_cb_info(client, app_event_cb, data, req_key);
        if (cb_info == NULL) {
                g_variant_unref(result);
-               return PKGMGR_R_ENOMEM;
+               return PKGMGR_R_ERROR;
        }
        g_variant_unref(result);
        ret = pkgmgr_client_connection_set_callback(client, cb_info);
@@ -1082,11 +1571,18 @@ API int pkgmgr_client_activate_global_app_for_uid(pkgmgr_client *pc,
        }
        client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
 
-       return PKGMGR_R_OK;
+       return cb_info->req_id;
 }
 
-API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid,
-               pkgmgr_app_handler app_event_cb, uid_t uid)
+API int pkgmgr_client_activate_apps(pkgmgr_client *pc, const char **appids,
+               int n_apps, pkgmgr_app_handler app_event_cb, void *data)
+{
+       return pkgmgr_client_usr_activate_apps(pc, appids, n_apps,
+                       app_event_cb, data, _getuid());
+}
+
+API int pkgmgr_client_activate_global_app_for_uid(pkgmgr_client *pc,
+               const char *appid, pkgmgr_app_handler app_event_cb, void *data, uid_t uid)
 {
        GVariant *result;
        int ret = PKGMGR_R_ECOMM;
@@ -1099,7 +1595,8 @@ API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid,
                return PKGMGR_R_EINVAL;
        }
 
-       ret = pkgmgr_client_connection_send_request(client, "disable_app",
+       ret = pkgmgr_client_connection_send_request(client,
+                       "enable_global_app_for_uid",
                        g_variant_new("(us)", uid, appid), &result);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
@@ -1116,7 +1613,7 @@ API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid,
                return ret;
        }
 
-       cb_info = __create_app_event_cb_info(client, app_event_cb, NULL,
+       cb_info = __create_app_event_cb_info(client, app_event_cb, data,
                        req_key);
        if (cb_info == NULL) {
                g_variant_unref(result);
@@ -1130,18 +1627,11 @@ API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid,
        }
        client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
 
-       return PKGMGR_R_OK;
-}
-
-API int pkgmgr_client_deactivate_app(pkgmgr_client *pc, const char *appid,
-               pkgmgr_app_handler app_event_cb)
-{
-       return pkgmgr_client_usr_deactivate_app(pc, appid, app_event_cb,
-                       _getuid());
+       return cb_info->req_id;
 }
 
-API int pkgmgr_client_deactivate_global_app_for_uid(pkgmgr_client *pc,
-               const char *appid, pkgmgr_app_handler app_event_cb, uid_t uid)
+API int pkgmgr_client_usr_deactivate_app(pkgmgr_client *pc, const char *appid,
+               pkgmgr_app_handler app_event_cb, void *data, uid_t uid)
 {
        GVariant *result;
        int ret = PKGMGR_R_ECOMM;
@@ -1154,8 +1644,7 @@ API int pkgmgr_client_deactivate_global_app_for_uid(pkgmgr_client *pc,
                return PKGMGR_R_EINVAL;
        }
 
-       ret = pkgmgr_client_connection_send_request(client,
-                       "disable_global_app_for_uid",
+       ret = pkgmgr_client_connection_send_request(client, "disable_app",
                        g_variant_new("(us)", uid, appid), &result);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
@@ -1172,7 +1661,7 @@ API int pkgmgr_client_deactivate_global_app_for_uid(pkgmgr_client *pc,
                return ret;
        }
 
-       cb_info = __create_app_event_cb_info(client, app_event_cb, NULL,
+       cb_info = __create_app_event_cb_info(client, app_event_cb, data,
                        req_key);
        if (cb_info == NULL) {
                g_variant_unref(result);
@@ -1186,48 +1675,209 @@ API int pkgmgr_client_deactivate_global_app_for_uid(pkgmgr_client *pc,
        }
        client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
 
-       return PKGMGR_R_OK;
+       return cb_info->req_id;
 }
 
-API int pkgmgr_client_usr_clear_user_data(pkgmgr_client *pc,
-               const char *pkg_type, const char *appid, pkgmgr_mode mode,
-               uid_t uid)
+API int pkgmgr_client_deactivate_app(pkgmgr_client *pc, const char *appid,
+               pkgmgr_app_handler app_event_cb, void *data)
+{
+       return pkgmgr_client_usr_deactivate_app(pc, appid, app_event_cb, data,
+                       _getuid());
+}
+
+API int pkgmgr_client_usr_deactivate_apps(pkgmgr_client *pc,
+               const char **appids, int n_apps,
+               pkgmgr_app_handler app_event_cb, void *data, uid_t uid)
 {
        GVariant *result;
-       int ret;
+       GVariantBuilder *builder;
+       int ret = PKGMGR_R_ECOMM;
+       char *req_key = NULL;
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+       int i;
 
-       if (pc == NULL || appid == NULL || uid == GLOBAL_USER) {
+       if (pc == NULL || appids == NULL || n_apps < 1) {
                ERR("invalid parameter");
                return PKGMGR_R_EINVAL;
        }
 
        if (client->pc_type != PC_REQUEST) {
-               ERR("client->pc_type is not PC_REQUEST");
+               ERR("client type is not PC_REQUEST");
                return PKGMGR_R_EINVAL;
        }
 
-       ret = pkgmgr_client_connection_send_request(client, "cleardata",
-                       g_variant_new("(us)", uid, appid), &result);
+       builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+       for (i = 0; i < n_apps; i++)
+               g_variant_builder_add(builder, "s", appids[i]);
+
+       ret = pkgmgr_client_connection_send_request(client, "disable_apps",
+               g_variant_new("(uas)", uid, builder), &result);
+       g_variant_builder_unref(builder);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
                return ret;
        }
 
-       g_variant_get(result, "(i)", &ret);
-       g_variant_unref(result);
-
-       return ret;
-}
-
-API int pkgmgr_client_clear_user_data(pkgmgr_client *pc, const char *pkg_type,
-               const char *appid, pkgmgr_mode mode)
-{
-       return pkgmgr_client_usr_clear_user_data(pc, pkg_type, appid, mode,
-                       _getuid());
-}
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
 
-API int pkgmgr_client_set_status_type(pkgmgr_client *pc, int status_type)
+       cb_info = __create_app_event_cb_info(client, app_event_cb, data, req_key);
+       if (cb_info == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ERROR;
+       }
+       g_variant_unref(result);
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_deactivate_apps(pkgmgr_client *pc, const char **appids,
+               int n_apps, pkgmgr_app_handler app_event_cb, void *data)
+{
+       return pkgmgr_client_usr_deactivate_apps(pc, appids, n_apps,
+                       app_event_cb, data, _getuid());
+}
+
+API int pkgmgr_client_deactivate_global_app_for_uid(pkgmgr_client *pc,
+               const char *appid, pkgmgr_app_handler app_event_cb, void *data, uid_t uid)
+{
+       GVariant *result;
+       int ret = PKGMGR_R_ECOMM;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+
+       if (pc == NULL || appid == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "disable_global_app_for_uid",
+                       g_variant_new("(us)", uid, appid), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_app_event_cb_info(client, app_event_cb, data,
+                       req_key);
+       if (cb_info == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ENOMEM;
+       }
+       g_variant_unref(result);
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_usr_clear_user_data(pkgmgr_client *pc,
+               const char *pkg_type, const char *pkgid, pkgmgr_mode mode,
+               uid_t uid)
+{
+       GVariant *result;
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL || pkgid == NULL || uid == GLOBAL_USER) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client, "cleardata",
+                       g_variant_new("(us)", uid, pkgid), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       g_variant_unref(result);
+
+       return ret;
+}
+
+API int pkgmgr_client_clear_user_data(pkgmgr_client *pc, const char *pkg_type,
+               const char *pkgid, pkgmgr_mode mode)
+{
+       return pkgmgr_client_usr_clear_user_data(pc, pkg_type, pkgid, mode,
+                       _getuid());
+}
+
+API int pkgmgr_client_usr_clear_user_data_with_path(pkgmgr_client *pc,
+               const char *pkg_type, const char *pkgid, const char *file_path,
+               pkgmgr_mode mode, uid_t uid)
+{
+       GVariant *result;
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (!pc || !pkgid || !file_path || uid == GLOBAL_USER) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_REQUEST) {
+               ERR("client->pc_type is not PC_REQUEST");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client, "cleardata_with_path",
+                       g_variant_new("(uss)", uid, pkgid, file_path), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       g_variant_unref(result);
+
+       return ret;
+}
+
+API int pkgmgr_client_clear_user_data_with_path(pkgmgr_client *pc, const char *pkg_type,
+               const char *pkgid, const char *file_path, pkgmgr_mode mode)
+{
+       return pkgmgr_client_usr_clear_user_data_with_path(pc, pkg_type, pkgid,
+                       file_path, mode, _getuid());
+}
+
+API int pkgmgr_client_set_status_type(pkgmgr_client *pc, int status_type)
 {
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
 
@@ -1303,6 +1953,68 @@ API int pkgmgr_client_listen_app_status(pkgmgr_client *pc,
        return cb_info->req_id;
 }
 
+API int pkgmgr_client_listen_res_status(pkgmgr_client *pc,
+               pkgmgr_res_handler event_cb, void *data)
+{
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+
+       if (pc == NULL || event_cb == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_LISTENING) {
+               ERR("client->pc_type is not PC_LISTENING");
+               return PKGMGR_R_EINVAL;
+       }
+
+       cb_info = __create_res_event_cb_info(client, event_cb, data, NULL);
+       if (cb_info == NULL)
+               return PKGMGR_R_ENOMEM;
+       cb_info->status_type = client->status_type;
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_listen_pkg_upgrade_status(pkgmgr_client *pc,
+               pkgmgr_pkg_upgrade_handler event_cb, void *data)
+{
+       int ret;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+
+       if (pc == NULL || event_cb == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->pc_type != PC_LISTENING) {
+               ERR("client->pc_type is not PC_LISTENING");
+               return PKGMGR_R_EINVAL;
+       }
+
+       cb_info = __create_upgrade_event_cb_info(client, event_cb, data, NULL);
+       if (cb_info == NULL)
+               return PKGMGR_R_ENOMEM;
+       cb_info->status_type = client->status_type;
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
 API int pkgmgr_client_remove_listen_status(pkgmgr_client *pc)
 {
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
@@ -1364,7 +2076,7 @@ API int pkgmgr_client_usr_request_service(
        case PM_REQUEST_MOVE:
                tryvm_if(pkgid == NULL, ret = PKGMGR_R_EINVAL, "pkgid is NULL\n");
                tryvm_if(pc == NULL, ret = PKGMGR_R_EINVAL, "pc is NULL\n");
-               tryvm_if((service_mode < PM_MOVE_TO_INTERNAL) || (service_mode > PM_MOVE_TO_SDCARD), ret = PKGMGR_R_EINVAL, "service_mode is wrong\n");
+               tryvm_if((service_mode < PM_MOVE_TO_INTERNAL) || (service_mode > PM_MOVE_TO_EXTENDED), ret = PKGMGR_R_EINVAL, "service_mode is wrong\n");
 
                ret = __move_pkg_process(pc, pkgid, pkg_type, uid, (pkgmgr_move_type)service_mode, event_cb, data);
                break;
@@ -1401,32 +2113,6 @@ catch:
        return ret;
 }
 
-
-API int pkgmgr_client_usr_request_size_info(uid_t uid)
-{
-       int ret;
-       struct pkgmgr_client *client;
-
-       client = pkgmgr_client_new(PC_REQUEST);
-       if (client == NULL) {
-               ERR("out of memory");
-               return PKGMGR_R_ENOMEM;
-       }
-
-       ret = __request_size_info(client, uid);
-       if (ret < 0)
-               ERR("__request_size_info fail");
-
-       pkgmgr_client_free(client);
-       return ret;
-}
-
-API int pkgmgr_client_request_size_info(void)
-{
-       /* get all package size (data, total) */
-       return pkgmgr_client_usr_request_size_info(_getuid());
-}
-
 API int pkgmgr_client_usr_clear_cache_dir(const char *pkgid, uid_t uid)
 {
        GVariant *result;
@@ -1448,11 +2134,13 @@ API int pkgmgr_client_usr_clear_cache_dir(const char *pkgid, uid_t uid)
                        g_variant_new("(us)", uid, pkgid), &result);
        if (ret != PKGMGR_R_OK) {
                ERR("request failed: %d", ret);
+               pkgmgr_client_free(client);
                return ret;
        }
 
        g_variant_get(result, "(i)", &ret);
        g_variant_unref(result);
+       pkgmgr_client_free(client);
 
        return ret;
 }
@@ -2078,6 +2766,7 @@ API int pkgmgr_client_free_pkginfo(pkgmgr_info *info)
                return PKGMGR_R_EINVAL;
        }
 
+       g_list_free_full(pkg_info->privilege_list, free);
        free(pkg_info->icon_buf);
        free(pkg_info);
 
@@ -2115,6 +2804,42 @@ API int pkgmgr_client_set_app_label(pkgmgr_client *pc, char *appid, char *label)
        return pkgmgr_client_usr_set_app_label(pc, appid, label, _getuid());
 }
 
+API int pkgmgr_client_usr_set_app_icon(pkgmgr_client *pc, char *appid,
+               char *icon_path, uid_t uid)
+{
+       GVariant *result;
+       int ret = -1;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL || appid == NULL || icon_path == NULL) {
+               ERR("Invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (access(icon_path, F_OK) != 0) {
+               ERR("failed to access: %s", icon_path);
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "set_app_icon",
+                       g_variant_new("(uss)", uid, appid, icon_path), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("Request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       g_variant_unref(result);
+
+       return ret;
+}
+
+API int pkgmgr_client_set_app_icon(pkgmgr_client *pc, char *appid, char *icon_path)
+{
+       return pkgmgr_client_usr_set_app_icon(pc, appid, icon_path, _getuid());
+}
+
 API int pkgmgr_client_set_debug_mode(pkgmgr_client *pc, bool debug_mode)
 {
        struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
@@ -2128,3 +2853,410 @@ API int pkgmgr_client_set_debug_mode(pkgmgr_client *pc, bool debug_mode)
 
        return PKGMGR_R_OK;
 }
+
+API int pkgmgr_client_set_skip_optimization(pkgmgr_client *pc, bool skip_optimization)
+{
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       client->skip_optimization = skip_optimization;
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_usr_migrate_external_image(pkgmgr_client *pc,
+               const char *pkgid, uid_t uid)
+{
+       GVariant *result;
+       int ret = PKGMGR_R_ECOMM;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "migrate_external_image",
+                       g_variant_new("(us)", uid, pkgid), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       g_variant_unref(result);
+
+       return ret;
+}
+
+API int pkgmgr_client_add_res_copy_path(pkgmgr_client *pc,
+               const char *src_path, const char *dest_path)
+{
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL || src_path == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->res_copy_builder == NULL) {
+               client->res_copy_builder =
+                               g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
+               if (client->res_copy_builder == NULL) {
+                       ERR("out of memory");
+                       return PKGMGR_R_ENOMEM;
+               }
+       }
+
+       g_variant_builder_add(client->res_copy_builder, "(ss)",
+                       src_path, dest_path ? dest_path : "");
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_res_copy(pkgmgr_client *pc,
+               pkgmgr_res_handler event_cb, void *user_data)
+{
+       GVariant *result;
+       int ret;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+
+       if (pc == NULL || event_cb == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "res_copy",
+                       g_variant_new("(a(ss))",
+                       client->res_copy_builder), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_res_event_cb_info(client,
+                       event_cb, user_data, req_key);
+       g_variant_unref(result);
+       if (cb_info == NULL)
+               return PKGMGR_R_ENOMEM;
+
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_add_res_create_dir_path(pkgmgr_client *pc,
+               const char *dir_path)
+{
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL || dir_path == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->res_create_dir_builder == NULL) {
+               client->res_create_dir_builder =
+                               g_variant_builder_new(G_VARIANT_TYPE("as"));
+               if (client->res_create_dir_builder == NULL) {
+                       ERR("out of memory");
+                       return PKGMGR_R_ENOMEM;
+               }
+       }
+
+       g_variant_builder_add(client->res_create_dir_builder, "s", dir_path);
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_res_create_dir(pkgmgr_client *pc,
+               pkgmgr_res_handler event_cb, void *user_data)
+{
+       GVariant *result;
+       int ret;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+
+       if (pc == NULL || event_cb == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "res_create_dir",
+                       g_variant_new("(as)",
+                       client->res_create_dir_builder), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_res_event_cb_info(client,
+                       event_cb, user_data, req_key);
+       g_variant_unref(result);
+       if (cb_info == NULL)
+               return PKGMGR_R_ENOMEM;
+
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_add_res_remove_path(pkgmgr_client *pc,
+               const char *res_path)
+{
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL || res_path == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (client->res_remove_builder == NULL) {
+               client->res_remove_builder =
+                               g_variant_builder_new(G_VARIANT_TYPE("as"));
+               if (client->res_remove_builder == NULL) {
+                       ERR("out of memory");
+                       return PKGMGR_R_ENOMEM;
+               }
+       }
+
+       g_variant_builder_add(client->res_remove_builder, "s", res_path);
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_client_res_remove(pkgmgr_client *pc,
+               pkgmgr_res_handler event_cb, void *user_data)
+{
+       GVariant *result;
+       int ret;
+       char *req_key = NULL;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+       struct cb_info *cb_info;
+
+       if (pc == NULL || event_cb == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "res_remove",
+                       g_variant_new("(as)",
+                       client->res_remove_builder), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i&s)", &ret, &req_key);
+       if (req_key == NULL) {
+               g_variant_unref(result);
+               return PKGMGR_R_ECOMM;
+       }
+       if (ret != PKGMGR_R_OK) {
+               g_variant_unref(result);
+               return ret;
+       }
+
+       cb_info = __create_res_event_cb_info(client,
+                       event_cb, user_data, req_key);
+       g_variant_unref(result);
+       if (cb_info == NULL)
+               return PKGMGR_R_ENOMEM;
+
+       ret = pkgmgr_client_connection_set_callback(client, cb_info);
+       if (ret != PKGMGR_R_OK) {
+               __free_cb_info(cb_info);
+               return ret;
+       }
+       client->cb_info_list = g_list_append(client->cb_info_list, cb_info);
+
+       return cb_info->req_id;
+}
+
+API int pkgmgr_client_res_uninstall(pkgmgr_client *pc, const char *pkgid)
+{
+       return pkgmgr_client_res_usr_uninstall(pc, pkgid, _getuid());
+}
+
+API int pkgmgr_client_res_usr_uninstall(pkgmgr_client *pc, const char *pkgid,
+               uid_t uid)
+{
+       GVariant *result;
+       int ret = PKGMGR_R_ECOMM;
+       struct pkgmgr_client_t *client = (struct pkgmgr_client_t *)pc;
+
+       if (pc == NULL || pkgid == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       ret = pkgmgr_client_connection_send_request(client,
+                       "res_uninstall",
+                       g_variant_new("(us)", uid, pkgid), &result);
+       if (ret != PKGMGR_R_OK) {
+               ERR("request failed: %d", ret);
+               return ret;
+       }
+
+       g_variant_get(result, "(i)", &ret);
+       g_variant_unref(result);
+
+       return ret;
+}
+
+API pkgmgr_res_event_info *pkgmgr_res_event_info_new()
+{
+       pkgmgr_res_event_info_t *info;
+
+       info = calloc(1, sizeof(pkgmgr_res_event_info_t));
+       if (info == NULL) {
+               ERR("out of memory");
+               return NULL;
+       }
+
+       return (pkgmgr_res_event_info *)info;
+}
+
+static void __free_path_states(gpointer data)
+{
+       res_event_path_state_t *path_state = (res_event_path_state_t *)data;
+
+       if (path_state == NULL)
+               return;
+       if (path_state->path)
+               free(path_state->path);
+       free(path_state);
+}
+
+API int pkgmgr_res_event_info_free(pkgmgr_res_event_info *info)
+{
+       pkgmgr_res_event_info_t *event_info =
+                       (pkgmgr_res_event_info_t *)info;
+
+       if (event_info == NULL) {
+               ERR("invalid argument");
+               return PKGMGR_R_EINVAL;
+       }
+
+       if (event_info->path_states)
+               g_list_free_full(event_info->path_states, __free_path_states);
+       free(event_info);
+
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_set_error_code(pkgmgr_res_event_info *handle, int error_code)
+{
+       pkgmgr_res_event_info_t *info = handle;
+       if (info == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       info->error_code = error_code;
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_get_error_code(pkgmgr_res_event_info *handle, int *error_code)
+{
+       pkgmgr_res_event_info_t *info = handle;
+       if (info == NULL || error_code == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       *error_code = info->error_code;
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_add_path_state(pkgmgr_res_event_info *handle,
+               const char *path, pkgmgr_res_event_path_state state)
+{
+       pkgmgr_res_event_info_t *info = handle;
+       res_event_path_state_t *path_state;
+
+       if (info == NULL || path == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       path_state = calloc(1, sizeof(res_event_path_state_t));
+       if (path_state == NULL) {
+               ERR("out of memory");
+               return PKGMGR_R_ENOMEM;
+       }
+
+       path_state->path = strdup(path);
+       if (path_state->path == NULL) {
+               ERR("out of memory");
+               free(path_state);
+               return PKGMGR_R_ENOMEM;
+       }
+       path_state->state = state;
+
+       info->path_states = g_list_prepend(info->path_states , path_state);
+       return PKGMGR_R_OK;
+}
+
+API int pkgmgr_res_event_info_foreach_path(pkgmgr_res_event_info *handle,
+               pkgmgr_res_event_path_cb callback, void *user_data)
+{
+       pkgmgr_res_event_info_t *info = handle;
+       GList *list;
+       res_event_path_state_t *path_state;
+
+       if (info == NULL) {
+               ERR("invalid parameter");
+               return PKGMGR_R_EINVAL;
+       }
+
+       for (list = info->path_states; list != NULL; list = list->next) {
+               path_state = (res_event_path_state_t *)list->data;
+               if (callback(path_state->path, path_state->state,
+                               user_data) < 0)
+                       return PKGMGR_R_OK;
+       }
+
+       return PKGMGR_R_OK;
+}