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