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