355fb03dafa086c79c72f98d3daf3598dcb6c0c0
[platform/core/system/deviced.git] / src / power / power-off.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <unistd.h>
20 #include <string.h>
21 #include <time.h>
22 #include <limits.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <vconf.h>
26 #include <assert.h>
27 #include <sys/syscall.h>
28 #include <linux/reboot.h>
29 #include <sys/time.h>
30 #include <mntent.h>
31 #include <sys/mount.h>
32 #include <bundle.h>
33 #include <eventsystem.h>
34 #include <stdbool.h>
35 #include <signal.h>
36 #include <systemd/sd-daemon.h>
37 #include <libsyscommon/libgdbus.h>
38 #include <libsyscommon/libsystemd.h>
39 #include <libsyscommon/ini-parser.h>
40 #include <libsyscommon/proc.h>
41
42 #include "dd-deviced.h"
43 #include "core/log.h"
44 #include "shared/device-notifier.h"
45 #include "shared/common.h"
46 #include "shared/devices.h"
47 #include "poll.h"
48 #include "setting.h"
49 #include "core.h"
50 #include "display-ops.h"
51 #include "power-off.h"
52 #include "power.h"
53 #include "power-boot.h"
54 #include "shared/plugin.h"
55
56 #define POWEROFF_WAIT_RESOURCED     (0.5*1000) /* 0.5 seconds */
57 #define POWEROFF_WAIT_MAX           10 /* 10 seconds */
58 #define POWEROFF_WAIT_SYSTEMD_MS    (30 * 1000/*ms*/) /* 30 seconds */
59 #define SIGNAL_POWEROFF_STATE       "ChangeState"
60 #define POWER_CONF_FILE             "/etc/deviced/power.conf"
61
62 static struct timeval tv_start_poweroff;
63 static int poweroff_delay_second = 0;
64 static int silent_reboot = 0;
65
66 static void poweroff_start_animation(void)
67 {
68         int ret_val;
69
70         ret_val = systemd_start_unit_async("shutdown-animation.service", NULL);
71         if (ret_val < 0)
72                 _E("Failed to start shutdown animation.");
73
74         gettimeofday(&tv_start_poweroff, NULL);
75 }
76
77 static void poweroff_notify_resourced(void)
78 {
79         _I("Request to stop systemd service to resourced.");
80         gdbus_call_sync_with_reply_timeout(RESOURCED_BUS_NAME,
81                                 RESOURCED_PATH_PROCESS,
82                                 RESOURCED_INTERFACE_PROCESS,
83                                 "PrePoweroff",
84                                 NULL,
85                                 NULL,
86                                 POWEROFF_WAIT_RESOURCED);
87 }
88
89 static void disable_display(void)
90 {
91         const struct device_ops *display_device_ops = NULL;
92         FIND_DEVICE_VOID(display_device_ops, "display");
93         if (display_device_ops->stop)
94                 display_device_ops->stop(NORMAL_MODE);
95 }
96
97 static int disable_systemd_journald(void)
98 {
99         int ret_val;
100
101         ret_val = systemd_stop_unit_async("systemd-journald.socket", NULL);
102         if (ret_val < 0) {
103                 _E("Failed to stop 'systemd-journald.socket'.");
104                 return ret_val;
105         }
106
107         ret_val = systemd_stop_unit_async("systemd-journald.service", NULL);
108         if (ret_val < 0) {
109                 _E("Failed to stop 'systemd-journald.service'.");
110                 return ret_val;
111         }
112         return 0;
113 }
114
115 /* processes might start to fail abnormally after we kill them via
116  * umount_partition_by_kill. Failing services can trigger coredump
117  * handler, which might have trouble handling core in inconsistent
118  * system state (eg. lack of /opt).  Due to this we disable the
119  * coredump handler for the shutdown period.
120  */
121 static bool disable_coredump_handler(void)
122 {
123         int ret_val = 0;
124         int fd = open("/proc/sys/kernel/core_pattern", O_WRONLY);
125         if (fd >= 0) {
126                 ret_val = write(fd, "/dev/null", sizeof("/dev/null") - 1);
127                 close(fd);
128         }
129
130         bool is_ok = ret_val > 0;
131         _I("Disabling core dumps %s.", is_ok  ? "succeeded" : "failed");
132
133         return is_ok;
134 }
135
136 void poweroff_request_shutdown(int state)
137 {
138         const char *systemd_method = "PowerOff";
139
140         if (!is_poweroff_state(state))
141                 return;
142
143         if (state == DEVICED_POWER_STATE_POWEROFF)
144                 systemd_method = "PowerOff";
145         else if (state == DEVICED_POWER_STATE_REBOOT)
146                 systemd_method = "Reboot";
147         else if (state == DEVICED_POWER_STATE_EXIT)
148                 systemd_method = "Exit";
149
150         CRITICAL_LOG("Requested %s via systemd.", systemd_method);
151         gdbus_call_sync_with_reply_timeout(SYSTEMD_DBUS_DEST,
152                                         SYSTEMD_DBUS_PATH,
153                                         SYSTEMD_DBUS_IFACE_MANAGER,
154                                         systemd_method,
155                                         NULL,
156                                         NULL,
157                                         POWEROFF_WAIT_SYSTEMD_MS);
158
159         raise(SIGUSR1);
160 }
161
162 static void poweroff_delay_for_seconds(void)
163 {
164         static int wait;
165         struct timeval now;
166         int check_duration = 0;
167
168         if (poweroff_delay_second == 0)
169                 return;
170
171         watchdog_notify();
172
173         gettimeofday(&now, NULL);
174         check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
175
176         while (check_duration < poweroff_delay_second) {
177                 if (wait == 0) {
178                         _I("Wait poweroff %d %d.", check_duration, poweroff_delay_second);
179                         wait = 1;
180                 }
181                 usleep(100000);
182
183                 gettimeofday(&now, NULL);
184                 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
185
186                 if (check_duration < 0)
187                         break;
188         }
189
190         watchdog_notify();
191 }
192
193 int poweroff_check_revived(void)
194 {
195         if (access(POWEROFF_OPTPATH_POWEROFF, F_OK) == 0) {
196                 return DEVICED_POWER_STATE_POWEROFF;
197         }
198
199         if (access(POWEROFF_OPTPATH_REBOOT, F_OK) == 0) {
200                 return DEVICED_POWER_STATE_REBOOT;
201         }
202
203         if (access(POWEROFF_OPTPATH_EXIT, F_OK) == 0) {
204                 return DEVICED_POWER_STATE_EXIT;
205         }
206
207         return DEVICED_POWER_STATE_NORMAL;
208 }
209
210 static void mark_poweroff_option(uint64_t state, const char *option)
211 {
212         int fd;
213         ssize_t len;
214         const char *optpath;
215
216         if (state == DEVICED_POWER_STATE_POWEROFF)
217                 optpath = POWEROFF_OPTPATH_POWEROFF;
218         else if (state == DEVICED_POWER_STATE_REBOOT)
219                 optpath = POWEROFF_OPTPATH_REBOOT;
220         else if (state == DEVICED_POWER_STATE_EXIT)
221                 optpath = POWEROFF_OPTPATH_EXIT;
222         else
223                 return;
224
225         if (option && strncmp(option, "silent", sizeof("silent")) == 0)
226                 silent_reboot = 1;
227
228         fd = open(optpath, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR);
229         if (fd < 0) {
230                 _E("Failed to create '%s'.", optpath);
231                 return;
232         }
233
234         len = option ? write(fd, option, strlen(option)) : 0;
235         if (len < 0)
236                 _E("Failed to store option: %zd", len < 0 ? errno : len);
237
238         close(fd);
239 }
240
241 static gboolean __poweroff_main(gpointer data)
242 {
243         int state = (int)(intptr_t) data;
244
245         CRITICAL_LOG("Starting poweroff sequence");
246
247         // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure.
248         sd_notifyf(0, "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000);
249
250         poweroff_notify_resourced();
251         disable_systemd_journald();
252         disable_coredump_handler();
253         poweroff_delay_for_seconds();
254         disable_display();
255
256         /* Below functions follow after notifying DEVICE_NOTIFIER_POWEROFF
257            1. pmlock
258            - pmlock_detector_poweroff_cb()
259            - cleanup_pmlock_statistics()
260            - do_copy_force()
261            - display_misc_save_display_log()
262            2. tzip
263            - tzip_poweroff()
264            - tzip_server_exit()
265            3. udev
266            - device_change_poweroff()
267            - uevent_control_stop()
268         */
269         syscommon_notifier_emit_notify_once(DEVICE_NOTIFIER_POWEROFF, data);
270
271         poweroff_request_shutdown(state);
272
273         return G_SOURCE_REMOVE;
274 }
275
276 void poweroff_main(void *udata)
277 {
278         static guint poweroff_id = 0;
279
280         if (poweroff_id > 0)
281                 return;
282
283         /* Terminate this subroutine at this point. The procedure returns to the caller, therefore
284          * the RemovePowerOffWait caller would not be blocked, if they invoked method synchronously.
285          * And the deviced enter poweroff_main on the next gmainloop iteration. */
286         poweroff_id = g_idle_add(__poweroff_main, udata);
287 }
288
289 static void system_shutdown_send_system_event(void)
290 {
291         bundle *b;
292
293         b = bundle_create();
294         bundle_add_str(b, EVT_KEY_SYSTEM_SHUTDOWN, EVT_VAL_SYSTEM_SHUTDOWN_TRUE);
295         eventsystem_send_system_event(SYS_EVENT_SYSTEM_SHUTDOWN, b);
296         bundle_free(b);
297 }
298
299 void poweroff_prepare(uint64_t state)
300 {
301         int vconf = VCONFKEY_SYSMAN_POWER_OFF_NONE;
302         int ret;
303
304         if (!is_poweroff_state(state))
305                 return;
306
307         if (state == DEVICED_POWER_STATE_POWEROFF)
308                 vconf = VCONFKEY_SYSMAN_POWER_OFF_DIRECT;
309         else if (state == DEVICED_POWER_STATE_REBOOT)
310                 vconf = VCONFKEY_SYSMAN_POWER_OFF_RESTART;
311         ret = vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, vconf);
312         if (ret < 0)
313                 _W("Failed to set vconf value for power off status: %d", vconf_get_ext_errno());
314
315         power_exit_autosleep();
316         syscommon_notifier_emit_notify_once(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, (void *)(intptr_t) vconf);
317
318         /* Poweroff event broadcasting */
319         system_shutdown_send_system_event();
320
321         /* Skip running animation if it is silent reboot */
322         if (silent_reboot)
323                 return;
324
325         poweroff_start_animation();
326 }
327
328 static int check_sender_process(GDBusConnection *conn, const char *sender)
329 {
330         pid_t pid;
331
332         if (sender == NULL || g_dbus_is_name(sender) == FALSE) {
333                 _E("Invalid sender");
334                 return -EINVAL;
335         }
336
337         pid = gdbus_connection_get_sender_pid(conn, sender);
338         if (pid == -1 || kill(pid, 0) == -1) {
339                 _E("Process(%d) does not exist, dbus ignored.", pid);
340                 return -ESRCH;
341         }
342
343         return pid;
344 }
345
346 static GVariant *dbus_poweroff_handler(GDBusConnection *conn,
347         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
348         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
349 {
350         int ret;
351         char comm[128] = "Unknown";
352         char *type;
353         int next;
354
355         g_variant_get(param, "(s)", &type);
356
357         ret = check_sender_process(conn, sender);
358         if (ret < 0)
359                 goto out;
360
361         syscommon_proc_get_comm(ret, comm, sizeof(comm));
362
363         if (strncmp(type, "poweroff", sizeof("poweroff")) == 0)
364                 next = DEVICED_POWER_STATE_POWEROFF;
365         else if (strncmp(type, "reboot", sizeof("reboot")) == 0)
366                 next = DEVICED_POWER_STATE_REBOOT;
367         else if (strncmp(type, "exit", sizeof("exit")) == 0)
368                 next = DEVICED_POWER_STATE_EXIT;
369         else {
370                 ret = -EINVAL;
371                 goto out;
372         }
373
374         CRITICAL_LOG("Poweroff pid=%d(%s) requests %s.", ret, comm, type);
375         power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 9000, NULL);
376
377 out:
378         g_free(type);
379         return g_variant_new("(i)", ret);
380 }
381
382 static GVariant *dbus_poweroff_option_handler(GDBusConnection *conn,
383         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
384         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
385 {
386         int ret;
387         char comm[128] = "Unknown";
388         char *type, *option;
389         int next;
390
391         g_variant_get(param, "(ss)", &type, &option);
392
393         ret = check_sender_process(conn, sender);
394         if (ret < 0)
395                 goto out;
396
397         syscommon_proc_get_comm(ret, comm, sizeof(comm));
398
399         if (strncmp(type, "poweroff", sizeof("poweroff")) == 0)
400                 next = DEVICED_POWER_STATE_POWEROFF;
401         else if (strncmp(type, "reboot", sizeof("reboot")) == 0)
402                 next = DEVICED_POWER_STATE_REBOOT;
403         else if (strncmp(type, "exit", sizeof("exit")) == 0)
404                 next = DEVICED_POWER_STATE_EXIT;
405         else {
406                 ret = -EINVAL;
407                 goto out;
408         }
409
410         mark_poweroff_option(next, option);
411
412         CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option);
413         power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 9000, NULL);
414
415 out:
416         g_free(type);
417         g_free(option);
418         return g_variant_new("(i)", ret);
419 }
420
421 static GVariant *add_poweroff_time(GDBusConnection *conn,
422         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
423         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
424 {
425         return g_variant_new("(i)", 0);
426 }
427
428 static GVariant *remove_poweroff_time(GDBusConnection *conn,
429         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
430         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
431 {
432         return g_variant_new("(i)", 0);
433 }
434
435 static const dbus_method_s dbus_methods[] = {
436         { "PowerOff"          , "s" , "i", dbus_poweroff_handler },
437         { "PowerOffWithOption", "ss", "i", dbus_poweroff_option_handler },
438         /* Public API device_power_reboot() calls this dbus method. */
439         { "AddPowerOffWait"   , NULL, "i", add_poweroff_time }, /* deprecated */
440         { "RemovePowerOffWait", NULL, "i", remove_poweroff_time }, /* deprecated */
441         /* Add methods here */
442 };
443
444 static const dbus_interface_u dbus_interface = {
445         .oh = NULL,
446         .name = DEVICED_INTERFACE_POWEROFF,
447         .methods = dbus_methods,
448         .nr_methods = ARRAY_SIZE(dbus_methods),
449 };
450
451 static int load_config(struct parse_result *result, void *user_data)
452 {
453         if (MATCH(result->section, "PowerState") && MATCH(result->name, "PowerOffDelaySecond")) {
454                 sscanf(result->value, "%d", &poweroff_delay_second);
455         }
456
457         return 0;
458 }
459
460 static int delayed_init_done(void *data)
461 {
462         static int done;
463
464         if (data == NULL)
465                 goto out;
466
467         done = *(int *)data;
468 out:
469         return done;
470 }
471
472 void power_off_init(void)
473 {
474         int ret_val;
475
476         /* init dbus interface */
477         ret_val = gdbus_add_object(NULL, DEVICED_PATH_POWEROFF, &dbus_interface);
478         if (ret_val < 0)
479                 _E("Failed to init dbus method: %d", ret_val);
480
481         add_delayed_init_done_handler(NULL);
482
483         syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
484
485         ret_val = config_parse(POWER_CONF_FILE, load_config, NULL);
486         if (ret_val < 0)
487                 _E("Failed to load power off config: %d", ret_val);
488 }