aa86d4488651a44e93359955bad54ec18de60480
[apps/native/starter.git] / src / common / 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 <sys/types.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
28 #include <vconf.h>
29
30 #include "util.h"
31 #include "dbus_util.h"
32 #include "status.h"
33 #include "process_mgr.h"
34 #include "popup.h"
35
36 #define VOLUME_ENABLE 1
37
38 #define HOME_TERMINATED "home_terminated"
39 #define ISTRUE "TRUE"
40 #define SYSPOPUPID_VOLUME "org.tizen.volume-nui"
41
42 #define DEAD_TIMER_SEC 10.0
43 #define DEAD_TIMER_COUNT_MAX 2
44
45 #define APPID_INDICATOR "org.tizen.indicator"
46 #define APPID_SOFTKEY "org.tizen.softkey-container"
47 #define APPID_TASKBAR "org.tizen.taskbar"
48
49 #define HOMESCREEN_NUI_PKG_NAME "org.tizen.homescreen-nui"
50
51 int errno;
52 static struct {
53         pid_t home_pid;
54         pid_t volume_pid;
55         pid_t indicator_pid;
56         pid_t softkey_pid;
57         pid_t taskbar_pid;
58         int power_off;
59
60         Ecore_Timer *dead_timer;
61         int dead_count;
62
63         Evas_Object *popup;
64 } s_home_mgr = {
65         .home_pid = (pid_t)-1,
66         .volume_pid = (pid_t)-1,
67         .indicator_pid = (pid_t)-1,
68         .softkey_pid = (pid_t)-1,
69         .taskbar_pid = (pid_t)-1,
70         .power_off = 0,
71
72         .dead_timer = NULL,
73         .dead_count = 0,
74
75         .popup = NULL,
76 };
77
78 static void home_mgr_softkey_change(void *user_data);
79
80 int home_mgr_get_home_pid(void)
81 {
82         return s_home_mgr.home_pid;
83 }
84
85
86
87 int home_mgr_get_volume_pid(void)
88 {
89         return s_home_mgr.volume_pid;
90 }
91
92 int home_mgr_get_indicator_pid(void)
93 {
94         return s_home_mgr.indicator_pid;
95 }
96
97 int home_mgr_get_softkey_pid(void)
98 {
99         return s_home_mgr.softkey_pid;
100 }
101
102 int home_mgr_get_taskbar_pid(void)
103 {
104         return s_home_mgr.taskbar_pid;
105 }
106
107 void home_mgr_softkey_dead_signal_received()
108 {
109         s_home_mgr.softkey_pid = -1;
110 }
111
112 static void _after_launch_home(int pid)
113 {
114         if (pid != s_home_mgr.home_pid) {
115                 _I("home is created by power key new[%d] != old[%d]", pid, s_home_mgr.home_pid);
116                 if (pid > 0) {
117                         dbus_util_send_perceptible_signal(pid);
118                 }
119                 s_home_mgr.home_pid = pid;
120         }
121 }
122
123
124 /* Remove change home callback as no alternative home app in IoT profile */
125 /*static int _change_home_cb(const char *appid, const char *key, const char *value, void *cfn, void *afn)
126 {
127         if (!strcmp(appid, MENU_SCREEN_PKG_NAME)) {
128                 _E("We cannot do anything anymore.");
129         } else if (!strcmp(appid, status_active_get()->setappl_selected_package_name)) {
130                 if (vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, MENU_SCREEN_PKG_NAME) != 0) {
131                         _E("cannot set the vconf key as %s", MENU_SCREEN_PKG_NAME);
132                 }
133                 // change_home func will be called by changing the home
134                 return 0;
135         }
136         _E("cannot change home");
137         return -1;
138 }*/
139
140
141
142 void home_mgr_open_home(const char *appid, const char *key, const char *val)
143 {
144         const char *home_appid = NULL;
145
146         if (!appid) {
147                 home_appid = status_active_get()->setappl_selected_package_name;
148                 if(strcmp(home_appid, HOMESCREEN_NUI_PKG_NAME) != 0){
149                         home_appid = HOMESCREEN_NUI_PKG_NAME;
150                         if(vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOMESCREEN_NUI_PKG_NAME) != 0){
151                                 _E("cannot set the vconf key as [%s]", HOMESCREEN_NUI_PKG_NAME );
152                         }
153                 }
154         } else {
155                 home_appid = appid;
156         }
157         ret_if(!home_appid);
158         process_mgr_must_launch(home_appid, key, val, NULL, _after_launch_home);
159 }
160
161
162
163 static int _show_home_cb(status_active_key_e key, void *data)
164 {
165         int seq = status_active_get()->starter_sequence;
166         int is_fallback = 0;
167
168         _D("[MENU_DAEMON] _show_home_cb is invoked(%d) (key: %d)", seq, key);
169
170         switch (seq) {
171         case 0:
172                 if (s_home_mgr.home_pid > 0) {
173                         _D("Home[%d] has to be terminated.", s_home_mgr.home_pid);
174                         if (aul_terminate_pid(s_home_mgr.home_pid) != AUL_R_OK) {
175                                 _E("Failed to terminate %d", s_home_mgr.home_pid);
176                         }
177                         s_home_mgr.home_pid = -1; /* to freeze the dead_cb */
178                 }
179                 break;
180         case 1:
181                 if (vconf_get_int(VCONFKEY_STARTER_IS_FALLBACK, &is_fallback) < 0) {
182                         _E("Failed to get vconfkey : %s", VCONFKEY_STARTER_IS_FALLBACK);
183                 }
184
185                 /* No need to set fallback package as no alternative home app in IoT profile */
186                 /*if (is_fallback) {
187                         if (vconf_set_int(VCONFKEY_STARTER_IS_FALLBACK, 0)) {
188                                 _E("Failed to set vconfkey : %s", VCONFKEY_STARTER_IS_FALLBACK);
189                         }
190                         if (!strcmp(status_active_get()->setappl_selected_package_name, MENU_SCREEN_PKG_NAME)) {
191                                 char *fallback_pkg;
192                                 fallback_pkg = vconf_get_str(VCONFKEY_STARTER_FALLBACK_PKG);
193                                 _D("fallback pkg : %s", fallback_pkg);
194                                 if (fallback_pkg) {
195                                         int status;
196
197                                         status = vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, fallback_pkg);
198                                         free(fallback_pkg);
199                                         if (status == 0) {
200                                                 break;
201                                         }
202                                         _E("Failed to set vconfkey : %s (%d)", VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, status);
203                                 } else {
204                                         _E("Failed to get vconfkey : %s", VCONFKEY_STARTER_FALLBACK_PKG);
205                                 }
206                         }
207                 }*/
208
209                 home_mgr_open_home(NULL, NULL, NULL);
210                 // we need to launch softkey after home-screen.
211                 home_mgr_softkey_change(NULL);
212                 break;
213         default:
214                 _E("False sequence [%d]", seq);
215                 break;
216         }
217
218         return 1;
219 }
220
221
222
223 static int _change_selected_package_name(status_active_key_e key, void *data)
224 {
225         const char *appid = NULL;
226         int seq = status_active_get()->starter_sequence;
227
228         if (seq < 1) {
229                 _E("Sequence is not ready yet, do nothing");
230                 return 1;
231         }
232
233         _D("_change_selected_package_name is invoked");
234
235         appid = status_active_get()->setappl_selected_package_name;
236         if (!appid) {
237                 return 1;
238         }
239         _SECURE_D("pkg_name : %s", appid);
240
241         if (s_home_mgr.home_pid > 0) {
242                 char old_appid[BUF_SIZE_512] = { 0 , };
243
244                 if (aul_app_get_pkgname_bypid(s_home_mgr.home_pid, old_appid, sizeof(old_appid)) == AUL_R_OK) {
245                         if (!strcmp(appid, old_appid)) {
246                                 _D("Package is changed but same package is selected");
247                                 return 1;
248                         }
249                 }
250
251                 if (AUL_R_OK != aul_terminate_pid(s_home_mgr.home_pid)) {
252                         _D("Failed to terminate pid %d", s_home_mgr.home_pid);
253                 }
254                 s_home_mgr.home_pid = -1;
255                 s_home_mgr.dead_count = 0;
256                 if (s_home_mgr.dead_timer) {
257                         ecore_timer_del(s_home_mgr.dead_timer);
258                         s_home_mgr.dead_timer = NULL;
259                 }
260         }
261
262         home_mgr_open_home(appid, NULL, NULL);
263
264         return 1;
265 }
266
267
268
269 #if VOLUME_ENABLE
270 static void _after_launch_volume(int pid)
271 {
272         if (pid != s_home_mgr.volume_pid) {
273                 _I("volume is launched new[%d] != old[%d]", pid, s_home_mgr.volume_pid);
274                 if (pid > 0) {
275                         dbus_util_send_perceptible_signal(pid);
276                 }
277                 s_home_mgr.volume_pid = pid;
278         }
279 }
280 #endif
281
282
283 static void _after_launch_indicator(int pid)
284 {
285         s_home_mgr.indicator_pid = pid;
286 }
287
288 static void _after_launch_softkey(int pid)
289 {
290         s_home_mgr.softkey_pid = pid;
291 }
292
293 static void _after_launch_taskbar(int pid)
294 {
295         s_home_mgr.taskbar_pid = pid;
296 }
297
298 static void _launch_after_home(int pid)
299 {
300         if (pid != s_home_mgr.home_pid) {
301                 _I("home is created by power key new[%d] != old[%d]", pid, s_home_mgr.home_pid);
302                 if (pid > 0) {
303                         dbus_util_send_perceptible_signal(pid);
304                 }
305                 s_home_mgr.home_pid = pid;
306         }
307 }
308
309
310
311 static void _launch_home(const char *appid)
312 {
313         const char *home_appid = NULL;
314
315         if (!appid) {
316                 home_appid = status_active_get()->setappl_selected_package_name;
317         } else {
318                 home_appid = appid;
319         }
320         ret_if(!home_appid);
321
322         process_mgr_must_launch(home_appid, HOME_TERMINATED, ISTRUE, NULL, _launch_after_home);
323 }
324
325
326
327 static void _popup_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
328 {
329         _D("popup is deleted");
330
331         s_home_mgr.popup = NULL;
332 }
333
334
335
336 static Eina_Bool _dead_timer_cb(void *data)
337 {
338         Evas_Object *popup = NULL;
339         char title[BUF_SIZE_128] = { 0, };
340         char text[BUF_SIZE_1024] = { 0, };
341         const char *appid = NULL;
342
343         appid = status_active_get()->setappl_selected_package_name;
344         if (!appid) {
345                 _E("appid is NULL");
346                 return ECORE_CALLBACK_CANCEL;
347         }
348
349         _D("dead count : %s(%d)", appid, s_home_mgr.dead_count);
350
351         if (s_home_mgr.dead_count >= DEAD_TIMER_COUNT_MAX) {
352                 _D("Change homescreen package to default");
353
354                 /* set fallback status */
355                 /* No need to set fallback package as no alternative home app in IoT profile */
356                 /*if (vconf_set_int(VCONFKEY_STARTER_IS_FALLBACK, 1) < 0) {
357                         _E("Failed to set vconfkey : %s", VCONFKEY_STARTER_IS_FALLBACK);
358                 }
359
360                 if (vconf_set_str(VCONFKEY_STARTER_FALLBACK_PKG, appid) < 0) {
361                         _E("Failed to set vconfkey : %s", VCONFKEY_STARTER_FALLBACK_PKG);
362                 }*/
363
364                 strncpy(title, _("IDS_COM_POP_WARNING"), sizeof(title));
365                 title[sizeof(title) - 1] = '\0';
366
367                 snprintf(text, sizeof(text), _("IDS_IDLE_POP_UNABLE_TO_LAUNCH_PS"), appid);
368                 _D("title : %s / text : %s", title, text);
369
370                 if (!s_home_mgr.popup) {
371                         popup = popup_create(title, text);
372                         if (!popup) {
373                                 _E("Failed to create popup");
374                         } else {
375                                 s_home_mgr.popup = popup;
376                                 evas_object_event_callback_add(popup, EVAS_CALLBACK_DEL, _popup_del_cb, NULL);
377                         }
378                 }
379
380                 /*if (vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, appid) != 0) {
381                         _E("cannot set the vconf key as %s", appid);
382                         return ECORE_CALLBACK_RENEW;
383                 }*/
384                 home_mgr_relaunch_homescreen();
385         }
386
387         s_home_mgr.dead_timer = NULL;
388         s_home_mgr.dead_count = 0;
389
390         return ECORE_CALLBACK_CANCEL;
391 }
392
393
394
395 void home_mgr_relaunch_homescreen(void)
396 {
397         const char *appid = NULL;
398
399         if (s_home_mgr.power_off) {
400                 _E("power off");
401                 return;
402         }
403
404         appid = status_active_get()->setappl_selected_package_name;
405         if (!appid) {
406                 _E("appid is NULL");
407                 return;
408         }
409
410         s_home_mgr.dead_count++;
411         _D("home dead count : %d", s_home_mgr.dead_count);
412
413         if (!s_home_mgr.dead_timer) {
414                 _D("Add dead timer");
415                 s_home_mgr.dead_timer = ecore_timer_add(DEAD_TIMER_SEC, _dead_timer_cb, NULL);
416                 if (!s_home_mgr.dead_timer) {
417                         _E("Failed to add a dead timer");
418                 }
419         }
420
421         _launch_home(appid);
422 }
423
424
425
426 void home_mgr_relaunch_volume(void)
427 {
428 #if VOLUME_ENABLE
429         process_mgr_must_syspopup_launch(SYSPOPUPID_VOLUME, NULL, NULL, NULL, _after_launch_volume);
430 #endif
431 }
432
433
434 void home_mgr_relaunch_indicator(void)
435 {
436         process_mgr_must_launch(APPID_INDICATOR, NULL, NULL, NULL, _after_launch_indicator);
437 }
438
439 void home_mgr_relaunch_taskbar(void)
440 {
441         process_mgr_must_launch(APPID_TASKBAR, NULL, NULL, NULL, _after_launch_taskbar);
442 }
443
444 void home_mgr_softkey_process_terminate(void)
445 {
446         process_mgr_terminate_app(s_home_mgr.softkey_pid,1);
447         s_home_mgr.softkey_pid = 0;
448 }
449
450 static void home_mgr_softkey_change(void *user_data)
451 {
452         _D("home_mgr_softkey_change");
453         int state = TRUE;
454         int ret = 0;
455         int pid = -1;
456
457         ret = vconf_get_bool(VCONFKEY_SETAPPL_SOFT_KEY, &state);
458         if (ret < 0) {
459                 _D("fail to get VCONFKEY_SETAPPL_SOFT_KEY:%d", ret);
460                 return;
461         }
462
463         _D("VCONFKEY_SETAPPL_SOFT_KEY STATUS == %d ", state);
464
465         pid = home_mgr_get_softkey_pid();
466         _D("SoftKey Process Id == %d ", pid);
467
468         if (!state) {
469                 if (pid > 0) {
470                         _D("terminating softkey");
471                         home_mgr_softkey_process_terminate();
472                 }
473                 return;
474         }
475
476         if (pid > 0)
477                 _D("softkey is already running with PID: %d", pid);
478         else
479                 process_mgr_must_launch(APPID_SOFTKEY, NULL, NULL, NULL, _after_launch_softkey);
480 }
481
482 static void _softkey_vconf_change_cb(keynode_t *node, void *data)
483 {
484         _D("_softkey_vconf_change_cb");
485         home_mgr_softkey_change(data);
486 }
487
488 void softkey_mgr_init(void)
489 {
490         int ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_SOFT_KEY, _softkey_vconf_change_cb, NULL);
491         if (ret != 0) {
492                 _E("Failed to get vconfkey change for softkey app");
493         }
494 }
495
496 void softkey_mgr_fini(void)
497 {
498         if (vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOFT_KEY, _softkey_vconf_change_cb) < 0) {
499                 _E("Failed to unregister the callback for %s", VCONFKEY_SETAPPL_SOFT_KEY);
500         }
501 }
502
503 static int _power_off_cb(status_active_key_e key, void *data)
504 {
505         int val = status_active_get()->sysman_power_off_status;
506
507         if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART) {
508                 s_home_mgr.power_off = 1;
509         } else {
510                 s_home_mgr.power_off = 0;
511         }
512
513         _D("power off status : %d", s_home_mgr.power_off);
514
515         return 1;
516 }
517
518
519
520
521 static Eina_Bool _launch_apps_idler_cb(void *data)
522 {
523 #if VOLUME_ENABLE
524         process_mgr_must_syspopup_launch(SYSPOPUPID_VOLUME, NULL, NULL, NULL, _after_launch_volume);
525 #endif
526         process_mgr_must_launch(APPID_INDICATOR, NULL, NULL, NULL, _after_launch_indicator);
527         return ECORE_CALLBACK_CANCEL;
528 }
529
530
531 void home_mgr_init(void)
532 {
533         _D("[MENU_DAEMON]home_mgr_init is invoked");
534
535         status_active_register_cb(STATUS_ACTIVE_KEY_STARTER_SEQUENCE, _show_home_cb, NULL);
536         status_active_register_cb(STATUS_ACTIVE_KEY_SYSMAN_POWER_OFF_STATUS, _power_off_cb, NULL);
537         status_active_register_cb(STATUS_ACTIVE_KEY_SETAPPL_SELECTED_PACKAGE_NAME, _change_selected_package_name, NULL);
538         _change_selected_package_name(STATUS_ACTIVE_KEY_SETAPPL_SELECTED_PACKAGE_NAME, NULL);
539
540         ecore_idler_add(_launch_apps_idler_cb, NULL);
541 }
542
543
544
545 void home_mgr_fini(void)
546 {
547 #if VOLUME_ENABLE
548         if (s_home_mgr.volume_pid > 0) {
549                 process_mgr_terminate_app(s_home_mgr.volume_pid, 1);
550                 s_home_mgr.volume_pid = -1;
551         }
552 #endif
553
554         status_active_unregister_cb(STATUS_ACTIVE_KEY_STARTER_SEQUENCE, _show_home_cb);
555         status_active_unregister_cb(STATUS_ACTIVE_KEY_SYSMAN_POWER_OFF_STATUS, _power_off_cb);
556         status_active_unregister_cb(STATUS_ACTIVE_KEY_SETAPPL_SELECTED_PACKAGE_NAME, _change_selected_package_name);
557 }