4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <sys/syscall.h>
28 #include <linux/reboot.h>
31 #include <sys/mount.h>
33 #include <eventsystem.h>
36 #include <systemd/sd-daemon.h>
37 #include <libsyscommon/libgdbus.h>
38 #include <libsyscommon/libsystemd.h>
39 #include <libsyscommon/ini-parser.h>
41 #include "dd-deviced.h"
43 #include "shared/device-notifier.h"
44 #include "shared/common.h"
45 #include "shared/devices.h"
46 #include "display/poll.h"
47 #include "display/setting.h"
48 #include "display/core.h"
49 #include "display/display-ops.h"
50 #include "power-off.h"
52 #include "power-boot.h"
53 #include "shared/plugin.h"
55 #define POWEROFF_WAIT_RESOURCED (0.5*1000) /* 0.5 seconds */
56 #define POWEROFF_WAIT_MAX 10 /* 10 seconds */
57 #define POWEROFF_WAIT_SYSTEMD_MS (30 * 1000/*ms*/) /* 30 seconds */
58 #define SIGNAL_POWEROFF_STATE "ChangeState"
59 #define POWER_CONF_FILE "/etc/deviced/power.conf"
61 static struct timeval tv_start_poweroff;
62 static int poweroff_delay_second = 0;
64 static void poweroff_start_animation(void)
68 ret_val = systemd_start_unit_async("shutdown-animation.service", NULL);
70 _E("Failed to start shutdown animation.");
72 gettimeofday(&tv_start_poweroff, NULL);
75 static void poweroff_notify_resourced(void)
77 _I("Request to stop systemd service to resourced.");
78 gdbus_call_sync_with_reply_timeout(RESOURCED_BUS_NAME,
79 RESOURCED_PATH_PROCESS,
80 RESOURCED_INTERFACE_PROCESS,
84 POWEROFF_WAIT_RESOURCED);
87 static void disable_display(void)
89 const struct device_ops *display_device_ops = NULL;
90 FIND_DEVICE_VOID(display_device_ops, "display");
91 if (display_device_ops->stop)
92 display_device_ops->stop(NORMAL_MODE);
95 static int disable_systemd_journald(void)
99 ret_val = systemd_stop_unit_async("systemd-journald.socket", NULL);
101 _E("Failed to stop 'systemd-journald.socket'.");
105 ret_val = systemd_stop_unit_async("systemd-journald.service", NULL);
107 _E("Failed to stop 'systemd-journald.service'.");
113 /* processes might start to fail abnormally after we kill them via
114 * umount_partition_by_kill. Failing services can trigger coredump
115 * handler, which might have trouble handling core in inconsistent
116 * system state (eg. lack of /opt). Due to this we disable the
117 * coredump handler for the shutdown period.
119 static bool disable_coredump_handler(void)
122 int fd = open("/proc/sys/kernel/core_pattern", O_WRONLY);
124 ret_val = write(fd, "/dev/null", sizeof("/dev/null") - 1);
128 bool is_ok = ret_val > 0;
129 _I("Disabling core dumps %s.", is_ok ? "succeeded" : "failed");
134 void poweroff_request_shutdown(int state)
136 const char *systemd_method = "PowerOff";
138 if (!is_poweroff_state(state))
141 if (state == POWER_STATE_POWEROFF)
142 systemd_method = "PowerOff";
143 else if (state == POWER_STATE_REBOOT)
144 systemd_method = "Reboot";
145 else if (state == POWER_STATE_EXIT)
146 systemd_method = "Exit";
148 CRITICAL_LOG("Requested %s via systemd.", systemd_method);
149 gdbus_call_sync_with_reply_timeout(SYSTEMD_DBUS_DEST,
151 SYSTEMD_DBUS_IFACE_MANAGER,
155 POWEROFF_WAIT_SYSTEMD_MS);
160 static void poweroff_delay_for_seconds(void)
164 int check_duration = 0;
166 if (poweroff_delay_second == 0)
171 gettimeofday(&now, NULL);
172 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
174 while (check_duration < poweroff_delay_second) {
176 _I("Wait poweroff %d %d.", check_duration, poweroff_delay_second);
181 gettimeofday(&now, NULL);
182 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
184 if (check_duration < 0)
191 int poweroff_check_revived(void)
193 if (access(POWEROFF_OPTPATH_POWEROFF, F_OK) == 0) {
194 return POWER_STATE_POWEROFF;
197 if (access(POWEROFF_OPTPATH_REBOOT, F_OK) == 0) {
198 return POWER_STATE_REBOOT;
201 if (access(POWEROFF_OPTPATH_EXIT, F_OK) == 0) {
202 return POWER_STATE_EXIT;
205 return POWER_STATE_NORMAL;
208 static void mark_poweroff_option(uint64_t state, const char *option)
214 if (state == POWER_STATE_POWEROFF)
215 optpath = POWEROFF_OPTPATH_POWEROFF;
216 else if (state == POWER_STATE_REBOOT)
217 optpath = POWEROFF_OPTPATH_REBOOT;
218 else if (state == POWER_STATE_EXIT)
219 optpath = POWEROFF_OPTPATH_EXIT;
223 fd = open(optpath, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR);
225 _E("Failed to create '%s'.", optpath);
229 len = option ? write(fd, option, strlen(option)) : 0;
231 _E("Failed to store option: %zd", len < 0 ? errno : len);
236 static gboolean __poweroff_main(gpointer data)
238 int state = (int)(intptr_t) data;
240 CRITICAL_LOG("Starting poweroff sequence");
242 // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure.
243 sd_notifyf(0, "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000);
245 poweroff_notify_resourced();
246 disable_systemd_journald();
247 disable_coredump_handler();
248 poweroff_delay_for_seconds();
251 /* Below functions follow after notifying DEVICE_NOTIFIER_POWEROFF
253 - pmlock_detector_poweroff_cb()
254 - cleanup_pmlock_statistics()
261 - device_change_poweroff()
262 - uevent_control_stop()
264 device_notify_once(DEVICE_NOTIFIER_POWEROFF, data);
266 poweroff_request_shutdown(state);
268 return G_SOURCE_REMOVE;
271 void poweroff_main(void *udata)
273 static guint poweroff_id = 0;
278 /* Terminate this subroutine at this point. The procedure returns to the caller, therefore
279 * the RemovePowerOffWait caller would not be blocked, if they invoked method synchronously.
280 * And the deviced enter poweroff_main on the next gmainloop iteration. */
281 poweroff_id = g_idle_add(__poweroff_main, udata);
284 static void system_shutdown_send_system_event(void)
289 bundle_add_str(b, EVT_KEY_SYSTEM_SHUTDOWN, EVT_VAL_SYSTEM_SHUTDOWN_TRUE);
290 eventsystem_send_system_event(SYS_EVENT_SYSTEM_SHUTDOWN, b);
294 void poweroff_prepare(uint64_t state, void *option)
296 int vconf = VCONFKEY_SYSMAN_POWER_OFF_NONE;
298 if (!is_poweroff_state(state))
301 mark_poweroff_option(state, option);
303 if (state == POWER_STATE_POWEROFF)
304 vconf = VCONFKEY_SYSMAN_POWER_OFF_DIRECT;
305 else if (state == POWER_STATE_REBOOT)
306 vconf = VCONFKEY_SYSMAN_POWER_OFF_RESTART;
307 vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, vconf);
309 power_disable_autosleep();
310 device_notify_once(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, (void *)(intptr_t) vconf);
312 /* Poweroff event broadcasting */
313 system_shutdown_send_system_event();
315 /* Skip running animation if it is silent reboot */
316 if (option && strncmp(option, "silent", sizeof("silent")) == 0)
319 poweroff_start_animation();
322 static int check_sender_process(GDBusConnection *conn, const char *sender)
326 if (sender == NULL || g_dbus_is_name(sender) == FALSE) {
327 _E("Invalid sender");
331 pid = gdbus_connection_get_sender_pid(conn, sender);
332 if (pid == -1 || kill(pid, 0) == -1) {
333 _E("Process(%d) does not exist, dbus ignored.", pid);
340 static GVariant *dbus_poweroff_handler(GDBusConnection *conn,
341 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
342 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
345 char comm[128] = "Unknown";
349 g_variant_get(param, "(s)", &type);
351 ret = check_sender_process(conn, sender);
355 get_command(ret, comm, sizeof(comm));
357 if (strncmp(type, "poweroff", sizeof("poweroff")) == 0)
358 next = POWER_STATE_POWEROFF;
359 else if (strncmp(type, "reboot", sizeof("reboot")) == 0)
360 next = POWER_STATE_REBOOT;
361 else if (strncmp(type, "exit", sizeof("exit")) == 0)
362 next = POWER_STATE_EXIT;
368 CRITICAL_LOG("Poweroff pid=%d(%s) requests %s.", ret, comm, type);
369 power_request_change_state_strict(POWER_STATE_ALL, next, 9000, NULL);
373 return g_variant_new("(i)", ret);
376 static GVariant *dbus_poweroff_option_handler(GDBusConnection *conn,
377 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
378 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
381 char comm[128] = "Unknown";
385 g_variant_get(param, "(ss)", &type, &option);
387 ret = check_sender_process(conn, sender);
391 get_command(ret, comm, sizeof(comm));
393 if (strncmp(type, "poweroff", sizeof("poweroff")) == 0)
394 next = POWER_STATE_POWEROFF;
395 else if (strncmp(type, "reboot", sizeof("reboot")) == 0)
396 next = POWER_STATE_REBOOT;
397 else if (strncmp(type, "exit", sizeof("exit")) == 0)
398 next = POWER_STATE_EXIT;
404 CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option);
405 power_request_change_state_strict(POWER_STATE_ALL, next, 9000, option);
410 return g_variant_new("(i)", ret);
413 static GVariant *add_poweroff_time(GDBusConnection *conn,
414 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
415 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
417 return g_variant_new("(i)", 0);
420 static GVariant *remove_poweroff_time(GDBusConnection *conn,
421 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
422 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
424 return g_variant_new("(i)", 0);
427 static const dbus_method_s dbus_methods[] = {
428 { "PowerOff" , "s" , "i", dbus_poweroff_handler },
429 { "PowerOffWithOption", "ss", "i", dbus_poweroff_option_handler },
430 /* Public API device_power_reboot() calls this dbus method. */
431 { "AddPowerOffWait" , NULL, "i", add_poweroff_time }, /* deprecated */
432 { "RemovePowerOffWait", NULL, "i", remove_poweroff_time }, /* deprecated */
433 /* Add methods here */
436 static const dbus_interface_u dbus_interface = {
438 .name = DEVICED_INTERFACE_POWEROFF,
439 .methods = dbus_methods,
440 .nr_methods = ARRAY_SIZE(dbus_methods),
443 static int load_config(struct parse_result *result, void *user_data)
445 if (MATCH(result->section, "PowerState") && MATCH(result->name, "PowerOffDelaySecond")) {
446 sscanf(result->value, "%d", &poweroff_delay_second);
452 static int delayed_init_done(void *data)
464 void power_off_init(void)
468 /* init dbus interface */
469 ret_val = gdbus_add_object(NULL, DEVICED_PATH_POWEROFF, &dbus_interface);
471 _E("Failed to init dbus method: %d", ret_val);
473 add_delayed_init_done_handler(NULL);
475 register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
477 ret_val = config_parse(POWER_CONF_FILE, load_config, NULL);
479 _E("Failed to load power off config: %d", ret_val);