/*
- * Copyright 2013 Samsung Electronics Co., Ltd
+ * Copyright 2016 Samsung Electronics Co., Ltd
*
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * 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://floralicense.org/license/
+ * 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,
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define _GNU_SOURCE
#include <stdio.h>
-#include <pthread.h>
-#include <secure_socket.h>
-#include <packet.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/timerfd.h>
+#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-
+#include <gio/gio.h>
#include <dlog.h>
-#include <Eina.h>
-#include <com-core.h>
-#if defined(HAVE_LIVEBOX)
-#include <dynamicbox_errno.h>
-#else
-#include <lite-errno.h>
-#endif
+#include <notification_setting.h>
+#include <notification_setting_internal.h>
+#include <notification_setting_service.h>
+#include <notification_noti.h>
+#include <badge_setting.h>
+#include <badge_setting_service.h>
+#include <badge_db.h>
+#include <package-manager.h>
+#include <tzplatform_config.h>
+#include <pkgmgr-info.h>
-#include "service_common.h"
-#include "util.h"
#include "debug.h"
-#include "conf.h"
-
-#define EVT_CH 'e'
-#define EVT_END_CH 'x'
-#define DEFAULT_TIMEOUT 2.0f
-
-int errno;
-
-struct service_event_item {
- enum {
- SERVICE_EVENT_TIMER
- } type;
-
- union {
- struct {
- int fd;
- } timer;
- } info;
-
- int (*event_cb)(struct service_context *svc_cx, void *data);
- void *cbdata;
-};
-
-struct tcb_event_cbdata {
- struct tcb *tcb;
- void (*cb)(struct service_context *svc_ctx, struct tcb *tcb, void *data);
- void *data;
-};
-
-/*!
- * \note
- * Server information and global (only in this file-scope) variables are defined
- */
-struct service_context {
- pthread_t server_thid; /*!< Server thread Id */
- int fd; /*!< Server socket handle */
-
- Eina_List *tcb_list; /*!< TCB list, list of every thread for client connections */
- pthread_mutex_t tcb_list_lock;
-
- Eina_List *packet_list;
- pthread_mutex_t packet_list_lock;
- int evt_pipe[PIPE_MAX];
- int tcb_pipe[PIPE_MAX];
-
- int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data);
- void *service_thread_data;
+#include "pkgmgr.h"
+#include "service_common.h"
+#include "notification_service.h"
+#include "badge_service.h"
+#include "shortcut_service.h"
- Eina_List *event_list;
+#define DBUS_NAME "org.freedesktop.DBus"
+#define DBUS_OBJECT_PATH "/org/freedesktop/DBus"
+#define DBUS_INTERFACE_NAME "org.freedesktop.DBus"
- Eina_List *tcb_create_cb_list;
- Eina_List *tcb_destroy_cb_list;
-};
+#define PROVIDER_BUS_NAME "org.tizen.data_provider_service"
+#define PROVIDER_OBJECT_PATH "/org/tizen/data_provider_service"
-struct packet_info {
- struct tcb *tcb;
- struct packet *packet;
-};
+static GDBusConnection *_gdbus_conn;
+static GHashTable *_noti_pkg_privilege_info;
+static GHashTable *_badge_pkg_privilege_info;
-/*!
- * \note
- * Thread Control Block
- * - The main server will create a thread for every client connections.
- * When a new client is comming to us, this TCB block will be allocated and initialized.
- */
-struct tcb { /* Thread controll block */
- struct service_context *svc_ctx;
- pthread_t thid; /*!< Thread Id */
- int fd; /*!< Connection handle */
- enum tcb_type type;
- int ctrl_pipe[PIPE_MAX];
- pid_t pid; /*!< Keep the PID of client, if the client is remote one, this will be -1 */
-};
-
-/*!
- * Do services for clients
- * Routing packets to destination processes.
- * CLIENT THREAD
- */
-static void *client_packet_pump_main(void *data)
+uid_t get_sender_uid(const char *sender_name)
{
- struct tcb *tcb = data;
- struct service_context *svc_ctx = tcb->svc_ctx;
- struct packet *packet = NULL;
- fd_set set;
- char *ptr = NULL;
- int size = 0;
- int packet_offset = 0;
- int recv_offset = 0;
- long ret;
- int fd;
- char evt_ch = EVT_CH;
- enum {
- RECV_INIT,
- RECV_HEADER,
- RECV_PAYLOAD,
- RECV_DONE,
- } recv_state;
- struct packet_info *packet_info;
- Eina_List *l;
-
- ret = 0;
- recv_state = RECV_INIT;
- /*!
- * \note
- * To escape from the switch statement, we use this ret value
- */
- while (ret == 0) {
- FD_ZERO(&set);
- FD_SET(tcb->fd, &set);
- FD_SET(tcb->ctrl_pipe[PIPE_READ], &set);
- fd = tcb->fd > tcb->ctrl_pipe[PIPE_READ] ? tcb->fd : tcb->ctrl_pipe[PIPE_READ];
- ret = select(fd + 1, &set, NULL, NULL, NULL);
- if (ret < 0) {
- ret = -errno;
- if (errno == EINTR) {
- ErrPrint("INTERRUPTED\n");
- ret = 0;
- continue;
- }
- ErrPrint("Error: %s\n", strerror(errno));
- DbgFree(ptr);
- ptr = NULL;
- break;
- } else if (ret == 0) {
- ErrPrint("Timeout\n");
- ret = -ETIMEDOUT;
- DbgFree(ptr);
- ptr = NULL;
- break;
+ GDBusMessage *msg = NULL;
+ GDBusMessage *reply = NULL;
+ GError *err = NULL;
+ GVariant *body;
+ uid_t uid = 0;
+
+ msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
+ DBUS_INTERFACE_NAME, "GetConnectionUnixUser");
+ if (!msg) {
+ LOGE("Failed to alloc new method call");
+ goto out;
}
- if (FD_ISSET(tcb->ctrl_pipe[PIPE_READ], &set)) {
- DbgPrint("Thread is canceled\n");
- ret = -ECANCELED;
- DbgFree(ptr);
- ptr = NULL;
- break;
- }
+ g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
+ reply = g_dbus_connection_send_message_with_reply_sync(_gdbus_conn, msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
- if (!FD_ISSET(tcb->fd, &set)) {
- ErrPrint("Unexpected handler is toggled\n");
- ret = -EINVAL;
- DbgFree(ptr);
- ptr = NULL;
- break;
+ if (!reply) {
+ if (err != NULL) {
+ LOGE("Failed to get uid [%s]", err->message);
+ g_error_free(err);
+ }
+ goto out;
}
- /*!
- * \TODO
- * Service!!! Receive packet & route packet
- */
- switch (recv_state) {
- case RECV_INIT:
- size = packet_header_size();
- packet_offset = 0;
- recv_offset = 0;
- packet = NULL;
- ptr = malloc(size);
- if (!ptr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- ret = -ENOMEM;
- break;
- }
- recv_state = RECV_HEADER;
- /* Go through, don't break from here */
- case RECV_HEADER:
- ret = secure_socket_recv(tcb->fd, ptr, size - recv_offset, &tcb->pid);
- if (ret <= 0) {
- if (ret == 0) {
- ret = -ECANCELED;
- }
- DbgFree(ptr);
- ptr = NULL;
- break;
- }
+ body = g_dbus_message_get_body(reply);
+ g_variant_get(body, "(u)", &uid);
- recv_offset += ret;
- ret = 0;
-
- if (recv_offset == size) {
- packet = packet_build(packet, packet_offset, ptr, size);
- DbgFree(ptr);
- ptr = NULL;
- if (!packet) {
- ret = -EFAULT;
- break;
- }
-
- packet_offset += recv_offset;
-
- size = packet_payload_size(packet);
- if (size <= 0) {
- recv_state = RECV_DONE;
- recv_offset = 0;
- break;
- }
-
- recv_state = RECV_PAYLOAD;
- recv_offset = 0;
-
- ptr = malloc(size);
- if (!ptr) {
- ErrPrint("Heap: %s\n", strerror(errno));
- ret = -ENOMEM;
- }
- }
- break;
- case RECV_PAYLOAD:
- ret = secure_socket_recv(tcb->fd, ptr, size - recv_offset, &tcb->pid);
- if (ret <= 0) {
- if (ret == 0) {
- ret = -ECANCELED;
- }
- DbgFree(ptr);
- ptr = NULL;
- break;
- }
+out:
+ if (msg)
+ g_object_unref(msg);
+ if (reply)
+ g_object_unref(reply);
- recv_offset += ret;
- ret = 0;
+ return uid;
+}
- if (recv_offset == size) {
- packet = packet_build(packet, packet_offset, ptr, size);
- DbgFree(ptr);
- ptr = NULL;
- if (!packet) {
- ret = -EFAULT;
- break;
- }
+pid_t get_sender_pid(const char *sender_name)
+{
+ GDBusMessage *msg = NULL;
+ GDBusMessage *reply = NULL;
+ GError *err = NULL;
+ GVariant *body;
+ pid_t pid = 0;
+
+ msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
+ DBUS_INTERFACE_NAME, "GetConnectionUnixProcessID");
+ if (!msg) {
+ LOGE("Failed to alloc new method call");
+ goto out;
+ }
- packet_offset += recv_offset;
+ g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
+ reply = g_dbus_connection_send_message_with_reply_sync(_gdbus_conn, msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
- recv_state = RECV_DONE;
- recv_offset = 0;
+ if (!reply) {
+ if (err != NULL) {
+ LOGE("Failed to get uid [%s]", err->message);
+ g_error_free(err);
}
- break;
- case RECV_DONE:
- default:
- /* Dead code */
- break;
+ goto out;
}
- if (recv_state == RECV_DONE) {
- /*!
- * Push this packet to the packet list with TCB
- * Then the service main function will get this.
- */
- packet_info = malloc(sizeof(*packet_info));
- if (!packet_info) {
- ret = -errno;
- ErrPrint("Heap: %s\n", strerror(errno));
- packet_destroy(packet);
- break;
- }
-
- packet_info->packet = packet;
- packet_info->tcb = tcb;
-
- CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
- svc_ctx->packet_list = eina_list_append(svc_ctx->packet_list, packet_info);
- CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
-
- if (write(svc_ctx->evt_pipe[PIPE_WRITE], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) {
- ret = -errno;
- ErrPrint("Unable to write a pipe: %s\n", strerror(errno));
- CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
- svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
- CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
-
- packet_destroy(packet);
- DbgFree(packet_info);
- ErrPrint("Terminate thread: %p\n", tcb);
- break;
- } else {
- DbgPrint("Packet received: %d bytes\n", packet_offset);
- recv_state = RECV_INIT;
- }
-
- /* Take a breathe */
- pthread_yield();
- }
- }
+ body = g_dbus_message_get_body(reply);
+ g_variant_get(body, "(u)", &pid);
- CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
- EINA_LIST_FOREACH(svc_ctx->packet_list, l, packet_info) {
- if (packet_info->tcb == tcb) {
- DbgPrint("Reset ptr of the TCB[%p] in the list of packet info\n", tcb);
- packet_info->tcb = NULL;
- }
- }
- CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
-
- /*!
- * \note
- * Emit a signal to collect this TCB from the SERVER THREAD.
- */
- if (write(svc_ctx->tcb_pipe[PIPE_WRITE], &tcb, sizeof(tcb)) != sizeof(tcb)) {
- ErrPrint("Unable to write pipe: %s\n", strerror(errno));
- }
-
- return (void *)ret;
-}
+out:
+ if (msg)
+ g_object_unref(msg);
+ if (reply)
+ g_object_unref(reply);
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int service_register_tcb_callback(struct service_context *svc_ctx, struct tcb *tcb, enum tcb_event_type event, void (*cb)(struct service_context *svc_ctx, struct tcb *tcb, void *data), void *data)
-{
- struct tcb_event_cbdata *cbdata;
-
- cbdata = malloc(sizeof(*cbdata));
- if (!cbdata) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
- }
-
- cbdata->tcb = tcb;
- cbdata->cb = cb;
- cbdata->data = data;
-
- switch (event) {
- case TCB_EVENT_CREATE:
- if (tcb) {
- DbgPrint("To catch the create event of TCB does not requires \"tcb\" handle\n");
- }
- svc_ctx->tcb_create_cb_list = eina_list_append(svc_ctx->tcb_create_cb_list, cbdata);
- break;
- case TCB_EVENT_DESTROY:
- svc_ctx->tcb_destroy_cb_list = eina_list_append(svc_ctx->tcb_destroy_cb_list, cbdata);
- break;
- default:
- DbgFree(cbdata);
- return DBOX_STATUS_ERROR_INVALID_PARAMETER;
- }
-
- return DBOX_STATUS_ERROR_NONE;
+ return pid;
}
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int service_unregister_tcb_callback(struct service_context *svc_ctx, struct tcb *tcb, enum tcb_event_type event, void (*cb)(struct service_context *svc_ctx, struct tcb *tcb, void *data), void *data)
+bool is_existed_busname(const char *sender_name)
{
- struct tcb_event_cbdata *cbdata;
- Eina_List *l;
-
- switch (event) {
- case TCB_EVENT_CREATE:
- EINA_LIST_FOREACH(svc_ctx->tcb_create_cb_list, l, cbdata) {
- if (cbdata->tcb == tcb && cbdata->cb == cb && cbdata->data == data) {
- svc_ctx->tcb_create_cb_list = eina_list_remove(svc_ctx->tcb_create_cb_list, cbdata);
- DbgFree(cbdata);
- return DBOX_STATUS_ERROR_NONE;
- }
- }
- break;
- case TCB_EVENT_DESTROY:
- EINA_LIST_FOREACH(svc_ctx->tcb_destroy_cb_list, l, cbdata) {
- if (cbdata->tcb == tcb && cbdata->cb == cb && cbdata->data == data) {
- svc_ctx->tcb_destroy_cb_list = eina_list_remove(svc_ctx->tcb_destroy_cb_list, cbdata);
- DbgFree(cbdata);
- return DBOX_STATUS_ERROR_NONE;
- }
- }
- break;
- default:
- return DBOX_STATUS_ERROR_INVALID_PARAMETER;
- }
-
- return DBOX_STATUS_ERROR_NOT_EXIST;
-}
-
-/*!
- * \note
- * SERVER THREAD
- */
-static inline struct tcb *tcb_create(struct service_context *svc_ctx, int fd)
-{
- struct tcb *tcb;
- int status;
- struct tcb_event_cbdata *cbdata;
- Eina_List *l;
- Eina_List *n;
-
- tcb = malloc(sizeof(*tcb));
- if (!tcb) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return NULL;
- }
-
- if (pipe2(tcb->ctrl_pipe, O_CLOEXEC) < 0) {
- ErrPrint("pipe2: %s\n", strerror(errno));
- DbgFree(tcb);
- return NULL;
- }
-
- tcb->fd = fd;
- tcb->svc_ctx = svc_ctx;
- tcb->type = TCB_CLIENT_TYPE_APP;
- tcb->pid = -1;
-
- DbgPrint("Create a new service thread [%d]\n", fd);
- status = pthread_create(&tcb->thid, NULL, client_packet_pump_main, tcb);
- if (status != 0) {
- ErrPrint("Unable to create a new thread: %s\n", strerror(status));
- CLOSE_PIPE(tcb->ctrl_pipe);
- DbgFree(tcb);
- return NULL;
- }
-
- CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
- svc_ctx->tcb_list = eina_list_append(svc_ctx->tcb_list, tcb);
- CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
-
- EINA_LIST_FOREACH_SAFE(svc_ctx->tcb_create_cb_list, l, n, cbdata) {
- if (!cbdata->cb) {
- /* ASSERT */
- ErrPrint("invalid CB\n");
- svc_ctx->tcb_create_cb_list = eina_list_remove(svc_ctx->tcb_create_cb_list, cbdata);
- DbgFree(cbdata);
- continue;
+ GDBusMessage *msg = NULL;
+ GDBusMessage *reply = NULL;
+ GError *err = NULL;
+ GVariant *body;
+ bool is_existed = false;
+
+ msg = g_dbus_message_new_method_call(DBUS_NAME, DBUS_OBJECT_PATH,
+ DBUS_INTERFACE_NAME, "NameHasOwner");
+ if (!msg) {
+ LOGE("Failed to alloc new method call");
+ goto out;
}
- cbdata->cb(svc_ctx, tcb, cbdata->data);
- }
-
- return tcb;
-}
+ g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
+ reply = g_dbus_connection_send_message_with_reply_sync(_gdbus_conn, msg,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
-/*!
- * \note
- * SERVER THREAD
- */
-static inline void tcb_teminate_all(struct service_context *svc_ctx)
-{
- struct tcb *tcb;
- void *ret;
- int status;
- char ch = EVT_END_CH;
-
- /*!
- * We don't need to make critical section on here.
- * If we call this after terminate the server thread first.
- * Then there is no other thread to access tcb_list.
- */
- EINA_LIST_FREE(svc_ctx->tcb_list, tcb) {
- /*!
- * ASSERT(tcb->fd >= 0);
- */
- if (write(tcb->ctrl_pipe[PIPE_WRITE], &ch, sizeof(ch)) != sizeof(ch)) {
- ErrPrint("write: %s\n", strerror(errno));
+ if (!reply) {
+ if (err != NULL) {
+ LOGE("Failed to get uid [%s]", err->message);
+ g_error_free(err);
+ }
+ goto out;
}
- status = pthread_join(tcb->thid, &ret);
- if (status != 0) {
- ErrPrint("Unable to join a thread: %s\n", strerror(status));
- } else {
- DbgPrint("Thread returns: %p\n", ret);
- }
+ body = g_dbus_message_get_body(reply);
+ g_variant_get(body, "(b)", &is_existed);
- secure_socket_destroy_handle(tcb->fd);
+out:
+ if (msg)
+ g_object_unref(msg);
+ if (reply)
+ g_object_unref(reply);
- CLOSE_PIPE(tcb->ctrl_pipe);
- DbgFree(tcb);
- }
+ return is_existed;
}
-/*!
- * \note
- * SERVER THREAD
- */
-static inline void tcb_destroy(struct service_context *svc_ctx, struct tcb *tcb)
+int send_notify(GVariant *body, char *cmd, GHashTable **monitoring_hash, char *interface_name, uid_t uid)
{
- void *ret;
- int status;
- char ch = EVT_END_CH;
- struct tcb_event_cbdata *cbdata;
- Eina_List *l;
- Eina_List *n;
-
- EINA_LIST_FOREACH_SAFE(svc_ctx->tcb_destroy_cb_list, l, n, cbdata) {
- if (!cbdata->cb) {
- /* ASSERT */
- ErrPrint("invalid CB\n");
- svc_ctx->tcb_destroy_cb_list = eina_list_remove(svc_ctx->tcb_destroy_cb_list, cbdata);
- DbgFree(cbdata);
- continue;
- }
-
- if (cbdata->tcb != tcb) {
- continue;
+ GError *err = NULL;
+ GList *monitoring_list = NULL;
+ GList *target_list;
+ char *target_bus_name;
+ int monitoring_count = 0;
+ bool is_existed = false;
+
+ monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(uid));
+ target_list = g_list_first(monitoring_list);
+ for (; target_list != NULL; ) {
+ err = NULL;
+ target_bus_name = target_list->data;
+ target_list = target_list->next;
+
+ if (g_variant_is_floating(body))
+ g_variant_ref(body);
+
+ if (g_dbus_connection_emit_signal(_gdbus_conn,
+ target_bus_name,
+ PROVIDER_OBJECT_PATH,
+ interface_name,
+ cmd,
+ body,
+ &err) == FALSE) {
+ if (err != NULL) {
+ ERR("Emit signal err [%s]", err->message);
+ g_error_free(err);
+ }
+ is_existed = is_existed_busname(target_bus_name);
+ if (is_existed == false)
+ delete_monitoring_list(monitoring_hash, target_bus_name, uid);
+ ERR("Fail, emit signal to [%s]", target_bus_name);
+ }
+ monitoring_count++;
+ DBG("Success, emit signal to [%s]", target_bus_name);
}
- cbdata->cb(svc_ctx, tcb, cbdata->data);
-
- if (eina_list_data_find(svc_ctx->tcb_destroy_cb_list, cbdata)) {
- svc_ctx->tcb_destroy_cb_list = eina_list_remove(svc_ctx->tcb_destroy_cb_list, cbdata);
- DbgFree(cbdata);
- }
- }
-
- CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
- svc_ctx->tcb_list = eina_list_remove(svc_ctx->tcb_list, tcb);
- CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
- /*!
- * ASSERT(tcb->fd >= 0);
- * Close the connection, and then collecting the return value of thread
- */
- if (write(tcb->ctrl_pipe[PIPE_WRITE], &ch, sizeof(ch)) != sizeof(ch)) {
- ErrPrint("write: %s\n", strerror(errno));
- }
-
- status = pthread_join(tcb->thid, &ret);
- if (status != 0) {
- ErrPrint("Unable to join a thread: %s\n", strerror(status));
- } else {
- DbgPrint("Thread returns: %p\n", ret);
- }
-
- secure_socket_destroy_handle(tcb->fd);
-
- CLOSE_PIPE(tcb->ctrl_pipe);
- DbgFree(tcb);
+ DBG("Success, cmd[%s] monitoring count[%d]", cmd, monitoring_count);
+ return SERVICE_COMMON_ERROR_NONE;
}
-/*!
- * \note
- * SERVER THREAD
- */
-static inline int update_fdset(struct service_context *svc_ctx, fd_set *set)
+int send_event_notify_by_busname(GVariant *body, char *cmd, char *busname, char *interface_name)
{
- Eina_List *l;
- struct service_event_item *item;
- int fd = 0;
-
- FD_ZERO(set);
-
- FD_SET(svc_ctx->fd, set);
- fd = svc_ctx->fd;
-
- FD_SET(svc_ctx->tcb_pipe[PIPE_READ], set);
- if (svc_ctx->tcb_pipe[PIPE_READ] > fd) {
- fd = svc_ctx->tcb_pipe[PIPE_READ];
- }
-
- FD_SET(svc_ctx->evt_pipe[PIPE_READ], set);
- if (svc_ctx->evt_pipe[PIPE_READ] > fd) {
- fd = svc_ctx->evt_pipe[PIPE_READ];
- }
-
- EINA_LIST_FOREACH(svc_ctx->event_list, l, item) {
- if (item->type == SERVICE_EVENT_TIMER) {
- FD_SET(item->info.timer.fd, set);
- if (fd < item->info.timer.fd) {
- fd = item->info.timer.fd;
- }
+ GError *err = NULL;
+
+ if (g_variant_is_floating(body))
+ g_variant_ref(body);
+
+ if (g_dbus_connection_emit_signal(_gdbus_conn,
+ busname,
+ PROVIDER_OBJECT_PATH,
+ interface_name,
+ cmd,
+ body,
+ &err) == FALSE) {
+ if (err != NULL) {
+ ERR("Emit signal err [%s]",
+ err->message);
+ g_error_free(err);
+ }
+ ERR("Failed to emit signal to [%s]", busname);
+ return SERVICE_COMMON_ERROR_IO_ERROR;
}
- }
+ DBG("Success, Emit signal to [%s] cmd[%s]", busname, cmd);
+ return SERVICE_COMMON_ERROR_NONE;
+}
- return fd + 1;
+/* register service */
+
+static int _monitoring_app_list_compare_cb(gconstpointer a, gconstpointer b)
+{
+ return strcmp(a, b);
}
-/*!
- * \note
- * SERVER THREAD
- */
-static inline void processing_timer_event(struct service_context *svc_ctx, fd_set *set)
+int service_register(GVariant *parameters, GVariant **reply_body, const gchar *sender,
+ GBusNameAppearedCallback name_appeared_handler,
+ GBusNameVanishedCallback name_vanished_handler,
+ GHashTable **monitoring_hash,
+ uid_t uid)
{
- uint64_t expired_count;
- Eina_List *l;
- Eina_List *n;
- struct service_event_item *item;
-
- EINA_LIST_FOREACH_SAFE(svc_ctx->event_list, l, n, item) {
- switch (item->type) {
- case SERVICE_EVENT_TIMER:
- if (!FD_ISSET(item->info.timer.fd, set)) {
- break;
+ GList *added_list = NULL;
+ const char *bus_name = sender;
+ monitoring_info_s *m_info = NULL;
+ uid_t request_uid = 0;
+ GList *monitoring_list = NULL;
+
+ if (sender == NULL)
+ return SERVICE_COMMON_ERROR_IO_ERROR;
+
+ g_variant_get(parameters, "(i)", &request_uid);
+ if (uid > NORMAL_UID_BASE && uid != request_uid)
+ return SERVICE_COMMON_ERROR_IO_ERROR;
+
+ DBG("service_register : uid %d , request_uid %d", uid, request_uid);
+ monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid));
+ added_list = g_list_find_custom(monitoring_list, bus_name,
+ (GCompareFunc)_monitoring_app_list_compare_cb);
+
+ if (added_list == NULL) {
+ DBG("add new sender to list");
+ m_info = (monitoring_info_s *)calloc(1, sizeof(monitoring_info_s));
+ if (m_info == NULL) {
+ ERR("Failed to alloc memory");
+ return SERVICE_COMMON_ERROR_IO_ERROR;
}
- if (read(item->info.timer.fd, &expired_count, sizeof(expired_count)) == sizeof(expired_count)) {
- DbgPrint("Expired %d times\n", expired_count);
- if (item->event_cb(svc_ctx, item->cbdata) >= 0) {
- break;
- }
- } else {
- ErrPrint("read: %s\n", strerror(errno));
+ m_info->bus_name = strdup(bus_name);
+ m_info->uid = request_uid;
+ m_info->watcher_id = g_bus_watch_name_on_connection(
+ _gdbus_conn,
+ bus_name,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ name_appeared_handler,
+ name_vanished_handler,
+ m_info,
+ NULL);
+ if (m_info->watcher_id == 0) {
+ ERR("Fail to watch name [%s]", bus_name);
+ free(m_info->bus_name);
+ free(m_info);
+ return SERVICE_COMMON_ERROR_IO_ERROR;
}
+ DBG("Watch on [%s] success", bus_name);
- if (!eina_list_data_find(svc_ctx->event_list, item)) {
- break;
- }
+ monitoring_list = g_list_append(monitoring_list, strdup(bus_name));
+ DBG("Success, sender[%s] length[%d]",
+ sender, g_list_length(monitoring_list));
+ if (g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid)) == NULL)
+ g_hash_table_insert(*monitoring_hash, GUINT_TO_POINTER(request_uid), monitoring_list);
+ } else {
+ ERR("Sender [%s] already exist", sender);
+ }
- svc_ctx->event_list = eina_list_remove(svc_ctx->event_list, item);
- if (close(item->info.timer.fd) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
+ *reply_body = g_variant_new("()");
+ if (*reply_body == NULL) {
+ if (m_info) {
+ if (m_info->bus_name)
+ free(m_info->bus_name);
+ free(m_info);
}
- DbgFree(item);
- break;
- default:
- ErrPrint("Unknown event: %d\n", item->type);
- break;
+ monitoring_list = g_list_remove(monitoring_list, bus_name);
+ ERR("Failed to make reply");
+ return SERVICE_COMMON_ERROR_OUT_OF_MEMORY;
}
- }
+ return SERVICE_COMMON_ERROR_NONE;
}
-/*!
- * Accept new client connections
- * And create a new thread for service.
- *
- * Create Client threads & Destroying them
- * SERVER THREAD
- */
-static void *server_main(void *data)
+int delete_monitoring_list(GHashTable **monitoring_hash, const char *sender, uid_t uid)
{
- struct service_context *svc_ctx = data;
- fd_set set;
- fd_set except_set;
- long ret;
- int client_fd;
- struct tcb *tcb;
- int fd;
- char evt_ch;
- struct packet_info *packet_info;
-
- DbgPrint("Server thread is activated\n");
- while (1) {
- fd = update_fdset(svc_ctx, &set);
- memcpy(&except_set, &set, sizeof(set));
-
- ret = select(fd, &set, NULL, &except_set, NULL);
- if (ret < 0) {
- ret = -errno;
- if (errno == EINTR) {
- DbgPrint("INTERRUPTED\n");
- continue;
- }
- ErrPrint("Error: %s\n", strerror(errno));
- break;
- } else if (ret == 0) {
- ErrPrint("Timeout\n");
- ret = -ETIMEDOUT;
- break;
- }
-
- if (FD_ISSET(svc_ctx->fd, &set)) {
- client_fd = secure_socket_get_connection_handle(svc_ctx->fd);
- if (client_fd < 0) {
- ErrPrint("Failed to establish a new connection [%d]\n", svc_ctx->fd);
- ret = -EFAULT;
- break;
- }
-
- tcb = tcb_create(svc_ctx, client_fd);
- if (!tcb) {
- ErrPrint("Failed to create a new TCB: %d (%d)\n", client_fd, svc_ctx->fd);
- secure_socket_destroy_handle(client_fd);
- }
+ GList *monitoring_list = NULL;
+ GList *del_list = NULL;
+ char *bus_name;
+
+ monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(uid));
+ if (monitoring_list == NULL) {
+ ERR("No uid[%d] in monitoring hash", uid);
+ return SERVICE_COMMON_ERROR_IO_ERROR;
}
- if (FD_ISSET(svc_ctx->evt_pipe[PIPE_READ], &set)) {
- if (read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch)) != sizeof(evt_ch)) {
- ErrPrint("Unable to read pipe: %s\n", strerror(errno));
- ret = -EFAULT;
- break;
- }
-
- CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
- packet_info = eina_list_nth(svc_ctx->packet_list, 0);
- svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
- CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
-
- if (packet_info) {
- /*!
- * \CRITICAL
- * What happens if the client thread is terminated, so the packet_info->tcb is deleted
- * while processing svc_ctx->service_thread_main?
- */
- ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
- if (ret < 0) {
- ErrPrint("Service thread returns: %d\n", ret);
- }
-
- packet_destroy(packet_info->packet);
- DbgFree(packet_info);
- }
-
- /* Take a breathe */
- pthread_yield();
- }
+ monitoring_list = g_list_first(monitoring_list);
+ del_list = g_list_find_custom(monitoring_list, sender,
+ (GCompareFunc)_monitoring_app_list_compare_cb);
- processing_timer_event(svc_ctx, &set);
-
- /*!
- * \note
- * Destroying TCB should be processed at last.
- */
- if (FD_ISSET(svc_ctx->tcb_pipe[PIPE_READ], &set)) {
- Eina_List *lockfree_packet_list;
- Eina_List *l;
- Eina_List *n;
-
- if (read(svc_ctx->tcb_pipe[PIPE_READ], &tcb, sizeof(tcb)) != sizeof(tcb)) {
- ErrPrint("Unable to read pipe: %s\n", strerror(errno));
- ret = -EFAULT;
- break;
- }
-
- if (!tcb) {
- ErrPrint("Terminate service thread\n");
- ret = -ECANCELED;
- break;
- }
-
- lockfree_packet_list = NULL;
- CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
- EINA_LIST_FOREACH_SAFE(svc_ctx->packet_list, l, n, packet_info) {
- if (packet_info->tcb != tcb) {
- continue;
- }
+ if (del_list) {
+ DBG("Find delete list - uid[%d] sender[%s]", uid, sender);
+ bus_name = g_list_nth_data(del_list, 0);
+ if (bus_name)
+ free(bus_name);
+ monitoring_list = g_list_delete_link(monitoring_list, del_list);
- svc_ctx->packet_list = eina_list_remove(svc_ctx->packet_list, packet_info);
- lockfree_packet_list = eina_list_append(lockfree_packet_list, packet_info);
- }
- CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
-
- EINA_LIST_FREE(lockfree_packet_list, packet_info) {
- ret = read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch));
- DbgPrint("Flushing filtered pipe: %d (%c)\n", ret, evt_ch);
- ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
- if (ret < 0) {
- ErrPrint("Service thread returns: %d\n", ret);
+ if (monitoring_list == NULL) {
+ g_hash_table_steal(*monitoring_hash, GUINT_TO_POINTER(uid));
+ } else {
+ monitoring_list = g_list_first(monitoring_list);
+ g_hash_table_replace(*monitoring_hash, GUINT_TO_POINTER(uid), monitoring_list);
}
- packet_destroy(packet_info->packet);
- DbgFree(packet_info);
- }
-
- /*!
- * \note
- * Invoke the service thread main, to notify the termination of a TCB
- */
- ret = svc_ctx->service_thread_main(tcb, NULL, svc_ctx->service_thread_data);
-
- /*!
- * at this time, the client thread can access this tcb.
- * how can I protect this TCB from deletion without disturbing the server thread?
- */
- tcb_destroy(svc_ctx, tcb);
}
+ return SERVICE_COMMON_ERROR_NONE;
+}
- /* If there is no such triggered FD? */
- }
-
- /*!
- * Consuming all pended packets before terminates server thread.
- *
- * If the server thread is terminated, we should flush all pended packets.
- * And we should services them.
- * While processing this routine, the mutex is locked.
- * So every other client thread will be slowed down, sequently, every clients can meet problems.
- * But in case of termination of server thread, there could be systemetic problem.
- * This only should be happenes while terminating the master daemon process.
- */
- CRITICAL_SECTION_BEGIN(&svc_ctx->packet_list_lock);
- EINA_LIST_FREE(svc_ctx->packet_list, packet_info) {
- ret = read(svc_ctx->evt_pipe[PIPE_READ], &evt_ch, sizeof(evt_ch));
- DbgPrint("Flushing pipe: %d (%c)\n", ret, evt_ch);
- ret = svc_ctx->service_thread_main(packet_info->tcb, packet_info->packet, svc_ctx->service_thread_data);
- if (ret < 0) {
- ErrPrint("Service thread returns: %d\n", ret);
+static int _dbus_init(void)
+{
+ GError *error = NULL;
+
+ if (_gdbus_conn == NULL) {
+ _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (_gdbus_conn == NULL) {
+ if (error != NULL) {
+ ERR("Failed to get dbus [%s]", error->message);
+ g_error_free(error);
+ }
+ return SERVICE_COMMON_ERROR_IO_ERROR;
+ }
}
- packet_destroy(packet_info->packet);
- DbgFree(packet_info);
- }
- CRITICAL_SECTION_END(&svc_ctx->packet_list_lock);
- tcb_teminate_all(svc_ctx);
- return (void *)ret;
+ return SERVICE_COMMON_ERROR_NONE;
}
-/*!
- * \NOTE
- * MAIN THREAD
- */
-HAPI struct service_context *service_common_create(const char *addr, int (*service_thread_main)(struct tcb *tcb, struct packet *packet, void *data), void *data)
+int service_common_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable)
{
- int status;
- struct service_context *svc_ctx;
-
- if (!service_thread_main || !addr) {
- ErrPrint("Invalid argument\n");
- return NULL;
- }
-
- if (strncmp(addr, COM_CORE_REMOTE_SCHEME, strlen(COM_CORE_REMOTE_SCHEME))) {
- int offset = 0;
-
- offset = strlen(COM_CORE_LOCAL_SCHEME);
- if (strncmp(addr, COM_CORE_LOCAL_SCHEME, offset)) {
- offset = 0;
+ int result;
+ int owner_id, noti_registration_id;
+ GError *error = NULL;
+ GDBusNodeInfo *introspection_data = NULL;
+
+ result = _dbus_init();
+ if (result != SERVICE_COMMON_ERROR_NONE) {
+ ERR("Can't init dbus [%d]", result);
+ result = SERVICE_COMMON_ERROR_IO_ERROR;
+ goto out;
}
- if (unlink(addr + offset) < 0) {
- ErrPrint("[%s] - %s\n", addr, strerror(errno));
+ owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ PROVIDER_BUS_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL,
+ NULL,
+ NULL,
+ NULL, NULL);
+ if (!owner_id) {
+ ERR("Failed to own name");
+ result = SERVICE_COMMON_ERROR_IO_ERROR;
+ goto out;
}
- }
-
- svc_ctx = calloc(1, sizeof(*svc_ctx));
- if (!svc_ctx) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return NULL;
- }
-
- svc_ctx->fd = secure_socket_create_server(addr);
- if (svc_ctx->fd < 0) {
- DbgFree(svc_ctx);
- return NULL;
- }
-
- svc_ctx->service_thread_main = service_thread_main;
- svc_ctx->service_thread_data = data;
-
- if (fcntl(svc_ctx->fd, F_SETFD, FD_CLOEXEC) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
- }
-
- if (fcntl(svc_ctx->fd, F_SETFL, O_NONBLOCK) < 0) {
- ErrPrint("fcntl: %s\n", strerror(errno));
- }
-
- if (pipe2(svc_ctx->evt_pipe, O_CLOEXEC) < 0) {
- ErrPrint("pipe: %d\n", strerror(errno));
- secure_socket_destroy_handle(svc_ctx->fd);
- DbgFree(svc_ctx);
- return NULL;
- }
-
- if (pipe2(svc_ctx->tcb_pipe, O_CLOEXEC) < 0) {
- ErrPrint("pipe: %s\n", strerror(errno));
- CLOSE_PIPE(svc_ctx->evt_pipe);
- secure_socket_destroy_handle(svc_ctx->fd);
- DbgFree(svc_ctx);
- return NULL;
- }
-
- status = pthread_mutex_init(&svc_ctx->packet_list_lock, NULL);
- if (status != 0) {
- ErrPrint("Unable to create a mutex: %s\n", strerror(status));
- CLOSE_PIPE(svc_ctx->evt_pipe);
- CLOSE_PIPE(svc_ctx->tcb_pipe);
- secure_socket_destroy_handle(svc_ctx->fd);
- DbgFree(svc_ctx);
- return NULL;
- }
-
- DbgPrint("Creating server thread\n");
- status = pthread_create(&svc_ctx->server_thid, NULL, server_main, svc_ctx);
- if (status != 0) {
- ErrPrint("Unable to create a thread for shortcut service: %s\n", strerror(status));
- status = pthread_mutex_destroy(&svc_ctx->packet_list_lock);
- if (status != 0) {
- ErrPrint("Error: %s\n", strerror(status));
+
+ DBG("Acquiring the own name [%d]", owner_id);
+ introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
+ if (!introspection_data) {
+ ERR("g_dbus_node_info_new_for_xml is failed.");
+ result = SERVICE_COMMON_ERROR_IO_ERROR;
+ if (error != NULL) {
+ ERR("g_dbus_node_info_new_for_xml err [%s]", error->message);
+ g_error_free(error);
+ }
+ goto out;
}
- CLOSE_PIPE(svc_ctx->evt_pipe);
- CLOSE_PIPE(svc_ctx->tcb_pipe);
- secure_socket_destroy_handle(svc_ctx->fd);
- DbgFree(svc_ctx);
- return NULL;
- }
-
- /*!
- * \note
- * To give a chance to run for server thread.
- */
- pthread_yield();
-
- return svc_ctx;
-}
-/*!
- * \note
- * MAIN THREAD
- */
-HAPI int service_common_destroy(struct service_context *svc_ctx)
-{
- int status = 0;
- void *ret;
-
- if (!svc_ctx) {
- return -EINVAL;
- }
-
- /*!
- * \note
- * Terminate server thread
- */
- if (write(svc_ctx->tcb_pipe[PIPE_WRITE], &status, sizeof(status)) != sizeof(status)) {
- ErrPrint("Failed to write: %s\n", strerror(errno));
- }
-
- status = pthread_join(svc_ctx->server_thid, &ret);
- if (status != 0) {
- ErrPrint("Join: %s\n", strerror(status));
- } else {
- DbgPrint("Thread returns: %p\n", ret);
- }
-
- secure_socket_destroy_handle(svc_ctx->fd);
-
- status = pthread_mutex_destroy(&svc_ctx->packet_list_lock);
- if (status != 0) {
- ErrPrint("Unable to destroy a mutex: %s\n", strerror(status));
- }
-
- CLOSE_PIPE(svc_ctx->evt_pipe);
- CLOSE_PIPE(svc_ctx->tcb_pipe);
- DbgFree(svc_ctx);
- return 0;
-}
+ noti_registration_id = g_dbus_connection_register_object(_gdbus_conn,
+ PROVIDER_OBJECT_PATH, introspection_data->interfaces[0],
+ &interface_vtable, NULL, NULL, NULL);
-/*!
- * \note
- * SERVER THREAD or OTHER THREAD (not main)
- */
-HAPI int tcb_is_valid(struct service_context *svc_ctx, struct tcb *tcb)
-{
- Eina_List *l;
- struct tcb *tmp;
- int ret = -ENOENT;
-
- CRITICAL_SECTION_BEGIN(&svc_ctx->tcb_list_lock);
- EINA_LIST_FOREACH(svc_ctx->tcb_list, l, tmp) {
- if (tmp == tcb /* && tcb->svc_ctx == svc_ctx */) {
- ret = tcb->fd;
- break;
+ DBG("registration id[%d]", noti_registration_id);
+ if (noti_registration_id == 0) {
+ ERR("Failed to g_dbus_connection_register_object");
+ result = SERVICE_COMMON_ERROR_IO_ERROR;
+ goto out;
}
- }
- CRITICAL_SECTION_END(&svc_ctx->tcb_list_lock);
- return ret;
-}
-
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int tcb_pid(struct tcb *tcb)
-{
- if (!tcb) {
- return -1;
- }
+out:
+ if (introspection_data)
+ g_dbus_node_info_unref(introspection_data);
- return tcb->pid;
+ return result;
}
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int tcb_fd(struct tcb *tcb)
-{
- if (!tcb) {
- return -EINVAL;
- }
+static int _init_pkg_privilege_info() {
- return tcb->fd;
-}
+ if (_noti_pkg_privilege_info != NULL)
+ return 0;
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int tcb_client_type(struct tcb *tcb)
-{
- if (!tcb) {
- return -EINVAL;
- }
-
- return tcb->type;
+ _noti_pkg_privilege_info =
+ g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+ _badge_pkg_privilege_info =
+ g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+ DBG("init pkg privilege info done");
+ return 0;
}
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int tcb_client_type_set(struct tcb *tcb, enum tcb_type type)
+static int _package_install_cb(uid_t uid, const char *pkgname, enum pkgmgr_status status, double value, void *data)
{
- if (!tcb) {
- return -EINVAL;
- }
+ int ret;
+ gpointer tmp;
+ int privilege_info;
- DbgPrint("TCB[%p] Client type is changed to %d from %d\n", tcb, type, tcb->type);
- tcb->type = type;
- return 0;
-}
+ if (status != PKGMGR_STATUS_END)
+ return 0;
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI struct service_context *tcb_svc_ctx(struct tcb *tcb)
-{
- if (!tcb) {
- return NULL;
- }
+ if (uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))
+ uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
- return tcb->svc_ctx;
-}
+ _init_pkg_privilege_info();
+ if (g_hash_table_contains(_noti_pkg_privilege_info, pkgname)) {
+ tmp = g_hash_table_lookup(_noti_pkg_privilege_info, pkgname);
+ privilege_info = GPOINTER_TO_UINT(tmp);
+ if (privilege_info == 1)
+ notification_setting_db_update_pkg_disabled(pkgname, false, uid);
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int service_common_unicast_packet(struct tcb *tcb, struct packet *packet)
-{
- if (!tcb || !packet) {
- DbgPrint("Invalid unicast: tcb[%p], packet[%p]\n", tcb, packet);
- return -EINVAL;
- }
+ g_hash_table_remove(_noti_pkg_privilege_info, pkgname);
+ } else {
+ /* In consideration of the reboot status, change the disable information. */
+ ret = notification_setting_db_update_pkg_disabled(pkgname, false, uid);
+ if (ret != NOTIFICATION_ERROR_NONE)
+ notification_setting_insert_package_for_uid(pkgname, uid);
+ }
- DbgPrint("Unicast packet\n");
- return com_core_send(tcb->fd, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
-}
+ if (g_hash_table_contains(_badge_pkg_privilege_info, pkgname)) {
+ tmp = g_hash_table_lookup(_badge_pkg_privilege_info, pkgname);
+ privilege_info = GPOINTER_TO_UINT(tmp);
+ if (privilege_info == 1)
+ badge_db_update_pkg_disabled(pkgname, false, uid);
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int service_common_multicast_packet(struct tcb *tcb, struct packet *packet, int type)
-{
- Eina_List *l;
- struct tcb *target;
- struct service_context *svc_ctx;
- int ret;
-
- if (!tcb || !packet) {
- DbgPrint("Invalid multicast: tcb[%p], packet[%p]\n", tcb, packet);
- return -EINVAL;
- }
-
- svc_ctx = tcb->svc_ctx;
-
- DbgPrint("Multicasting packets\n");
-
- /*!
- * \note
- * Does not need to make a critical section from here.
- */
- EINA_LIST_FOREACH(svc_ctx->tcb_list, l, target) {
- if (target == tcb || target->type != type) {
- DbgPrint("Skip target: %p(%d) == %p/%d\n", target, target->type, tcb, type);
- continue;
+ g_hash_table_remove(_badge_pkg_privilege_info, pkgname);
+ } else {
+ /* In consideration of the reboot status, change the disable information. */
+ ret = badge_db_update_pkg_disabled(pkgname, false, uid);
+ if (ret != BADGE_ERROR_NONE)
+ badge_setting_insert_package_for_uid(pkgname, uid);
}
- ret = com_core_send(target->fd, (void *)packet_data(packet), packet_size(packet), DEFAULT_TIMEOUT);
- if (ret < 0) {
- ErrPrint("Failed to send packet: %d\n", ret);
- }
- }
- DbgPrint("Finish to multicast packet\n");
- return 0;
+ return 0;
}
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI struct service_event_item *service_common_add_timer(struct service_context *svc_ctx, double timer, int (*timer_cb)(struct service_context *svc_cx, void *data), void *data)
+static int _package_uninstall_cb(uid_t uid, const char *pkgname, enum pkgmgr_status status, double value, void *data)
{
- struct service_event_item *item;
-
- item = calloc(1, sizeof(*item));
- if (!item) {
- ErrPrint("Heap: %s\n", strerror(errno));
- return NULL;
- }
-
- item->type = SERVICE_EVENT_TIMER;
- item->info.timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
- if (item->info.timer.fd < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- DbgFree(item);
- return NULL;
- }
-
- if (service_common_update_timer(item, timer) < 0) {
- if (close(item->info.timer.fd) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
+ int ret;
+ pkgmgrinfo_pkginfo_h pkginfo;
+
+ if (status != PKGMGR_STATUS_END)
+ return 0;
+
+ if (uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))
+ uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+
+ ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(pkgname, uid, &pkginfo);
+ if (ret == PMINFO_R_OK) {
+ pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+
+ _init_pkg_privilege_info();
+ ret = notification_setting_db_update_pkg_disabled(pkgname, true, uid);
+ if (ret == NOTIFICATION_ERROR_NONE)
+ g_hash_table_insert(_noti_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(1));
+ else
+ g_hash_table_insert(_noti_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(0));
+
+ ret = badge_db_update_pkg_disabled(pkgname, true, uid);
+ if (ret == BADGE_ERROR_NONE)
+ g_hash_table_insert(_badge_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(1));
+ else
+ g_hash_table_insert(_badge_pkg_privilege_info, strdup(pkgname), GUINT_TO_POINTER(0));
+ } else {
+ notification_setting_delete_package_for_uid(pkgname, uid);
+ badge_db_delete_by_pkgname(pkgname, uid);
+ badge_setting_delete_package_for_uid(pkgname, uid);
+ notification_noti_delete_template(pkgname);
}
- DbgFree(item);
- return NULL;
- }
-
- item->event_cb = timer_cb;
- item->cbdata = data;
- svc_ctx->event_list = eina_list_append(svc_ctx->event_list, item);
- return item;
+ return 0;
}
-HAPI int service_common_update_timer(struct service_event_item *item, double timer)
+static int _app_enabled_cb(uid_t uid, const char *app_id, enum pkgmgr_status status, double value, void *data)
{
- struct itimerspec spec;
-
- spec.it_interval.tv_sec = (time_t)timer;
- spec.it_interval.tv_nsec = (timer - spec.it_interval.tv_sec) * 1000000000;
+ if (status == PKGMGR_STATUS_END)
+ notification_setting_db_update_app_disabled(app_id, false, uid);
- if (clock_gettime(CLOCK_MONOTONIC, &spec.it_value) < 0) {
- ErrPrint("clock_gettime: %s\n", strerror(errno));
- return -EFAULT;
- }
-
- spec.it_value.tv_sec += spec.it_interval.tv_sec;
- spec.it_value.tv_nsec += spec.it_interval.tv_nsec;
-
- if (timerfd_settime(item->info.timer.fd, TFD_TIMER_ABSTIME, &spec, NULL) < 0) {
- ErrPrint("Error: %s\n", strerror(errno));
- return -EFAULT;
- }
-
- DbgPrint("Armed interval: %u %u\n", spec.it_interval.tv_sec, spec.it_interval.tv_nsec);
- return 0;
+ return 0;
}
-/*!
- * \note
- * SERVER THREAD
- */
-HAPI int service_common_del_timer(struct service_context *svc_ctx, struct service_event_item *item)
+static int _app_disabled_cb(uid_t uid, const char *app_id, enum pkgmgr_status status, double value, void *data)
{
- if (!eina_list_data_find(svc_ctx->event_list, item)) {
- ErrPrint("Invalid event item\n");
- return -EINVAL;
- }
-
- svc_ctx->event_list = eina_list_remove(svc_ctx->event_list, item);
-
- if (close(item->info.timer.fd) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
- DbgFree(item);
- return 0;
+ if (status == PKGMGR_STATUS_END) {
+ notification_delete_noti_by_app_id(app_id, uid);
+ notification_setting_db_update_app_disabled(app_id, true, uid);
+ }
+
+ return 0;
}
-HAPI int service_common_fd(struct service_context *ctx)
+void service_common_init(void)
{
- return ctx->fd;
+ pkgmgr_init();
+ pkgmgr_add_event_callback(PKGMGR_EVENT_INSTALL, _package_install_cb, NULL);
+ pkgmgr_add_event_callback(PKGMGR_EVENT_UPDATE, _package_install_cb, NULL);
+ pkgmgr_add_event_callback(PKGMGR_EVENT_UNINSTALL, _package_uninstall_cb, NULL);
+ pkgmgr_add_event_callback(PKGMGR_EVENT_APP_ENABLE, _app_enabled_cb, NULL);
+ pkgmgr_add_event_callback(PKGMGR_EVENT_APP_DISABLE, _app_disabled_cb, NULL);
}
-/* End of a file */
+void service_common_set_connection(GDBusConnection *conn)
+{
+ _gdbus_conn = conn;
+}
\ No newline at end of file