add alarm session agent 72/69972/8
authorJiwoong Im <jiwoong.im@samsung.com>
Tue, 17 May 2016 11:51:53 +0000 (20:51 +0900)
committerJiwoong Im <jiwoong.im@samsung.com>
Thu, 9 Jun 2016 04:22:28 +0000 (13:22 +0900)
- To send alarm expired dbus signal to session bus, add alarm-session-agent.
  alarm-server send request to alarm-session-agent.
  alarm-session-agent started by socket activation and send alarm
  expired signal to session bus.
  After sending dbus signal, alarm-session-agent exited.

Change-Id: Ieec687154db5f156cbe52d65a39282e49ad69d11
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
CMakeLists.txt
alarm-manager.c
alarm-session-agent/CMakeLists.txt [new file with mode: 0644]
alarm-session-agent/agent.c [new file with mode: 0644]
alarm-session-agent/agent.h [new file with mode: 0644]
include/alarm-internal.h
packaging/alarm-agent.conf [new file with mode: 0644]
packaging/alarm-manager.spec
packaging/alarm-session-agent.service [new file with mode: 0644]
packaging/alarm-session-agent.socket [new file with mode: 0644]
src/alarm-lib.c

index ce37919..e1c4786 100644 (file)
@@ -47,6 +47,7 @@ TARGET_LINK_LIBRARIES(${this_target} alarm)
 
 ADD_SUBDIRECTORY(src)
 ADD_SUBDIRECTORY(tool)
+ADD_SUBDIRECTORY(alarm-session-agent)
 
 CONFIGURE_FILE(alarm-service.conf.in alarm-service.conf @ONLY)
 INSTALL(TARGETS ${this_target} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
index e36ad32..d068393 100644 (file)
@@ -20,6 +20,8 @@
 #include <time.h>
 #include <signal.h>
 #include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -142,7 +144,7 @@ static bool __alarm_create_appsvc(alarm_info_t *alarm_info, alarm_id_t *alarm_id
 static bool __alarm_delete(uid_t uid, alarm_id_t alarm_id, int *error_code);
 static bool __alarm_update(uid_t uid, int pid, char *app_service_name, alarm_id_t alarm_id,
                           alarm_info_t *alarm_info, int *error_code);
-static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id);
+static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id, uid_t uid);
 static void __alarm_expired();
 static gboolean __alarm_handler_idle(gpointer user_data);
 static void __on_system_time_external_changed(keynode_t *node, void *data);
@@ -1131,11 +1133,59 @@ static bool __can_skip_expired_cb(alarm_id_t alarm_id)
        return false;
 }
 
