diff options
author | youngsub ko <ys4610.ko@samsung.com> | 2013-05-02 15:16:25 +0900 |
---|---|---|
committer | youngsub ko <ys4610.ko@samsung.com> | 2013-05-02 15:17:00 +0900 |
commit | 75175ca407bf56b48da2429467ef52e1e4c09f02 (patch) | |
tree | 884edb96b79580d27768486a9b78a24bf6ca5808 | |
parent | 615c3d94eacc87cb6a174e95b670ff9f7eb22ac6 (diff) | |
download | badge-75175ca407bf56b48da2429467ef52e1e4c09f02.tar.gz badge-75175ca407bf56b48da2429467ef52e1e4c09f02.tar.bz2 badge-75175ca407bf56b48da2429467ef52e1e4c09f02.zip |
sync with private git
Change-Id: I28369e921ae9d208cdcafbf1c06751ce23ecd6ba
-rwxr-xr-x[-rw-r--r--] | CMakeLists.txt | 5 | ||||
-rwxr-xr-x | include/badge.h | 9 | ||||
-rwxr-xr-x | include/badge_db.h | 44 | ||||
-rwxr-xr-x | include/badge_error.h | 2 | ||||
-rwxr-xr-x | include/badge_internal.h | 3 | ||||
-rwxr-xr-x | include/badge_ipc.h | 50 | ||||
-rwxr-xr-x | packaging/badge.spec | 6 | ||||
-rwxr-xr-x | src/badge.c | 74 | ||||
-rwxr-xr-x | src/badge_db.c | 99 | ||||
-rwxr-xr-x | src/badge_internal.c | 206 | ||||
-rwxr-xr-x | src/badge_ipc.c | 620 |
11 files changed, 882 insertions, 236 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ae54f2..71d3088 100644..100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,11 +16,14 @@ SET(CMAKE_SKIP_BUILD_RPATH true) SET(INSTALL_HEADERS badge.h + badge_db.h badge_error.h ) SET(SRCS src/badge.c + src/badge_db.c + src/badge_ipc.c src/badge_internal.c ) @@ -35,6 +38,8 @@ pkg_check_modules(pkgs REQUIRED dlog dbus-1 dbus-glib-1 + vconf + com-core ) FOREACH(flag ${pkgs_CFLAGS}) diff --git a/include/badge.h b/include/badge.h index f2d5d93..0abd8eb 100755 --- a/include/badge.h +++ b/include/badge.h @@ -54,6 +54,7 @@ enum _badge_action { BADGE_ACTION_REMOVE, BADGE_ACTION_UPDATE, BADGE_ACTION_CHANGED_DISPLAY, + BADGE_ACTION_SERVICE_READY, }; @@ -297,6 +298,14 @@ badge_error_e badge_register_changed_cb(badge_change_cb callback, void *data); */ badge_error_e badge_unregister_changed_cb(badge_change_cb callback); +int badge_is_service_ready(void); + +badge_error_e badge_add_deffered_task( + void (*deffered_task_cb)(void *data), void *user_data); + +badge_error_e badge_del_deffered_task( + void (*deffered_task_cb)(void *data)); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/badge_db.h b/include/badge_db.h new file mode 100755 index 0000000..ce593f9 --- /dev/null +++ b/include/badge_db.h @@ -0,0 +1,44 @@ +/* + * libbadge + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngjoo Park <yjoo93.park@samsung.com>, + * Seungtaek Chung <seungtaek.chung@samsung.com>, Youngsub Ko <ys4610.ko@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#ifndef __BADGE_DB_DEF_H__ +#define __BADGE_DB_DEF_H__ + +#include <stdbool.h> +#include <badge_error.h> + +#ifdef __cplusplus +extern "C" { +#endif + +badge_error_e badge_db_insert(const char *pkgname, const char *writable_pkg, const char *caller); +badge_error_e badge_db_delete(const char *pkgname, const char *caller_pkg); +badge_error_e badge_db_set_count(const char *pkgname, const char *caller_pkg, int count); +badge_error_e badge_db_set_display_option(const char *pkgname, const char *caller_pkg, int is_display); + +#ifdef __cplusplus + } +#endif + +#endif /* __BADGE_DB_DEF_H__ */ + diff --git a/include/badge_error.h b/include/badge_error.h index ea28aa1..405933a 100755 --- a/include/badge_error.h +++ b/include/badge_error.h @@ -51,6 +51,8 @@ typedef enum _badge_error_e { BADGE_ERROR_FROM_DBUS = -5, /**< Error from DBus */ BADGE_ERROR_NOT_EXIST = -6, /**< Not exist */ BADGE_ERROR_PERMISSION_DENIED = -7, /**< Permission denied */ + BADGE_ERROR_IO = -8, /**< Error from I/O */ + BADGE_ERROR_SERVICE_NOT_READY = -9, /**< Error service not ready */ } badge_error_e; #ifdef __cplusplus diff --git a/include/badge_internal.h b/include/badge_internal.h index 4c62d7b..d3b6681 100755 --- a/include/badge_internal.h +++ b/include/badge_internal.h @@ -69,5 +69,8 @@ char *_badge_pkgs_new(badge_error_e *err, const char *pkg1, ...); char *_badge_pkgs_new_valist(badge_error_e *err, const char *pkg1, va_list args); +void badge_changed_cb_call(unsigned int action, const char *pkgname, + unsigned int count); + #endif /* __BADGE_INTERNAL_DEF_H__ */ diff --git a/include/badge_ipc.h b/include/badge_ipc.h new file mode 100755 index 0000000..8c96026 --- /dev/null +++ b/include/badge_ipc.h @@ -0,0 +1,50 @@ +/* + * libnotification + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Seungtaek Chung <seungtaek.chung@samsung.com>, Mi-Ju Lee <miju52.lee@samsung.com>, Xi Zhichan <zhichan.xi@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __BADGE_IPC_H__ +#define __BADGE_IPC_H__ + +#include <badge.h> + +#define BADGE_ADDR "/tmp/.badge.service" + +#ifdef __cplusplus +extern "C" { +#endif + +struct packet; + +badge_error_e badge_ipc_monitor_init(void); +badge_error_e badge_ipc_monitor_fini(void); + +badge_error_e badge_ipc_request_insert(const char *pkgname, const char *writable_pkg, const char *caller); +badge_error_e badge_ipc_request_delete(const char *pkgname, const char *caller); +badge_error_e badge_ipc_request_set_count(const char *pkgname, const char *caller, int count); +badge_error_e badge_ipc_request_set_display(const char *pkgname, const char *caller, int display_option); + +int badge_ipc_is_master_ready(void); +badge_error_e badge_ipc_add_deffered_task(void (*deffered_task_cb)(void *data), void *user_data); +badge_error_e badge_ipc_del_deffered_task(void (*deffered_task_cb)(void *data)); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/packaging/badge.spec b/packaging/badge.spec index 9aa4b0d..6c8f831 100755 --- a/packaging/badge.spec +++ b/packaging/badge.spec @@ -1,8 +1,8 @@ %define DBDIR "/opt/dbspace" Name: badge Summary: badge library -Version: 0.0.2 -Release: 2 +Version: 0.0.4 +Release: 1 Group: TBD License: Apache-2.0 Source0: %{name}-%{version}.tar.gz @@ -10,6 +10,8 @@ BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(dbus-1) BuildRequires: pkgconfig(dbus-glib-1) BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(com-core) BuildRequires: cmake Requires(post): /sbin/ldconfig requires(postun): /sbin/ldconfig diff --git a/src/badge.c b/src/badge.c index d5c7efc..4350b68 100755 --- a/src/badge.c +++ b/src/badge.c @@ -27,45 +27,23 @@ #include "badge_log.h" #include "badge_error.h" #include "badge_internal.h" +#include "badge_ipc.h" EXPORT_API badge_error_e badge_create(const char *pkgname, const char *writable_pkg) { + char *caller = NULL; badge_error_e err = BADGE_ERROR_NONE; - badge_h *badge = NULL; - char *pkgs = NULL; - - if (!pkgname) { - WARN("package name is NULL"); - return BADGE_ERROR_INVALID_DATA; - } - - pkgs = _badge_pkgs_new(&err, writable_pkg, NULL); - if (!pkgs) { - ERR("fail to _badge_pkgs_new : %d", err); - return err; - } - - INFO("pkgs : %s", pkgs); - - badge = _badge_new(pkgname, pkgs, &err); - if (!badge) { - ERR("fail to _badge_new : %d", err); - free(pkgs); - return err; - } - free(pkgs); - err = _badge_insert(badge); - if (err != BADGE_ERROR_NONE) { - ERR("fail to _badge_insert : %d", err); - _badge_free(badge); - return err; + caller = _badge_get_pkgname_by_pid(); + if (!caller) { + ERR("fail to get caller pkgname"); + return BADGE_ERROR_PERMISSION_DENIED; } - _badge_free(badge); + err = badge_ipc_request_insert(pkgname, writable_pkg, caller); - return BADGE_ERROR_NONE; + return err; } EXPORT_API @@ -78,11 +56,9 @@ badge_error_e badge_remove(const char *pkgname) if (!caller) { ERR("fail to get caller pkgname"); return BADGE_ERROR_PERMISSION_DENIED; - } - result = _badge_remove(caller, pkgname); - free(caller); + result = badge_ipc_request_delete(pkgname, caller); return result; } @@ -112,9 +88,7 @@ badge_error_e badge_set_count(const char *pkgname, unsigned int count) return BADGE_ERROR_PERMISSION_DENIED; } - result = _badget_set_count(caller, pkgname, count); - - free(caller); + result = badge_ipc_request_set_count(pkgname, caller, count); return result; } @@ -128,9 +102,16 @@ badge_error_e badge_get_count(const char *pkgname, unsigned int *count) EXPORT_API badge_error_e badge_set_display(const char *pkgname, unsigned int is_display) { + char *caller = NULL; badge_error_e result = BADGE_ERROR_NONE; - result = _badget_set_display(pkgname, is_display); + caller = _badge_get_pkgname_by_pid(); + if (!caller) { + ERR("fail to get caller pkgname"); + return BADGE_ERROR_PERMISSION_DENIED; + } + + result = badge_ipc_request_set_display(pkgname, caller, is_display); return result; } @@ -153,3 +134,22 @@ badge_error_e badge_unregister_changed_cb(badge_change_cb callback) return _badge_unregister_changed_cb(callback); } +EXPORT_API +int badge_is_service_ready(void) +{ + return badge_ipc_is_master_ready(); +} + +EXPORT_API +badge_error_e badge_add_deffered_task( + void (*deffered_task_cb)(void *data), void *user_data) +{ + return badge_ipc_add_deffered_task(deffered_task_cb, user_data); +} + +EXPORT_API +badge_error_e badge_del_deffered_task( + void (*deffered_task_cb)(void *data)) +{ + return badge_ipc_del_deffered_task(deffered_task_cb); +} diff --git a/src/badge_db.c b/src/badge_db.c new file mode 100755 index 0000000..4246cef --- /dev/null +++ b/src/badge_db.c @@ -0,0 +1,99 @@ +/* + * libbadge + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngjoo Park <yjoo93.park@samsung.com>, + * Seungtaek Chung <seungtaek.chung@samsung.com>, Youngsub Ko <ys4610.ko@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <stdlib.h> +#include <stdarg.h> + +#include "badge.h" +#include "badge_log.h" +#include "badge_error.h" +#include "badge_internal.h" + +EXPORT_API +badge_error_e badge_db_insert(const char *pkgname, const char *writable_pkg, const char *caller) +{ + badge_error_e err = BADGE_ERROR_NONE; + badge_h *badge = NULL; + char *pkgs = NULL; + + if (!pkgname) { + WARN("package name is NULL"); + return BADGE_ERROR_INVALID_DATA; + } + + pkgs = _badge_pkgs_new(&err, writable_pkg, caller, NULL); + if (!pkgs) { + ERR("fail to _badge_pkgs_new : %d", err); + return err; + } + + INFO("pkgs : %s", pkgs); + + badge = _badge_new(pkgname, pkgs, &err); + if (!badge) { + ERR("fail to _badge_new : %d", err); + free(pkgs); + return err; + } + free(pkgs); + + err = _badge_insert(badge); + if (err != BADGE_ERROR_NONE) { + ERR("fail to _badge_insert : %d", err); + _badge_free(badge); + return err; + } + + _badge_free(badge); + + return BADGE_ERROR_NONE; +} + +EXPORT_API +badge_error_e badge_db_delete(const char *pkgname, const char *caller) +{ + badge_error_e result = BADGE_ERROR_NONE; + + result = _badge_remove(caller, pkgname); + + return result; +} + +EXPORT_API +badge_error_e badge_db_set_count(const char *pkgname, const char *caller, int count) +{ + badge_error_e result = BADGE_ERROR_NONE; + + result = _badget_set_count(caller, pkgname, count); + + return result; +} + +EXPORT_API +badge_error_e badge_db_set_display_option(const char *pkgname, const char *caller, int is_display) +{ + badge_error_e result = BADGE_ERROR_NONE; + + result = _badget_set_display(pkgname, is_display); + + return result; +} diff --git a/src/badge_internal.c b/src/badge_internal.c index bacedd2..83155a2 100755 --- a/src/badge_internal.c +++ b/src/badge_internal.c @@ -35,15 +35,13 @@ #include "badge_log.h" #include "badge_error.h" #include "badge_internal.h" +#include "badge_ipc.h" #define BADGE_PKGNAME_LEN 512 #define BADGE_TABLE_NAME "badge_data" #define BADGE_OPTION_TABLE_NAME "badge_option" #define BADGE_CHANGED_NOTI "badge_changed" -#define BADGE_DBUS_BUS_NAME "org.tizen.libbadge" -#define BADGE_DBUS_PATH "/org/tizen/libbadge" -#define BADGE_DBUS_INTERFACE "org.tizen.libbadge.signal" struct _badge_h { char *pkgname; @@ -56,7 +54,6 @@ struct _badge_cb_data { }; static GList *g_badge_cb_list; -static DBusConnection *g_badge_cb_handle; static inline long _get_max_len(void) { @@ -114,65 +111,6 @@ char *_badge_get_pkgname_by_pid(void) return pkgname; } - -static void _badge_changed(unsigned int action, const char *pkgname, - unsigned int count) -{ - DBusConnection *connection = NULL; - DBusMessage *message = NULL; - DBusError err; - dbus_bool_t ret; - - if (!pkgname) { - ERR("pkgname is NULL"); - return; - } - - dbus_error_init(&err); - connection = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - if (!connection) { - ERR("Fail to dbus_bus_get : %s", err.message); - dbus_error_free(&err); - return; - } - - message = dbus_message_new_signal(BADGE_DBUS_PATH, - BADGE_DBUS_INTERFACE, - BADGE_CHANGED_NOTI); - - if (!message) { - ERR("fail to create dbus message"); - goto release_n_return; - } - - dbus_message_append_args(message, - DBUS_TYPE_UINT32, &action, - DBUS_TYPE_STRING, &pkgname, - DBUS_TYPE_UINT32, &count, - DBUS_TYPE_INVALID); - - ret = dbus_connection_send(connection, message, NULL); - if (!ret) { - ERR("fail to send dbus message : [%u][%s][%u]", - action, pkgname, count); - goto release_n_return; - } - - dbus_connection_flush(connection); - - DBG("success to emit signal [%u][%s][%u]", - action, pkgname, count); - -release_n_return: - dbus_error_free(&err); - - if (message) - dbus_message_unref(message); - - if (connection) - dbus_connection_unref(connection); -} - static badge_error_e _badge_check_data_inserted(const char *pkgname, sqlite3 *db) { @@ -505,8 +443,6 @@ badge_error_e _badge_insert(badge_h *badge) goto return_close_db; } - _badge_changed(BADGE_ACTION_CREATE, badge->pkgname, 0); - /* inserting badge options */ ret = _badge_check_option_inserted(badge->pkgname, db); if (ret != BADGE_ERROR_NOT_EXIST) { @@ -536,7 +472,7 @@ badge_error_e _badge_insert(badge_h *badge) return_close_db: if (err_msg) - free(err_msg); + sqlite3_free(err_msg); if (sqlbuf) sqlite3_free(sqlbuf); @@ -597,8 +533,6 @@ badge_error_e _badge_remove(const char *caller, const char *pkgname) goto return_close_db; } - _badge_changed(BADGE_ACTION_REMOVE, pkgname, 0); - /* treating option table */ ret = _badge_check_option_inserted(pkgname, db); if (ret != BADGE_ERROR_ALREADY_EXIST) { @@ -624,7 +558,7 @@ badge_error_e _badge_remove(const char *caller, const char *pkgname) return_close_db: if (err_msg) - free(err_msg); + sqlite3_free(err_msg); if (sqlbuf) sqlite3_free(sqlbuf); @@ -687,11 +621,9 @@ badge_error_e _badget_set_count(const char *caller, const char *pkgname, goto return_close_db; } - _badge_changed(BADGE_ACTION_UPDATE, pkgname, count); - return_close_db: if (err_msg) - free(err_msg); + sqlite3_free(err_msg); if (sqlbuf) sqlite3_free(sqlbuf); @@ -833,11 +765,9 @@ badge_error_e _badget_set_display(const char *pkgname, goto return_close_db; } - _badge_changed(BADGE_ACTION_CHANGED_DISPLAY, pkgname, is_display); - return_close_db: if (err_msg) - free(err_msg); + sqlite3_free(err_msg); if (sqlbuf) sqlite3_free(sqlbuf); @@ -913,7 +843,7 @@ return_close_db: return result; } -static void _badge_changed_cb_call(unsigned int action, const char *pkgname, +void badge_changed_cb_call(unsigned int action, const char *pkgname, unsigned int count) { GList *list = g_badge_cb_list; @@ -930,131 +860,14 @@ static void _badge_changed_cb_call(unsigned int action, const char *pkgname, } } -static DBusHandlerResult _badge_signal_filter(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - const char *interface; - DBusError error; - dbus_bool_t ret; - unsigned int action = 0; - const char *pkgname = NULL; - unsigned int count = 0; - - dbus_error_init(&error); - - interface = dbus_message_get_interface(msg); - DBG("path : %s", dbus_message_get_path(msg)); - DBG("interface : %s", interface); - - if (g_strcmp0(BADGE_DBUS_INTERFACE, interface)) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - ret = dbus_message_is_signal(msg, interface, BADGE_CHANGED_NOTI); - if (!ret) { - DBG("this msg is not signal"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - ret = dbus_message_get_args(msg, &error, - DBUS_TYPE_UINT32, &action, - DBUS_TYPE_STRING, &pkgname, - DBUS_TYPE_UINT32, &count, - DBUS_TYPE_INVALID); - if (!ret) { - ERR("fail to get args : %s", error.message); - dbus_error_free(&error); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - _badge_changed_cb_call(action, pkgname, count); - - return DBUS_HANDLER_RESULT_HANDLED; -} - -static inline void __bus_rule_get(char *buf, int buf_len) -{ - if (!buf) - return; - if (buf_len <= 1) - return; - - snprintf(buf, buf_len, - "path='%s',type='signal',interface='%s',member='%s'", - BADGE_DBUS_PATH, - BADGE_DBUS_INTERFACE, - BADGE_CHANGED_NOTI); -} - static void _badge_changed_monitor_init() { - DBusError err; - DBusConnection *conn = NULL; - char rule[1024] = {'\0', }; - - if (g_badge_cb_handle) - return; - - dbus_error_init(&err); - conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); - if (!conn) { - ERR("fail to get bus : %s", err.message); - dbus_error_free(&err); - return; - } - dbus_connection_setup_with_g_main(conn, NULL); - - __bus_rule_get(rule, sizeof(rule)); - - dbus_bus_add_match(conn, rule, &err); - if (dbus_error_is_set(&err)) { - ERR("fail to dbus_bus_remove_match : %s", - err.message); - dbus_error_free(&err); - dbus_connection_close(conn); - return; - } - - if (dbus_connection_add_filter(conn, _badge_signal_filter, - NULL, NULL) == FALSE) { - ERR("fail to dbus_connection_add_filter : %s", - err.message); - dbus_error_free(&err); - dbus_connection_close(conn); - return; - } - - dbus_connection_set_exit_on_disconnect(conn, FALSE); - - g_badge_cb_handle = conn; - - return; + badge_ipc_monitor_init(); } static void _badge_chanaged_monitor_fini() { - DBusConnection *conn = g_badge_cb_handle; - char rule[1024] = {'\0', }; - DBusError err; - - if (!conn) - return; - - dbus_error_init(&err); - - dbus_connection_remove_filter(conn, _badge_signal_filter, NULL); - - __bus_rule_get(rule, sizeof(rule)); - - dbus_bus_remove_match(conn, rule, &err); - if (dbus_error_is_set(&err)) { - ERR("fail to dbus_bus_remove_match : %s", - err.message); - dbus_error_free(&err); - } - - dbus_connection_close(conn); - - g_badge_cb_handle = NULL; + badge_ipc_monitor_fini(); } static gint _badge_data_compare(gconstpointer a, gconstpointer b) @@ -1076,8 +889,7 @@ badge_error_e _badge_register_changed_cb(badge_change_cb callback, void *data) struct _badge_cb_data *bd = NULL; GList *found = NULL; - if (!g_badge_cb_handle) - _badge_changed_monitor_init(); + _badge_changed_monitor_init(); found = g_list_find_custom(g_badge_cb_list, (gconstpointer)callback, _badge_data_compare); diff --git a/src/badge_ipc.c b/src/badge_ipc.c new file mode 100755 index 0000000..c6db5ca --- /dev/null +++ b/src/badge_ipc.c @@ -0,0 +1,620 @@ +/* + * libbadge + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngjoo Park <yjoo93.park@samsung.com>, + * Seungtaek Chung <seungtaek.chung@samsung.com>, Youngsub Ko <ys4610.ko@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <stdlib.h> +#include <stdarg.h> + +#include <vconf.h> + +#include <packet.h> +#include <com-core.h> +#include <com-core_packet.h> + +#include "badge.h" +#include "badge_log.h" +#include "badge_error.h" +#include "badge_internal.h" +#include "badge_ipc.h" + +#define BADGE_IPC_TIMEOUT 1.0 + +#if !defined(VCONFKEY_MASTER_STARTED) +#define VCONFKEY_MASTER_STARTED "memory/data-provider-master/started" +#endif + +static struct info { + int server_fd; + int client_fd; + const char *socket_file; + struct { + int (*request_cb)(const char *appid, const char *name, int type, const char *content, const char *icon, pid_t pid, double period, int allow_duplicate, void *data); + void *data; + } server_cb; + int initialized; + int is_started_cb_set_svc; + int is_started_cb_set_task; +} s_info = { + .server_fd = -1, + .client_fd = -1, + .socket_file = BADGE_ADDR, + .initialized = 0, + .is_started_cb_set_svc = 0, + .is_started_cb_set_task = 0, +}; + +typedef struct _task_list task_list; +struct _task_list { + task_list *prev; + task_list *next; + + void (*task_cb) (void *data); + void *data; +}; + +static task_list *g_task_list; + +static badge_error_e badge_ipc_monitor_register(void); +static badge_error_e badge_ipc_monitor_deregister(void); +static void _do_deffered_task(void); +static void _master_started_cb_task(keynode_t *node, void *data); + +/*! + * functions to check state of master + */ +static inline void _set_master_started_cb(vconf_callback_fn cb) { + int ret = -1; + + ret = vconf_notify_key_changed(VCONFKEY_MASTER_STARTED, + cb, NULL); + if (ret != 0) { + ERR("failed to notify key(%s) : %d", + VCONFKEY_MASTER_STARTED, ret); + } +} + +static inline void _unset_master_started_cb(vconf_callback_fn cb) { + int ret = -1; + + ret = vconf_ignore_key_changed(VCONFKEY_MASTER_STARTED, + cb); + if (ret != 0) { + ERR("failed to notify key(%s) : %d", + VCONFKEY_MASTER_STARTED, ret); + } +} + +int badge_ipc_is_master_ready(void) +{ + int ret = -1, is_master_started = 0; + + ret = vconf_get_bool(VCONFKEY_MASTER_STARTED, &is_master_started); + if (ret == 0 && is_master_started == 1) { + ERR("the master has been started"); + } else { + is_master_started = 0; + ERR("the master has been stopped"); + } + + return is_master_started; +} + +badge_error_e +badge_ipc_add_deffered_task( + void (*deffered_task_cb)(void *data), + void *user_data) +{ + task_list *list = NULL; + task_list *list_new = NULL; + + list_new = + (task_list *) malloc(sizeof(task_list)); + + if (list_new == NULL) { + return BADGE_ERROR_NO_MEMORY; + } + + if (s_info.is_started_cb_set_task == 0) { + _set_master_started_cb(_master_started_cb_task); + s_info.is_started_cb_set_task = 1; + } + + list_new->next = NULL; + list_new->prev = NULL; + + list_new->task_cb = deffered_task_cb; + list_new->data = user_data; + + if (g_task_list == NULL) { + g_task_list = list_new; + } else { + list = g_task_list; + + while (list->next != NULL) { + list = list->next; + } + + list->next = list_new; + list_new->prev = list; + } + return BADGE_ERROR_NONE; +} + +badge_error_e +badge_ipc_del_deffered_task( + void (*deffered_task_cb)(void *data)) +{ + task_list *list_del = NULL; + task_list *list_prev = NULL; + task_list *list_next = NULL; + + list_del = g_task_list; + + if (list_del == NULL) { + return BADGE_ERROR_INVALID_DATA; + } + + while (list_del->prev != NULL) { + list_del = list_del->prev; + } + + do { + if (list_del->task_cb == deffered_task_cb) { + list_prev = list_del->prev; + list_next = list_del->next; + + if (list_prev == NULL) { + g_task_list = list_next; + } else { + list_prev->next = list_next; + } + + if (list_next == NULL) { + if (list_prev != NULL) { + list_prev->next = NULL; + } + } else { + list_next->prev = list_prev; + } + + free(list_del); + + if (g_task_list == NULL) { + if (s_info.is_started_cb_set_task == 1) { + _unset_master_started_cb(_master_started_cb_task); + s_info.is_started_cb_set_task = 0; + } + } + + return BADGE_ERROR_NONE; + } + list_del = list_del->next; + } while (list_del != NULL); + + return BADGE_ERROR_INVALID_DATA; +} + +static void _do_deffered_task(void) { + task_list *list_do = NULL; + task_list *list_temp = NULL; + + if (g_task_list == NULL) { + return; + } + + list_do = g_task_list; + g_task_list = NULL; + if (s_info.is_started_cb_set_task == 1) { + _unset_master_started_cb(_master_started_cb_task); + s_info.is_started_cb_set_task = 0; + } + + while (list_do->prev != NULL) { + list_do = list_do->prev; + } + + while (list_do != NULL) { + if (list_do->task_cb != NULL) { + list_do->task_cb(list_do->data); + DBG("called:%p", list_do->task_cb); + } + list_temp = list_do->next; + free(list_do); + list_do = list_temp; + } +} + +static void _master_started_cb_service(keynode_t *node, + void *data) { + int ret = BADGE_ERROR_NONE; + + if (badge_ipc_is_master_ready()) { + ret = badge_ipc_monitor_register(); + if (ret != BADGE_ERROR_NONE) { + ERR("failed to register a monitor"); + } + } else { + ret = badge_ipc_monitor_deregister(); + if (ret != BADGE_ERROR_NONE) { + ERR("failed to deregister a monitor"); + } + } +} + +static void _master_started_cb_task(keynode_t *node, + void *data) { + + if (badge_ipc_is_master_ready()) { + _do_deffered_task(); + } +} + +/*! + * functions to handler services + */ +static struct packet *_handler_insert_badge(pid_t pid, int handle, const struct packet *packet) +{ + int ret = 0; + char *pkgname = NULL; + + if (!packet) { + ERR("a packet is null"); + return NULL; + } + + DBG(""); + + //return code, pkgname + if (packet_get(packet, "is", &ret, &pkgname) == 2) { + if (ret == BADGE_ERROR_NONE) { + badge_changed_cb_call(BADGE_ACTION_CREATE, pkgname, 0); + } else { + ERR("failed to insert a new badge:%d", ret); + } + } else { + ERR("failed to get data from a packet"); + } + + return NULL; +} + +static struct packet *_handler_delete_badge(pid_t pid, int handle, const struct packet *packet) +{ + int ret = 0; + char *pkgname = NULL; + + if (!packet) { + ERR("a packet is null"); + return NULL; + } + + DBG(""); + + if (packet_get(packet, "is", &ret, &pkgname) == 2) { + if (ret == BADGE_ERROR_NONE) { + badge_changed_cb_call(BADGE_ACTION_REMOVE, pkgname, 0); + } else { + ERR("failed to remove a badge:%d", ret); + } + } else { + ERR("failed to get data from a packet"); + } + + return NULL; +} + +static struct packet *_handler_set_badge_count(pid_t pid, int handle, const struct packet *packet) +{ + int ret = 0; + char *pkgname = NULL; + int count = 0; + + if (!packet) { + ERR("a packet is null"); + return NULL; + } + + DBG(""); + + if (packet_get(packet, "isi", &ret, &pkgname, &count) == 3) { + if (ret == BADGE_ERROR_NONE) { + badge_changed_cb_call(BADGE_ACTION_UPDATE, pkgname, count); + } else { + ERR("failed to update count of badge:%d", ret); + } + } else { + ERR("failed to get data from a packet"); + } + + return NULL; +} + +static struct packet *_handler_set_display_option(pid_t pid, int handle, const struct packet *packet) +{ + int ret = 0; + char *pkgname = NULL; + int is_display = 0; + + if (!packet) { + ERR("a packet is null"); + return NULL; + } + + DBG(""); + + if (packet_get(packet, "isi", &ret, &pkgname, &is_display) == 3) { + if (ret == BADGE_ERROR_NONE) { + badge_changed_cb_call(BADGE_ACTION_CHANGED_DISPLAY, pkgname, is_display); + } else { + ERR("failed to update the display option of badge:%d, %d", ret, is_display); + } + } else { + ERR("failed to get data from a packet"); + } + + return NULL; +} + +static int _handler_service_register(pid_t pid, int handle, const struct packet *packet, void *data) +{ + int ret; + + DBG(""); + + if (!packet) { + ERR("Packet is not valid\n"); + ret = BADGE_ERROR_INVALID_DATA; + } else if (packet_get(packet, "i", &ret) != 1) { + ERR("Packet is not valid\n"); + ret = BADGE_ERROR_INVALID_DATA; + } else { + if (ret == BADGE_ERROR_NONE) { + badge_changed_cb_call(BADGE_ACTION_SERVICE_READY, NULL, 0); + } + } + return ret; +} + +/*! + * functions to initialize and register a monitor + */ +static badge_error_e badge_ipc_monitor_register(void) +{ + int ret; + struct packet *packet; + static struct method service_table[] = { + { + .cmd = "insert_badge", + .handler = _handler_insert_badge, + }, + { + .cmd = "delete_badge", + .handler = _handler_delete_badge, + }, + { + .cmd = "set_badge_count", + .handler = _handler_set_badge_count, + }, + { + .cmd = "set_disp_option", + .handler = _handler_set_display_option, + }, + { + .cmd = NULL, + .handler = NULL, + }, + }; + + if (s_info.initialized == 1) { + return BADGE_ERROR_NONE; + } else { + s_info.initialized = 1; + } + + ERR("register a service\n"); + + s_info.server_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table); + if (s_info.server_fd < 0) { + ERR("Failed to make a connection to the master\n"); + return BADGE_ERROR_IO; + } + + packet = packet_create("service_register", ""); + if (!packet) { + ERR("Failed to build a packet\n"); + return BADGE_ERROR_IO; + } + + ret = com_core_packet_async_send(s_info.server_fd, packet, 1.0, _handler_service_register, NULL); + DBG("Service register sent: %d\n", ret); + packet_destroy(packet); + if (ret != 0) { + com_core_packet_client_fini(s_info.server_fd); + s_info.server_fd = BADGE_ERROR_INVALID_DATA; + ret = BADGE_ERROR_IO; + } else { + ret = BADGE_ERROR_NONE; + } + + DBG("Server FD: %d\n", s_info.server_fd); + return ret; +} + +badge_error_e badge_ipc_monitor_deregister(void) +{ + if (s_info.initialized == 0) { + return BADGE_ERROR_NONE; + } + + com_core_packet_client_fini(s_info.server_fd); + s_info.server_fd = BADGE_ERROR_INVALID_DATA; + + s_info.initialized = 0; + + return BADGE_ERROR_NONE; +} + +badge_error_e badge_ipc_monitor_init(void) +{ + int ret = BADGE_ERROR_NONE; + + if (badge_ipc_is_master_ready()) { + ret = badge_ipc_monitor_register(); + } + + if (s_info.is_started_cb_set_svc == 0) { + _set_master_started_cb(_master_started_cb_service); + s_info.is_started_cb_set_svc = 1; + } + + return ret; +} + +badge_error_e badge_ipc_monitor_fini(void) +{ + int ret = BADGE_ERROR_NONE; + + if (s_info.is_started_cb_set_svc == 1) { + _unset_master_started_cb(_master_started_cb_service); + s_info.is_started_cb_set_svc = 0; + } + + ret = badge_ipc_monitor_deregister(); + + return ret; +} + + +badge_error_e badge_ipc_request_insert(const char *pkgname, const char *writable_pkg, const char *caller) { + int ret = 0; + struct packet *packet; + struct packet *result; + + packet = packet_create("insert_badge", "sss", pkgname, writable_pkg, caller); + result = com_core_packet_oneshot_send(BADGE_ADDR, + packet, + BADGE_IPC_TIMEOUT); + packet_destroy(packet); + + if (result != NULL) { + if (packet_get(result, "i", &ret) != 1) { + ERR("Failed to get a result packet"); + packet_unref(result); + return BADGE_ERROR_IO; + } + + if (ret != BADGE_ERROR_NONE) { + return ret; + } + } else { + badge_ipc_is_master_ready(); + return BADGE_ERROR_SERVICE_NOT_READY; + } + + return BADGE_ERROR_NONE; +} + +badge_error_e badge_ipc_request_delete(const char *pkgname, const char *caller) { + int ret = 0; + struct packet *packet; + struct packet *result; + + packet = packet_create("delete_badge", "ss", pkgname, caller); + result = com_core_packet_oneshot_send(BADGE_ADDR, + packet, + BADGE_IPC_TIMEOUT); + packet_destroy(packet); + + if (result != NULL) { + if (packet_get(result, "i", &ret) != 1) { + ERR("Failed to get a result packet"); + packet_unref(result); + return BADGE_ERROR_IO; + } + + if (ret != BADGE_ERROR_NONE) { + return ret; + } + } else { + badge_ipc_is_master_ready(); + return BADGE_ERROR_SERVICE_NOT_READY; + } + + return BADGE_ERROR_NONE; +} + +badge_error_e badge_ipc_request_set_count(const char *pkgname, const char *caller, int count) { + int ret = 0; + struct packet *packet; + struct packet *result; + + packet = packet_create("set_badge_count", "ssi", pkgname, caller, count); + result = com_core_packet_oneshot_send(BADGE_ADDR, + packet, + BADGE_IPC_TIMEOUT); + packet_destroy(packet); + + if (result != NULL) { + if (packet_get(result, "i", &ret) != 1) { + ERR("Failed to get a result packet"); + packet_unref(result); + return BADGE_ERROR_IO; + } + + if (ret != BADGE_ERROR_NONE) { + return ret; + } + } else { + badge_ipc_is_master_ready(); + return BADGE_ERROR_SERVICE_NOT_READY; + } + + return BADGE_ERROR_NONE; +} + +badge_error_e badge_ipc_request_set_display(const char *pkgname, const char *caller, int display_option) { + int ret = 0; + struct packet *packet; + struct packet *result; + + packet = packet_create("set_disp_option", "ssi", pkgname, caller, display_option); + result = com_core_packet_oneshot_send(BADGE_ADDR, + packet, + BADGE_IPC_TIMEOUT); + packet_destroy(packet); + + if (result != NULL) { + if (packet_get(result, "i", &ret) != 1) { + ERR("Failed to get a result packet"); + packet_unref(result); + return BADGE_ERROR_IO; + } + + if (ret != BADGE_ERROR_NONE) { + return ret; + } + } else { + badge_ipc_is_master_ready(); + return BADGE_ERROR_SERVICE_NOT_READY; + } + + return BADGE_ERROR_NONE; +} |