tizen 2.4 release
[framework/appfw/aul-1.git] / src / app_signal.c
1 /*
2  *  aul
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #define _GNU_SOURCE
23 #include <stdio.h>
24 #include <dbus/dbus-glib-lowlevel.h>
25
26 #include "app_signal.h"
27 #include "aul_api.h"
28 #include "simple_util.h"
29 #include "aul.h"
30
31
32 static int (*_app_dead_handler) (int pid, void *data);
33 static void *_app_dead_data;
34
35 static int (*_app_launch_handler) (int pid, void *data);
36 static void *_app_launch_data;
37
38 static int (*_booting_done_handler) (int pid, void *data);
39 static void *_booting_done_data;
40
41 static int (*_status_handler) (int pid, int status, void *data);
42 static void *_status_data;
43
44 static int (*_cooldown_handler) (const char *cooldown_status, void *data);
45 static void *_cooldown_data;
46
47 static DBusConnection *bus;
48 static int app_dbus_signal_handler_initialized = 0;
49
50 DBusError err;
51 DBusConnection* conn = NULL;
52
53 static DBusHandlerResult
54 __app_dbus_signal_filter(DBusConnection *conn, DBusMessage *message,
55                        void *user_data)
56 {
57         const char *sender;
58         const char *interface;
59         const char *cooldown_status;
60         int pid = -1;
61         int status;
62
63         DBusError error;
64         dbus_error_init(&error);
65
66         sender = dbus_message_get_sender(message);
67         if (sender == NULL)
68                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
69
70         /*if (dbus_bus_get_unix_user(conn, sender, &error) != 0) {
71                 _E("reject by security issue - no allowed sender\n");
72                 dbus_error_free(&error);
73                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
74         }*/
75
76         interface = dbus_message_get_interface(message);
77         if (interface == NULL) {
78                 _E("reject by security issue - no interface\n");
79                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
80         }
81
82         if (dbus_message_is_signal(
83           message, interface, AUL_DBUS_APPDEAD_SIGNAL)) {
84                 if (dbus_message_get_args(message, &error, DBUS_TYPE_UINT32,
85                      &pid, DBUS_TYPE_INVALID) == FALSE) {
86                         _E("Failed to get data: %s", error.message);
87                         dbus_error_free(&error);
88                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
89                 }
90                 if (_app_dead_handler)
91                         _app_dead_handler(pid, _app_dead_data);
92         } else if (dbus_message_is_signal(
93           message, interface, AUL_DBUS_APPLAUNCH_SIGNAL)) {
94                 if (dbus_message_get_args(message, &error, DBUS_TYPE_UINT32,
95                      &pid, DBUS_TYPE_INVALID) == FALSE) {
96                         _E("Failed to get data: %s", error.message);
97                         dbus_error_free(&error);
98                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
99                 }
100                 if (_app_launch_handler)
101                         _app_launch_handler(pid, _app_launch_data);
102         } else if (dbus_message_is_signal(
103           message, interface, SYSTEM_SIGNAL_BOOTING_DONE)) {
104                 if (_booting_done_handler)
105                         _booting_done_handler(pid, _booting_done_data);
106         } else if (dbus_message_is_signal(
107           message, interface, RESOURCED_SIGNAL_PROCESS_STATUS)) {
108                 if (dbus_message_get_args(message, &error, DBUS_TYPE_INT32,&status,
109                         DBUS_TYPE_INT32,&pid, DBUS_TYPE_INVALID) == FALSE) {
110                         _E("Failed to get data: %s", error.message);
111                         dbus_error_free(&error);
112                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
113                 }
114                 if (_status_handler)
115                         _status_handler(pid, status, _status_data);
116         } else if (dbus_message_is_signal(
117           message, interface, SYSTEM_SIGNAL_COOLDOWN_CHANGED)) {
118                 if (dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &cooldown_status,
119                         DBUS_TYPE_INVALID) == FALSE) {
120                         _E("Failed to get data: %s", error.message);
121                         dbus_error_free(&error);
122                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
123                 }
124                 if (_cooldown_handler)
125                         _cooldown_handler(cooldown_status, _cooldown_data);
126         }
127
128         return DBUS_HANDLER_RESULT_HANDLED;
129 }
130
131 static int __app_dbus_signal_handler_init_with_param(const char* path, const char* interface)
132 {
133         DBusError error;
134         char rule[MAX_LOCAL_BUFSZ];
135
136         dbus_error_init(&error);
137         bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
138         if (!bus) {
139                 _E("Failed to connect to the D-BUS daemon: %s", error.message);
140                 dbus_error_free(&error);
141                 return -1;
142         }
143         dbus_connection_setup_with_g_main(bus, NULL);
144
145         snprintf(rule, MAX_LOCAL_BUFSZ,
146                  "path='%s',type='signal',interface='%s'", path, interface);
147         /* listening to messages */
148         dbus_bus_add_match(bus, rule, &error);
149         if (dbus_error_is_set(&error)) {
150                 _E("Fail to rule set: %s", error.message);
151                 dbus_error_free(&error);
152                 return -1;
153         }
154
155         if (dbus_connection_add_filter(bus,
156                 __app_dbus_signal_filter, NULL, NULL) == FALSE) {
157                 _E("add filter fail");
158                 return -1;
159         }
160
161         _D("app signal initialized");
162
163         return 0;
164 }
165
166 static int __app_dbus_signal_handler_init(void)
167 {
168         int ret = 0;
169
170         if (app_dbus_signal_handler_initialized)
171                 return 0;
172
173         ret = __app_dbus_signal_handler_init_with_param(AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE);
174
175         app_dbus_signal_handler_initialized = 1;
176
177         return ret;
178 }
179
180 static int __app_dbus_signal_handler_fini_with_param(const char* path, const char* interface)
181 {
182         DBusError error;
183         char rule[MAX_LOCAL_BUFSZ];
184
185
186         dbus_error_init(&error);
187
188         dbus_connection_remove_filter(bus, __app_dbus_signal_filter, NULL);
189
190         snprintf(rule, MAX_LOCAL_BUFSZ,
191                  "path='%s',type='signal',interface='%s'", path, interface);
192         dbus_bus_remove_match(bus, rule, &error);
193         if (dbus_error_is_set(&error)) {
194                 _E("Fail to rule unset: %s", error.message);
195                 dbus_error_free(&error);
196                 return -1;
197         }
198
199         dbus_connection_close(bus);
200         dbus_connection_unref(bus);
201
202         _D("app signal finialized");
203
204         return 0;
205 }
206
207 static int __app_dbus_signal_handler_fini(void)
208 {
209         int ret = 0;
210
211         if (!app_dbus_signal_handler_initialized)
212                 return 0;
213
214         ret = __app_dbus_signal_handler_fini_with_param(AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE);
215
216         app_dbus_signal_handler_initialized = 0;
217
218         return ret;
219 }
220
221 SLPAPI int aul_listen_app_dead_signal(int (*func) (int, void *), void *data)
222 {
223         if (func) {
224                 if (__app_dbus_signal_handler_init() < 0) {
225                         _E("error app signal init");
226                         return AUL_R_ERROR;
227                 }
228         } else if (_app_launch_handler == NULL) {
229                 if (__app_dbus_signal_handler_fini() < 0) {
230                         _E("error app signal fini");
231                         return AUL_R_ERROR;
232                 }
233         }
234         _app_dead_handler = func;
235         _app_dead_data = data;
236
237         return AUL_R_OK;
238 }
239
240 SLPAPI int aul_listen_app_launch_signal(int (*func) (int, void *), void *data)
241 {
242         if (func) {
243                 if (__app_dbus_signal_handler_init() < 0) {
244                         _E("error app signal init");
245                         return AUL_R_ERROR;
246                 }
247         } else if (_app_dead_handler == NULL) {
248                 if (__app_dbus_signal_handler_fini() < 0) {
249                         _E("error app signal fini");
250                         return AUL_R_ERROR;
251                 }
252         }
253         _app_launch_handler = func;
254         _app_launch_data = data;
255
256         return AUL_R_OK;
257 }
258
259 SLPAPI int aul_listen_booting_done_signal(int (*func) (int, void *), void *data)
260 {
261         if (func) {
262                 if (__app_dbus_signal_handler_init_with_param(SYSTEM_PATH_CORE, SYSTEM_INTERFACE_CORE) < 0) {
263                         _E("error app signal init");
264                         return AUL_R_ERROR;
265                 }
266         } else if (_booting_done_handler == NULL) {
267                 if (__app_dbus_signal_handler_fini_with_param(SYSTEM_PATH_CORE, SYSTEM_INTERFACE_CORE) < 0) {
268                         _E("error app signal fini");
269                         return AUL_R_ERROR;
270                 }
271         }
272         _booting_done_handler = func;
273         _booting_done_data = data;
274
275         return AUL_R_OK;
276
277 }
278
279 SLPAPI int aul_listen_cooldown_signal(int (*func) (const char *, void *), void *data)
280 {
281         if (func) {
282                 if (__app_dbus_signal_handler_init_with_param(SYSTEM_PATH_SYSNOTI, SYSTEM_INTERFACE_SYSNOTI) < 0) {
283                         _E("error app signal init");
284                         return AUL_R_ERROR;
285                 }
286         } else if (_cooldown_handler == NULL) {
287                 if (__app_dbus_signal_handler_fini_with_param(SYSTEM_PATH_SYSNOTI, SYSTEM_INTERFACE_SYSNOTI) < 0) {
288                         _E("error app signal fini");
289                         return AUL_R_ERROR;
290                 }
291         }
292         _cooldown_handler = func;
293         _cooldown_data = data;
294
295         return AUL_R_OK;
296
297 }
298
299 SLPAPI int aul_listen_e17_status_signal(int (*func) (int, int, void *), void *data)
300 {
301         if (func) {
302                 if (__app_dbus_signal_handler_init_with_param(RESOURCED_PATH_CORE, RESOURCED_INTERFACE_CORE) < 0) {
303                         _E("error app signal init");
304                         return AUL_R_ERROR;
305                 }
306         }
307         _status_handler = func;
308         _status_data = data;
309
310         return AUL_R_OK;
311 }
312
313 SLPAPI int aul_update_freezer_status(int pid, const char* type)
314 {
315         DBusError err;
316         DBusConnection* conn = NULL;
317         DBusMessage* msg = NULL;
318         dbus_uint32_t serial = 0;
319
320         int ret = -1;
321
322         dbus_error_init(&err);
323
324         _W("send_update_freezer_status, pid: %d, type: %s", pid, type);
325
326         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
327         if (!conn) {
328                 _E("Fail to dbus_bus_get : %s", err.message);
329                 return -1;
330         }
331
332         msg = dbus_message_new_signal(RESOURCED_PROC_OBJECT,
333                         RESOURCED_PROC_INTERFACE,
334                         RESOURCED_PROC_METHOD);
335         if (!msg) {
336                 _E("Could not create DBus Message.");
337                 ret = -1;
338                 goto end;
339         }
340
341         if (!dbus_message_append_args(msg,
342                         DBUS_TYPE_STRING, &type,
343                         DBUS_TYPE_INT32, &pid,
344                         DBUS_TYPE_INVALID)) {
345                 _E("Failed to append a D-Bus Message.");
346                 ret = -1;
347         }
348
349         if (!dbus_connection_send(conn, msg, &serial)) {
350                 _E("Failed to send a D-Bus Message.");
351                 ret = -1;
352         }
353
354         dbus_connection_flush(conn);
355
356 end:
357         dbus_error_free(&err);
358
359         if (msg) {
360                 dbus_message_unref(msg);
361         }
362
363         if (conn) {
364                 dbus_connection_unref(conn);
365         }
366
367         return ret;
368
369 }
370
371 int __app_status_dbus_init(void)
372 {
373         int ret = 0;
374
375         if (conn)
376                 return 0;
377
378         dbus_error_init(&err);
379         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
380
381         return ret;
382 }
383
384 SLPAPI int aul_send_app_launch_request_signal(int pid, const char* appid, const char* pkgid, const char* type)
385 {
386         DBusMessage* msg = NULL;
387         dbus_uint32_t serial = 0;
388
389         int ret = -1;
390
391         __app_status_dbus_init();
392
393         _W("send_app_launch_signal, pid: %d, appid: %s", pid, appid);
394
395         msg = dbus_message_new_signal(AUL_APP_STATUS_DBUS_PATH,
396                         AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
397                         AUL_APP_STATUS_DBUS_LAUNCH_REQUEST);
398         if (!msg) {
399                 _E("Could not create DBus Message.");
400                 ret = -1;
401                 goto end;
402         }
403
404         if (!dbus_message_append_args(msg,
405                         DBUS_TYPE_INT32, &pid,
406                         DBUS_TYPE_STRING, &appid,
407                         DBUS_TYPE_STRING, &pkgid,
408                         DBUS_TYPE_STRING, &type,
409                         DBUS_TYPE_INVALID)) {
410                 _E("Failed to append a D-Bus Message.");
411                 ret = -1;
412         }
413
414         if (!dbus_connection_send(conn, msg, &serial)) {
415                 _E("Failed to send a D-Bus Message.");
416                 ret = -1;
417         }
418
419         dbus_connection_flush(conn);
420
421 end:
422         if (msg) {
423                 dbus_message_unref(msg);
424         }
425         return ret;
426 }
427
428 SLPAPI int aul_send_app_resume_request_signal(int pid, const char* appid, const char* pkgid, const char* type)
429 {
430         DBusMessage* msg = NULL;
431         dbus_uint32_t serial = 0;
432         const char       *empty_string = "";
433
434         int ret = -1;
435
436         __app_status_dbus_init();
437
438         _W("send_app_resume_signal, pid: %d, appid: %s", pid, appid);
439
440         msg = dbus_message_new_signal(AUL_APP_STATUS_DBUS_PATH,
441                         AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
442                         AUL_APP_STATUS_DBUS_RESUME_REQUEST);
443         if (!msg) {
444                 _E("Could not create DBus Message.");
445                 ret = -1;
446                 goto end;
447         }
448
449         if(appid) {
450                 if (!dbus_message_append_args(msg,
451                                 DBUS_TYPE_INT32, &pid,
452                                 DBUS_TYPE_STRING, &appid,
453                                 DBUS_TYPE_STRING, &pkgid,
454                                 DBUS_TYPE_STRING, &type,
455                                 DBUS_TYPE_INVALID)) {
456                         _E("Failed to append a D-Bus Message.");
457                         ret = -1;
458                 }
459         } else {
460                 if (!dbus_message_append_args(msg,
461                                 DBUS_TYPE_INT32, &pid,
462                                 DBUS_TYPE_STRING, &empty_string,
463                                 DBUS_TYPE_STRING, &empty_string,
464                                 DBUS_TYPE_STRING, &empty_string,
465                                 DBUS_TYPE_INVALID)) {
466                         _E("Failed to append a D-Bus Message.");
467                         ret = -1;
468                 }
469         }
470
471         if (!dbus_connection_send(conn, msg, &serial)) {
472                 _E("Failed to send a D-Bus Message.");
473                 ret = -1;
474         }
475
476         dbus_connection_flush(conn);
477
478 end:
479         if (msg) {
480                 dbus_message_unref(msg);
481         }
482
483         return ret;
484 }
485
486 SLPAPI int aul_send_app_terminate_request_signal(int pid, const char* appid, const char* pkgid, const char *type)
487 {
488         DBusMessage* msg = NULL;
489         dbus_uint32_t serial = 0;
490         const char       *empty_string = "";
491
492         int ret = -1;
493
494         __app_status_dbus_init();
495
496         msg = dbus_message_new_signal(AUL_APP_STATUS_DBUS_PATH,
497                         AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
498                         AUL_APP_STATUS_DBUS_TERMINATE_REQUEST);
499         if (!msg) {
500                 _E("Could not create DBus Message.");
501                 ret = -1;
502                 goto end;
503         }
504
505         if(appid) {
506                 if (!dbus_message_append_args(msg,
507                                 DBUS_TYPE_INT32, &pid,
508                                 DBUS_TYPE_STRING, &appid,
509                                 DBUS_TYPE_STRING, &pkgid,
510                                 DBUS_TYPE_STRING, &type,
511                                 DBUS_TYPE_INVALID)) {
512                         _E("Failed to append a D-Bus Message.");
513                         ret = -1;
514                 }
515         } else {
516                 if (!dbus_message_append_args(msg,
517                                 DBUS_TYPE_INT32, &pid,
518                                 DBUS_TYPE_STRING, &empty_string,
519                                 DBUS_TYPE_STRING, &empty_string,
520                                 DBUS_TYPE_STRING, &empty_string,
521                                 DBUS_TYPE_INVALID)) {
522                         _E("Failed to append a D-Bus Message.");
523                         ret = -1;
524                 }
525         }
526
527         if (!dbus_connection_send(conn, msg, &serial)) {
528                 _E("Failed to send a D-Bus Message.");
529                 ret = -1;
530         }
531
532         dbus_connection_flush(conn);
533
534 end:
535         if (msg) {
536                 dbus_message_unref(msg);
537         }
538
539         return ret;
540
541 }
542
543 SLPAPI int aul_send_app_status_change_signal(int pid, const char* appid, const char* pkgid, const char* status, const char *type)
544 {
545         DBusMessage* msg = NULL;
546         dbus_uint32_t serial = 0;
547         const char       *empty_string = "";
548
549         int ret = -1;
550
551         _W("send_app_status_change_signal, pid: %d, appid: %s, status: %s", pid, appid, status);
552
553         __app_status_dbus_init();
554
555         msg = dbus_message_new_signal(AUL_APP_STATUS_DBUS_PATH,
556                         AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
557                         AUL_APP_STATUS_DBUS_STATUS_CHANGE);
558         if (!msg) {
559                 _E("Could not create DBus Message.");
560                 ret = -1;
561                 goto end;
562         }
563
564         if(appid) {
565                 if (!dbus_message_append_args(msg,
566                                 DBUS_TYPE_INT32, &pid,
567                                 DBUS_TYPE_STRING, &appid,
568                                 DBUS_TYPE_STRING, &pkgid,
569                                 DBUS_TYPE_STRING, &status,
570                                 DBUS_TYPE_STRING, &type,
571                                 DBUS_TYPE_INVALID)) {
572                         _E("Failed to append a D-Bus Message.");
573                         ret = -1;
574                 }
575         } else {
576                 if (!dbus_message_append_args(msg,
577                                 DBUS_TYPE_INT32, &pid,
578                                 DBUS_TYPE_STRING, &empty_string,
579                                 DBUS_TYPE_STRING, &empty_string,
580                                 DBUS_TYPE_STRING, &status,
581                                 DBUS_TYPE_STRING, &type,
582                                 DBUS_TYPE_INVALID)) {
583                         _E("Failed to append a D-Bus Message.");
584                         ret = -1;
585                 }
586         }
587
588         if (!dbus_connection_send(conn, msg, &serial)) {
589                 _E("Failed to send a D-Bus Message.");
590                 ret = -1;
591         }
592
593         dbus_connection_flush(conn);
594
595 end:
596         if (msg) {
597                 dbus_message_unref(msg);
598         }
599
600         return ret;
601 }
602
603 SLPAPI int aul_send_app_terminated_signal(int pid)
604 {
605         DBusMessage* msg = NULL;
606         dbus_uint32_t serial = 0;
607
608         int ret = -1;
609
610         __app_status_dbus_init();
611
612         msg = dbus_message_new_signal(AUL_APP_STATUS_DBUS_PATH,
613                         AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
614                         AUL_APP_STATUS_DBUS_TERMINATED);
615         if (!msg) {
616                 _E("Could not create DBus Message.");
617                 ret = -1;
618                 goto end;
619         }
620
621         if (!dbus_message_append_args(msg,
622                         DBUS_TYPE_INT32, &pid,
623                         DBUS_TYPE_INVALID)) {
624                 _E("Failed to append a D-Bus Message.");
625                 ret = -1;
626         }
627
628         if (!dbus_connection_send(conn, msg, &serial)) {
629                 _E("Failed to send a D-Bus Message.");
630                 ret = -1;
631         }
632
633         dbus_connection_flush(conn);
634
635 end:
636         if (msg) {
637                 dbus_message_unref(msg);
638         }
639         return ret;
640 }
641
642 SLPAPI int aul_send_app_group_signal(int owner_pid, int child_pid, const char *child_pkgid)
643 {
644         DBusMessage* msg = NULL;
645         dbus_uint32_t serial = 0;
646         const char  *empty_string = "";
647
648         int ret = -1;
649
650         _W("send_app_group_signal, owner: %d, child: %d", owner_pid, child_pid);
651
652         __app_status_dbus_init();
653
654         msg = dbus_message_new_signal(AUL_APP_STATUS_DBUS_PATH,
655                                       AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE,
656                                       AUL_APP_STATUS_DBUS_GROUP);
657         if (!msg) {
658                 _E("Could not create DBus Message.");
659                 ret = -1;
660                 goto end;
661         }
662
663         if (child_pkgid) {
664                 if (!dbus_message_append_args(msg,
665                                               DBUS_TYPE_INT32, &owner_pid,
666                                               DBUS_TYPE_INT32, &child_pid,
667                                               DBUS_TYPE_STRING, &child_pkgid,
668                                               DBUS_TYPE_INVALID)) {
669                         _E("Failed to append a D-Bus Message.");
670                         ret = -1;
671                 }
672         } else {
673                 if (!dbus_message_append_args(msg,
674                                               DBUS_TYPE_INT32, &owner_pid,
675                                               DBUS_TYPE_INT32, &child_pid,
676                                               DBUS_TYPE_STRING, &empty_string,
677                                               DBUS_TYPE_INVALID)) {
678                         _E("Failed to append a D-Bus Message.");
679                         ret = -1;
680                 }
681         }
682
683         if (!dbus_connection_send(conn, msg, &serial)) {
684                 _E("Failed to send a D-Bus Message.");
685                 ret = -1;
686         }
687
688         dbus_connection_flush(conn);
689
690 end:
691         if (msg) {
692                 dbus_message_unref(msg);
693         }
694
695         return ret;
696 }