2 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <sys/types.h>
26 #include "package-manager.h"
27 #include "pkgmgr_client_debug.h"
28 #include "pkgmgr_client_internal.h"
29 #include "../../installer/pkgmgr_installer.h"
30 #include "../../installer/pkgmgr_installer_config.h"
32 #define CONNECTION_RETRY_MAX 5
33 #define CONNECTION_WAIT_USEC (1000000 / 2) /* 0.5 sec */
34 #define REGULAR_USER 5000
36 static int _is_system_user(void)
40 if (uid < REGULAR_USER)
46 static GBusType __get_bus_type(pkgmgr_client_type type)
48 if (type == PC_REQUEST || _is_system_user())
49 return G_BUS_TYPE_SYSTEM;
51 return G_BUS_TYPE_SESSION;
54 int pkgmgr_client_connection_connect(struct pkgmgr_client_t *pc)
59 #if !GLIB_CHECK_VERSION(2, 35, 0)
62 bus_type = __get_bus_type(pc->pc_type);
63 pc->conn = g_bus_get_sync(bus_type, NULL, &error);
65 ERR("gdbus connection error (%s)", error->message);
67 return PKGMGR_R_ECOMM;
73 void pkgmgr_client_connection_disconnect(struct pkgmgr_client_t *pc)
75 /* flush remaining buffer: blocking mode */
76 g_dbus_connection_flush_sync(pc->conn, NULL, NULL);
77 g_object_unref(pc->conn);
82 const char *signal_str;
86 struct signal_map map[] = {
87 {PKGMGR_INSTALLER_INSTALL_EVENT_STR, PKGMGR_CLIENT_STATUS_INSTALL},
88 {PKGMGR_INSTALLER_UNINSTALL_EVENT_STR, PKGMGR_CLIENT_STATUS_UNINSTALL},
89 {PKGMGR_INSTALLER_UPGRADE_EVENT_STR, PKGMGR_CLIENT_STATUS_UPGRADE},
90 {PKGMGR_INSTALLER_CLEAR_EVENT_STR, PKGMGR_CLIENT_STATUS_CLEAR_DATA},
91 {PKGMGR_INSTALLER_MOVE_EVENT_STR, PKGMGR_CLIENT_STATUS_MOVE},
92 {PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR,
93 PKGMGR_CLIENT_STATUS_INSTALL_PROGRESS},
94 {PKGMGR_INSTALLER_GET_SIZE_KEY_STR, PKGMGR_CLIENT_STATUS_GET_SIZE},
95 {PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR,
96 PKGMGR_CLIENT_STATUS_CLEAR_CACHE},
97 {PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
98 PKGMGR_CLIENT_STATUS_ENABLE_APP},
99 {PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
100 PKGMGR_CLIENT_STATUS_DISABLE_APP},
101 {PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR,
102 PKGMGR_CLIENT_STATUS_ENABLE_APP_SPLASH_SCREEN},
103 {PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR,
104 PKGMGR_CLIENT_STATUS_DISABLE_APP_SPLASH_SCREEN},
108 static int __get_signal_type(const char *name)
115 for (i = 0; map[i].signal_str != NULL; i++) {
116 if (strcmp(map[i].signal_str, name) == 0)
117 return map[i].signal_type;
123 static void __handle_size_info_callback(struct cb_info *cb_info,
124 const char *pkgid, const char *val)
126 pkg_size_info_t size_info;
130 pkgmgr_total_pkg_size_info_receive_cb callback;
132 snprintf(buf, sizeof(buf), "%s", val);
134 DBG("%s, %s", pkgid, val);
136 token = strtok_r(buf, ":", &saveptr);
138 ERR("failed to parse size info");
141 size_info.data_size = atoll(token);
142 token = strtok_r(NULL, ":", &saveptr);
144 ERR("failed to parse size info");
147 size_info.cache_size = atoll(token);
148 token = strtok_r(NULL, ":", &saveptr);
150 ERR("failed to parse size info");
153 size_info.app_size = atoll(token);
154 token = strtok_r(NULL, ":", &saveptr);
156 ERR("failed to parse size info");
159 size_info.ext_data_size = atoll(token);
160 token = strtok_r(NULL, ":", &saveptr);
162 ERR("failed to parse size info");
165 size_info.ext_cache_size = atoll(token);
166 token = strtok_r(NULL, ":", &saveptr);
168 ERR("failed to parse size info");
171 size_info.ext_app_size = atoll(token);
173 DBG("data: %lld, cache: %lld, app: %lld, ext_data: %lld, "
174 "ext_cache: %lld, ext_app: %lld",
175 size_info.data_size, size_info.cache_size,
176 size_info.app_size, size_info.ext_data_size,
177 size_info.ext_cache_size, size_info.ext_app_size);
179 if (strcmp(pkgid, PKG_SIZE_INFO_TOTAL) == 0) {
180 callback = (pkgmgr_total_pkg_size_info_receive_cb)
181 cb_info->size_info_cb;
182 callback(cb_info->client, &size_info, cb_info->data);
184 cb_info->size_info_cb(cb_info->client, pkgid, &size_info,
189 static void __signal_handler(GDBusConnection *conn, const gchar *sender_name,
190 const gchar *object_path, const gchar *interface_name,
191 const gchar *signal_name, GVariant *parameters,
196 char *pkg_type = NULL;
202 struct cb_info *cb_info = (struct cb_info *)user_data;
204 g_variant_get(parameters, "(u&s&s&s&s&s&s)",
205 &target_uid, &req_id, &pkg_type,
206 &pkgid, &appid, &key, &val);
208 /* in case of request, check reqkey */
209 if (cb_info->req_key) {
210 if (strcmp(cb_info->req_key, req_id) != 0)
213 signal_type = __get_signal_type(signal_name);
214 if (signal_type < 0 || !(cb_info->status_type & signal_type))
218 /* each cb_data can only has one callback */
219 if (cb_info->event_cb && strcmp(appid, "") == 0)
220 cb_info->event_cb(target_uid, cb_info->req_id,
221 pkg_type, pkgid, key, val, NULL, cb_info->data);
222 else if (cb_info->app_event_cb && strcmp(appid, "") != 0)
223 cb_info->app_event_cb(target_uid, cb_info->req_id,
224 pkg_type, pkgid, appid, key, val, NULL,
226 else if (cb_info->size_info_cb)
227 __handle_size_info_callback(cb_info, pkgid, val);
229 /* TODO: unsubscribe request callback */
232 int pkgmgr_client_connection_set_callback(struct pkgmgr_client_t *pc,
233 struct cb_info *cb_info)
235 cb_info->sid = g_dbus_connection_signal_subscribe(pc->conn, NULL,
236 PKGMGR_INSTALLER_DBUS_INTERFACE, NULL,
237 PKGMGR_INSTALLER_DBUS_OBJECT_PATH, NULL,
238 G_DBUS_SIGNAL_FLAGS_NONE, __signal_handler,
239 (gpointer)cb_info, NULL);
241 ERR("failed to subscribe singal");
242 return PKGMGR_R_ERROR;
248 void pkgmgr_client_connection_unset_callback(struct pkgmgr_client_t *pc,
249 struct cb_info *cb_info)
251 g_dbus_connection_signal_unsubscribe(pc->conn, cb_info->sid);
254 int pkgmgr_client_connection_send_request(struct pkgmgr_client_t *pc,
255 const char *method, GVariant *params, GVariant **result)
257 GError *error = NULL;
261 int ret = PKGMGR_R_ECOMM;
263 /* convert floating ref into normal ref */
264 g_variant_ref_sink(params);
267 proxy = g_dbus_proxy_new_sync(pc->conn,
268 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
269 NULL, PKGMGR_DBUS_SERVICE,
270 PKGMGR_DBUS_OBJECT_PATH,
271 PKGMGR_DBUS_INTERFACE, NULL, &error);
273 ERR("failed to get proxy object, sleep and retry[%s]",
277 usleep(CONNECTION_WAIT_USEC);
282 r = g_dbus_proxy_call_sync(proxy, method, params,
283 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
284 g_object_unref(proxy);
285 if (error && error->code == G_DBUS_ERROR_ACCESS_DENIED) {
286 ERR("failed to send request, privilege denied[%s]",
289 ret = PKGMGR_R_EPRIV;
298 ERR("failed to send request, sleep and retry[%s]",
302 usleep(CONNECTION_WAIT_USEC);
304 } while (retry_cnt <= CONNECTION_RETRY_MAX);
306 /* decrease ref count to 0 to free resource */
307 g_variant_unref(params);