-static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id)
+static gboolean __send_noti_to_session_bus(char *service_name,
+               alarm_id_t alarm_id, uid_t uid)
+{
+       int fd;
+       int ret;
+       int len;
+       struct sockaddr_un saddr;
+       uint8_t *data;
+       GVariant *gv;
+       uint8_t *gv_data;
+
+       fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+       if (fd < 0)
+               return FALSE;
+
+       saddr.sun_family = AF_UNIX;
+       snprintf(saddr.sun_path, sizeof(saddr.sun_path),
+                       "/run/alarm_agent/%d", uid);
+
+       ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
+       if (ret < 0) {
+               ALARM_MGR_EXCEPTION_PRINT("connect failed - (errno %d)", errno);
+               return FALSE;
+       }
+
+       gv = g_variant_new("(is)", alarm_id, service_name);
+       len = g_variant_get_size(gv);
+
+       gv_data = malloc(len);
+       if (!gv_data)
+               return FALSE;
+
+       g_variant_store(gv, gv_data);
+
+       data = malloc(len + 4);
+
+       memcpy(data, &len, 4);
+       memcpy(data + 4, gv_data, len);
+
+       if (send(fd, data, len + 4, 0) == -1) {
+               ALARM_MGR_EXCEPTION_PRINT("sendto() failed (errno %d)", errno);
+               return FALSE;
+       }
+
+       close(fd);
+
+       return TRUE;
+}
+
+static void __alarm_send_noti_to_application(const char *app_service_name, alarm_id_t alarm_id, uid_t uid)
 {
        char service_name[MAX_SERVICE_NAME_LEN] = {0,};
        gboolean ret;
-       GError *err = NULL;
 
        if (app_service_name == NULL || strlen(app_service_name) == 0) {
                ALARM_MGR_EXCEPTION_PRINT("This alarm destination is invalid.");
@@ -1148,16 +1198,24 @@ static void __alarm_send_noti_to_application(const char *app_service_name, alarm
        memcpy(service_name, app_service_name, strlen(app_service_name));
        SECURE_LOGI("[alarm server][send expired_alarm(alarm_id=%d) to app_service_name(%s)]", alarm_id, service_name);
 
-       ret = g_dbus_connection_emit_signal(alarm_context.connection,
-                       service_name,
-                       "/org/tizen/alarm/manager",
-                       "org.tizen.alarm.manager",
-                       "alarm_expired",
-                       g_variant_new("(is)", alarm_id, service_name),
-                       &err);
-       if (ret != TRUE) {
-               ALARM_MGR_EXCEPTION_PRINT("failed to send expired signal for %d, %s: %s", alarm_id, service_name, err->message);
-               g_error_free(err);
+       if (uid >= REGULAR_UID_MIN) {
+               ret = __send_noti_to_session_bus(service_name, alarm_id, uid);
+               if (ret != TRUE)
+                       ALARM_MGR_EXCEPTION_PRINT("failed to send alarm expired noti for %d, %s",
+                                       alarm_id, service_name);
+       } else {
+               g_dbus_connection_call(alarm_context.connection,
+                               service_name,
+                               "/org/tizen/alarm/client",
+                               "org.tizen.alarm.client",
+                               "alarm_expired",
+                               g_variant_new("(is)", alarm_id, service_name),
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               NULL,
+                               NULL);
        }
 }
 
@@ -1514,7 +1572,8 @@ static void __alarm_expired()
 
                                /* TODO: implement aul_update_freezer_status */
                                /* aul_update_freezer_status(__alarm_info->pid, "wakeup"); */
-                               __alarm_send_noti_to_application(destination_app_service_name, alarm_id); /* dbus auto activation */
+                               __alarm_send_noti_to_application(destination_app_service_name,
+                                               alarm_id, __alarm_info->uid); /* dbus auto activation */
                                ALARM_MGR_LOG_PRINT("after __alarm_send_noti_to_application");
                        }
                }
@@ -3219,7 +3278,7 @@ void on_bus_name_owner_changed(GDBusConnection  *connection,
 
                                if (strcmp(expire_info->service_name, service_name) == 0) {
                                        SECURE_LOGE("expired service name(%s) alarm_id (%d)", expire_info->service_name, expire_info->alarm_id);
-                                       __alarm_send_noti_to_application(expire_info->service_name, expire_info->alarm_id);
+                                       __alarm_send_noti_to_application(expire_info->service_name, expire_info->alarm_id, 0);
                                        g_expired_alarm_list = g_slist_remove(g_expired_alarm_list, entry->data);
                                        g_free(expire_info);
                                }
diff --git a/alarm-session-agent/CMakeLists.txt b/alarm-session-agent/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4b11ca4
--- /dev/null
@@ -0,0 +1,20 @@
+PKG_CHECK_MODULES(D_PKGS REQUIRED gio-2.0 glib-2.0 dlog bundle libsystemd-daemon)
+
+FOREACH(flag ${D_PKGS_CFLAGS})
+       SET(DAEMON_CFLAGS "${DAEMON_CFLAGS} ${flag}")
+ENDFOREACH()
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/include)
+
+SET(TARGET "alarm_session_agent")
+SET(SRC
+       agent.c
+)
+ADD_EXECUTABLE(${TARGET} ${SRC})
+SET_TARGET_PROPERTIES(${TARGET} PROPERTIES
+               LINK_FLAGS "-fPIE"
+               COMPILE_FLAGS "${DAEMON_CFLAGS}"
+)
+TARGET_LINK_LIBRARIES(${TARGET} ${PKGS_LDFLAGS} ${D_PKGS_LDFLAGS} -ldl)
+INSTALL(TARGETS ${TARGET} DESTINATION bin)
+
diff --git a/alarm-session-agent/agent.c b/alarm-session-agent/agent.c
new file mode 100644 (file)
index 0000000..0a59824
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * alarm session agent
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <systemd/sd-daemon.h>
+#include <bundle.h>
+#include <dlog.h>
+#include <glib.h>
+#include <glib-unix.h>
+#include <gio/gio.h>
+
+#include "agent.h"
+
+#define POLLFD_MAX 1
+
+GMainLoop *mainloop;
+
+static int _sock_create(const char *path)
+{
+       int r;
+       int fd;
+       struct sockaddr_un sa;
+
+       assert(path && *path);
+
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd == -1) {
+               LOGE("Socket '%s': socket %d", path, errno);
+               return -1;
+       }
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sun_family = AF_UNIX;
+       strncpy(sa.sun_path, path, sizeof(sa.sun_path));
+       sa.sun_path[sizeof(sa.sun_path) - 1] = '\0';
+
+       r = unlink(sa.sun_path);
+       if (r == -1 && errno != ENOENT) {
+               LOGE("Socket '%s': unlink %d", path, errno);
+               close(fd);
+               return -1;
+       }
+
+       r = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
+       if (r == -1) {
+               LOGE("Socket '%s': bind %d", path, errno);
+               close(fd);
+               return -1;
+       }
+
+       chmod(sa.sun_path, 0666);
+
+       r = listen(fd, SOMAXCONN);
+       if (r == -1) {
+               LOGE("Socket '%s': listen %d", path, errno);
+               close(fd);
+               return -1;
+       }
+
+       return fd;
+}
+
+static int _get_socket(const char *path)
+{
+       int n;
+       int i;
+       int r;
+       int fd;
+
+       if (!path || !*path) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       n = sd_listen_fds(0);
+       if (n < 0) {
+               LOGE("sd_listen_fds: %d", n);
+               return -1;
+       }
+
+       if (n == 0)
+               return _sock_create(path);
+
+       fd = -1;
+       for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + n; i++) {
+               r = sd_is_socket_unix(i, SOCK_STREAM, -1, path, 0);
+               if (r > 0) {
+                       fd = i;
+                       break;
+               }
+       }
+
+       if (fd == -1) {
+               LOGE("Socket '%s' is not passed", path);
+               return _sock_create(path);
+       }
+
+       return fd;
+}
+
+static void _send_noti(char *service_name, int alarm_id)
+{
+       GDBusConnection *conn;
+       GError *err = NULL;
+       LOGE("send expired message, %s, %d", service_name, alarm_id);
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err);
+       if (!conn) {
+               LOGE("connection error %s", err->message);
+               exit(-1);
+       }
+
+       g_dbus_connection_call_sync(conn,
+                       service_name,
+                       "/org/tizen/alarm/client",
+                       "org.tizen.alarm.client",
+                       "alarm_expired",
+                       g_variant_new("(is)", alarm_id, service_name),
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1,
+                       NULL,
+                       NULL);
+
+       g_object_unref(conn);
+}
+
+static void flush_data(int fd, uint32_t len)
+{
+       int r;
+       uint32_t s;
+       char buf[4096];
+
+       while (len > 0) {
+               s = len > sizeof(buf) ? sizeof(buf) : len;
+
+               r = recv(fd, buf, s, 0);
+               if (r == -1)
+                       break;
+
+               len -= r;
+       }
+}
+
+static gboolean _alarm_agent_main(gint fd, GIOCondition condition,
+               gpointer user_data)
+{
+       int r;
+       int len;
+       int alarm_id;
+       int clifd;
+       char *service_name;
+       uint8_t *data;
+       struct sockaddr sa;
+       socklen_t addrlen;
+       GVariant *gv;
+
+       addrlen = sizeof(sa);
+       clifd = accept(fd, (struct sockaddr *)&sa, &addrlen);
+       if (clifd == -1) {
+               LOGE("Accept: %d", errno);
+               return G_SOURCE_REMOVE;
+       }
+
+       r = recv(clifd, &len, sizeof(len), 0);
+       if (r <= 0) {
+               if (r == 0) {
+                       LOGE("recv: fd %d closed", clifd);
+               } else {
+                       if (errno != EAGAIN && errno != EINTR)
+                               LOGE("recv: fd %d errno %d", clifd, errno);
+               }
+               return G_SOURCE_CONTINUE;
+       }
+
+       data = malloc(len);
+       if (!data) {
+               flush_data(clifd, len);
+               return G_SOURCE_CONTINUE;
+       }
+
+       r = recv(clifd, data, len, 0);
+       if (r <= 0) {
+               if (r == 0) {
+                       LOGE("recv: fd %d closed", clifd);
+               } else {
+                       if (errno != EAGAIN && errno != EINTR)
+                               LOGE("recv: fd %d errno %d", clifd, errno);
+               }
+
+               free(data);
+               return G_SOURCE_CONTINUE;
+       }
+
+       gv = g_variant_new_from_data(G_VARIANT_TYPE("(is)"),
+                       data, len, TRUE, NULL, NULL);
+       assert(gv);
+
+       g_variant_get(gv, "(i&s)", &alarm_id, &service_name);
+
+       _send_noti(service_name, alarm_id);
+       close(clifd);
+       return G_SOURCE_CONTINUE;
+}
+
+gboolean _timeout_handler(gpointer user_data)
+{
+       g_main_loop_quit(mainloop);
+       return G_SOURCE_REMOVE;
+}
+
+int main(int argc, char *argv[])
+{
+       int sock_fd;
+       char sockpath[PATH_MAX];
+
+       snprintf(sockpath, sizeof(sockpath), "/run/alarm_agent/%d", getuid());
+       LOGE("agent start");
+
+       sock_fd = _get_socket(sockpath);
+       if (sock_fd < 0) {
+               LOGE("agent pre init failed");
+               exit(0);
+       }
+
+       mainloop = g_main_loop_new(NULL, FALSE);
+       g_unix_fd_add(sock_fd, G_IO_IN, _alarm_agent_main, NULL);
+       g_timeout_add_seconds(100, _timeout_handler, NULL);
+
+       g_main_loop_run(mainloop);
+
+       g_main_loop_unref(mainloop);
+       close(sock_fd);
+
+       return 0;
+}
diff --git a/alarm-session-agent/agent.h b/alarm-session-agent/agent.h
new file mode 100644 (file)
index 0000000..c15d35e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * alarm session agent
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#define _GNU_SOURCE
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "ALARM_AGENT"
index 6214b6c..673260d 100644 (file)
@@ -43,6 +43,7 @@
 #define MAX_PKG_NAME_LEN MAX_SERVICE_NAME_LEN-8
 #define MAX_PKG_ID_LEN 256
 #define MIN_INEXACT_INTERVAL 600
