Merge tizen2.4 starter
[apps/native/starter.git] / src / mobile / home_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 <aul.h>
18 #include <app.h>
19 #include <db-util.h>
20 #include <Elementary.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <pkgmgr-info.h>
24 #include <stdio.h>
25 #include <dd-deviced.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <unistd.h>
29 #include <vconf.h>
30
31 #include "util.h"
32 #include "dbus_util.h"
33 #include "status.h"
34 #include "process_mgr.h"
35 #include "popup.h"
36
37 #define HOME_TERMINATED "home_terminated"
38 #define ISTRUE "TRUE"
39 #define SYSPOPUPID_VOLUME "volume"
40
41 #define DEAD_TIMER_SEC 2.0
42 #define DEAD_TIMER_COUNT_MAX 2
43
44 #define VCONFKEY_STARTER_IS_FALLBACK "db/starter/is_fallback"
45 #define VCONFKEY_STARTER_FALLBACK_PKG "db/starter/fallback_pkg"
46
47
48
49 int errno;
50 static struct {
51         pid_t home_pid;
52         pid_t volume_pid;
53         int power_off;
54
55         Ecore_Timer *dead_timer;
56         int dead_count;
57
58         Evas_Object *popup;
59 } s_home_mgr = {
60         .home_pid = (pid_t)-1,
61         .volume_pid = (pid_t)-1,
62         .power_off = 0,
63
64         .dead_timer = NULL,
65         .dead_count = 0,
66
67         .popup = NULL,
68 };
69
70
71
72 static void _after_launch_home(int pid)
73 {
74         if (dbus_util_send_oomadj(pid, OOM_ADJ_VALUE_HOMESCREEN) < 0){
75                 _E("failed to send oom dbus signal");
76         }
77         s_home_mgr.home_pid = pid;
78 }
79
80
81
82 static int _change_home_cb(const char *appid, const char *key, const char *value, void *cfn, void *afn)
83 {
84         if (!strcmp(appid, MENU_SCREEN_PKG_NAME)) {
85                 _E("We cannot do anything anymore.");
86         } else if (!strcmp(appid, status_active_get()->setappl_selected_package_name)) {
87                 if (vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, MENU_SCREEN_PKG_NAME) != 0) {
88                         _E("cannot set the vconf key as %s", MENU_SCREEN_PKG_NAME);
89                 }
90                 /* change_home func will be called by changing the home */
91                 return 0;
92         }
93         _E("cannot change home");
94         return -1;
95 }
96
97
98
99 #define SERVICE_OPERATION_MAIN_KEY "__APP_SVC_OP_TYPE__"
100 #define SERVICE_OPERATION_MAIN_VALUE "http://tizen.org/appcontrol/operation/main"
101 void home_mgr_open_home(const char *appid)
102 {
103         char *home_appid = NULL;
104
105         if (status_passive_get()->idle_screen_safemode) {
106                 home_appid = MENU_SCREEN_PKG_NAME;
107         } else if (!appid) {
108                 home_appid = status_active_get()->setappl_selected_package_name;
109         } else {
110                 home_appid = (char *) appid;
111         }
112         ret_if(!home_appid);
113
114         if (!strncmp(home_appid, MENU_SCREEN_PKG_NAME, strlen(home_appid))) {
115                 process_mgr_must_launch(home_appid, SERVICE_OPERATION_MAIN_KEY, SERVICE_OPERATION_MAIN_VALUE, _change_home_cb, _after_launch_home);
116         } else {
117                 process_mgr_must_open(home_appid, _change_home_cb, _after_launch_home);
118         }
119 }
120
121
122
123 static int _show_home_cb(status_active_key_e key, void *data)
124 {
125         int seq = status_active_get()->starter_sequence;
126         int is_fallback = 0;
127         char *fallback_pkg = NULL;
128
129         _D("[MENU_DAEMON] _show_home_cb is invoked(%d)", seq);
130
131         switch (seq) {
132         case 0:
133                 if (s_home_mgr.home_pid > 0) {
134                         _D("Home[%d] has to be terminated.", s_home_mgr.home_pid);
135                         if (aul_terminate_pid(s_home_mgr.home_pid) != AUL_R_OK) {
136                                 _E("Failed to terminate %d", s_home_mgr.home_pid);
137                         }
138                         s_home_mgr.home_pid = -1; /* to freeze the dead_cb */
139                 }
140                 break;
141         case 1:
142                 if (vconf_get_int(VCONFKEY_STARTER_IS_FALLBACK, &is_fallback) < 0) {
143                         _E("Failed to get vconfkey : %s", VCONFKEY_STARTER_IS_FALLBACK);
144                 }
145
146                 if (is_fallback) {
147                         fallback_pkg = vconf_get_str(VCONFKEY_STARTER_FALLBACK_PKG);
148                         if (!fallback_pkg) {
149                                 _E("Failed to get vconfkey : %s", VCONFKEY_STARTER_FALLBACK_PKG);
150                                 home_mgr_open_home(NULL);
151                                 break;
152                         }
153                         _D("fallback pkg : %s", fallback_pkg);
154
155                         if (vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, fallback_pkg) < 0) {
156                                 _E("Failed to set vconfkey : %s", VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
157                                 home_mgr_open_home(NULL);
158                                 free(fallback_pkg);
159                                 break;
160                         }
161
162                         if (vconf_set_int(VCONFKEY_STARTER_IS_FALLBACK, 0)) {
163                                 _E("Failed to set vconfkey : %s", VCONFKEY_STARTER_IS_FALLBACK);
164                         }
165
166                         free(fallback_pkg);
167                 } else {
168                         home_mgr_open_home(NULL);
169                 }
170                 break;
171         default:
172                 _E("False sequence [%d]", seq);
173                 break;
174         }
175
176         return 1;
177 }
178
179
180
181 static int _change_selected_package_name(status_active_key_e key, void *data)
182 {
183         char *appid = NULL;
184         int seq = status_active_get()->starter_sequence;
185
186         if (seq < 1) {
187                 _E("Sequence is not ready yet, do nothing");
188                 return 1;
189         }
190
191         _D("_change_selected_package_name is invoked");
192
193         appid = status_active_get()->setappl_selected_package_name;
194         if (!appid) {
195                 return 1;
196         }
197         _SECURE_D("pkg_name : %s", appid);
198
199         if (s_home_mgr.home_pid > 0) {
200                 char old_appid[BUF_SIZE_512] = { 0 , };
201
202                 if (aul_app_get_pkgname_bypid(s_home_mgr.home_pid, old_appid, sizeof(old_appid)) == AUL_R_OK) {
203                         if (!strcmp(appid, old_appid)) {
204                                 _D("Package is changed but same package is selected");
205                                 return 1;
206                         }
207                 }
208
209                 if (AUL_R_OK != aul_terminate_pid(s_home_mgr.home_pid)) {
210                         _D("Failed to terminate pid %d", s_home_mgr.home_pid);
211                 }
212                 s_home_mgr.home_pid = -1;
213                 s_home_mgr.dead_count = 0;
214                 if (s_home_mgr.dead_timer) {
215                         ecore_timer_del(s_home_mgr.dead_timer);
216                         s_home_mgr.dead_timer = NULL;
217                 }
218         }
219
220         home_mgr_open_home(appid);
221
222         return 1;
223 }
224
225
226
227 static void _after_launch_volume(int pid)
228 {
229         if (dbus_util_send_oomadj(pid, OOM_ADJ_VALUE_DEFAULT) < 0){
230                 _E("failed to send oom dbus signal");
231         }
232         s_home_mgr.volume_pid = pid;
233 }
234
235
236
237 static void _launch_after_home(int pid)
238 {
239         if (pid > 0) {
240                 if(dbus_util_send_oomadj(pid, OOM_ADJ_VALUE_HOMESCREEN) < 0){
241                         _E("failed to send oom dbus signal");
242                 }
243         }
244         s_home_mgr.home_pid = pid;
245 }
246
247
248
249 static void _launch_home(const char *appid)
250 {
251         const char *home_appid = NULL;
252
253         if (status_passive_get()->idle_screen_safemode) {
254                 home_appid = MENU_SCREEN_PKG_NAME;
255         } else if (!appid) {
256                 home_appid = status_active_get()->setappl_selected_package_name;
257         } else {
258                 home_appid = (char *) appid;
259         }
260         ret_if(!home_appid);
261
262         process_mgr_must_launch(home_appid, HOME_TERMINATED, ISTRUE, _change_home_cb, _launch_after_home);
263 }
264
265
266
267 static void _popup_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
268 {
269         _D("popup is deleted");
270
271         s_home_mgr.popup = NULL;
272 }
273
274
275
276 static Eina_Bool _dead_timer_cb(void *data)
277 {
278         Evas_Object *popup = NULL;
279         char title[BUF_SIZE_128] = { 0, };
280         char text[BUF_SIZE_1024] = { 0, };
281
282         char *appid = (char *)data;
283         retv_if(!appid, ECORE_CALLBACK_CANCEL);
284
285         _D("dead count : %s(%d)", appid, s_home_mgr.dead_count);
286
287         if (s_home_mgr.dead_count >= DEAD_TIMER_COUNT_MAX) {
288                 _D("Change homescreen package to default");
289
290                 if (vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, MENU_SCREEN_PKG_NAME) != 0) {
291                         _E("cannot set the vconf key as %s", MENU_SCREEN_PKG_NAME);
292                         return ECORE_CALLBACK_RENEW;
293                 }
294
295                 strncpy(title, _("IDS_COM_POP_WARNING"), sizeof(title));
296                 title[sizeof(title) - 1] = '\0';
297
298                 snprintf(text, sizeof(text), _("IDS_IDLE_POP_UNABLE_TO_LAUNCH_PS"), appid);
299                 _D("title : %s / text : %s", title, text);
300
301                 if (!s_home_mgr.popup) {
302                         popup = popup_create(title, text);
303                         if (!popup) {
304                                 _E("Failed to create popup");
305                         } else {
306                                 s_home_mgr.popup = popup;
307                                 evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, _popup_del_cb, NULL);
308                         }
309                 }
310
311                 /* set fallback status */
312                 if (vconf_set_int(VCONFKEY_STARTER_IS_FALLBACK, 1) < 0) {
313                         _E("Failed to set vconfkey : %s", VCONFKEY_STARTER_IS_FALLBACK);
314                 }
315
316                 if (vconf_set_str(VCONFKEY_STARTER_FALLBACK_PKG, appid) < 0) {
317                         _E("Failed to set vconfkey : %s", VCONFKEY_STARTER_FALLBACK_PKG);
318                 }
319         }
320
321         s_home_mgr.dead_timer = NULL;
322         s_home_mgr.dead_count = 0;
323
324         return ECORE_CALLBACK_CANCEL;
325 }
326
327
328
329 int home_mgr_check_dead_signal(int pid, void *data)
330 {
331         char *appid = NULL;
332
333         _D("Process %d is termianted", pid);
334
335         if (pid < 0) {
336                 _E("pid : %d", pid);
337                 return 0;
338         }
339
340         if (s_home_mgr.power_off) {
341                 _E("power off");
342                 return 0;
343         }
344
345         appid = status_active_get()->setappl_selected_package_name;
346         if (!appid) {
347                 _E("appid is NULL");
348                 return 0;
349         }
350
351         if (pid == s_home_mgr.home_pid) {
352                 s_home_mgr.dead_count++;
353                 _D("home dead count : %d", s_home_mgr.dead_count);
354
355                 if (!s_home_mgr.dead_timer) {
356                         _D("Add dead timer");
357                         s_home_mgr.dead_timer = ecore_timer_add(DEAD_TIMER_SEC, _dead_timer_cb, (void *)appid);
358                 }
359
360                 _launch_home(appid);
361         } else if (pid == s_home_mgr.volume_pid) {
362                 process_mgr_must_syspopup_launch(SYSPOPUPID_VOLUME, NULL, NULL, NULL, _after_launch_volume);
363         } else {
364                 _D("Unknown process, ignore it (dead pid %d, home pid %d)", pid, s_home_mgr.home_pid);
365         }
366
367         return 0;
368 }
369
370
371
372 static int _power_off_cb(status_active_key_e key, void *data)
373 {
374         int val = status_active_get()->sysman_power_off_status;
375
376         if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART) {
377                 s_home_mgr.power_off = 1;
378         } else {
379                 s_home_mgr.power_off = 0;
380         }
381
382         _D("power off status : %d", s_home_mgr.power_off);
383
384         return 1;
385 }
386
387
388
389 static Eina_Bool _launch_volume_idler_cb(void *data)
390 {
391         process_mgr_must_syspopup_launch(SYSPOPUPID_VOLUME, NULL, NULL, NULL, _after_launch_volume);
392         return ECORE_CALLBACK_CANCEL;
393 }
394
395
396
397 void home_mgr_init(void *data)
398 {
399         _D( "[MENU_DAEMON]home_mgr_init is invoked");
400
401         status_active_register_cb(STATUS_ACTIVE_KEY_STARTER_SEQUENCE, _show_home_cb, NULL);
402         status_active_register_cb(STATUS_ACTIVE_KEY_SYSMAN_POWER_OFF_STATUS, _power_off_cb, NULL);
403         status_active_register_cb(STATUS_ACTIVE_KEY_SETAPPL_SELECTED_PACKAGE_NAME, _change_selected_package_name, NULL);
404         _change_selected_package_name(STATUS_ACTIVE_KEY_SETAPPL_SELECTED_PACKAGE_NAME, NULL);
405
406         ecore_idler_add(_launch_volume_idler_cb, NULL);
407
408         aul_listen_app_dead_signal(home_mgr_check_dead_signal, NULL);
409 }
410
411
412
413 void home_mgr_fini(void)
414 {
415         if (s_home_mgr.volume_pid > 0) {
416                 process_mgr_terminate_app(s_home_mgr.volume_pid, 1);
417                 s_home_mgr.volume_pid = -1;
418         }
419
420         status_active_unregister_cb(STATUS_ACTIVE_KEY_STARTER_SEQUENCE, _show_home_cb);
421         status_active_unregister_cb(STATUS_ACTIVE_KEY_SYSMAN_POWER_OFF_STATUS, _power_off_cb);
422         status_active_unregister_cb(STATUS_ACTIVE_KEY_SETAPPL_SELECTED_PACKAGE_NAME, _change_selected_package_name);
423 }
424
425
426
427 // End of a file