tizen 2.3.1 release
[framework/appfw/aul-1.git] / src / launch.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
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <dirent.h>
30 #include <glib.h>
31 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
32 #include <pkgmgr-info.h>
33 #endif
34
35 #include "aul.h"
36 #include "aul_api.h"
37 #include "app_sock.h"
38 #include "perf.h"
39 #include "simple_util.h"
40 #include "launch.h"
41 #include "key.h"
42 #include "aul_util.h"
43
44 static int aul_initialized = 0;
45 static int aul_fd;
46
47 static int (*_aul_handler) (aul_type type, bundle *kb, void *data) = NULL;
48 static void *_aul_data;
49
50
51
52 static int __call_aul_handler(aul_type type, bundle *kb);
53 static int app_resume();
54 static int app_terminate();
55 static void __clear_internal_key(bundle *kb);
56 static inline void __set_stime(bundle *kb);
57 static int __app_start_internal(gpointer data);
58 static int __app_launch_local(bundle *b);
59 static int __send_result_to_launchpad(int fd, int res);
60
61 #ifdef _APPFW_FEATURE_PROCESS_POOL
62 static void *__window_object = NULL;
63 static void *__bg_object = NULL;
64 static void *__conformant_object = NULL;
65 #endif
66
67 #ifdef _APPFW_FEATURE_DATA_CONTROL
68 static data_control_provider_handler_fn __dc_handler = NULL;
69 #endif
70
71 extern  int aul_launch_fini();
72
73 int aul_is_initialized()
74 {
75         return aul_initialized;
76 }
77
78 static int __call_aul_handler(aul_type type, bundle *kb)
79 {
80         if (_aul_handler)
81                 _aul_handler(type, kb, _aul_data);
82         return 0;
83 }
84
85 int app_start(bundle *kb)
86 {
87         const char *str = NULL;
88
89         _app_start_res_prepare(kb);
90         __call_aul_handler(AUL_START, kb);
91
92 #ifdef _APPFW_FEATURE_DATA_CONTROL
93         // Handle the DataControl callback
94         str = bundle_get_val(kb, AUL_K_DATA_CONTROL_TYPE);
95         if (str != NULL && strcmp(str, "CORE") == 0)
96         {
97                 if (__dc_handler != NULL)
98                 {
99                         __dc_handler(kb, 0, NULL); // bundle, request_id, data
100                 }
101         }
102 #endif
103         return 0;
104 }
105
106 static int app_resume()
107 {
108         __call_aul_handler(AUL_RESUME, NULL);
109         return 0;
110 }
111
112 static int app_terminate()
113 {
114         __call_aul_handler(AUL_TERMINATE, NULL);
115         return 0;
116 }
117
118 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
119 static int app_resume_lcd_on()
120 {
121         __call_aul_handler(AUL_RESUME_LCD_ON, NULL);
122         return 0;
123 }
124
125 static int app_pause_lcd_off()
126 {
127         __call_aul_handler(AUL_PAUSE_LCD_OFF, NULL);
128         return 0;
129 }
130 #endif
131
132 /**
133  * @brief       encode kb and send it to 'pid'
134  * @param[in]   pid             receiver's pid
135  * @param[in]   cmd             message's status (APP_START | APP_RESULT)
136  * @param[in]   kb              data
137  */
138 SLPAPI int app_send_cmd(int pid, int cmd, bundle *kb)
139 {
140         int datalen;
141         bundle_raw *kb_data;
142         int res;
143
144         bundle_encode(kb, &kb_data, &datalen);
145         if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) {
146                 switch (res) {
147                 case -EINVAL:
148                         res = AUL_R_EINVAL;
149                         break;
150                 case -ECOMM:
151                         res = AUL_R_ECOMM;
152                         break;
153                 case -EAGAIN:
154                         res = AUL_R_ETIMEOUT;
155                         break;
156                 case -ELOCALLAUNCH_ID:
157                         res = AUL_R_LOCAL;
158                         break;
159                 case -EILLEGALACCESS:
160                         res = AUL_R_EILLACC;
161                         break;
162                 case -ETERMINATING:
163                         res = AUL_R_ETERMINATING;
164                         break;
165                 case -ENOLAUNCHPAD:
166                         res = AUL_R_ENOLAUNCHPAD;
167                         break;
168 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
169                 case -EUGLOCAL_LAUNCH:
170                         res = AUL_R_UG_LOCAL;
171                         break;
172 #endif
173                 case -EREJECTED:
174                         res = AUL_R_EREJECTED;
175                         break;
176                 default:
177                         res = AUL_R_ERROR;
178                 }
179         }
180         free(kb_data);
181
182         return res;
183 }
184
185 SLPAPI int app_send_cmd_with_noreply(int pid, int cmd, bundle *kb)
186 {
187         int datalen;
188         bundle_raw *kb_data;
189         int res;
190
191         bundle_encode(kb, &kb_data, &datalen);
192         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0) {
193                 switch (res) {
194                 case -EINVAL:
195                         res = AUL_R_EINVAL;
196                         break;
197                 case -ECOMM:
198                         res = AUL_R_ECOMM;
199                         break;
200                 case -EAGAIN:
201                         res = AUL_R_ETIMEOUT;
202                         break;
203                 case -ELOCALLAUNCH_ID:
204                         res = AUL_R_LOCAL;
205                         break;
206                 case -EILLEGALACCESS:
207                         res = AUL_R_EILLACC;
208                         break;
209                 default:
210                         res = AUL_R_ERROR;
211                 }
212         }
213         free(kb_data);
214
215         return res;
216 }
217
218 static void __clear_internal_key(bundle *kb)
219 {
220         bundle_del(kb, AUL_K_CALLER_PID);
221         bundle_del(kb, AUL_K_PKG_NAME);
222         bundle_del(kb, AUL_K_WAIT_RESULT);
223         bundle_del(kb, AUL_K_SEND_RESULT);
224         bundle_del(kb, AUL_K_ARGV0);
225 }
226
227 static inline void __set_stime(bundle *kb)
228 {
229         struct timeval tv;
230         char tmp[MAX_LOCAL_BUFSZ];
231
232         gettimeofday(&tv, NULL);
233         snprintf(tmp, MAX_LOCAL_BUFSZ, "%ld/%ld", tv.tv_sec, tv.tv_usec);
234         bundle_add(kb, AUL_K_STARTTIME, tmp);
235 }
236
237 static int __app_start_internal(gpointer data)
238 {
239         bundle *kb;
240
241         kb = (bundle *) data;
242         app_start(kb);
243         bundle_free(kb);
244
245         return 0;
246 }
247
248 static int __app_launch_local(bundle *b)
249 {
250         if (!aul_is_initialized())
251                 return AUL_R_ENOINIT;
252
253         if (b == NULL) {
254                 _E("bundle for APP_START is NULL");
255         }
256         if (g_idle_add(__app_start_internal, b) > 0)
257                 return AUL_R_OK;
258         else
259                 return AUL_R_ERROR;
260 }
261
262 static int __app_resume_local()
263 {
264         if (!aul_is_initialized())
265                 return AUL_R_ENOINIT;
266
267         app_resume();
268
269         return 0;
270 }
271
272 /**
273  * @brief       start caller with kb
274  * @return      callee's pid
275  */
276 int app_request_to_launchpad(int cmd, const char *pkgname, bundle *kb)
277 {
278         int must_free = 0;
279         int ret = 0;
280
281         SECURE_LOGD("launch request : %s", pkgname);
282         if (kb == NULL) {
283                 kb = bundle_create();
284                 must_free = 1;
285         } else
286                 __clear_internal_key(kb);
287
288         bundle_add(kb, AUL_K_PKG_NAME, pkgname);
289         __set_stime(kb);
290         if(cmd == APP_START_ASYNC)
291                 ret = app_send_cmd_with_noreply(AUL_UTIL_PID, cmd, kb);
292         else
293                 ret = app_send_cmd(AUL_UTIL_PID, cmd, kb);
294
295         _D("launch request result : %d", ret);
296         if (ret == AUL_R_LOCAL
297 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
298                 || ret == AUL_R_UG_LOCAL
299 #endif
300                 ) {
301                 _E("app_request_to_launchpad : Same Process Send Local");
302                 bundle *b;
303
304 #ifdef _APPFW_FEATURE_APP_CONTROL_LITE
305                 if(ret == AUL_R_UG_LOCAL) {
306                         pkgmgrinfo_appinfo_h handle;
307                         char *exec = NULL;
308
309                         pkgmgrinfo_appinfo_get_appinfo(pkgname, &handle);
310                         pkgmgrinfo_appinfo_get_exec(handle, &exec);
311
312                         bundle_add(kb, "__AUL_UG_EXEC__", exec);
313
314                         pkgmgrinfo_appinfo_destroy_appinfo(handle);
315                 }
316 #endif
317
318                 switch (cmd) {
319                         case APP_START:
320                         case APP_START_RES:
321 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
322                         case APP_START_MULTI_INSTANCE:
323 #endif
324                                 b = bundle_dup(kb);
325                                 ret = __app_launch_local(b);
326                                 break;
327                         case APP_OPEN:
328                         case APP_RESUME:
329                         case APP_RESUME_BY_PID:
330                                 ret = __app_resume_local();
331                                 break;
332                         default:
333                                 _E("no support packet");
334                 }
335
336         }
337
338         /* cleanup */
339         if (must_free)
340                 bundle_free(kb);
341
342         return ret;
343 }
344
345 static int __send_result_to_launchpad(int fd, int res)
346 {
347         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
348                 if (errno == EPIPE) {
349                         _E("send failed due to EPIPE.\n");
350                         close(fd);
351                         return -1;
352                 }
353                 _E("send fail to client");
354         }
355         close(fd);
356         return 0;
357 }
358
359 /**
360  * @brief       caller & callee's sock handler
361  */
362 int aul_sock_handler(int fd)
363 {
364         app_pkt_t *pkt;
365         bundle *kbundle;
366         int clifd;
367         struct ucred cr;
368
369         const char *str = NULL;
370         int pid;
371         int ret;
372
373         if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) {
374                 _E("recv error");
375                 return -1;
376         }
377
378         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL && cr.uid != 0) {
379                 _E("security error");
380                 __send_result_to_launchpad(clifd, -1);
381                 free(pkt);
382                 return -1;
383         }
384
385         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL && pkt->cmd != APP_KEY_EVENT && pkt->cmd != APP_TERM_BY_PID_ASYNC
386 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
387                 && pkt->cmd != APP_PAUSE_LCD_OFF && pkt->cmd != APP_RESUME_LCD_ON
388 #endif
389                 ) {
390                 ret = __send_result_to_launchpad(clifd, 0);
391                 if (ret < 0) {
392                         free(pkt);
393                         return -1;
394                 }
395         } else {
396                 close(clifd);
397         }
398
399         switch (pkt->cmd) {
400         case APP_START: /* run in callee */
401         case APP_START_RES:
402         case APP_START_ASYNC:
403 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
404         case APP_START_MULTI_INSTANCE:
405 #endif
406                 kbundle = bundle_decode(pkt->data, pkt->len);
407                 if (kbundle == NULL)
408                         goto err;
409                 app_start(kbundle);
410                 bundle_free(kbundle);
411                 break;
412
413         case APP_OPEN:  /* run in callee */
414         case APP_RESUME:
415         case APP_RESUME_BY_PID:
416                 app_resume();
417                 break;
418
419         case APP_TERM_BY_PID:   /* run in callee */
420         case APP_TERM_BY_PID_ASYNC:
421                 app_terminate();
422                 break;
423
424         case APP_TERM_REQ_BY_PID:       /* run in callee */
425                 app_subapp_terminate_request();
426                 break;
427
428         case APP_RESULT:        /* run in caller */
429         case APP_CANCEL:
430                 kbundle = bundle_decode(pkt->data, pkt->len);
431                 if (kbundle == NULL)
432                         goto err;
433
434                 str = bundle_get_val(kbundle, AUL_K_CALLEE_PID);
435                 if(str) {
436                         pid = atoi(str);
437                         app_result(pkt->cmd, kbundle, pid);
438                 }
439                 bundle_free(kbundle);
440                 break;
441
442         case APP_KEY_EVENT:     /* run in caller */
443                 kbundle = bundle_decode(pkt->data, pkt->len);
444                 if (kbundle == NULL)
445                         goto err;
446                 app_key_event(kbundle);
447                 bundle_free(kbundle);
448                 break;
449
450 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
451         case APP_PAUSE_LCD_OFF:
452                 app_pause_lcd_off();
453                 break;
454
455         case APP_RESUME_LCD_ON:
456                 app_resume_lcd_on();
457                 break;
458 #endif
459         default:
460                 _E("no support packet");
461         }
462
463         free(pkt);
464         return 0;
465
466 err:
467         free(pkt);
468         return -1;
469 }
470
471 int aul_make_bundle_from_argv(int argc, char **argv, bundle **kb)
472 {
473         int ac = 1;
474
475         char *buf = NULL;
476
477         *kb = bundle_create();
478         if (*kb == NULL)
479                 return AUL_R_ERROR;
480
481         if (argv == NULL)
482                 return AUL_R_OK;
483
484         if ((argv != NULL) && (argv[0] != NULL)) {
485                 buf = strdup(argv[0]);
486                 if (NULL == buf) {
487                         _E("Malloc failed");
488                         return AUL_R_ERROR;
489                 }
490
491                 bundle_add(*kb, AUL_K_ARGV0, buf);
492         }
493         if (buf) {              /*Prevent FIX: ID 38717 */
494                 free(buf);
495                 buf = NULL;
496         }
497
498         while (ac < argc) {
499                 if (ac + 1 == argc) {
500                         if (bundle_add(*kb, argv[ac], "") < 0) {
501                                 _E("bundle add error pos - %d", ac);
502                                 return AUL_R_ECANCELED;
503                         }
504                 } else {
505                         if (bundle_add(*kb, argv[ac], argv[ac + 1]) < 0) {
506                                 _E("bundle add error pos - %d", ac);
507                                 return AUL_R_ECANCELED;
508                         }
509                 }
510                 ac = ac + 2;
511         }
512
513         return AUL_R_OK;
514 }
515
516 int aul_register_init_callback(
517         int (*aul_handler) (aul_type type, bundle *, void *), void *data)
518 {
519         /* Save start handler function in static var */
520         _aul_handler = aul_handler;
521         _aul_data = data;
522         return 0;
523 }
524
525 int aul_initialize()
526 {
527         if (aul_initialized) {
528                 //_E("aul already initialized");
529                 return AUL_R_ECANCELED;
530         }
531
532         aul_fd = __create_server_sock(getpid());
533         if (aul_fd < 0) {
534                 _E("aul_init create sock failed");
535                 return AUL_R_ECOMM;
536         }
537         aul_initialized = 1;
538
539         return aul_fd;
540 }
541
542 SLPAPI void aul_finalize()
543 {
544
545         aul_launch_fini();
546
547         if (aul_initialized) {
548                 close(aul_fd);
549         }
550
551         return;
552 }
553
554
555 SLPAPI int aul_launch_app(const char *appid, bundle *kb)
556 {
557         if (appid == NULL)
558                 return AUL_R_EINVAL;
559
560         return app_request_to_launchpad(APP_START, appid, kb);
561 }
562
563 SLPAPI int aul_launch_app_async(const char *appid, bundle *kb)
564 {
565         if (appid == NULL)
566                 return AUL_R_EINVAL;
567
568         return app_request_to_launchpad(APP_START_ASYNC, appid, kb);
569 }
570
571 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
572 SLPAPI int aul_launch_app_for_multi_instance(const char *appid, bundle *kb)
573 {
574         if (appid == NULL)
575                 return AUL_R_EINVAL;
576
577         return app_request_to_launchpad(APP_START_MULTI_INSTANCE, appid, kb);
578 }
579 #endif
580
581 SLPAPI int aul_open_app(const char *appid)
582 {
583         if (appid == NULL)
584                 return AUL_R_EINVAL;
585
586         return app_request_to_launchpad(APP_OPEN, appid, NULL);
587 }
588
589 SLPAPI int aul_resume_app(const char *appid)
590 {
591         if (appid == NULL)
592                 return AUL_R_EINVAL;
593
594         return app_request_to_launchpad(APP_RESUME, appid, NULL);
595 }
596
597 SLPAPI int aul_resume_pid(int pid)
598 {
599         char pkgname[MAX_PID_STR_BUFSZ];
600         int ret;
601
602         if (pid <= 0)
603                 return AUL_R_EINVAL;
604
605         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
606         ret = app_request_to_launchpad(APP_RESUME_BY_PID, pkgname, NULL);
607         return ret;
608 }
609
610 SLPAPI int aul_terminate_pid(int pid)
611 {
612         char pkgname[MAX_PID_STR_BUFSZ];
613         int ret;
614
615         if (pid <= 0)
616                 return AUL_R_EINVAL;
617
618         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
619         ret = app_request_to_launchpad(APP_TERM_BY_PID, pkgname, NULL);
620         return ret;
621 }
622
623 SLPAPI int aul_terminate_pid_without_restart(int pid)
624 {
625         char pkgname[MAX_PID_STR_BUFSZ];
626         int ret;
627
628         if (pid <= 0)
629                 return AUL_R_EINVAL;
630
631         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
632         ret = app_request_to_launchpad(APP_TERM_BY_PID_WITHOUT_RESTART, pkgname, NULL);
633         return ret;
634 }
635
636 SLPAPI int aul_terminate_pid_async(int pid)
637 {
638         char pkgname[MAX_PID_STR_BUFSZ];
639         int ret;
640
641         if (pid <= 0)
642                 return AUL_R_EINVAL;
643
644         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
645         ret = app_request_to_launchpad(APP_TERM_BY_PID_ASYNC, pkgname, NULL);
646         return ret;
647 }
648
649 SLPAPI int aul_kill_pid(int pid)
650 {
651         char pkgname[MAX_PID_STR_BUFSZ];
652         int ret;
653
654         if (pid <= 0)
655                 return AUL_R_EINVAL;
656
657         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
658         ret = app_request_to_launchpad(APP_KILL_BY_PID, pkgname, NULL);
659         return ret;
660 }
661
662 #ifdef _APPFW_FEATURE_PROCESS_POOL
663 SLPAPI void aul_set_preinit_window(void *evas_object)
664 {
665         __window_object = evas_object;
666 }
667
668 SLPAPI void* aul_get_preinit_window(const char *win_name)
669 {
670         return __window_object;
671 }
672
673 SLPAPI void aul_set_preinit_background(void *evas_object)
674 {
675         __bg_object = evas_object;
676 }
677
678 SLPAPI void* aul_get_preinit_background(void)
679 {
680         return __bg_object;
681 }
682
683 SLPAPI void aul_set_preinit_conformant(void *evas_object)
684 {
685         __conformant_object = evas_object;
686 }
687
688 SLPAPI void* aul_get_preinit_conformant(void)
689 {
690         return __conformant_object;
691 }
692 #endif
693
694 #ifdef _APPFW_FEATURE_DATA_CONTROL
695 SLPAPI int aul_set_data_control_provider_cb(data_control_provider_handler_fn handler)
696 {
697         __dc_handler = handler;
698         return 0;
699 }
700
701 SLPAPI int aul_unset_data_control_provider_cb(void)
702 {
703         __dc_handler = NULL;
704         return 0;
705 }
706 #endif
707
708 /* vi: set ts=8 sts=8 sw=8: */