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