4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7 * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
26 * comm_client library using gdbus
38 #include "comm_config.h"
39 #include "comm_client.h"
40 #include "comm_debug.h"
42 #define COMM_CLIENT_RETRY_MAX 5
43 #define COMM_CLIENT_WAIT_USEC (1000000 / 2) /* 0.5 sec */
49 /* Storing status_cb */
50 struct signal_callback_data {
58 guint subscription_id;
59 GDBusConnection *conn;
60 struct signal_callback_data *sig_cb_data;
63 static int __get_signal_type(const char *name)
68 if (strcmp(name, COMM_STATUS_BROADCAST_SIGNAL_STATUS) == 0)
69 return COMM_STATUS_BROADCAST_ALL;
70 else if (strcmp(name, COMM_STATUS_BROADCAST_EVENT_INSTALL) == 0)
71 return COMM_STATUS_BROADCAST_INSTALL;
72 else if (strcmp(name, COMM_STATUS_BROADCAST_EVENT_UNINSTALL) == 0)
73 return COMM_STATUS_BROADCAST_UNINSTALL;
74 else if (strcmp(name, COMM_STATUS_BROADCAST_EVENT_MOVE) == 0)
75 return COMM_STATUS_BROADCAST_MOVE;
76 else if (strcmp(name, COMM_STATUS_BROADCAST_EVENT_INSTALL_PROGRESS) == 0)
77 return COMM_STATUS_BROADCAST_INSTALL_PROGRESS;
78 else if (strcmp(name, COMM_STATUS_BROADCAST_EVENT_UPGRADE) == 0)
79 return COMM_STATUS_BROADCAST_UPGRADE;
80 else if (strcmp(name, COMM_STATUS_BROADCAST_EVENT_GET_SIZE) == 0)
81 return COMM_STATUS_BROADCAST_GET_SIZE;
87 * signal handler filter
88 * Filter signal, and run user callback
90 void _on_signal_handle_filter(GDBusConnection *conn,
91 const gchar *sender_name,
92 const gchar *object_path,
93 const gchar *interface_name,
94 const gchar *signal_name,
98 if (interface_name && strcmp(interface_name, "org.tizen.pkgmgr.signal")) {
99 DBG("Interface name did not match. Drop the message");
104 /* Values to be received by signal */
107 char *pkg_type = NULL;
112 /* User's signal handler */
113 struct signal_callback_data *sig_cb_data;
115 sig_cb_data = (struct signal_callback_data *)user_data;
119 status_type = __get_signal_type(signal_name);
120 if (status_type < 0 || !(status_type & sig_cb_data->type))
123 g_variant_get(parameters, "(u&s&s&s&s&s)",
124 &target_uid, &req_id, &pkg_type, &pkgid, &key, &val);
126 /* Run signal callback if exist */
127 if (sig_cb_data && sig_cb_data->cb)
128 sig_cb_data->cb(sig_cb_data->cb_data, target_uid, req_id,
129 pkg_type, pkgid, key, val);
135 * signal_callback_data free function
138 void _free_sig_cb_data(void *data)
140 struct signal_callback_data *sig_cb_data = NULL;
141 sig_cb_data = (struct signal_callback_data *)data;
150 * Create a new comm_client object
152 comm_client *comm_client_new(void)
154 GError *error = NULL;
155 comm_client *cc = NULL;
157 /* Allocate memory for ADT:comm_client */
158 #if !GLIB_CHECK_VERSION(2,35,0)
161 cc = calloc(1, sizeof(comm_client));
167 /* Connect to gdbus. Gets shared BUS */
168 cc->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
170 ERR("gdbus connection error (%s)", error->message);
174 if (NULL == cc->conn) {
175 ERR("gdbus connection is not set, even gdbus error isn't raised");
187 * Free comm_client object
189 int comm_client_free(comm_client *cc)
193 if (!(cc->conn) || g_dbus_connection_is_closed(cc->conn)) {
194 ERR("Invalid gdbus connection");
198 if (cc->sig_cb_data) {
199 g_dbus_connection_signal_unsubscribe(cc->conn, cc->subscription_id);
200 /* TODO: Is it needed to free cc->sig_cb_data here? */
201 /* _free_sig_cb_data(cc->sig_cb_data); */
205 /* flush remaining buffer: blocking mode */
206 g_dbus_connection_flush_sync(cc->conn, NULL, NULL);
208 /* Free signal filter if signal callback is exist */
210 /* just unref because it is shared BUS.
211 If ref count is 0 it will get free'd automatically
213 g_object_unref(cc->conn);
223 comm_client_request(comm_client *cc, const char *req_id, const int req_type,
224 const char *pkg_type, const char *pkgid, const char *args,
225 uid_t uid, int is_block)
227 GError *error = NULL;
230 GVariant *result = NULL;
233 /* Assign default values if NULL (NULL is not allowed) */
235 req_id = "tmp_reqid";
236 if (pkg_type == NULL)
244 proxy = g_dbus_proxy_new_sync(cc->conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
245 COMM_PKGMGR_DBUS_SERVICE, COMM_PKGMGR_DBUS_OBJECT_PATH,
246 COMM_PKGMGR_DBUS_INTERFACE, NULL, &error);
248 ERR("failed to get proxy object, sleep and retry[%s]", error->message);
251 usleep(COMM_CLIENT_WAIT_USEC);
256 result = g_dbus_proxy_call_sync(proxy, "Request", g_variant_new("(sisssi)", req_id, req_type, pkg_type, pkgid, args, uid),
257 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
258 g_object_unref(proxy);
262 ERR("failed to send request, sleep and retry[%s]", error->message);
265 usleep(COMM_CLIENT_WAIT_USEC);
267 } while (retry_cnt <= COMM_CLIENT_RETRY_MAX);
272 g_variant_get(result, "(i)", &rc);
273 g_variant_unref(result);
275 return rc == 0 ? COMM_RET_OK : COMM_RET_ERROR;
279 * Set a callback for status signal
282 comm_client_set_status_callback(int comm_status_type, comm_client *cc, status_cb cb, void *cb_data)
284 int r = COMM_RET_ERROR;
287 return COMM_RET_ERROR;
289 /* Create new sig_cb_data */
290 cc->sig_cb_data = calloc(1, sizeof(struct signal_callback_data));
291 if ( cc->sig_cb_data ) {
292 (cc->sig_cb_data)->type = comm_status_type;
293 (cc->sig_cb_data)->cb = cb;
294 (cc->sig_cb_data)->cb_data = cb_data;
299 /* Add a filter for signal */
300 cc->subscription_id = g_dbus_connection_signal_subscribe(cc->conn, NULL, "org.tizen.pkgmgr.signal",
301 NULL, NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
302 _on_signal_handle_filter, (gpointer)cc->sig_cb_data, _free_sig_cb_data);
303 if (!cc->subscription_id) {
304 ERR("Failed to add filter\n");
312 ERR("General error");