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