Initialize Tizen 2.3
[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
32 #include "aul.h"
33 #include "aul_api.h"
34 #include "app_sock.h"
35 #include "perf.h"
36 #include "simple_util.h"
37 #include "launch.h"
38 #include "key.h"
39 #include "aul_util.h"
40
41 static int aul_initialized = 0;
42 static int aul_fd;
43
44 static int (*_aul_handler) (aul_type type, bundle *kb, void *data) = NULL;
45 static void *_aul_data;
46
47
48
49 static int __call_aul_handler(aul_type type, bundle *kb);
50 static int app_resume();
51 static int app_terminate();
52 static void __clear_internal_key(bundle *kb);
53 static inline void __set_stime(bundle *kb);
54 static int __app_start_internal(gpointer data);
55 static int __app_launch_local(bundle *b);
56 static int __send_result_to_launchpad(int fd, int res);
57
58
59 #ifdef PROCESS_POOL_ENABLE
60 static void *__window_object = NULL;
61 #endif
62
63 extern  int aul_launch_fini();
64
65 int aul_is_initialized()
66 {
67         return aul_initialized;
68 }
69
70 static int __call_aul_handler(aul_type type, bundle *kb)
71 {
72         if (_aul_handler)
73                 _aul_handler(type, kb, _aul_data);
74         return 0;
75 }
76
77 int app_start(bundle *kb)
78 {
79         _app_start_res_prepare(kb);
80         __call_aul_handler(AUL_START, kb);
81         return 0;
82 }
83
84 static int app_resume()
85 {
86         __call_aul_handler(AUL_RESUME, NULL);
87         return 0;
88 }
89
90 static int app_terminate()
91 {
92         __call_aul_handler(AUL_TERMINATE, NULL);
93         return 0;
94 }
95
96
97 /**
98  * @brief       encode kb and send it to 'pid'
99  * @param[in]   pid             receiver's pid
100  * @param[in]   cmd             message's status (APP_START | APP_RESULT)
101  * @param[in]   kb              data
102  */
103 SLPAPI int app_send_cmd(int pid, int cmd, bundle *kb)
104 {
105         int datalen;
106         bundle_raw *kb_data;
107         int res;
108
109         bundle_encode(kb, &kb_data, &datalen);
110         if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) {
111                 switch (res) {
112                 case -EINVAL:
113                         res = AUL_R_EINVAL;
114                         break;
115                 case -ECOMM:
116                         res = AUL_R_ECOMM;
117                         break;
118                 case -EAGAIN:
119                         res = AUL_R_ETIMEOUT;
120                         break;
121                 case -ELOCALLAUNCH_ID:
122                         res = AUL_R_LOCAL;
123                         break;
124                 case -EILLEGALACCESS:
125                         res = AUL_R_EILLACC;
126                         break;
127                 case -ETERMINATING:
128                         res = AUL_R_ETERMINATING;
129                         break;
130                 case -ENOLAUNCHPAD:
131                         res = AUL_R_ENOLAUNCHPAD;
132                         break;
133                 default:
134                         res = AUL_R_ERROR;
135                 }
136         }
137         free(kb_data);
138
139         return res;
140 }
141
142 SLPAPI int app_send_cmd_with_noreply(int pid, int cmd, bundle *kb)
143 {
144         int datalen;
145         bundle_raw *kb_data;
146         int res;
147
148         bundle_encode(kb, &kb_data, &datalen);
149         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0) {
150                 switch (res) {
151                 case -EINVAL:
152                         res = AUL_R_EINVAL;
153                         break;
154                 case -ECOMM:
155                         res = AUL_R_ECOMM;
156                         break;
157                 case -EAGAIN:
158                         res = AUL_R_ETIMEOUT;
159                         break;
160                 case -ELOCALLAUNCH_ID:
161                         res = AUL_R_LOCAL;
162                         break;
163                 case -EILLEGALACCESS:
164                         res = AUL_R_EILLACC;
165                         break;
166                 default:
167                         res = AUL_R_ERROR;
168                 }
169         }
170         free(kb_data);
171
172         return res;
173 }
174
175 static void __clear_internal_key(bundle *kb)
176 {
177         bundle_del(kb, AUL_K_CALLER_PID);
178         bundle_del(kb, AUL_K_PKG_NAME);
179         bundle_del(kb, AUL_K_WAIT_RESULT);
180         bundle_del(kb, AUL_K_SEND_RESULT);
181         bundle_del(kb, AUL_K_ARGV0);
182 }
183
184 static inline void __set_stime(bundle *kb)
185 {
186         struct timeval tv;
187         char tmp[MAX_LOCAL_BUFSZ];
188
189         gettimeofday(&tv, NULL);
190         snprintf(tmp, MAX_LOCAL_BUFSZ, "%ld/%ld", tv.tv_sec, tv.tv_usec);
191         bundle_add(kb, AUL_K_STARTTIME, tmp);
192 }
193
194 static int __app_start_internal(gpointer data)
195 {
196         bundle *kb;
197
198         kb = (bundle *) data;
199         app_start(kb);
200         bundle_free(kb);
201
202         return 0;
203 }
204
205 static int __app_launch_local(bundle *b)
206 {
207         if (!aul_is_initialized())
208                 return AUL_R_ENOINIT;
209
210         if (b == NULL) {
211                 _E("bundle for APP_START is NULL");
212         }
213         if (g_idle_add(__app_start_internal, b) > 0)
214                 return AUL_R_OK;
215         else
216                 return AUL_R_ERROR;
217 }
218
219 static int __app_resume_local()
220 {
221         if (!aul_is_initialized())
222                 return AUL_R_ENOINIT;
223
224         app_resume();
225
226         return 0;
227 }
228
229 /**
230  * @brief       start caller with kb
231  * @return      callee's pid
232  */
233 int app_request_to_launchpad(int cmd, const char *pkgname, bundle *kb)
234 {
235         int must_free = 0;
236         int ret = 0;
237
238         SECURE_LOGD("launch request : %s", pkgname);
239         if (kb == NULL) {
240                 kb = bundle_create();
241                 must_free = 1;
242         } else
243                 __clear_internal_key(kb);
244
245         bundle_add(kb, AUL_K_PKG_NAME, pkgname);
246         __set_stime(kb);
247         if(cmd == APP_START_ASYNC)
248                 ret = app_send_cmd_with_noreply(AUL_UTIL_PID, cmd, kb);
249         else
250                 ret = app_send_cmd(AUL_UTIL_PID, cmd, kb);
251
252         _D("launch request result : %d", ret);
253         if (ret == AUL_R_LOCAL) {
254                 _E("app_request_to_launchpad : Same Process Send Local");
255                 bundle *b;
256
257                 switch (cmd) {
258                         case APP_START:
259                         case APP_START_RES:
260                                 b = bundle_dup(kb);
261                                 ret = __app_launch_local(b);
262                                 break;
263                         case APP_OPEN:
264                         case APP_RESUME:
265                         case APP_RESUME_BY_PID:
266                                 ret = __app_resume_local();
267                                 break;
268                         default:
269                                 _E("no support packet");
270                 }
271
272         }
273
274         /* cleanup */
275         if (must_free)
276                 bundle_free(kb);
277
278         return ret;
279 }
280
281 static int __send_result_to_launchpad(int fd, int res)
282 {
283         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
284                 if (errno == EPIPE) {
285                         _E("send failed due to EPIPE.\n");
286                         close(fd);
287                         return -1;
288                 }
289                 _E("send fail to client");
290         }
291         close(fd);
292         return 0;
293 }
294
295 /**
296  * @brief       caller & callee's sock handler
297  */
298 int aul_sock_handler(int fd)
299 {
300         app_pkt_t *pkt;
301         bundle *kbundle;
302         int clifd;
303         struct ucred cr;
304
305         const char *pid_str = NULL;
306         int pid;
307         int ret;
308
309         if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) {
310                 _E("recv error");
311                 return -1;
312         }
313
314         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL && cr.uid != 0) {
315                 _E("security error");
316                 __send_result_to_launchpad(clifd, -1);
317                 free(pkt);
318                 return -1;
319         }
320
321         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL) {
322                 ret = __send_result_to_launchpad(clifd, 0);
323                 if (ret < 0) {
324                         free(pkt);
325                         return -1;
326                 }
327         } else {
328                 close(clifd);
329         }
330
331         switch (pkt->cmd) {
332         case APP_START: /* run in callee */
333         case APP_START_RES:
334         case APP_START_ASYNC:
335                 kbundle = bundle_decode(pkt->data, pkt->len);
336                 if (kbundle == NULL)
337                         goto err;
338                 app_start(kbundle);
339                 bundle_free(kbundle);
340                 break;
341
342         case APP_OPEN:  /* run in callee */
343         case APP_RESUME:
344         case APP_RESUME_BY_PID:
345                 app_resume();
346                 break;
347
348         case APP_TERM_BY_PID:   /* run in callee */
349                 app_terminate();
350                 break;
351
352         case APP_TERM_REQ_BY_PID:       /* run in callee */
353                 app_subapp_terminate_request();
354                 break;
355
356         case APP_RESULT:        /* run in caller */
357         case APP_CANCEL:
358                 kbundle = bundle_decode(pkt->data, pkt->len);
359                 if (kbundle == NULL)
360                         goto err;
361
362                 pid_str = bundle_get_val(kbundle, AUL_K_CALLEE_PID);
363                 if(pid_str) {
364                         pid = atoi(pid_str);
365                         app_result(pkt->cmd, kbundle, pid);
366                 }
367                 bundle_free(kbundle);
368                 break;
369
370         case APP_KEY_EVENT:     /* run in caller */
371                 kbundle = bundle_decode(pkt->data, pkt->len);
372                 if (kbundle == NULL)
373                         goto err;
374                 app_key_event(kbundle);
375                 bundle_free(kbundle);
376                 break;
377
378         default:
379                 _E("no support packet");
380         }
381
382         free(pkt);
383         return 0;
384
385 err:
386         free(pkt);
387         return -1;
388 }
389
390 int aul_make_bundle_from_argv(int argc, char **argv, bundle **kb)
391 {
392         int ac = 1;
393
394         char *buf = NULL;
395
396         *kb = bundle_create();
397         if (*kb == NULL)
398                 return AUL_R_ERROR;
399
400         if (argv == NULL)
401                 return AUL_R_OK;
402
403         if ((argv != NULL) && (argv[0] != NULL)) {
404                 buf = strdup(argv[0]);
405                 if (NULL == buf) {
406                         _E("Malloc failed");
407                         return AUL_R_ERROR;
408                 }
409
410                 bundle_add(*kb, AUL_K_ARGV0, buf);
411         }
412         if (buf) {              /*Prevent FIX: ID 38717 */
413                 free(buf);
414                 buf = NULL;
415         }
416
417         while (ac < argc) {
418                 if (ac + 1 == argc) {
419                         if (bundle_add(*kb, argv[ac], "") < 0) {
420                                 _E("bundle add error pos - %d", ac);
421                                 return AUL_R_ECANCELED;
422                         }
423                 } else {
424                         if (bundle_add(*kb, argv[ac], argv[ac + 1]) < 0) {
425                                 _E("bundle add error pos - %d", ac);
426                                 return AUL_R_ECANCELED;
427                         }
428                 }
429                 ac = ac + 2;
430         }
431
432         return AUL_R_OK;
433 }
434
435 int aul_register_init_callback(
436         int (*aul_handler) (aul_type type, bundle *, void *), void *data)
437 {
438         /* Save start handler function in static var */
439         _aul_handler = aul_handler;
440         _aul_data = data;
441         return 0;
442 }
443
444 int aul_initialize()
445 {
446         if (aul_initialized) {
447                 //_E("aul already initialized");
448                 return AUL_R_ECANCELED;
449         }
450
451         aul_fd = __create_server_sock(getpid());
452         if (aul_fd < 0) {
453                 _E("aul_init create sock failed");
454                 return AUL_R_ECOMM;
455         }
456         aul_initialized = 1;
457
458         return aul_fd;
459 }
460
461 SLPAPI void aul_finalize()
462 {
463
464         aul_launch_fini();
465
466         if (aul_initialized) {
467                 close(aul_fd);
468         }
469
470         return;
471 }
472
473
474 SLPAPI int aul_launch_app(const char *appid, bundle *kb)
475 {
476         int ret;
477
478         if (appid == NULL)
479                 return AUL_R_EINVAL;
480
481         ret = app_request_to_launchpad(APP_START, appid, kb);
482         return ret;
483 }
484
485 SLPAPI int aul_launch_app_async(const char *appid, bundle *kb)
486 {
487         int ret;
488
489         if (appid == NULL)
490                 return AUL_R_EINVAL;
491
492         ret = app_request_to_launchpad(APP_START_ASYNC, appid, kb);
493         return ret;
494 }
495
496 SLPAPI int aul_open_app(const char *appid)
497 {
498         int ret;
499
500         if (appid == NULL)
501                 return AUL_R_EINVAL;
502
503         ret = app_request_to_launchpad(APP_OPEN, appid, NULL);
504         return ret;
505 }
506
507 SLPAPI int aul_resume_app(const char *appid)
508 {
509         int ret;
510
511         if (appid == NULL)
512                 return AUL_R_EINVAL;
513
514         ret = app_request_to_launchpad(APP_RESUME, appid, NULL);
515         return ret;
516 }
517
518 SLPAPI int aul_resume_pid(int pid)
519 {
520         char pkgname[MAX_PID_STR_BUFSZ];
521         int ret;
522
523         if (pid <= 0)
524                 return AUL_R_EINVAL;
525
526         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
527         ret = app_request_to_launchpad(APP_RESUME_BY_PID, pkgname, NULL);
528         return ret;
529 }
530
531 SLPAPI int aul_terminate_pid(int pid)
532 {
533         char pkgname[MAX_PID_STR_BUFSZ];
534         int ret;
535
536         if (pid <= 0)
537                 return AUL_R_EINVAL;
538
539         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
540         ret = app_request_to_launchpad(APP_TERM_BY_PID, pkgname, NULL);
541         return ret;
542 }
543
544 SLPAPI int aul_kill_pid(int pid)
545 {
546         char pkgname[MAX_PID_STR_BUFSZ];
547         int ret;
548
549         if (pid <= 0)
550                 return AUL_R_EINVAL;
551
552         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
553         ret = app_request_to_launchpad(APP_KILL_BY_PID, pkgname, NULL);
554         return ret;
555 }
556
557 #ifdef PROCESS_POOL_ENABLE
558 SLPAPI void aul_set_preinit_window(void *evas_object)
559 {
560         __window_object = evas_object;
561 }
562
563 SLPAPI void* aul_get_preinit_window(void)
564 {
565         return __window_object;
566 }
567 #endif
568
569 /* vi: set ts=8 sts=8 sw=8: */
570