Merge "merge tizen 2.4" into tizen
[platform/core/api/application.git] / event / event.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <glib.h>
19 #include <tizen.h>
20 #include <dlog.h>
21 #include <app_event.h>
22 #include <eventsystem.h>
23 #include <app_internal.h>
24
25 #ifdef LOG_TAG
26 #undef LOG_TAG
27 #endif
28
29 #define LOG_TAG "CAPI_APPFW_EVENT"
30
31 typedef struct event_handler {
32         char *event_name;
33         int event_type;
34         unsigned int reg_id;
35         event_cb cb;
36         void *user_data;
37 } event_handler_s;
38
39 typedef struct event_cb_data {
40         bundle *event_data;
41         void *user_data;
42 } event_cb_data_s;
43
44 static GHashTable *interested_event_table;
45 static int _initialized;
46 static event_cb earlier_callback;
47 static pthread_mutex_t register_sync_lock = PTHREAD_MUTEX_INITIALIZER;
48
49 static const char *event_error_to_string(event_error_e error)
50 {
51         switch (error) {
52         case EVENT_ERROR_NONE:
53                 return "NONE";
54
55         case EVENT_ERROR_INVALID_PARAMETER:
56                 return "INVALID_PARAMETER";
57
58         case EVENT_ERROR_OUT_OF_MEMORY:
59                 return "OUT_OF_MEMORY";
60
61         case EVENT_ERROR_TIMED_OUT:
62                 return "TIMED_OUT";
63
64         case EVENT_ERROR_IO_ERROR:
65                 return "IO ERROR";
66
67         case EVENT_ERROR_PERMISSION_DENIED:
68                 return "PERMISSION DENIED";
69
70         default:
71                 return "UNKNOWN";
72         }
73 }
74
75 int event_error(event_error_e error, const char *function, const char *description)
76 {
77         if (description) {
78                 LOGE("[%s] %s(0x%08x) : %s", function, event_error_to_string(error),
79                         error, description);
80         } else {
81                 LOGE("[%s] %s(0x%08x)", function, event_error_to_string(error), error);
82         }
83
84         return error;
85 }
86
87 static void event_do_cb(gpointer data, gpointer user_data)
88 {
89         event_handler_h handler = (event_handler_h)data;
90         event_cb_data_s *cb_data = (event_cb_data_s *)user_data;
91
92         if (handler->cb) {
93                 handler->cb(handler->event_name,
94                         cb_data->event_data, cb_data->user_data);
95         }
96 }
97
98 static void event_eventsystem_callback(const char *event_name,
99         bundle_raw *event_data, int len, void *user_data)
100 {
101         bundle *b_to = NULL;
102         bundle *b = NULL;
103
104         LOGD("event_name(%s)", event_name);
105
106         if (earlier_callback != NULL) {
107                 b_to = bundle_decode(event_data, len);
108                 if (b_to == NULL) {
109                         LOGE("bundle_decode failed");
110                         return;
111                 }
112                 earlier_callback(event_name, b_to, user_data);
113                 bundle_free(b_to);
114                 return;
115         }
116
117         GList *handler_list = (GList *)g_hash_table_lookup(interested_event_table,
118                 event_name);
119         if (handler_list) {
120                 event_cb_data_s *cb_data = NULL;
121                 cb_data = calloc(1, sizeof(event_cb_data_s));
122                 if (cb_data == NULL) {
123                         LOGE("memory alloc failed");
124                         return;
125                 }
126                 b_to = bundle_decode(event_data, len);
127                 if (b_to == NULL) {
128                         LOGE("bundle_decode failed");
129                         free(cb_data);
130                         return;
131                 }
132                 b = bundle_dup(b_to);
133                 bundle_free(b_to);
134
135                 cb_data->event_data = b;
136                 cb_data->user_data = user_data;
137
138                 g_list_foreach(handler_list, event_do_cb, cb_data);
139
140                 bundle_free(b);
141         }
142 }
143
144 int event_add_event_handler(const char *event_name, event_cb callback, void *user_data,
145         event_handler_h *event_handler)
146 {
147         int ret = 0;
148         int event_type = 0;
149         unsigned int reg_id = 0;
150         event_handler_h handler = NULL;
151
152         if (!_initialized) {
153                 if (interested_event_table == NULL) {
154                         interested_event_table = g_hash_table_new(g_str_hash, g_str_equal);
155                         if (interested_event_table == NULL) {
156                                 return event_error(EVENT_ERROR_OUT_OF_MEMORY,
157                                         __FUNCTION__, NULL);
158                         }
159                 }
160                 _initialized = 1;
161         }
162
163         if (event_handler == NULL || event_name == NULL || callback == NULL) {
164                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
165         }
166
167         handler = calloc(1, sizeof(event_handler_s));
168         if (handler == NULL) {
169                 return event_error(EVENT_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
170         }
171
172         pthread_mutex_lock(&register_sync_lock);
173         earlier_callback = callback;
174         ret = eventsystem_register_application_event(event_name, &reg_id, &event_type,
175                 (eventsystem_cb)event_eventsystem_callback, user_data);
176         earlier_callback = NULL;
177         pthread_mutex_unlock(&register_sync_lock);
178         if (ret < 0) {
179                 free(handler);
180                 if (ret == ES_R_ENOTPERMITTED) {
181                         return event_error(EVENT_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL);
182                 } else {
183                         return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
184                 }
185         }
186
187         handler->event_name = strdup(event_name);
188         if (handler->event_name == NULL) {
189                 free(handler);
190                 return event_error(EVENT_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
191         }
192
193         handler->reg_id = reg_id;
194         handler->event_type = event_type;
195         handler->cb = callback;
196         handler->user_data = user_data;
197
198         *event_handler = handler;
199
200         GList *handler_list = (GList *)g_hash_table_lookup(interested_event_table,
201                 handler->event_name);
202         if (handler_list) {
203                 LOGD("add new handler");
204                 handler_list = g_list_append(handler_list, handler);
205         } else {
206                 LOGD("add new table item");
207                 GList *ehl = NULL;
208                 ehl = g_list_append(ehl, handler);
209                 g_hash_table_insert(interested_event_table, handler->event_name, ehl);
210         }
211
212         return EVENT_ERROR_NONE;
213 }
214
215 int event_remove_event_handler(event_handler_h event_handler)
216 {
217         int ret = 0;
218
219         if (!_initialized) {
220                 LOGI("handler list is not initialized");
221                 return EVENT_ERROR_NONE;
222         }
223
224         if (event_handler == NULL) {
225                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
226         }
227
228         ret = eventsystem_unregister_application_event(event_handler->reg_id);
229         if (ret < 0) {
230                 return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
231         }
232
233         GList *handler_list = (GList *)g_hash_table_lookup(interested_event_table,
234                 event_handler->event_name);
235         if (handler_list) {
236                 GList *list = NULL;
237                 list = g_list_find(handler_list, event_handler);
238                 if (list) {
239                         LOGD("remove match handler");
240                         handler_list = g_list_remove_all(handler_list, event_handler);
241                         GList *first_list = NULL;
242                         first_list = g_list_first(handler_list);
243                         if (first_list == NULL) {
244                                 LOGD("remove table item");
245                                 g_hash_table_remove(interested_event_table,
246                                         event_handler->event_name);
247                         }
248                 }
249         }
250
251         free(event_handler->event_name);
252         free(event_handler);
253
254         return EVENT_ERROR_NONE;
255 }
256
257 int event_publish_app_event(const char *event_name, bundle *event_data)
258 {
259         if (event_data == NULL || event_name == NULL) {
260                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
261         }
262
263         if (eventsystem_send_user_event(event_name, event_data, false) < 0) {
264                 return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
265         }
266
267         return EVENT_ERROR_NONE;
268 }
269
270 int event_publish_trusted_app_event(const char *event_name, bundle *event_data)
271 {
272         if (event_data == NULL || event_name == NULL) {
273                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
274         }
275
276         if (eventsystem_send_user_event(event_name, event_data, true) < 0) {
277                 return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
278         }
279
280         return EVENT_ERROR_NONE;
281 }