Tizen 2.1 base
[apps/native/starter.git] / src / menu_daemon.c
1  /*
2   * Copyright 2012  Samsung Electronics Co., Ltd
3   *
4   * Licensed under the Flora License, Version 1.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://floralicense.org/license/
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
18
19 #include <ail.h>
20 #include <aul.h>
21 #include <db-util.h>
22 #include <Elementary.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <sysman.h>
26 #include <syspopup_caller.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <vconf.h>
30 #include <errno.h>
31
32 #include "hw_key.h"
33 #include "pkg_event.h"
34 #include "util.h"
35 #include "xmonitor.h"
36
37
38 int errno;
39
40
41 #define QUERY_UPDATE_NAME "UPDATE app_info SET name='%s' where package='%s';"
42 #define SAT_DESKTOP_FILE "/opt/share/applications/org.tizen.sat-ui.desktop"
43 #define RELAUNCH_INTERVAL 100*1000
44 #define RETRY_MAXCOUNT 30
45
46 static struct info {
47         pid_t home_pid;
48         pid_t volume_pid;
49         int power_off;
50 } s_info = {
51         .home_pid = -1,
52         .volume_pid = -1,
53         .power_off = 0,
54 };
55
56
57
58 bool menu_daemon_is_homescreen(pid_t pid)
59 {
60         if (s_info.home_pid == pid) return true;
61         return false;
62 }
63
64
65
66 static inline char *_get_selected_pkgname(void)
67 {
68         char *pkgname;
69
70         pkgname = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
71         if (!pkgname) {
72                 _E("Cannot get pkgname from vconf.");
73
74                 pkgname = strdup(HOME_SCREEN_PKG_NAME);
75                 if (!pkgname) {
76                         _E("strdup error for pkgname, %s", strerror(errno));
77                         return NULL;
78                 }
79         }
80
81         return pkgname;
82 }
83
84
85
86 static inline void _open_homescreen(const char *pkgname)
87 {
88         int ret;
89         char *homescreen = (char *) pkgname;
90
91         system("echo -e '[${_G}menu-daemon launches home-screen${C_}]' > /dev/kmsg");
92         ret = aul_open_app(homescreen);
93         _D("can%s launch %s now. (%d)", ret < 0 ? "not" : "", homescreen, ret);
94         if (ret < 0 && strcmp(homescreen, HOME_SCREEN_PKG_NAME)) {
95                 _E("cannot launch package %s", homescreen);
96
97                 if (-1 == ret) {
98                         ret = aul_open_app(HOME_SCREEN_PKG_NAME);
99                         if (ret < 0) {
100                                 _E("Failed to open a default home, %s(err:%d)", HOME_SCREEN_PKG_NAME, ret);
101                         }
102                 }
103         }
104
105         s_info.home_pid = ret;
106         if (ret > 0) {
107                 if (-1 == sysconf_set_mempolicy_bypid(ret, OOM_IGNORE)) {
108                         _E("Cannot set the memory policy for Home-screen(%d)", ret);
109                 } else {
110                         _E("Set the memory policy for Home-screen(%d)", ret);
111                 }
112         }
113 }
114
115
116
117 static void _show_cb(keynode_t* node, void *data)
118 {
119         int seq;
120         char *pkgname;
121
122         _D("[MENU_DAEMON] _show_cb is invoked");
123
124         pkgname = _get_selected_pkgname();
125         if (!pkgname)
126                 return;
127
128         if (node) {
129                 seq = vconf_keynode_get_int(node);
130         } else {
131                 if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) {
132                         _E("Failed to get sequence info");
133                         free(pkgname);
134                         return;
135                 }
136         }
137
138         switch (seq) {
139                 case 0:
140                         if (s_info.home_pid > 0) {
141                                 int pid;
142                                 _D("pid[%d] is terminated.", s_info.home_pid);
143
144                                 pid = s_info.home_pid;
145                                 s_info.home_pid = -1;
146
147                                 if (aul_terminate_pid(pid) != AUL_R_OK)
148                                         _E("Failed to terminate %d", s_info.home_pid);
149                         }
150                         break;
151                 case 1:
152                         _open_homescreen(pkgname);
153                         break;
154                 default:
155                         _E("False sequence [%d]", seq);
156                         break;
157         }
158
159         free(pkgname);
160         return;
161
162 }
163
164
165
166 static void _pkg_changed(keynode_t* node, void *data)
167 {
168         char *pkgname;
169         int seq;
170
171         if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) {
172                 _E("Do nothing, there is no sequence info yet");
173                 return;
174         }
175
176         if (seq < 1) {
177                 _E("Sequence is not ready yet, do nothing");
178                 return;
179         }
180
181         _D("_pkg_changed is invoked");
182
183         pkgname = _get_selected_pkgname();
184         if (!pkgname)
185                 return;
186
187         _D("pkg_name : %s", pkgname);
188
189         if (s_info.home_pid > 0) {
190                 char old_pkgname[256];
191
192                 if (aul_app_get_pkgname_bypid(s_info.home_pid, old_pkgname, sizeof(old_pkgname)) == AUL_R_OK) {
193                         if (!strcmp(pkgname, old_pkgname)) {
194                                 _D("Package is changed but same package is selected");
195                                 free(pkgname);
196                                 return;
197                         }
198                 }
199
200                 if (aul_terminate_pid(s_info.home_pid) != AUL_R_OK)
201                         _D("Failed to terminate pid %d", s_info.home_pid);
202         } else {
203                 _open_homescreen(pkgname);
204         }
205
206         free(pkgname);
207         return;
208 }
209
210 static void _launch_volume(void)
211 {
212         int pid;
213         int i;
214         _D("_launch_volume");
215
216         for (i=0; i<RETRY_MAXCOUNT; i++)
217         {
218                 pid = syspopup_launch("volume", NULL);
219
220                 _D("syspopup_launch(volume), pid = %d", pid);
221
222                 if (pid <0) {
223                         _D("syspopup_launch(volume)is failed [%d]times", i);
224                         usleep(RELAUNCH_INTERVAL);
225                 } else {
226                         s_info.volume_pid = pid;
227                         return;
228                 }
229         }
230 }
231
232 int menu_daemon_check_dead_signal(int pid)
233 {
234         char *pkgname;
235
236         if (s_info.power_off) {
237                 _D("Power off. ignore dead cb\n");
238                 return 0;
239         }
240
241         _D("Process %d is termianted", pid);
242
243         if (pid < 0)
244                 return 0;
245
246         pkgname = _get_selected_pkgname();
247         if (!pkgname)
248                 return 0;
249
250         if (pid == s_info.home_pid) {
251                 _D("pkg_name : %s", pkgname);
252                 _open_homescreen(pkgname);
253         } else if (pid == s_info.volume_pid) {
254                 _launch_volume();
255         } else {
256                 _D("Unknown process, ignore it (pid %d, home pid %d)",
257                                 pid, s_info.home_pid);
258         }
259
260         free(pkgname);
261
262         return 0;
263 }
264
265
266
267 void menu_daemon_init(void *data)
268 {
269         _D( "[MENU_DAEMON]menu_daemon_init is invoked");
270
271         aul_launch_init(NULL,NULL);
272
273         create_key_window();
274         if (xmonitor_init() < 0) _E("cannot init xmonitor");
275
276         pkg_event_init();
277         _launch_volume();
278
279         if (unlink(SAT_DESKTOP_FILE) != 0)
280                 _E("cannot remove sat-ui desktop.");
281
282         if (vconf_notify_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, _pkg_changed, NULL) < 0)
283                 _E("Failed to add callback for package change event");
284
285         if (vconf_notify_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb, NULL) < 0)
286                 _E("Failed to add callback for show event");
287
288         _pkg_changed(NULL, NULL);
289         vconf_set_int(VCONFKEY_IDLE_SCREEN_LAUNCHED, VCONFKEY_IDLE_SCREEN_LAUNCHED_TRUE);
290 }
291
292
293
294 void menu_daemon_fini(void)
295 {
296         vconf_ignore_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb);
297         vconf_ignore_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, _pkg_changed);
298
299         xmonitor_fini();
300         pkg_event_fini();
301         destroy_key_window();
302 }