apply FSL(Flora Software License)
[apps/home/menu-daemon.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://www.tizenopensource.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 <heynoti.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <vconf.h>
28 #include <errno.h>
29
30 #include "desktop_to_db.h"
31 #include "hw_key.h"
32 #include "parser.h"
33 #include "pkg_event.h"
34 #include "util.h"
35
36
37 int errno;
38
39
40 #define QUERY_UPDATE_NAME "UPDATE app_info SET name='%s' where package='%s';"
41 #define SAT_DESKTOP_FILE "/opt/share/applications/org.tizen.sat-ui.desktop"
42
43
44
45 // Define prototype of the "hidden API of AUL"
46 extern int aul_listen_app_dead_signal(int (*func)(int signal, void *data), void *data);
47
48
49
50 static struct info {
51         pid_t pid;
52 } s_info = {
53         .pid = -1,
54 };
55
56
57
58 static inline char *_get_pkgname(keynode_t *node)
59 {
60         char *pkgname;
61
62         if (node)
63                 pkgname = vconf_keynode_get_str(node);
64         else
65                 pkgname = vconf_get_str(MENU_PKG_VCONF_KEY);
66
67         if (!pkgname) {
68                 _E("Cannot get pkgname from vconf.");
69                 pkgname = strdup(HOME_SCREEN_PKG_NAME);
70                 if (!pkgname)
71                         _E("strdup error for pkgname, %s", strerror(errno));
72         }
73
74         return pkgname;
75 }
76
77
78
79 static inline void _open_homescreen(const char *pkgname)
80 {
81         int ret;
82         char *homescreen = (char *) pkgname;
83
84         ret = aul_open_app(homescreen);
85         _D("can%s launch %s now. (%d)", ret < 0 ? "not" : "", homescreen, ret);
86         if (ret < 0 && strcmp(homescreen, HOME_SCREEN_PKG_NAME)) {
87                 ret = aul_open_app(HOME_SCREEN_PKG_NAME);
88                 if (ret < 0) {
89                         _E("Failed to open a default home, %s", HOME_SCREEN_PKG_NAME);
90                 } else {
91                         homescreen = HOME_SCREEN_PKG_NAME;
92                 }
93         }
94
95         s_info.pid = ret;
96 }
97
98
99
100 static void _show_cb(keynode_t* node, void *data)
101 {
102         int seq;
103         char *pkgname;
104
105         _D("[MENU_DAEMON] _show_cb is invoked");
106
107         pkgname = _get_pkgname(NULL);
108         if (!pkgname)
109                 return;
110
111         if (node) {
112                 seq = vconf_keynode_get_int(node);
113         } else {
114                 if (vconf_get_int("memory/startapps/sequence", &seq) < 0) {
115                         _E("Failed to get sequence info");
116                         free(pkgname);
117                         return;
118                 }
119         }
120
121         switch (seq) {
122                 case 0:
123                         if (s_info.pid > 0) {
124                                 int pid;
125                                 _D("pid[%d] is terminated.", s_info.pid);
126
127                                 pid = s_info.pid;
128                                 s_info.pid = -1; /* to freeze the dead_cb */
129
130                                 if (aul_terminate_pid(pid) != AUL_R_OK)
131                                         _E("Failed to terminate %d", s_info.pid);
132                         }
133                         break;
134                 case 1:
135                         _open_homescreen(pkgname);
136                         break;
137                 default:
138                         _E("False sequence [%d]", seq);
139                         break;
140         }
141
142         free(pkgname);
143         return;
144
145 }
146
147
148
149 static void _pkg_changed(keynode_t* node, void *data)
150 {
151         char *pkgname;
152         int seq;
153
154         if (vconf_get_int("memory/startapps/sequence", &seq) < 0) {
155                 _E("Do nothing, there is no sequence info yet");
156                 return;
157         }
158
159         if (seq < 1) {
160                 _E("Sequence is not ready yet, do nothing");
161                 return;
162         }
163
164         _D("_pkg_changed is invoked");
165
166         pkgname = _get_pkgname(node);
167         if (!pkgname)
168                 return;
169
170         _D("pkg_name : %s", pkgname);
171
172         if (s_info.pid > 0) {
173                 char old_pkgname[256];
174
175                 if (aul_app_get_pkgname_bypid(s_info.pid, old_pkgname, sizeof(old_pkgname)) == AUL_R_OK) {
176                         if (!strcmp(pkgname, old_pkgname)) {
177                                 _D("Package is changed but same package is selected");
178                                 free(pkgname);
179                                 return;
180                         }
181                 }
182
183                 if (aul_terminate_pid(s_info.pid) != AUL_R_OK)
184                         _D("Failed to terminate pid %d", s_info.pid);
185         } else {
186                 /* If there is no running home */
187                 _open_homescreen(pkgname);
188         }
189
190         /* NOTE: Dead callback will catch the termination of a current menuscreen 
191          * _open_homescreen(pkgname);
192          */
193         free(pkgname);
194         return;
195 }
196
197
198
199 static int _dead_cb(int pid, void *data)
200 {
201         char *pkgname;
202
203         _D("Process %d is termianted", pid);
204         if (pid != s_info.pid || s_info.pid <= 0) {
205                 _D("Unknown process, ignore it (pid %d, menu pid %d)", pid, s_info.pid);
206                 return 0;
207         }
208
209         pkgname = _get_pkgname(NULL);
210         if (!pkgname)
211                 return 0;
212
213         _D("pkg_name : %s", pkgname);
214
215         /* Relaunch */
216         _open_homescreen(pkgname);
217         free(pkgname);
218         return 0;
219 }
220
221
222
223 static void _hibernation_preleave_cb(void *data)
224 {
225         _D( "[MENU_DAEMON]_hibernation_preleave_cb is invoked");
226
227         aul_launch_init(NULL,NULL);
228         aul_listen_app_dead_signal(_dead_cb, NULL);
229
230         create_key_window();
231         pkg_event_init();
232
233         if (unlink(SAT_DESKTOP_FILE) != 0)
234                 _E("cannot remove sat-ui desktop.");
235
236         if (vconf_notify_key_changed(MENU_PKG_VCONF_KEY, _pkg_changed, NULL) < 0)
237                 _E("Failed to add callback for package change event");
238
239         if (vconf_notify_key_changed("memory/startapps/sequence", _show_cb, NULL) < 0)
240                 _E("Failed to add callback for show event");
241
242         _pkg_changed(NULL, NULL);
243         // THIS ROUTINE IS FOR SAT.
244         vconf_set_int("memory/menu-screen/is_menu_screen_done", 1);
245 }
246
247
248
249 int elm_main(int argc, char *argv[])
250 {
251         FILE *fp;
252         int fd;
253
254         elm_init(argc, argv);
255         fd = heynoti_init();
256
257         system("/usr/bin/ail_initdb");
258
259         fp = fopen("/opt/etc/.hib_capturing", "r");
260         if (!fp) {
261                 fprintf(stderr, "[MENU_DAEMON]hib_capturing file is not found\n");
262                 _hibernation_preleave_cb(NULL);
263         } else {
264                 fprintf(stderr,"\n\n\n Menu Daemon enter %s hey noti init\n", __func__);
265                 if (fd < 0) {
266                         fprintf(stderr, "[MENU_DAEMON]\n\n\n Hey Noti Init Failed\n");
267                 } else {
268                         if (heynoti_subscribe(fd, "HIBERNATION_PRELEAVE", _hibernation_preleave_cb, NULL)) {
269                                 fprintf(stderr,"Heynoti subscribe is failed\n");
270                         } else {
271                                 fprintf(stderr,"Heynoti subscribe is done\n");
272                         }
273
274                         if (heynoti_attach_handler(fd)) {
275                                 fprintf(stderr,"Heynoti attach handler is failed\n");
276                         } else {
277                                 fprintf(stderr,"Heynoti attach handler is done\n");
278                                 if (vconf_set_int("memory/hibernation/menuscreen_ready", 1)) {
279                                         fprintf(stderr, "[MENU_DAEMON]vconf_set_int FAIL\n");
280                                 } else {
281                                         fprintf(stderr, "[MENU_DAEMON]vconf_set_int OK\n");
282                                 }
283                         }
284                 }
285                 fclose(fp);
286         }
287
288         elm_run();
289         destroy_key_window();
290         elm_exit();
291         return 0;
292 }
293
294
295
296 ELM_MAIN()
297
298
299
300 // End of a file