sync with private git
authoryoungsub ko <ys4610.ko@samsung.com>
Thu, 2 May 2013 06:16:25 +0000 (15:16 +0900)
committeryoungsub ko <ys4610.ko@samsung.com>
Thu, 2 May 2013 06:17:00 +0000 (15:17 +0900)
Change-Id: I28369e921ae9d208cdcafbf1c06751ce23ecd6ba

CMakeLists.txt [changed mode: 0644->0755]
include/badge.h
include/badge_db.h [new file with mode: 0755]
include/badge_error.h
include/badge_internal.h
include/badge_ipc.h [new file with mode: 0755]
packaging/badge.spec
src/badge.c
src/badge_db.c [new file with mode: 0755]
src/badge_internal.c
src/badge_ipc.c [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 3ae54f2..71d3088
@@ -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})
index f2d5d93..0abd8eb 100755 (executable)
@@ -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 (executable)
index 0000000..ce593f9
--- /dev/null
@@ -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__ */
+
index ea28aa1..405933a 100755 (executable)
@@ -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
index 4c62d7b..d3b6681 100755 (executable)
@@ -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 (executable)
index 0000000..8c96026
--- /dev/null
@@ -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
index 9aa4b0d..6c8f831 100755 (executable)
@@ -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
index d5c7efc..4350b68 100755 (executable)
 #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 (executable)
index 0000000..4246cef
--- /dev/null
@@ -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;
+}
index bacedd2..83155a2 100755 (executable)
 #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 (executable)
index 0000000..c6db5ca
--- /dev/null
@@ -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;
+}