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