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