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