New features : Power-off, Set the vconf key when not launching selected home-screen...
[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 <fcntl.h>
24 #include <heynoti.h>
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <vconf.h>
29 #include <errno.h>
30
31 #include "desktop_to_db.h"
32 #include "hw_key.h"
33 #include "parser.h"
34 #include "pkg_event.h"
35 #include "util.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 HIBERNATION_DIR "/tmp/hibernation"
44 #define HIBERNATION_READY "/tmp/hibernation/menuscreen_ready"
45
46
47
48 // Define prototype of the "hidden API of AUL"
49 extern int aul_listen_app_dead_signal(int (*func)(int signal, void *data), void *data);
50
51
52
53 static struct info {
54         pid_t pid;
55         int power_off;
56 } s_info = {
57         .pid = -1,
58         .power_off = 0,
59 };
60
61
62
63 static inline char *_get_selected_pkgname(void)
64 {
65         char *pkgname;
66
67         pkgname = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
68         if (!pkgname) {
69                 _E("Cannot get pkgname from vconf.");
70
71                 if (0 != vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOME_SCREEN_PKG_NAME)) {
72                         _E("Cannot set value(%s) into key(%s)", VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOME_SCREEN_PKG_NAME);
73                 }
74
75                 pkgname = strdup(HOME_SCREEN_PKG_NAME);
76                 if (!pkgname) {
77                         _E("strdup error for pkgname, %s", strerror(errno));
78                         return NULL;
79                 }
80         }
81
82         return pkgname;
83 }
84
85
86
87 static inline void _open_homescreen(const char *pkgname)
88 {
89         int ret;
90         char *homescreen = (char *) pkgname;
91
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                 if (0 != vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOME_SCREEN_PKG_NAME)) {
96                         _E("Cannot set value(%s) into key(%s)", VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOME_SCREEN_PKG_NAME);
97                 }
98
99                 ret = aul_open_app(HOME_SCREEN_PKG_NAME);
100                 if (ret < 0) {
101                         _E("Failed to open a default home, %s", HOME_SCREEN_PKG_NAME);
102                 } else {
103                         homescreen = HOME_SCREEN_PKG_NAME;
104                 }
105         }
106
107         s_info.pid = ret;
108 }
109
110
111
112 static void _show_cb(keynode_t* node, void *data)
113 {
114         int seq;
115         char *pkgname;
116
117         _D("[MENU_DAEMON] _show_cb is invoked");
118
119         pkgname = _get_selected_pkgname();
120         if (!pkgname)
121                 return;
122
123         if (node) {
124                 seq = vconf_keynode_get_int(node);
125         } else {
126                 if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) {
127                         _E("Failed to get sequence info");
128                         free(pkgname);
129                         return;
130                 }
131         }
132
133         switch (seq) {
134                 case 0:
135                         if (s_info.pid > 0) {
136                                 int pid;
137                                 _D("pid[%d] is terminated.", s_info.pid);
138
139                                 pid = s_info.pid;
140                                 s_info.pid = -1; /* to freeze the dead_cb */
141
142                                 if (aul_terminate_pid(pid) != AUL_R_OK)
143                                         _E("Failed to terminate %d", s_info.pid);
144                         }
145                         break;
146                 case 1:
147                         _open_homescreen(pkgname);
148                         break;
149                 default:
150                         _E("False sequence [%d]", seq);
151                         break;
152         }
153
154         free(pkgname);
155         return;
156
157 }
158
159
160
161 static void _pkg_changed(keynode_t* node, void *data)
162 {
163         char *pkgname;
164         int seq;
165
166         if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) {
167                 _E("Do nothing, there is no sequence info yet");
168                 return;
169         }
170
171         if (seq < 1) {
172                 _E("Sequence is not ready yet, do nothing");
173                 return;
174         }
175
176         _D("_pkg_changed is invoked");
177
178         pkgname = _get_selected_pkgname();
179         if (!pkgname)
180                 return;
181
182         _D("pkg_name : %s", pkgname);
183
184         if (s_info.pid > 0) {
185                 char old_pkgname[256];
186
187                 if (aul_app_get_pkgname_bypid(s_info.pid, old_pkgname, sizeof(old_pkgname)) == AUL_R_OK) {
188                         if (!strcmp(pkgname, old_pkgname)) {
189                                 _D("Package is changed but same package is selected");
190                                 free(pkgname);
191                                 return;
192                         }
193                 }
194
195                 if (aul_terminate_pid(s_info.pid) != AUL_R_OK)
196                         _D("Failed to terminate pid %d", s_info.pid);
197         } else {
198                 /* If there is no running home */
199                 _open_homescreen(pkgname);
200         }
201
202         /* NOTE: Dead callback will catch the termination of a current menuscreen 
203          * _open_homescreen(pkgname);
204          */
205         free(pkgname);
206         return;
207 }
208
209
210
211 static int _dead_cb(int pid, void *data)
212 {
213         char *pkgname;
214
215         if (s_info.power_off) {
216                 _D("Power off. ignore dead cb\n");
217                 return 0;
218         }
219
220         _D("Process %d is termianted", pid);
221
222         if (pid < 0)
223                 return 0;
224
225         pkgname = _get_selected_pkgname();
226         if (!pkgname)
227                 return 0;
228
229         _D("pkg_name : %s", pkgname);
230
231         /* Relaunch */
232         _open_homescreen(pkgname);
233         free(pkgname);
234         return 0;
235 }
236
237
238
239 static void _hibernation_preleave_cb(void *data)
240 {
241         _D( "[MENU_DAEMON]_hibernation_preleave_cb is invoked");
242
243         aul_launch_init(NULL,NULL);
244         aul_listen_app_dead_signal(_dead_cb, NULL);
245
246         create_key_window();
247         pkg_event_init();
248
249         if (unlink(SAT_DESKTOP_FILE) != 0)
250                 _E("cannot remove sat-ui desktop.");
251
252         if (vconf_notify_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, _pkg_changed, NULL) < 0)
253                 _E("Failed to add callback for package change event");
254
255         if (vconf_notify_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb, NULL) < 0)
256                 _E("Failed to add callback for show event");
257
258         _pkg_changed(NULL, NULL);
259         // THIS ROUTINE IS FOR SAT.
260         vconf_set_int(VCONFKEY_IDLE_SCREEN_LAUNCHED, VCONFKEY_IDLE_SCREEN_LAUNCHED_TRUE);
261 }
262
263
264
265 static void power_off_cb(void *data)
266 {
267         _D("heynoti power off\n");
268         s_info.power_off = 1;
269 }
270
271
272
273 int elm_main(int argc, char *argv[])
274 {
275         FILE *fp;
276         int fd;
277         int ret;
278
279         elm_init(argc, argv);
280
281         fd = heynoti_init();
282         if (fd < 0)
283                 fprintf(stderr, "heynoti_init\n");
284
285         ret = heynoti_subscribe(fd, "power_off_start", power_off_cb, NULL);
286         if (ret < 0)
287                 fprintf(stderr, "heynoti_subscribe\n");
288
289         ret = system("/usr/bin/ail_initdb");
290         if (-1 == ret)
291                 _D("Cannot execute ail_initdb");
292
293         fp = fopen("/opt/etc/.hib_capturing", "r");
294         if (!fp) {
295                 fprintf(stderr, "[MENU_DAEMON]hib_capturing file is not found\n");
296                 _hibernation_preleave_cb(NULL);
297         } else {
298                 fprintf(stderr,"\n\n\n Menu Daemon enter %s hey noti init\n", __func__);
299                 if (fd < 0) {
300                         fprintf(stderr, "[MENU_DAEMON]\n\n\n Hey Noti Init Failed\n");
301                 } else {
302                         if (heynoti_subscribe(fd, "HIBERNATION_PRELEAVE", _hibernation_preleave_cb, NULL)) {
303                                 fprintf(stderr,"Heynoti subscribe is failed\n");
304                         } else {
305                                 fprintf(stderr,"Heynoti subscribe is done\n");
306                                 int fd;
307                                 if (mkdir(HIBERNATION_DIR, 0777) != -1)
308                                         _D("Make a directory - [%s]", HIBERNATION_DIR);
309
310                                 fd = creat(HIBERNATION_READY, 0644);
311                                 if (fd != -1) {
312                                         _D("Create a file for hibernation_ready");
313                                         close(fd);
314                                 }
315                         }
316
317                 }
318                 fclose(fp);
319         }
320
321         if (heynoti_attach_handler(fd))
322                 fprintf(stderr,"Heynoti attach handler is failed\n");
323         else
324                 fprintf(stderr,"Heynoti attach handler is done\n");
325
326         elm_run();
327         destroy_key_window();
328         elm_exit();
329         return 0;
330 }
331
332
333
334 ELM_MAIN()
335
336
337
338 // End of a file