Implement lazy mount
[apps/native/starter.git] / src / mobile / starter.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 <Elementary.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <malloc.h>
26
27 #include <E_DBus.h>
28 #include <lazy_mount.h>
29 #include <systemd/sd-daemon.h>
30
31 #include <aul.h>
32 #include <vconf.h>
33 #include <signal.h>
34
35 #include "starter.h"
36 #include "lock_mgr.h"
37 #include "home_mgr.h"
38 #include "hw_key.h"
39 #include "process_mgr.h"
40 #include "util.h"
41 #include "status.h"
42 #include "hw_key.h"
43 #include "dbus_util.h"
44
45 #define APPID_SYS_LOCK "org.tizen.sys-lock"
46
47
48 #if 0
49 static void _hide_home(void)
50 {
51         int seq = status_active_get()->starter_sequence;
52         ret_if(seq == 1);
53
54         vconf_set_int(VCONFKEY_STARTER_SEQUENCE, 0);
55 }
56 #endif
57
58
59
60 static void _show_home(void)
61 {
62         vconf_set_int(VCONFKEY_STARTER_SEQUENCE, 1);
63 }
64
65
66
67 static void _signal_handler(int signum, siginfo_t *info, void *unused)
68 {
69     _D("_signal_handler : Terminated...");
70     elm_exit();
71 }
72
73
74
75 static int _power_off_cb(status_active_key_e key, void *data)
76 {
77         int val = status_active_get()->sysman_power_off_status;
78
79         if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT
80                 || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART)
81         {
82             _D("_power_off_cb : Terminated...");
83             elm_exit();
84         }
85
86         return 1;
87 }
88
89
90
91 static void _language_changed_cb(keynode_t *node, void *data)
92 {
93         char *lang = NULL;
94
95         ret_if(!node);
96
97         lang = vconf_keynode_get_str(node);
98         ret_if(!lang);
99
100         _D("language is changed : %s", lang);
101
102         elm_language_set(lang);
103 }
104
105
106
107 static int _set_i18n(const char *domain, const char *dir)
108 {
109         char *r = NULL;
110
111         if (domain == NULL) {
112                 errno = EINVAL;
113                 return -1;
114         }
115
116         char *lang = vconf_get_str(VCONFKEY_LANGSET);
117         r = setlocale(LC_ALL, lang);
118         if (!r) {
119                 _E("setlocale() error");
120         }
121         if (lang) {
122                 free(lang);
123         }
124
125         r = bindtextdomain(domain, dir);
126         if (!r) {
127                 _E("bindtextdomain() error");
128         }
129
130         r = textdomain(domain);
131         if (!r) {
132                 _E("textdomain() error");
133         }
134
135         if (vconf_notify_key_changed(VCONFKEY_LANGSET, _language_changed_cb, NULL) < 0) {
136                 _E("Failed to register changed cb : %s", VCONFKEY_LANGSET);
137         }
138
139         return 0;
140 }
141
142
143
144 static int _check_dead_signal(int pid, void *data)
145 {
146 #ifndef TIZEN_ARCH_ARM64
147         int home_pid = 0;
148         int volume_pid = 0;
149         int indicator_pid = 0;
150         int quickpanel_pid = 0;
151         int lock_pid = 0;
152
153         _D("Process %d is termianted", pid);
154
155         if (pid < 0) {
156                 _E("pid : %d", pid);
157                 return 0;
158         }
159
160         /*
161          * If the architecture is not 64bit,
162          * starter try to re-launch these apps when the app is dead.
163          */
164         home_pid = home_mgr_get_home_pid();
165         volume_pid = home_mgr_get_volume_pid();
166         indicator_pid = home_mgr_get_indicator_pid();
167         quickpanel_pid = home_mgr_get_quickpanel_pid();
168         lock_pid = lock_mgr_get_lock_pid();
169
170         if (pid == home_pid) {
171                 _D("Homescreen is dead");
172                 home_mgr_relaunch_homescreen();
173         } else if (pid == volume_pid) {
174                 _D("volume is dead");
175                 home_mgr_relaunch_volume();
176         } else if (pid == indicator_pid) {
177                 _D("indicator is dead");
178                 home_mgr_relaunch_indicator();
179         } else if (pid == quickpanel_pid) {
180                 _D("quickpanel is dead");
181                 home_mgr_relaunch_quickpanel();
182         } else if (pid == lock_pid) {
183                 _D("lockscreen is dead");
184                 lock_mgr_unlock();
185         } else {
186                 _D("Unknown process, ignore it");
187         }
188 #else
189         _D("Process %d is termianted", pid);
190
191         if (pid < 0) {
192                 _E("pid : %d", pid);
193                 return 0;
194         }
195 #endif
196
197         return 0;
198 }
199
200
201
202 static void _mount_and_launch_apps(void)
203 {
204         int ret = 0;
205
206         /*
207          * Do mount user data partition
208          */
209         ret = do_mount_user();
210         if (ret != 0) {
211                 _E("Failed to do mount [/opt] area");
212                 return;
213         }
214
215         /*
216          * Wait user data partition mount
217          */
218         ret = wait_mount_user();
219         if (ret != 0) {
220                 _E("Failed to wait mount [/opt] area");
221                 return;
222         }
223
224         /* Tells the service manager that service startup is finished */
225         sd_notify(0, "READY=1");
226
227         /*
228          * After user data partition mount,
229          * launch lockscreen, homescreen, etc.
230          */
231         hw_key_create_window();
232
233         lock_mgr_init();
234         home_mgr_init(NULL);
235
236         _show_home();
237 }
238
239
240
241 static void _sys_lock_status_changed_cb(void *data, DBusMessage *msg)
242 {
243         int is_unlock = 0;
244
245         is_unlock = dbus_message_is_signal(msg, SYS_LOCK_INTERFACE_UNLOCK, SYS_LOCK_MEMBER_UNLOCK);
246
247         _D("sys-lock signal is received. unlock state(%d).", is_unlock);
248
249         if (is_unlock) {
250                 _mount_and_launch_apps();
251
252                 /*
253                  * Send DBus signal to terminate sys-lock
254                  */
255                 dbus_util_send_sys_lock_teminate_signal();
256         }
257 }
258
259
260
261 static void _init(struct appdata *ad)
262 {
263         struct sigaction act;
264         char err_buf[128] = { 0, };
265         int is_lazy_mount = 0;
266         int ret = 0;
267
268         memset(&act,0x00,sizeof(struct sigaction));
269         act.sa_sigaction = _signal_handler;
270         act.sa_flags = SA_SIGINFO;
271
272         ret = sigemptyset(&act.sa_mask);
273         if (ret < 0) {
274                 if (strerror_r(errno, err_buf, sizeof(err_buf)) == 0) {
275                         _E("Failed to sigemptyset[%d / %s]", errno, err_buf);
276                 }
277         }
278         ret = sigaddset(&act.sa_mask, SIGTERM);
279         if (ret < 0) {
280                 if (strerror_r(errno, err_buf, sizeof(err_buf)) == 0) {
281                         _E("Failed to sigaddset[%d / %s]", errno, err_buf);
282                 }
283         }
284         ret = sigaction(SIGTERM, &act, NULL);
285         if (ret < 0) {
286                 if (strerror_r(errno, err_buf, sizeof(err_buf)) == 0) {
287                         _E("Failed to sigaction[%d / %s]", errno, err_buf);
288                 }
289         }
290
291         _set_i18n(PACKAGE, LOCALEDIR);
292
293         status_register();
294         status_active_register_cb(STATUS_ACTIVE_KEY_SYSMAN_POWER_OFF_STATUS, _power_off_cb, NULL);
295
296         e_dbus_init();
297
298         is_lazy_mount = get_need_ui_for_lazy_mount();
299         _D("Lazy mount : %d", is_lazy_mount);
300         if (is_lazy_mount) {
301                 /*
302                  * Launch Sys-lock
303                  */
304                 process_mgr_must_launch(APPID_SYS_LOCK, NULL, NULL, NULL, NULL);
305
306                 /*
307                  * Register sys-lock status changed cb
308                  */
309                 dbus_util_receive_sys_lock_status(_sys_lock_status_changed_cb, NULL);
310         } else {
311                 _mount_and_launch_apps();
312         }
313
314         aul_listen_app_dead_signal(_check_dead_signal, NULL);
315 }
316
317
318
319 static void _fini(struct appdata *ad)
320 {
321         hw_key_destroy_window();
322
323         home_mgr_fini();
324         lock_mgr_fini();
325
326         e_dbus_shutdown();
327
328         status_active_unregister_cb(STATUS_ACTIVE_KEY_SYSMAN_POWER_OFF_STATUS, _power_off_cb);
329         status_unregister();
330
331         if (vconf_ignore_key_changed(VCONFKEY_LANGSET, _language_changed_cb) < 0) {
332                 _E("Failed to unregister changed cb : %s", VCONFKEY_LANGSET);
333         }
334 }
335
336
337
338 int main(int argc, char *argv[])
339 {
340         struct appdata ad;
341
342         _D("starter is launched..!!");
343
344         elm_init(argc, argv);
345         _init(&ad);
346
347         malloc_trim(0);
348         elm_run();
349
350         _fini(&ad);
351         elm_shutdown();
352
353         return 0;
354 }