summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiwoong Im <jiwoong.im@samsung.com>2016-05-17 20:51:53 +0900
committerJiwoong Im <jiwoong.im@samsung.com>2016-06-09 13:22:28 +0900
commitd5abb1c47bd8f545a201e5210285cf9f16ca4777 (patch)
treec054ea6242a7fa2430b1d4430128faa9d185dfba
parent29fbbe553ddbea5bc5f66f5ca95ead52e034077a (diff)
downloadalarm-manager-d5abb1c47bd8f545a201e5210285cf9f16ca4777.tar.gz
alarm-manager-d5abb1c47bd8f545a201e5210285cf9f16ca4777.tar.bz2
alarm-manager-d5abb1c47bd8f545a201e5210285cf9f16ca4777.zip
add alarm session agent
- 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>
-rw-r--r--CMakeLists.txt1
-rw-r--r--alarm-manager.c89
-rw-r--r--alarm-session-agent/CMakeLists.txt20
-rw-r--r--alarm-session-agent/agent.c260
-rw-r--r--alarm-session-agent/agent.h26
-rw-r--r--include/alarm-internal.h2
-rw-r--r--packaging/alarm-agent.conf1
-rw-r--r--packaging/alarm-manager.spec20
-rw-r--r--packaging/alarm-session-agent.service9
-rw-r--r--packaging/alarm-session-agent.socket9
-rw-r--r--src/alarm-lib.c120
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;