Merge "[Common] Initialize e-dbus" into tizen
[apps/native/starter.git] / src / process_mgr.c
1 /*
2  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <vconf.h>
18 #include <aul.h>
19 #include <Ecore.h>
20 #include <syspopup_caller.h>
21 #include <sys/time.h>
22 #include <sys/resource.h>
23 #include <bundle_internal.h>
24 #include <app_manager.h>
25 #include <app_control.h>
26
27 #include "process_mgr.h"
28 #include "util.h"
29 #include "dbus_util.h"
30
31 #define LOCKD_VOICE_CALL_PKG_NAME "org.tizen.call-ui"
32 #define LOCKD_VIDEO_CALL_PKG_NAME "org.tizen.vtmain"
33
34 #define NICE_VALUE_PWLOCK -5
35 #define NICE_VALUE_LOCKSCREEN -20
36
37
38
39 typedef struct _launch_info_s {
40         char *appid;
41         char *key;
42         char *value;
43         after_func afn;
44         change_func cfn;
45 } launch_info_s;
46
47
48
49 static int _try_to_launch(const char *appid, const char *key, const char *value, after_func afn)
50 {
51         int pid = -1;
52
53         retv_if(!appid, -1);
54
55         int ret = 0;
56         app_control_h app_control_handle = NULL;
57         app_context_h app_context_handle = NULL;
58
59         ret = app_control_create(&app_control_handle);
60         if (ret != APP_CONTROL_ERROR_NONE) {
61                 _E("Failed to create appcontrol");
62                 return -1;
63         }
64
65         ret = app_control_set_operation(app_control_handle, APP_CONTROL_OPERATION_DEFAULT);
66         if (ret != APP_CONTROL_ERROR_NONE) {
67                 _E("Failed to set operation to appcontrol");
68                 app_control_destroy(app_control_handle);
69                 return -1;
70         }
71
72         if (key && value) {
73                 _D("key(%s), value(%s)", key, value);
74                 ret = app_control_add_extra_data(app_control_handle, key, value);
75                 if (ret != APP_CONTROL_ERROR_NONE) {
76                         _E("Failed to add extra data to appcontrol");
77                         app_control_destroy(app_control_handle);
78                         return -1;
79                 }
80         }
81
82         ret = app_control_set_app_id(app_control_handle, appid);
83         if (ret != APP_CONTROL_ERROR_NONE) {
84                 _E("Failed to set app id to appcontrol");
85                 app_control_destroy(app_control_handle);
86                 return -1;
87         }
88
89         ret = app_control_send_launch_request(app_control_handle, NULL, NULL);
90         if (ret != APP_CONTROL_ERROR_NONE) {
91                 _E("Failed to send launch request : %s", appid);
92                 app_control_destroy(app_control_handle);
93                 return -1;
94         }
95
96         app_control_destroy(app_control_handle);
97
98         ret = app_manager_get_app_context(appid, &app_context_handle);
99         if (ret != APP_MANAGER_ERROR_NONE) {
100                 _E("Failed to get app context : %s", appid);
101                 return -1;
102         }
103
104         ret = app_context_get_pid(app_context_handle, &pid);
105         if (ret != APP_MANAGER_ERROR_NONE) {
106                 _E("Failed to get pid : %s", appid);
107                 app_context_destroy(app_context_handle);
108                 return -1;
109         }
110
111         app_context_destroy(app_context_handle);
112
113         _D("Succeed to launch : %s(%d)", appid, pid);
114         if (afn) afn(pid);
115
116         return pid;
117 }
118
119
120
121 static Eina_Bool _must_launch_cb(void *data)
122 {
123         launch_info_s *launch_info = data;
124         int pid;
125
126         retv_if(!launch_info, ECORE_CALLBACK_CANCEL);
127
128         pid = _try_to_launch(launch_info->appid, launch_info->key, launch_info->value, launch_info->afn);
129         if (pid > 0) {
130                 goto OUT;
131         }
132
133         retv_if(pid == AUL_R_ECOMM, ECORE_CALLBACK_RENEW);
134         retv_if(pid == AUL_R_ETERMINATING, ECORE_CALLBACK_RENEW);
135         if (pid == AUL_R_ERROR) {
136                 if (launch_info->cfn
137                         && 0 == launch_info->cfn(launch_info->appid, launch_info->key, launch_info->value, (void *) launch_info->cfn, (void *) launch_info->afn))
138                 {
139                         _D("change func has set the next appid");
140                 } else {
141                         _E("change func has returned error");
142                 }
143                 goto OUT;
144         }
145
146         return ECORE_CALLBACK_RENEW;
147
148 OUT:
149         free(launch_info->appid);
150         free(launch_info->key);
151         free(launch_info->value);
152         free(launch_info);
153         return ECORE_CALLBACK_CANCEL;
154 }
155
156
157
158 void process_mgr_must_launch(const char *appid, const char *key, const char *value, change_func cfn, after_func afn)
159 {
160         Ecore_Timer *timer = NULL;
161         launch_info_s *launch_info = NULL;
162         int pid = -1;
163
164         _D("Must launch : %s", appid);
165
166         pid = _try_to_launch(appid, key, value, afn);
167         if (pid > 0) return;
168
169         _E("Failed the first try to launch %s", appid);
170
171         launch_info = calloc(1, sizeof(launch_info_s));
172         ret_if(!launch_info);
173
174         if (appid) launch_info->appid = strdup(appid);
175         if (key) launch_info->key = strdup(key);
176         if (value) launch_info->value = strdup(value);
177         launch_info->cfn = cfn;
178         launch_info->afn = afn;
179
180         timer = ecore_timer_add(0.1f, _must_launch_cb, launch_info);
181         if (!timer) {
182                 _E("cannot add a timer for must_launch");
183                 free(launch_info->appid);
184                 free(launch_info->key);
185                 free(launch_info->value);
186                 free(launch_info);
187         }
188 }
189
190
191
192 static int _try_to_open(const char *appid, after_func afn)
193 {
194         int pid = -1;
195
196         retv_if(!appid, -1);
197
198         pid = aul_open_app(appid);
199         if (pid > 0) {
200                 _D("Succeed to open %s", appid);
201                 if (afn) afn(pid);
202         }
203
204         return pid;
205 }
206
207
208
209 static Eina_Bool _must_open_cb(void *data)
210 {
211         launch_info_s *launch_info = data;
212         int pid;
213
214         retv_if(!launch_info, ECORE_CALLBACK_CANCEL);
215
216         pid = _try_to_open(launch_info->appid, launch_info->afn);
217         if (pid > 0) {
218                 goto OUT;
219         }
220
221         retv_if(pid == AUL_R_ECOMM, ECORE_CALLBACK_RENEW);
222         retv_if(pid == AUL_R_ETERMINATING, ECORE_CALLBACK_RENEW);
223         if (pid == AUL_R_ERROR) {
224                 if (launch_info->cfn && 0 == launch_info->cfn(launch_info->appid, NULL, NULL, launch_info->cfn, launch_info->afn)) {
225                         _D("change func has set the next appid");
226                 } else {
227                         _E("change func has returned error");
228                 }
229                 goto OUT;
230         }
231
232         return ECORE_CALLBACK_RENEW;
233
234 OUT:
235         free(launch_info->appid);
236         free(launch_info);
237         return ECORE_CALLBACK_CANCEL;
238 }
239
240
241
242 void process_mgr_must_open(const char *appid, change_func cfn, after_func afn)
243 {
244         Ecore_Timer *timer = NULL;
245         launch_info_s *launch_info = NULL;
246         int pid = -1;
247
248         _D("Must open %s", appid);
249
250         pid = _try_to_open(appid, afn);
251         if (pid > 0) return;
252
253         _E("Failed the first try to open %s", appid);
254
255         launch_info = calloc(1, sizeof(launch_info_s));
256         ret_if(!launch_info);
257
258         if (appid) launch_info->appid = strdup(appid);
259         launch_info->cfn = cfn;
260         launch_info->afn = afn;
261
262         timer = ecore_timer_add(0.1f, _must_open_cb, launch_info);
263         if (!timer) {
264                 _E("cannot add a timer for must_launch");
265                 free(launch_info->appid);
266                 free(launch_info);
267         }
268 }
269
270
271
272 static int _try_to_syspopup_launch(const char *appid, const char *key, const char *value, after_func afn)
273 {
274         int pid = -1;
275         bundle *b = NULL;
276
277         retv_if(!appid, -1);
278
279         if (key) {
280                 b = bundle_create();
281                 bundle_add(b, key, value);
282         }
283
284         pid = aul_launch_app("org.tizen.volume", b);
285         if (b) bundle_free(b);
286         if (pid > 0) {
287                 _D("Succeed to launch %s", appid);
288                 if (afn) afn(pid);
289         }
290
291         return pid;
292 }
293
294
295
296 static Eina_Bool _must_syspopup_launch_cb(void *data)
297 {
298         launch_info_s *launch_info = data;
299         int pid;
300
301         retv_if(!launch_info, ECORE_CALLBACK_CANCEL);
302
303         pid = _try_to_syspopup_launch(launch_info->appid, launch_info->key, launch_info->value, launch_info->afn);
304         if (pid > 0) {
305                 goto OUT;
306         }
307
308         retv_if(pid == AUL_R_ECOMM, ECORE_CALLBACK_RENEW);
309         retv_if(pid == AUL_R_ETERMINATING, ECORE_CALLBACK_RENEW);
310         if (pid == AUL_R_ERROR) {
311                 if (launch_info->cfn
312                         && 0 == launch_info->cfn(launch_info->appid, launch_info->key, launch_info->value, launch_info->cfn, launch_info->afn)) {
313                         _D("change func has set the next appid");
314                 } else {
315                         _E("change func has returned error");
316                 }
317                 goto OUT;
318         }
319
320         return ECORE_CALLBACK_RENEW;
321
322 OUT:
323         free(launch_info->appid);
324         free(launch_info->key);
325         free(launch_info->value);
326         free(launch_info);
327         return ECORE_CALLBACK_CANCEL;
328 }
329
330
331
332 void process_mgr_must_syspopup_launch(const char *appid, const char *key, const char *value, change_func cfn, after_func afn)
333 {
334         Ecore_Timer *timer = NULL;
335         launch_info_s *launch_info = NULL;
336         int pid = -1;
337
338         _D("Must launch %s", appid);
339
340         pid = _try_to_syspopup_launch(appid, key, value, afn);
341         if (pid > 0) return;
342
343         _E("Failed the first try to launch %s", appid);
344
345         launch_info = calloc(1, sizeof(launch_info_s));
346         ret_if(!launch_info);
347
348         if (appid) launch_info->appid = strdup(appid);
349         if (key) launch_info->key = strdup(key);
350         if (value) launch_info->value = strdup(value);
351         launch_info->cfn = cfn;
352         launch_info->afn = afn;
353
354         timer = ecore_timer_add(0.1f, _must_syspopup_launch_cb, launch_info);
355         if (!timer) {
356                 _E("cannot add a timer for must_launch");
357                 free(launch_info->appid);
358                 free(launch_info->key);
359                 free(launch_info->value);
360                 free(launch_info);
361         }
362 }
363
364
365
366 static Eina_Bool _set_lock_priority_cb(void *data)
367 {
368         int prio;
369
370         prio = getpriority(PRIO_PROCESS, (pid_t)data);
371         if (prio == NICE_VALUE_LOCKSCREEN) {
372                 _D("%s (%d: %d)\n", "setpriority Success", (pid_t)data, prio);
373                 return ECORE_CALLBACK_CANCEL;
374         }
375
376         if (setpriority(PRIO_PROCESS, (pid_t)data, NICE_VALUE_LOCKSCREEN) < 0 ) {
377                 _D("error : %d", errno);
378                 return ECORE_CALLBACK_CANCEL;
379         }
380
381         return ECORE_CALLBACK_RENEW;
382 }
383
384
385
386 static Eina_Bool _set_pwlock_priority_cb(void *data)
387 {
388         int prio;
389
390         prio = getpriority(PRIO_PROCESS, (pid_t)data);
391         if (prio == NICE_VALUE_PWLOCK) {
392                 _D("%s (%d: %d)\n", "setpriority Success", (pid_t)data, prio);
393                 return ECORE_CALLBACK_CANCEL;
394         }
395
396         if (setpriority(PRIO_PROCESS, (pid_t)data, NICE_VALUE_PWLOCK) < 0 ) {
397                 _D("error : %d", errno);
398                 return ECORE_CALLBACK_CANCEL;
399         }
400
401         return ECORE_CALLBACK_RENEW;
402 }
403
404
405
406 int process_mgr_set_lock_priority(int pid)
407 {
408         return !ecore_timer_add(1.0f, _set_lock_priority_cb, (void *)pid);
409 }
410
411
412
413 int process_mgr_set_pwlock_priority(int pid)
414 {
415         return !ecore_timer_add(1.0f, _set_pwlock_priority_cb, (void *)pid);
416 }
417
418
419
420 void process_mgr_terminate_app(int pid, int state)
421 {
422         _D("process_mgr_terminate_app,  state:%d\n", state);
423
424         if (state == 1) {
425                 if (pid != 0) {
426                         _D("Terminate app(pid : %d)", pid);
427                         aul_terminate_pid(pid);
428                 }
429         }
430 }
431
432
433
434 extern int aul_kill_pid(int pid);
435 void process_mgr_kill_app(int pid)
436 {
437         _D ("process_mgr_kill_app [pid:%d]..", pid);
438         aul_kill_pid(pid);
439 }
440
441
442
443 int process_mgr_validate_app(int pid)
444 {
445         char buf[BUF_SIZE_128] = {0, };
446
447         /* Check pid is invalid. */
448         if (aul_app_get_pkgname_bypid(pid, buf, sizeof(buf)) < 0) {
449                 _D("no such pkg by pid %d\n", pid);
450         } else {
451                 _SECURE_D("appid = %s, pid = %d\n", buf, pid);
452                 if (aul_app_is_running(buf) == TRUE) {
453                         _D("%s [pid = %d] is running\n", buf, pid);
454                         return TRUE;
455                 } else {
456                         _SECURE_D("[pid = %d] is exist but %s is not running\n", pid, buf);
457                 }
458         }
459
460         return FALSE;
461 }
462
463
464
465 int process_mgr_validate_call(int pid)
466 {
467         char buf[BUF_SIZE_128] = {0, };
468
469         /* Check pid is invalid. */
470         if (aul_app_get_pkgname_bypid(pid, buf, sizeof(buf)) < 0) {
471                 _D("no such pkg by pid %d", pid);
472         } else {
473                 _SECURE_D("appid = %s, pid = %d", buf, pid);
474                 if ((!strncmp(buf, LOCKD_VOICE_CALL_PKG_NAME, strlen(buf)))
475                     || (!strncmp(buf, LOCKD_VIDEO_CALL_PKG_NAME, strlen(buf)))) {
476                     return TRUE;
477                 }
478         }
479
480         return FALSE;
481 }
482
483
484