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