{NULL, -1}
};
-static int __get_signal_type(const char *name)
-{
- int i;
-
- if (name == NULL)
- return -1;
-
- for (i = 0; map[i].signal_str != NULL; i++) {
- if (strcmp(map[i].signal_str, name) == 0)
- return map[i].signal_type;
- }
-
- return -1;
-}
-
static void __handle_size_info_callback(struct cb_info *cb_info,
const char *pkgid, const char *val)
{
}
}
+static void __convert_signal(char *event_type, char *event_status,
+ char *appid, int progress, char **key, char **val)
+{
+ *key = event_status;
+ if (strcmp(event_status, PKGMGR_INSTALLER_START_KEY_STR) == 0) {
+ *val = event_type;
+ } else if (strcmp(event_status, PKGMGR_INSTALLER_OK_EVENT_STR) == 0 ||
+ strcmp(event_status, PKGMGR_INSTALLER_FAIL_EVENT_STR) == 0) {
+ *key = PKGMGR_INSTALLER_END_KEY_STR;
+ *val = event_status;
+ } else if (strcmp(event_status, PKGMGR_INSTALLER_APPID_KEY_STR) == 0) {
+ if (!appid) {
+ ERR("appid is empty");
+ return;
+ }
+ *val = appid;
+ } else if (strcmp(event_type, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0) {
+ *key = event_type;
+ *val = event_status;
+ }
+ // TODO: should handle cleardata / clearacache signal
+}
+
static void __signal_handler(GDBusConnection *conn, const gchar *sender_name,
const gchar *object_path, const gchar *interface_name,
const gchar *signal_name, GVariant *parameters,
gpointer user_data)
{
+ int progress = 0;
uid_t target_uid;
+ char buf[BUFMAX];
char *req_id;
char *pkg_type = NULL;
+ char *appid = NULL;
char *pkgid = NULL;
+ char *event_type = NULL;
+ char *event_status = NULL;
char *key = NULL;
char *val = NULL;
- char *appid = NULL;
- int signal_type;
struct cb_info *cb_info = (struct cb_info *)user_data;
+ GVariantIter *iter = NULL;
+
+ g_variant_get(parameters, "(u&sa(sss)&s&si)", &target_uid, &req_id, &iter,
+ &event_type, &event_status, &progress);
+ while (g_variant_iter_loop(iter, "(&s&s&s)", &pkgid, &appid, &pkg_type)) {
+ if (cb_info->req_key) {
+ if (strcmp(cb_info->req_key, req_id) != 0)
+ continue;
+ }
- g_variant_get(parameters, "(u&s&s&s&s&s&s)",
- &target_uid, &req_id, &pkg_type,
- &pkgid, &appid, &key, &val);
-
- /* in case of request, check reqkey */
- if (cb_info->req_key) {
- if (strcmp(cb_info->req_key, req_id) != 0)
- return;
- } else {
- signal_type = __get_signal_type(signal_name);
- if (signal_type < 0 || !(cb_info->status_type & signal_type))
- return;
+ /* convert event_type and event_status into key-val pair */
+ __convert_signal(event_type, event_status, appid,
+ progress, &key, &val);
+ if (strcmp(event_status,
+ PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0 ||
+ strcmp(event_status, PKGMGR_INSTALLER_ERROR_KEY_STR) == 0) {
+ snprintf(buf, BUFMAX - 1, "%d", progress);
+ val = buf;
+ }
+ /* TODO: progress should be set properly when installation has
+ * completed or failed */
+
+ if (cb_info->event_cb) {
+ cb_info->event_cb(target_uid, cb_info->req_id,
+ pkg_type, pkgid, key, val, NULL, cb_info->data);
+ } else if (cb_info->app_event_cb && strcmp(appid, "") != 0) {
+ cb_info->app_event_cb(target_uid, cb_info->req_id,
+ pkg_type, pkgid, appid, key, val, NULL,
+ cb_info->data);
+ } else if (cb_info->size_info_cb)
+ __handle_size_info_callback(cb_info, pkgid, val);
+
+ /* TODO: unsubscribe request callback */
}
-
- /* each cb_data can only has one callback */
- if (cb_info->event_cb && strcmp(appid, "") == 0)
- cb_info->event_cb(target_uid, cb_info->req_id,
- pkg_type, pkgid, key, val, NULL, cb_info->data);
- else if (cb_info->app_event_cb && strcmp(appid, "") != 0)
- cb_info->app_event_cb(target_uid, cb_info->req_id,
- pkg_type, pkgid, appid, key, val, NULL,
- cb_info->data);
- else if (cb_info->size_info_cb)
- __handle_size_info_callback(cb_info, pkgid, val);
-
- /* TODO: unsubscribe request callback */
}
int pkgmgr_client_connection_set_callback(struct pkgmgr_client_t *pc,
int skip_check_reference;
int skip_optimization;
GDBusConnection *conn;
+ GHashTable *pkg_list;
};
+typedef struct pkg_signal_info {
+ char *pkgid;
+ char *pkg_type;
+} pkg_signal_info;
+
static uid_t g_target_uid;
static int g_debug_mode;
static int g_skip_optimization;
static pkgmgr_privilege_level g_privilege_level = PM_PRIVILEGE_UNKNOWN;
-static const char *__get_signal_name(pkgmgr_installer *pi, const char *key,
- const char *pkg_type)
+static const char *__get_event_type(pkgmgr_installer *pi)
{
- if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0)
- return key;
- else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
- return key;
- else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
- return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
- else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0)
- return pkg_type;
-
switch (pi->request_type) {
case PKGMGR_REQ_INSTALL:
case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
return NULL;
}
+static const char *__get_signal_name(pkgmgr_installer *pi, const char *key,
+ const char *pkg_type)
+{
+ if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0)
+ return key;
+ else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
+ return key;
+ else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
+ return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
+ else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0)
+ return pkg_type;
+
+ return __get_event_type(pi);
+}
+
static int __send_signal_for_event(pkgmgr_installer *pi, const char *pkg_type,
const char *pkgid, const char *appid, const char *key,
const char *val)
{
+ int progress = 0;
char *sid;
- const char *name;
+ const char *tmp_appid = appid;
+ const char *event_type;
+ const char *event_status;
+ const char *signal_name;
+ GVariantBuilder *builder;
GError *err = NULL;
if (!pi || pi->conn == NULL)
if (!sid)
sid = "";
- name = __get_signal_name(pi, key, pkg_type);
- if (name == NULL) {
- ERR("unknown signal type");
+ signal_name = __get_signal_name(pi, key, val);
+ if (!signal_name) {
+ ERR("unknown signal name");
return -1;
}
+ event_type = __get_event_type(pi);
+ if (!event_type) {
+ ERR("unknown event type");
+ return -1;
+ }
+
+ if (strcmp(key, PKGMGR_INSTALLER_END_KEY_STR) == 0 ||
+ strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
+ event_status = val;
+ else
+ event_status = key;
+
+ if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0 ||
+ strcmp(key, PKGMGR_INSTALLER_ERROR_KEY_STR) == 0)
+ progress = atoi(val);
+ else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
+ tmp_appid = val;
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
+ g_variant_builder_add(builder, "(sss)", pkgid,
+ (tmp_appid ? tmp_appid : ""), pkg_type);
if (g_dbus_connection_emit_signal(pi->conn, NULL,
PKGMGR_INSTALLER_DBUS_OBJECT_PATH,
- PKGMGR_INSTALLER_DBUS_INTERFACE, name,
- g_variant_new("(ussssss)", pi->target_uid, sid,
- pkg_type, pkgid, appid ? appid : "",
- key, val), &err)
- != TRUE) {
- ERR("failed to send dbus signal: %s", err->message);
- g_error_free(err);
+ PKGMGR_INSTALLER_DBUS_INTERFACE, signal_name,
+ g_variant_new("(usa(sss)ssi)", pi->target_uid, sid,
+ builder, event_type, event_status, progress),
+ &err) != TRUE) {
+ ERR("failed to send dbus signal");
+ if (err) {
+ ERR("err: %s", err->message);
+ g_error_free(err);
+ }
return -1;
}
-
return 0;
}
const char *pkg_type, const char *pkgid, const char *appid,
const char *key, const char *val)
{
+ int progress = 0;
char *sid;
- const char *name;
+ const char *signal_name;
+ const char *tmp_appid = appid;
+ const char *event_type;
+ const char *event_status;
size_t name_size;
+ GVariantBuilder *builder;
GVariant *gv;
gsize gv_len;
gpointer gv_data;
data_len = sizeof(size_t) + sizeof(gsize);
- name = __get_signal_name(pi, key, pkg_type);
- if (name == NULL) {
- ERR("unknown signal type");
+ signal_name = __get_signal_name(pi, key, pkg_type);
+ if (!signal_name) {
+ ERR("unknown signal name");
+ return -1;
+ }
+
+ event_type = __get_event_type(pi);
+ if (!event_type) {
+ ERR("unknown event type");
return -1;
}
+
+ if (strcmp(key, PKGMGR_INSTALLER_END_KEY_STR) == 0 ||
+ strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
+ event_status = val;
+ else
+ event_status = key;
+
+ if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0 ||
+ strcmp(key, PKGMGR_INSTALLER_ERROR_KEY_STR) == 0)
+ progress = atoi(val);
+ else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
+ tmp_appid = val;
+
+
/* including null byte */
- name_size = strlen(name) + 1;
+ name_size = strlen(signal_name) + 1;
data_len += name_size;
- gv = g_variant_new("(ussssss)", pi->target_uid, sid,
- pkg_type, pkgid, appid ? appid : "", key, val);
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
+ g_variant_builder_add(builder, "(sss)", pkgid,
+ (tmp_appid ? tmp_appid : ""), pkg_type);
+ gv = g_variant_new("(usa(sss)ssi)", pi->target_uid, sid,
+ builder, event_type, event_status, progress);
if (gv == NULL) {
ERR("failed to create GVariant instance");
return -1;
ptr += sizeof(size_t);
memcpy(ptr, &gv_len, sizeof(gsize));
ptr += sizeof(gsize);
- memcpy(ptr, name, name_size);
+ memcpy(ptr, signal_name, name_size);
ptr += name_size;
memcpy(ptr, gv_data, gv_len);
g_free(gv_data);
return 0;
}
+static void __free_pkg_list(gpointer data)
+{
+ pkg_signal_info *info = (pkg_signal_info *)data;
+ free(info->pkgid);
+ free(info->pkg_type);
+ free(info);
+}
+
API pkgmgr_installer *pkgmgr_installer_new(void)
{
pkgmgr_installer *pi;
pi->tep_path = NULL;
pi->tep_move = 0;
pi->request_type = PKGMGR_REQ_INVALID;
-
+ pi->pkg_list = g_hash_table_new_full(
+ g_str_hash, g_str_equal, NULL, __free_pkg_list);
return pi;
}
g_object_unref(pi->conn);
}
+ if (pi->pkg_list)
+ g_hash_table_destroy(pi->pkg_list);
+
free(pi);
return 0;
return PKGMGR_INSTALLER_ERRCODE_UNDEFINED_ERROR_STR;
}
}
+
+API int pkgmgr_installer_add_pkg(pkgmgr_installer *pi,
+ const char *pkgid, const char *pkg_type)
+{
+ pkg_signal_info *info;
+ if (!pi || !pkgid || !pkg_type) {
+ ERR("invalid argument");
+ return -1;
+ }
+
+ info = calloc(1, sizeof(pkg_signal_info));
+ if (!info) {
+ ERR("out of memory");
+ return -1;
+ }
+
+ info->pkgid = strdup(pkgid);
+ info->pkg_type = strdup(pkg_type);
+ if (!info->pkgid || info->pkg_type) {
+ ERR("out of memory");
+ free(info->pkgid);
+ free(info->pkg_type);
+ free(info);
+ return -1;
+ }
+ g_hash_table_insert(pi->pkg_list, (gpointer)pkgid, (gpointer)info);
+
+ return 0;
+}
+
+static void __build_multi_signal(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ GVariantBuilder *builder = (GVariantBuilder *)user_data;
+ char *pkgid = (char *)key;
+ pkg_signal_info *info = (pkg_signal_info *)value;
+
+ g_variant_builder_add(builder, "(sss)", pkgid, "", info->pkg_type);
+}
+
+API int pkgmgr_installer_send_signals(pkgmgr_installer *pi,
+ const char *event_type, const char *event_status, int progress)
+{
+ char *sid;
+ GError *err = NULL;
+ GVariantBuilder *builder;
+
+ if (!pi || !event_type || !event_status) {
+ ERR("invalid argument");
+ return -1;
+ }
+
+ sid = pi->session_id;
+ if (!sid)
+ sid = "";
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
+ g_hash_table_foreach(pi->pkg_list, __build_multi_signal, builder);
+ if (g_dbus_connection_emit_signal(pi->conn, NULL,
+ PKGMGR_INSTALLER_DBUS_OBJECT_PATH,
+ PKGMGR_INSTALLER_DBUS_INTERFACE, event_type,
+ g_variant_new("(usa(sss)ssi)",
+ pi->target_uid, sid, builder, event_type,
+ event_status, progress), &err) != TRUE) {
+ ERR("failed to send dbus signal");
+ if (err) {
+ ERR("err: %s", err->message);
+ g_error_free(err);
+ }
+ g_variant_builder_unref(builder);
+ return -1;
+ }
+ g_variant_builder_unref(builder);
+
+ return 0;
+}
\ No newline at end of file