diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | alarm-manager.c | 89 | ||||
-rw-r--r-- | alarm-session-agent/CMakeLists.txt | 20 | ||||
-rw-r--r-- | alarm-session-agent/agent.c | 260 | ||||
-rw-r--r-- | alarm-session-agent/agent.h | 26 | ||||
-rw-r--r-- | include/alarm-internal.h | 2 | ||||
-rw-r--r-- | packaging/alarm-agent.conf | 1 | ||||
-rw-r--r-- | packaging/alarm-manager.spec | 20 | ||||
-rw-r--r-- | packaging/alarm-session-agent.service | 9 | ||||
-rw-r--r-- | packaging/alarm-session-agent.socket | 9 | ||||
-rw-r--r-- | src/alarm-lib.c | 120 |
11 files changed, 504 insertions, 53 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ce37919..e1c4786 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/alarm-manager.c b/alarm-manager.c index e36ad32..d068393 100644 --- a/alarm-manager.c +++ b/alarm-manager.c @@ -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 index 0000000..4b11ca4 --- /dev/null +++ b/alarm-session-agent/CMakeLists.txt @@ -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 index 0000000..0a59824 --- /dev/null +++ b/alarm-session-agent/agent.c @@ -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 index 0000000..c15d35e --- /dev/null +++ b/alarm-session-agent/agent.h @@ -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" diff --git a/include/alarm-internal.h b/include/alarm-internal.h index 6214b6c..673260d 100644 --- a/include/alarm-internal.h +++ b/include/alarm-internal.h @@ -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 index 0000000..eae0124 --- /dev/null +++ b/packaging/alarm-agent.conf @@ -0,0 +1 @@ +d /run/alarm_agent 0777 root users - diff --git a/packaging/alarm-manager.spec b/packaging/alarm-manager.spec index 9456eb1..67bb34a 100644 --- a/packaging/alarm-manager.spec +++ b/packaging/alarm-manager.spec @@ -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 index 0000000..27a16b9 --- /dev/null +++ b/packaging/alarm-session-agent.service @@ -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 index 0000000..63c0a4c --- /dev/null +++ b/packaging/alarm-session-agent.socket @@ -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 diff --git a/src/alarm-lib.c b/src/alarm-lib.c index a18dcc8..8b0def5 100644 --- a/src/alarm-lib.c +++ b/src/alarm-lib.c @@ -39,16 +39,16 @@ #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; |