+#define REGULAR_UID_MIN 5000
 
 #define SYSTEM_TIME_CHANGED "setting_time_changed"
 
@@ -70,6 +71,7 @@ application server.*/
 
 typedef struct {
        GDBusConnection *connection;
+       GDBusConnection *session_conn;
        GDBusProxy *proxy;
        guint sid; /* signal subscription id */
        alarm_cb_t alarm_handler;
diff --git a/packaging/alarm-agent.conf b/packaging/alarm-agent.conf
new file mode 100644 (file)
index 0000000..eae0124
--- /dev/null
@@ -0,0 +1 @@
+d /run/alarm_agent 0777 root users -
index 9456eb1..67bb34a 100644 (file)
@@ -6,7 +6,10 @@ Group:      System/Libraries
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
 Source1:    alarm-server.service
-Source2:    99-rtc.rules
+Source2:    alarm-session-agent.service
+Source3:    alarm-session-agent.socket
+Source4:    alarm-agent.conf
+Source5:    99-rtc.rules
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 
@@ -24,7 +27,7 @@ BuildRequires: pkgconfig(gio-2.0)
 BuildRequires: pkgconfig(gio-unix-2.0)
 BuildRequires: pkgconfig(capi-system-device)
 BuildRequires: pkgconfig(libtzplatform-config)
-BuildRequires: pkgconfig(libsystemd-login)
+BuildRequires: pkgconfig(libsystemd)
 BuildRequires: pkgconfig(eventsystem)
 BuildRequires: python-xml
 
@@ -86,10 +89,16 @@ rm -rf %{buildroot}
 %make_install
 
 mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
+mkdir -p %{buildroot}%{_unitdir_user}/sockets.target.wants
 install -m 0644 %SOURCE1 %{buildroot}%{_unitdir}/alarm-server.service
+install -m 0644 %SOURCE2 %{buildroot}%{_unitdir_user}/alarm-session-agent.service
+install -m 0644 %SOURCE3 %{buildroot}%{_unitdir_user}/alarm-session-agent.socket
 ln -s ../alarm-server.service %{buildroot}%{_unitdir}/multi-user.target.wants/alarm-server.service
+ln -sf ../alarm_session_agent.socket %{buildroot}%{_unitdir_user}/sockets.target.wants/alarm-session-agent.socket
+mkdir -p %{buildroot}%{_tmpfilesdir}
+install -m 0644 %SOURCE4 %{buildroot}%{_tmpfilesdir}/alarm-agent.conf
 mkdir -p %{buildroot}%{_libdir}/udev/rules.d
-install -m 0644 %SOURCE2 %{buildroot}%{_libdir}/udev/rules.d
+install -m 0644 %SOURCE5 %{buildroot}%{_libdir}/udev/rules.d
 
 %post -p /sbin/ldconfig
 
@@ -107,11 +116,16 @@ install -m 0644 %SOURCE2 %{buildroot}%{_libdir}/udev/rules.d
 %manifest alarm-server.manifest
 %{_bindir}/*
 %attr(0755,root,root) %{_bindir}/alarm-server
+%attr(0755,root,root) %{_bindir}/alarm_session_agent
 %attr(0644,root,root) %{_unitdir}/alarm-server.service
 %{_unitdir}/multi-user.target.wants/alarm-server.service
+%{_unitdir_user}/alarm-session-agent.service
+%{_unitdir_user}/alarm-session-agent.socket
+%{_unitdir_user}/sockets.target.wants/alarm-session-agent.socket
 %attr(0644,root,root) %{_datadir}/dbus-1/system-services/org.tizen.alarm.manager.service
 %license LICENSE
 %config %{_sysconfdir}/dbus-1/system.d/alarm-service.conf
+%{_tmpfilesdir}/alarm-agent.conf
 %{_libdir}/udev/rules.d/99-rtc.rules
 %if 0%{?appfw_feature_alarm_manager_module_log}
 %attr(0755,root,root) %{_sysconfdir}/dump.d/module.d/alarmmgr_log_dump.sh
diff --git a/packaging/alarm-session-agent.service b/packaging/alarm-session-agent.service
new file mode 100644 (file)
index 0000000..27a16b9
--- /dev/null
@@ -0,0 +1,9 @@
+[Unit]
+Description=Start the alarm agent
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/alarm_session_agent
+
+[Install]
+WantedBy=default.target
diff --git a/packaging/alarm-session-agent.socket b/packaging/alarm-session-agent.socket
new file mode 100644 (file)
index 0000000..63c0a4c
--- /dev/null
@@ -0,0 +1,9 @@
+[Socket]
+ListenStream=/run/alarm_agent/%U
+DirectoryMode=0777
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+ExecStartPost=/usr/bin/chmod 0777 /run/alarm_agent/%U
+
+[Install]
+WantedBy=sockets.target
index a18dcc8..8b0def5 100644 (file)
 #define EXPORT_API __attribute__ ((visibility("default")))
 #endif
 
-static alarm_context_t alarm_context = { NULL, NULL, 0, NULL, NULL, -1 };
+static alarm_context_t alarm_context = { NULL, NULL, NULL, 0, NULL, NULL, -1 };
 
 static bool b_initialized = false;
 static bool sub_initialized = false;
 
 static pthread_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static void __handle_expired_signal(GDBusConnection *conn,
-               const gchar *name, const gchar *path, const gchar *interface,
-               const gchar *signal_name, GVariant *param, gpointer user_data);
+static void __handle_expiry_method_call(GDBusConnection *conn,
+       const gchar *name, const gchar *path, const gchar *interface,
+       const gchar *method, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data);
 
 static int __alarm_validate_date(alarm_date_t *date, int *error_code);
 static bool __alarm_validate_time(alarm_date_t *date, int *error_code);
@@ -71,6 +71,26 @@ struct alarm_async_param_t {
 
 static alarm_cb_info_t *alarmcb_head = NULL;
 
+guint registration_id;
+
+static GDBusNodeInfo *introspection_data;
+
+static const gchar introspection_xml[] =
+  "<node name='/org/tizen/alarm/client'>"
+  "  <interface name='org.tizen.alarm.client'>"
+  "    <method name='alarm_expired'>"
+  "      <arg type='i' name='alarm_id' direction='in'/>"
+  "      <arg type='s' name='service_name' direction='in'/>"
+  "    </method>"
+  "  </interface>"
+  "</node>";
+
+static const GDBusInterfaceVTable interface_vtable = {
+       __handle_expiry_method_call,
+       NULL,
+       NULL
+};
+
 static void __add_resultcb(alarm_id_t alarm_id, alarm_cb_t cb_func, void *data)
 {
        alarm_cb_info_t *info;
@@ -125,28 +145,25 @@ static void __remove_resultcb(alarm_cb_info_t *info)
        }
 }
 
-static void __handle_expired_signal(GDBusConnection *conn,
+static void __handle_expiry_method_call(GDBusConnection *conn,
                const gchar *name, const gchar *path, const gchar *interface,
-               const gchar *signal_name, GVariant *param, gpointer user_data)
+               const gchar *method, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
-       gchar *package_name = NULL;
-       alarm_id_t alarm_id = 0;
-       alarm_cb_info_t *info;
-
-       if (signal_name == NULL || strcmp(signal_name, "alarm_expired") != 0)
-               ALARM_MGR_EXCEPTION_PRINT("[alarm-lib] : unexpected signal");
-
-       g_variant_get(param, "(is)", &alarm_id, &package_name);
-       ALARM_MGR_LOG_PRINT("[alarm-lib] : Alarm expired for [%s] : Alarm id [%d]", package_name, alarm_id);
+       if (method && strcmp(method, "alarm_expired") == 0) {
+               gchar *package_name = NULL;
+               alarm_id_t alarm_id = 0;
+               alarm_cb_info_t *info = NULL;
+               g_variant_get(param, "(i&s)", &alarm_id, &package_name);
+               ALARM_MGR_LOG_PRINT("[alarm-lib] : Alarm expired for [%s] : Alarm id [%d]", package_name, alarm_id);
 
-       if (alarm_context.alarm_handler != NULL)
-               alarm_context.alarm_handler(alarm_id, alarm_context.user_param);
+               if (alarm_context.alarm_handler != NULL)
+                       alarm_context.alarm_handler(alarm_id, alarm_context.user_param);
 
-       info = __find_resultcb(alarm_id);
-       if (info && info->cb_func)
-               info->cb_func(alarm_id, info->priv_data);
-
-       g_free(package_name);
+               info = __find_resultcb(alarm_id);
+               if (info && info->cb_func)
+                       info->cb_func(alarm_id, info->priv_data);
+       }
+       g_dbus_method_invocation_return_value(invocation, NULL);
 }
 
 static int __alarm_validate_date(alarm_date_t *date, int *error_code)
@@ -421,6 +438,7 @@ EXPORT_API int alarmmgr_init(const char *appid)
        guint owner_id = 0;
        int i = 0;
        int j = 0;
+       bool is_user = false;
 
        if (appid == NULL)
                return ERR_ALARM_INVALID_PARAM;
@@ -454,24 +472,35 @@ EXPORT_API int alarmmgr_init(const char *appid)
                j++;
        }
 
-       owner_id = g_bus_own_name_on_connection(alarm_context.connection, service_name_mod,
+       if (getuid() >= REGULAR_UID_MIN) {
+               is_user = true;
+               alarm_context.session_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
+       }
+
+       owner_id = g_bus_own_name_on_connection(is_user ?
+                       alarm_context.session_conn : alarm_context.connection,
+                       service_name_mod,
                        G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
        if (owner_id == 0) {
                ALARM_MGR_EXCEPTION_PRINT("Acquiring the own name is failed. %s", service_name_mod);
-               return ERR_ALARM_SYSTEM_FAIL;
+               goto error;
        }
 
-       alarm_context.sid = g_dbus_connection_signal_subscribe(
-                       alarm_context.connection,
-                       NULL,
-                       "org.tizen.alarm.manager",
-                       "alarm_expired",
-                       "/org/tizen/alarm/manager",
-                       NULL,
-                       G_DBUS_SIGNAL_FLAGS_NONE,
-                       __handle_expired_signal,
-                       NULL,
-                       NULL);
+       introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
+       if (introspection_data == NULL) {
+               ALARM_MGR_EXCEPTION_PRINT("g_dbus_node_info_new_for_xml() is failed.");
+               goto error;
+       }
+
+       registration_id = g_dbus_connection_register_object(is_user ?
+                       alarm_context.session_conn : alarm_context.connection,
+                       "/org/tizen/alarm/client",
+                       introspection_data->interfaces[0],
+                       &interface_vtable, NULL, NULL, NULL);
+       if (registration_id == 0) {
+               ALARM_MGR_EXCEPTION_PRINT("Registering the callback is failed.");
+               goto error;
+       }
 
        alarm_context.quark_app_service_name = g_quark_from_string(service_name);
        alarm_context.quark_app_service_name_mod = g_quark_from_string(service_name_mod);
@@ -480,6 +509,22 @@ EXPORT_API int alarmmgr_init(const char *appid)
 
        SECURE_LOGD("Leave");
        return ALARMMGR_RESULT_SUCCESS;
+
+error:
+       if (introspection_data)
+               g_dbus_node_info_unref(introspection_data);
+
+       if (registration_id != 0)
+               g_dbus_connection_unregister_object(alarm_context.connection, registration_id);
+
+       g_object_unref(alarm_context.proxy);
+       alarm_context.proxy = NULL;
+
+       g_object_unref(alarm_context.connection);
+       alarm_context.connection = NULL;
+
+       sub_initialized = false;
+       return ERR_ALARM_INVALID_PARAM;
 }
 
 EXPORT_API void alarmmgr_fini()
@@ -500,6 +545,11 @@ EXPORT_API void alarmmgr_fini()
                alarm_context.connection = NULL;
        }
 
+       if (alarm_context.connection) {
+               g_object_unref(alarm_context.session_conn);
+               alarm_context.session_conn = NULL;
+       }
+
        b_initialized = false;
        sub_initialized = false;