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.
26 #include <sys/syscall.h>
27 #include <linux/reboot.h>
30 #include <sys/mount.h>
32 #include <eventsystem.h>
35 #include <systemd/sd-daemon.h>
36 #include <libsyscommon/libgdbus.h>
37 #include <libsyscommon/libsystemd.h>
38 #include <libsyscommon/ini-parser.h>
40 #include "dd-deviced.h"
42 #include "shared/device-notifier.h"
43 #include "shared/common.h"
44 #include "shared/devices.h"
45 #include "display/poll.h"
46 #include "display/setting.h"
47 #include "display/core.h"
48 #include "display/display-ops.h"
49 #include "power-off.h"
50 #include "apps/apps.h"
51 #include "power-boot.h"
52 #include "shared/plugin.h"
54 #define POWEROFF_WAIT_RESOURCED (0.5*1000) /* 0.5 seconds */
55 #define POWEROFF_WAIT_MAX 10 /* 10 seconds */
56 #define POWEROFF_WAIT_SYSTEMD_MS (30 * 1000/*ms*/) /* 30 seconds */
57 #define SIGNAL_POWEROFF_STATE "ChangeState"
58 #define POWER_CONF_FILE "/etc/deviced/power.conf"
60 static struct display_plugin *disp_plgn;
62 static struct timeval tv_start_poweroff;
63 static GList *poweroff_options;
64 static struct power_option poweroff_opt;
65 static GList *poweroff_handles;
67 static const char *poweroff_type_flagpaths[] = { // index denotes type
68 [POWEROFF_TYPE_POWEROFF] = POWER_FLAG_POWEROFF,
69 [POWEROFF_TYPE_REBOOT] = POWER_FLAG_REBOOT,
70 [POWEROFF_TYPE_EXIT] = POWER_FLAG_EXIT,
73 static const char *poweroff_type_names[] = { // index denotes type
74 [POWEROFF_TYPE_POWEROFF] = POWER_POWEROFF,
75 [POWEROFF_TYPE_REBOOT] = POWER_REBOOT,
76 [POWEROFF_TYPE_EXIT] = POWER_EXIT,
80 POWEROFF_DEFAULT, /* Default stage, poweroff has not been triggered */
81 POWEROFF_TRIGGERED, /* Poweroff is triggered. Wait timer can be added up to this stage */
82 POWEROFF_WAIT_OTHERS, /* Wait for other processes to clean up their resources */
85 static int poweroff_delay_second = 0;
86 static enum poweroff_stage poweroff_stage;
88 static const char *poweroff_type_to_name(enum poweroff_type type)
90 if (type <= 0 || type >= ARRAY_SIZE(poweroff_type_names))
93 return poweroff_type_names[type];
96 static enum poweroff_type poweroff_name_to_type(const char *name)
101 for (int i = 0; i < ARRAY_SIZE(poweroff_type_names); i++) {
102 if (poweroff_type_names[i] && strcmp(poweroff_type_names[i], name) == 0)
106 return POWEROFF_TYPE_INVALID;
109 static void poweroff_start_animation(void)
113 ret_val = systemd_start_unit_async("shutdown-animation.service", NULL);
115 _E("Failed to start shutdown animation.");
117 gettimeofday(&tv_start_poweroff, NULL);
120 static void poweroff_notify_resourced(void)
122 _I("Request to stop systemd service to resourced.");
123 gdbus_call_sync_with_reply_timeout(RESOURCED_BUS_NAME,
124 RESOURCED_PATH_PROCESS,
125 RESOURCED_INTERFACE_PROCESS,
129 POWEROFF_WAIT_RESOURCED);
132 static void disable_display(void)
134 const struct device_ops *display_device_ops = NULL;
135 FIND_DEVICE_VOID(display_device_ops, "display");
136 display_device_ops->stop(NORMAL_MODE);
139 static int disable_systemd_journald(void)
143 ret_val = systemd_stop_unit_async("systemd-journald.socket", NULL);
145 _E("Failed to stop 'systemd-journald.socket'.");
149 ret_val = systemd_stop_unit_async("systemd-journald.service", NULL);
151 _E("Failed to stop 'systemd-journald.service'.");
157 /* processes might start to fail abnormally after we kill them via
158 * umount_partition_by_kill. Failing services can trigger coredump
159 * handler, which might have trouble handling core in inconsistent
160 * system state (eg. lack of /opt). Due to this we disable the
161 * coredump handler for the shutdown period.
163 static bool disable_coredump_handler(void)
166 int fd = open("/proc/sys/kernel/core_pattern", O_WRONLY);
168 ret_val = write(fd, "/dev/null", sizeof("/dev/null") - 1);
172 bool is_ok = ret_val > 0;
173 _I("Disabling core dumps %s.", is_ok ? "succeeded" : "failed");
178 void poweroff_request_shutdown(void)
182 if (poweroff_opt.type == POWEROFF_TYPE_REBOOT)
184 else if (poweroff_opt.type == POWEROFF_TYPE_POWEROFF)
186 else if (poweroff_opt.type == POWEROFF_TYPE_EXIT)
189 _E("Poweroff invalid type(%d).", poweroff_opt.type);
193 CRITICAL_LOG("Requested %s via systemd.", method);
194 gdbus_call_sync_with_reply_timeout(SYSTEMD_DBUS_DEST,
196 SYSTEMD_DBUS_IFACE_MANAGER,
200 POWEROFF_WAIT_SYSTEMD_MS);
205 static void poweroff_delay_for_seconds(void)
209 int check_duration = 0;
211 if (poweroff_delay_second == 0)
216 gettimeofday(&now, NULL);
217 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
219 while (check_duration < poweroff_delay_second) {
221 _I("Wait poweroff %d %d.", check_duration, poweroff_delay_second);
226 gettimeofday(&now, NULL);
227 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
229 if (check_duration < 0)
236 void poweroff_prepare(void)
238 int off = poweroff_opt.type;
240 if (off == POWEROFF_TYPE_POWEROFF)
241 CRITICAL_LOG("Prepare PowerOff.");
242 else if (off == POWEROFF_TYPE_REBOOT)
243 CRITICAL_LOG("Prepare Reboot.");
245 poweroff_notify_resourced();
246 disable_systemd_journald();
247 disable_coredump_handler();
249 poweroff_delay_for_seconds();
253 /* Below functions follow after notifying DEVICE_NOTIFIER_POWEROFF
255 - pmlock_detector_poweroff_cb()
256 - cleanup_pmlock_statistics()
263 - device_change_poweroff()
264 - uevent_control_stop()
266 device_notify(DEVICE_NOTIFIER_POWEROFF, &off);
269 int poweroff_check_revived(void)
271 for (int i = 0; i < ARRAY_SIZE(poweroff_type_flagpaths); i++) {
272 if (access(poweroff_type_flagpaths[i], F_OK) == 0) {
273 poweroff_opt.type = i;
274 poweroff_opt.option = NULL;
282 static void make_power_flag(enum poweroff_type type, const char *option)
288 if (type <= 0 || type >= ARRAY_SIZE(poweroff_type_flagpaths))
291 path = poweroff_type_flagpaths[type];
295 fd = open(path, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR);
297 _E("Failed to create '%s'.", path);
302 len = write(fd, option, strlen(option));
304 _E("Failed to store option: %zd", len < 0 ? errno : len);
310 static void poweroff_remove_handle(pid_t pid)
312 struct poweroff_handle *handle;
315 SYS_G_LIST_FOREACH(poweroff_handles, elem, handle) {
316 if (handle->pid == pid)
322 _D("Remove handle pid=%d(%s) timeout=%d timeout_id=%d.", handle->pid, handle->comm, handle->timeout, handle->timeout_id);
323 SYS_G_LIST_REMOVE(poweroff_handles, handle);
325 if (handle->timeout_id) {
326 g_source_remove(handle->timeout_id);
328 handle->timeout_id = 0;
334 static int poweroff_add_handle(pid_t pid)
336 struct poweroff_handle *handle;
339 SYS_G_LIST_FOREACH(poweroff_handles, l, handle) {
340 if (handle->pid == pid)
345 poweroff_remove_handle(pid);
347 _D("Make a new handle.");
348 handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle));
349 if (handle == NULL) {
350 _E("Not enough memory.");
355 handle->timeout_id = 0;
356 handle->timeout = POWEROFF_WAIT_MAX;
357 get_command(pid, handle->comm, sizeof(handle->comm));
359 SYS_G_LIST_APPEND(poweroff_handles, handle);
360 _D("Add a new poweroff timer. pid=%d(%s) timeout=%d", handle->pid, handle->comm, handle->timeout);
365 static gboolean poweroff_wait_timeout_cb(void *data)
367 char timeout[50] = {0,};
368 pid_t pid = (pid_t)((intptr_t)data);
370 poweroff_remove_handle(pid);
372 /* All other processes finished cleanup. Poweroff is now on standby */
373 if (poweroff_stage == POWEROFF_WAIT_OTHERS && SYS_G_LIST_LENGTH(poweroff_handles) == 0) {
374 _D("The last poweroff wait timer for pid %d is expired. Poweroff is now on standby.", pid);
376 CRITICAL_LOG("Starting poweroff sequence.");
378 // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure.
379 snprintf(timeout, sizeof(timeout), "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000);
380 sd_notify(0, timeout);
382 make_power_flag(poweroff_opt.type, poweroff_opt.option);
384 if (disp_plgn->pm_lock_internal)
385 disp_plgn->pm_lock_internal(INTERNAL_LOCK_POWEROFF, LCD_OFF, STAY_CUR_STATE, 0);
388 poweroff_request_shutdown();
390 _D("Poweroff wait timer for pid %d is expired, but keep waiting for others...", pid);
393 return G_SOURCE_REMOVE;
396 static gboolean poweroff_start_timers(void *data)
398 struct poweroff_handle *handle = NULL;
400 bool timer_exist = false;
403 poweroff_stage = POWEROFF_WAIT_OTHERS;
405 SYS_G_LIST_FOREACH(poweroff_handles, l, handle) {
406 pid_alive = kill(handle->pid, 0);
407 if (pid_alive == -1) {
408 _D("Pid=%d(%s) is dead.", handle->pid, handle->comm);
412 _D("Run timer, pid=%d(%s) timeout=%d timeout_id=%d.", handle->pid, handle->comm, handle->timeout, handle->timeout_id);
414 handle->timeout_id = g_timeout_add_seconds(handle->timeout,
415 poweroff_wait_timeout_cb,
416 (void *)((intptr_t)(handle->pid)));
422 return G_SOURCE_REMOVE;
424 _D("Handle is NULL.");
426 handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle));
427 if (handle == NULL) {
428 _E("Not enough memory.");
429 return G_SOURCE_REMOVE;
432 handle->pid = getpid();
434 handle->timeout_id = g_timeout_add_seconds(handle->timeout,
435 poweroff_wait_timeout_cb,
436 (void *)((intptr_t)(handle->pid)));
438 if (!handle->timeout_id) {
439 _E("Failed to timer_add.");
441 return G_SOURCE_REMOVE;
444 SYS_G_LIST_APPEND(poweroff_handles, handle);
447 _D("Last Timer: timer_id=%d pid=%d timeout=%d", handle->timeout_id, handle->pid, handle->timeout);
449 return G_SOURCE_REMOVE;
452 static void system_shutdown_send_system_event(void)
457 bundle_add_str(b, EVT_KEY_SYSTEM_SHUTDOWN, EVT_VAL_SYSTEM_SHUTDOWN_TRUE);
458 eventsystem_send_system_event(SYS_EVENT_SYSTEM_SHUTDOWN, b);
462 static int poweroff_option_valid(enum poweroff_type type_e, const char *option)
465 struct power_option *elem;
467 SYS_G_LIST_FOREACH(poweroff_options, l, elem) {
468 if (elem->type != type_e)
471 /* Do not match option
473 if (elem->option == NULL)
475 if (strncmp(elem->option, option, strlen(elem->option)))
478 if (elem->option != NULL)
487 static void poweroff_send_broadcast(int status)
495 _D("Broadcast poweroff %d.", status);
499 /* Need to notify to deviced-vibrator. deviced-vibrator receives ChangeState signal for POWEROFF_TYPE_DIRECT and POWEROFF_TYPE_RESTART */
500 ret_dbus = gdbus_signal_emit(NULL,
501 DEVICED_PATH_POWEROFF,
502 DEVICED_INTERFACE_POWEROFF,
503 SIGNAL_POWEROFF_STATE,
504 g_variant_new("(i)", status));
506 _E("Failed to send dbus signal(%s)", SIGNAL_POWEROFF_STATE);
509 static int __poweroff_trigger_poweroff(const char *typename, const char *option)
513 if (poweroff_stage >= POWEROFF_TRIGGERED) {
514 _E("Duplicate poweroff request. Poweroff was already triggered.");
518 enum poweroff_type type_e = poweroff_name_to_type(typename);
519 if (type_e == POWEROFF_TYPE_INVALID) {
520 _E("Failed to get type enum value(%d).", type_e);
524 if (poweroff_option_valid(type_e, option)) {
525 poweroff_opt.type = type_e;
526 free(poweroff_opt.option);
527 poweroff_opt.option = NULL;
529 poweroff_opt.option = strdup(option);
531 _E("Failed to find supported type(%s). option=%s", typename, (option ? option : "NULL"));
535 ret_val = vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, poweroff_opt.type);
537 _E("Failed to set vconf value for power off status: %d", vconf_get_ext_errno());
539 poweroff_stage = POWEROFF_TRIGGERED;
540 if (disp_plgn->update_pm_setting)
541 disp_plgn->update_pm_setting(SETTING_POWEROFF, poweroff_opt.type);
543 /* Poweroff event broadcasting */
544 system_shutdown_send_system_event();
545 poweroff_send_broadcast(poweroff_opt.type);
547 /* Skip running animation if option is silent */
548 if (poweroff_opt.option != NULL && !strcmp(poweroff_opt.option, "silent"))
549 _D("Skip running poweroff animation.");
551 poweroff_start_animation();
553 /* Spare time for AddPowerOffWait requests */
554 g_timeout_add_seconds(1, poweroff_start_timers, NULL);
559 int poweroff_trigger_poweroff(void *data)
561 return __poweroff_trigger_poweroff((char *)data, NULL);
564 static int check_sender_process(GDBusConnection *conn, const char *sender)
568 if (sender == NULL || g_dbus_is_name(sender) == FALSE) {
569 _E("Invalid sender");
573 pid = gdbus_connection_get_sender_pid(conn, sender);
574 if (pid == -1 || kill(pid, 0) == -1) {
575 _E("Process(%d) does not exist, dbus ignored.", pid);
582 static GVariant *dbus_power_handler(GDBusConnection *conn,
583 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
584 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
587 char comm[128] = "Unknown";
590 g_variant_get(param, "(s)", &type_str);
592 ret = check_sender_process(conn, sender);
596 get_command(ret, comm, sizeof(comm));
598 CRITICAL_LOG("Poweroff pid=%d(%s) requests %s.", ret, comm, type_str);
599 ret = __poweroff_trigger_poweroff(type_str, NULL);
603 return g_variant_new("(i)", ret);
606 static GVariant *dbus_power_option_handler(GDBusConnection *conn,
607 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
608 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
611 char comm[128] = "Unknown";
614 g_variant_get(param, "(ss)", &type, &option);
616 ret = check_sender_process(conn, sender);
620 get_command(ret, comm, sizeof(comm));
622 CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option);
623 ret = __poweroff_trigger_poweroff(type, option);
628 return g_variant_new("(i)", ret);
631 /* timer can be added before the stage POWEROFF_WAIT_OTHERS */
632 static GVariant *add_poweroff_time(GDBusConnection *conn,
633 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
634 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
639 if (poweroff_stage >= POWEROFF_WAIT_OTHERS) {
640 _E("It's too late. Poweroff is already in waiting stage.");
645 ret = check_sender_process(conn, sender);
650 ret = poweroff_add_handle(pid);
653 return g_variant_new("(i)", ret);
656 static GVariant *remove_poweroff_time(GDBusConnection *conn,
657 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
658 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
660 struct poweroff_handle *handle;
665 ret = check_sender_process(conn, sender);
671 SYS_G_LIST_FOREACH(poweroff_handles, l, handle) {
672 if (handle->pid == pid)
677 if (handle->timeout_id)
678 g_source_remove(handle->timeout_id);
680 handle->timeout_id = g_timeout_add_seconds(handle->timeout,
681 poweroff_wait_timeout_cb,
682 (void *)((intptr_t)(handle->pid)));
684 _E("Invalid pid(%d).", pid);
689 return g_variant_new("(i)", ret);
692 static const dbus_method_s dbus_methods[] = {
693 { "PowerOff" , "s" , "i", dbus_power_handler },
694 { "PowerOffWithOption", "ss", "i", dbus_power_option_handler },
695 /* Public API device_power_reboot() calls this dbus method. */
696 { "AddPowerOffWait" , NULL, "i", add_poweroff_time },
697 { "RemovePowerOffWait", NULL, "i", remove_poweroff_time },
698 /* Add methods here */
701 static const dbus_interface_u dbus_interface = {
703 .name = DEVICED_INTERFACE_POWEROFF,
704 .methods = dbus_methods,
705 .nr_methods = ARRAY_SIZE(dbus_methods),
708 static int add_poweroff_option(enum poweroff_type type, const char *option)
710 struct power_option *opt;
713 name = poweroff_type_to_name(type);
715 _E("Invalid type(%d).", type);
719 opt = calloc(1, sizeof(struct power_option));
721 _E("Failed to calloc().");
726 opt->option = (option ? strdup(option) : NULL);
728 SYS_G_LIST_APPEND(poweroff_options, opt);
730 _D("Add %s option=%s", name, opt->option);
735 int poweroff_add_wait(pid_t pid)
737 return poweroff_add_handle(pid);
740 void poweroff_remove_wait(pid_t pid)
742 g_idle_add(poweroff_wait_timeout_cb, (void *)(intptr_t) pid);
745 static int load_config(struct parse_result *result, void *user_data)
747 enum poweroff_type type;
749 if (MATCH(result->section, "PowerOff") && MATCH(result->name, "Option")) {
750 type = POWEROFF_TYPE_DIRECT;
751 add_poweroff_option(type, result->value);
752 } else if (MATCH(result->section, "Reboot") && MATCH(result->name, "Option")) {
753 type = POWEROFF_TYPE_RESTART;
754 add_poweroff_option(type, result->value);
755 } else if (MATCH(result->section, "PowerState") && MATCH(result->name, "PowerOffDelaySecond")) {
756 sscanf(result->value, "%d", &poweroff_delay_second);
762 static int delayed_init_done(void *data)
774 void power_off_init(void)
778 /* init dbus interface */
779 ret_val = gdbus_add_object(NULL, DEVICED_PATH_POWEROFF, &dbus_interface);
781 _E("Failed to init dbus method: %d", ret_val);
783 add_delayed_init_done_handler(NULL);
785 register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
787 add_poweroff_option(POWEROFF_TYPE_POWEROFF, NULL);
788 add_poweroff_option(POWEROFF_TYPE_RESTART, NULL);
789 add_poweroff_option(POWEROFF_TYPE_EXIT, NULL);
791 ret_val = config_parse(POWER_CONF_FILE, load_config, NULL);
793 _E("Failed to load power off config: %d", ret_val);
795 poweroff_stage = POWEROFF_DEFAULT;
798 static void __CONSTRUCTOR__ initialize(void)
800 disp_plgn = get_var_display_plugin();
802 _E("Failed to get display plugin variable.");