add event_keep_last_event_data api
[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         case EVENT_ERROR_INVALID_PARAMETER:
55                 return "INVALID_PARAMETER";
56         case EVENT_ERROR_OUT_OF_MEMORY:
57                 return "OUT_OF_MEMORY";
58         case EVENT_ERROR_TIMED_OUT:
59                 return "TIMED_OUT";
60         case EVENT_ERROR_IO_ERROR:
61                 return "IO ERROR";
62         case EVENT_ERROR_PERMISSION_DENIED:
63                 return "PERMISSION DENIED";
64         default:
65                 return "UNKNOWN";
66         }
67 }
68
69 int event_error(event_error_e error, const char *function, const char *description)
70 {
71         if (description) {
72                 LOGE("[%s] %s(0x%08x) : %s", function, event_error_to_string(error),
73                         error, description);
74         } else {
75                 LOGE("[%s] %s(0x%08x)", function, event_error_to_string(error), error);
76         }
77
78         return error;
79 }
80
81 static void event_do_cb(gpointer data, gpointer user_data)
82 {
83         event_handler_h handler = (event_handler_h)data;
84         event_cb_data_s *cb_data = (event_cb_data_s *)user_data;
85
86         if (handler->cb) {
87                 handler->cb(handler->event_name,
88                         cb_data->event_data, cb_data->user_data);
89         }
90 }
91
92 static void event_eventsystem_callback(const char *event_name,
93         bundle_raw *event_data, int len, void *user_data)
94 {
95         bundle *b_to = NULL;
96         bundle *b = NULL;
97
98         LOGD("event_name(%s)", event_name);
99
100         if (earlier_callback != NULL) {
101                 b_to = bundle_decode(event_data, len);
102                 if (b_to == NULL) {
103                         LOGE("bundle_decode failed");
104                         return;
105                 }
106                 earlier_callback(event_name, b_to, user_data);
107                 bundle_free(b_to);
108                 return;
109         }
110
111         GList *handler_list = (GList *)g_hash_table_lookup(interested_event_table,
112                 event_name);
113         if (handler_list) {
114                 event_cb_data_s *cb_data = NULL;
115                 cb_data = calloc(1, sizeof(event_cb_data_s));
116                 if (cb_data == NULL) {
117                         LOGE("memory alloc failed");
118                         return;
119                 }
120                 b_to = bundle_decode(event_data, len);
121                 if (b_to == NULL) {
122                         LOGE("bundle_decode failed");
123                         free(cb_data);
124                         return;
125                 }
126                 b = bundle_dup(b_to);
127                 bundle_free(b_to);
128
129                 cb_data->event_data = b;
130                 cb_data->user_data = user_data;
131
132                 g_list_foreach(handler_list, event_do_cb, cb_data);
133
134                 bundle_free(b);
135         }
136 }
137
138 int event_add_event_handler(const char *event_name, event_cb callback, void *user_data,
139         event_handler_h *event_handler)
140 {
141         int ret = 0;
142         int event_type = 0;
143         unsigned int reg_id = 0;
144         event_handler_h handler = NULL;
145
146         if (!_initialized) {
147                 if (interested_event_table == NULL) {
148                         interested_event_table = g_hash_table_new(g_str_hash, g_str_equal);
149                         if (interested_event_table == NULL) {
150                                 return event_error(EVENT_ERROR_OUT_OF_MEMORY,
151                                         __FUNCTION__, NULL);
152                         }
153                 }
154                 _initialized = 1;
155         }
156
157         if (event_handler == NULL || event_name == NULL || callback == NULL)
158                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
159
160         handler = calloc(1, sizeof(event_handler_s));
161         if (handler == NULL)
162                 return event_error(EVENT_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
163
164         pthread_mutex_lock(&register_sync_lock);
165         earlier_callback = callback;
166         ret = eventsystem_register_application_event(event_name, &reg_id, &event_type,
167                 (eventsystem_cb)event_eventsystem_callback, user_data);
168         earlier_callback = NULL;
169         pthread_mutex_unlock(&register_sync_lock);
170         if (ret < 0) {
171                 free(handler);
172                 if (ret == ES_R_ENOTPERMITTED)
173                         return event_error(EVENT_ERROR_PERMISSION_DENIED, __FUNCTION__, NULL);
174                 else
175                         return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
176         }
177
178         handler->event_name = strdup(event_name);
179         if (handler->event_name == NULL) {
180                 free(handler);
181                 return event_error(EVENT_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
182         }
183
184         handler->reg_id = reg_id;
185         handler->event_type = event_type;
186         handler->cb = callback;
187         handler->user_data = user_data;
188
189         *event_handler = handler;
190
191         GList *handler_list = (GList *)g_hash_table_lookup(interested_event_table,
192                 handler->event_name);
193         if (handler_list) {
194                 LOGD("add new handler");
195                 handler_list = g_list_append(handler_list, handler);
196         } else {
197                 LOGD("add new table item");
198                 GList *ehl = NULL;
199                 ehl = g_list_append(ehl, handler);
200                 g_hash_table_insert(interested_event_table, handler->event_name, ehl);
201         }
202
203         return EVENT_ERROR_NONE;
204 }
205
206 int event_remove_event_handler(event_handler_h event_handler)
207 {
208         int ret = 0;
209
210         if (!_initialized) {
211                 LOGI("handler list is not initialized");
212                 return EVENT_ERROR_NONE;
213         }
214
215         if (event_handler == NULL)
216                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
217
218         ret = eventsystem_unregister_application_event(event_handler->reg_id);
219         if (ret < 0)
220                 return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
221
222         GList *handler_list = (GList *)g_hash_table_lookup(interested_event_table,
223                 event_handler->event_name);
224         if (handler_list) {
225                 GList *list = NULL;
226                 list = g_list_find(handler_list, event_handler);
227                 if (list) {
228                         LOGD("remove match handler");
229                         handler_list = g_list_remove_all(handler_list, event_handler);
230                         GList *first_list = NULL;
231                         first_list = g_list_first(handler_list);
232                         if (first_list == NULL) {
233                                 LOGD("remove table item");
234                                 g_hash_table_remove(interested_event_table,
235                                         event_handler->event_name);
236                         }
237                 }
238         }
239
240         free(event_handler->event_name);
241         free(event_handler);
242
243         return EVENT_ERROR_NONE;
244 }
245
246 int event_publish_app_event(const char *event_name, bundle *event_data)
247 {
248         if (event_data == NULL || event_name == NULL)
249                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
250
251         if (eventsystem_send_user_event(event_name, event_data, false) < 0)
252                 return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
253
254         return EVENT_ERROR_NONE;
255 }
256
257 int event_publish_trusted_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         if (eventsystem_send_user_event(event_name, event_data, true) < 0)
263                 return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
264
265         return EVENT_ERROR_NONE;
266 }
267
268 int event_keep_last_event_data(const char *event_name)
269 {
270         int ret;
271
272         if (event_name == NULL)
273                 return event_error(EVENT_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
274
275         ret = eventsystem_keep_last_event_data(event_name);
276         if (ret < 0) {
277                 if (ret == ES_R_ENOMEM)
278                         return event_error(EVENT_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL);
279                 else
280                         return event_error(EVENT_ERROR_IO_ERROR, __FUNCTION__, NULL);
281         }
282
283         return EVENT_ERROR_NONE;
284 }