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