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 "core/launch.h"
43 #include "shared/device-notifier.h"
44 #include "core/device-idler.h"
45 #include "shared/common.h"
46 #include "core/devices.h"
47 #include "core/launch.h"
48 #include "display/poll.h"
49 #include "display/setting.h"
50 #include "display/core.h"
51 #include "display/display-ops.h"
52 #include "power-handler.h"
53 #include "apps/apps.h"
55 #include "shared/plugin.h"
57 #define POWEROFF_DURATION 4
58 #define POWEROFF_WAIT_RESOURCED (0.5*1000) /* 0.5 seconds */
59 #define POWEROFF_WAIT_MAX 10 /* 10 seconds */
60 #define POWEROFF_WAIT_SYSTEMD_MS (30 * 1000/*ms*/) /* 30 seconds */
61 #define SIGNAL_POWEROFF_STATE "ChangeState"
62 #define POWER_CONF_FILE "/etc/deviced/power.conf"
64 static struct display_plugin *disp_plgn;
66 static struct timeval tv_start_poweroff;
67 static GList *poweroff_options;
68 static struct power_option poweroff_opt;
69 static GList *poweroff_handles;
71 static const char *poweroff_type_flagpaths[] = { // index denotes type
72 [POWEROFF_TYPE_POWEROFF] = POWER_FLAG_POWEROFF,
73 [POWEROFF_TYPE_REBOOT] = POWER_FLAG_REBOOT,
74 [POWEROFF_TYPE_EXIT] = POWER_FLAG_EXIT,
77 static const char *poweroff_type_names[] = { // index denotes type
78 [POWEROFF_TYPE_POWEROFF] = POWER_POWEROFF,
79 [POWEROFF_TYPE_REBOOT] = POWER_REBOOT,
80 [POWEROFF_TYPE_EXIT] = POWER_EXIT,
84 POWEROFF_DEFAULT, /* Default stage, poweroff has not been triggered */
85 POWEROFF_TRIGGERED, /* Poweroff is triggered. Wait timer can be added up to this stage */
86 POWEROFF_WAIT_OTHERS, /* Wait for other processes to clean up their resources */
89 static enum poweroff_stage poweroff_stage;
91 static const char *poweroff_type_to_name(enum poweroff_type type)
93 if (type <= 0 || type >= ARRAY_SIZE(poweroff_type_names))
96 return poweroff_type_names[type];
99 static enum poweroff_type poweroff_name_to_type(const char *name)
104 for (int i = 0; i < ARRAY_SIZE(poweroff_type_names); i++) {
105 if (poweroff_type_names[i] && strcmp(poweroff_type_names[i], name) == 0)
109 return POWEROFF_TYPE_INVALID;
112 static void poweroff_start_animation(void)
116 ret_val = systemd_start_unit_async("shutdown-animation.service", NULL);
118 _E("Failed to start shutdown animation.");
120 gettimeofday(&tv_start_poweroff, NULL);
123 static void poweroff_notify_resourced(void)
125 _I("Request to stop systemd service to resourced.");
126 gdbus_call_sync_with_reply_timeout(RESOURCED_BUS_NAME,
127 RESOURCED_PATH_PROCESS,
128 RESOURCED_INTERFACE_PROCESS,
132 POWEROFF_WAIT_RESOURCED);
135 static void disable_display(void)
137 const struct device_ops *display_device_ops = NULL;
138 FIND_DEVICE_VOID(display_device_ops, "display");
139 display_device_ops->stop(NORMAL_MODE);
142 static int disable_systemd_journald(void)
146 ret_val = systemd_stop_unit_async("systemd-journald.socket", NULL);
148 _E("Failed to stop 'systemd-journald.socket'.");
152 ret_val = systemd_stop_unit_async("systemd-journald.service", NULL);
154 _E("Failed to stop 'systemd-journald.service'.");
160 /* processes might start to fail abnormally after we kill them via
161 * umount_partition_by_kill. Failing services can trigger coredump
162 * handler, which might have trouble handling core in inconsistent
163 * system state (eg. lack of /opt). Due to this we disable the
164 * coredump handler for the shutdown period.
166 static bool disable_coredump_handler(void)
169 int fd = open("/proc/sys/kernel/core_pattern", O_WRONLY);
171 ret_val = write(fd, "/dev/null", sizeof("/dev/null") - 1);
175 bool is_ok = ret_val > 0;
176 _I("Disabling core dumps %s.", is_ok ? "succeeded" : "failed");
181 void poweroff_request_shutdown(void)
185 if (poweroff_opt.type == POWEROFF_TYPE_REBOOT)
187 else if (poweroff_opt.type == POWEROFF_TYPE_POWEROFF)
189 else if (poweroff_opt.type == POWEROFF_TYPE_EXIT)
192 _E("Poweroff invalid type(%d).", poweroff_opt.type);
196 CRITICAL_LOG("Requested %s via systemd.", method);
197 gdbus_call_sync_with_reply_timeout(SYSTEMD_DBUS_DEST,
199 SYSTEMD_DBUS_IFACE_MANAGER,
203 POWEROFF_WAIT_SYSTEMD_MS);
208 static void poweroff_wait_for_seconds(void)
212 int poweroff_duration = POWEROFF_DURATION;
213 int check_duration = 0;
217 gettimeofday(&now, NULL);
218 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
220 while (check_duration < poweroff_duration) {
222 _I("Wait poweroff %d %d.", check_duration, poweroff_duration);
227 gettimeofday(&now, NULL);
228 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
230 if (check_duration < 0)
237 void poweroff_prepare(void)
239 int off = poweroff_opt.type;
241 if (off == POWEROFF_TYPE_POWEROFF)
242 CRITICAL_LOG("Prepare PowerOff.");
243 else if (off == POWEROFF_TYPE_REBOOT)
244 CRITICAL_LOG("Prepare Reboot.");
246 poweroff_notify_resourced();
247 disable_systemd_journald();
248 disable_coredump_handler();
250 poweroff_wait_for_seconds();
254 /* Below functions follow after notifying DEVICE_NOTIFIER_POWEROFF
256 - pmlock_detector_poweroff_cb()
257 - cleanup_pmlock_statistics()
264 - device_change_poweroff()
265 - uevent_control_stop()
267 device_notify(DEVICE_NOTIFIER_POWEROFF, &off);
270 int check_power_flag(void)
272 for (int i = 0; i < ARRAY_SIZE(poweroff_type_flagpaths); i++) {
273 if (access(poweroff_type_flagpaths[i], F_OK) == 0) {
274 poweroff_opt.type = i;
275 poweroff_opt.option = NULL;
283 static void make_power_flag(enum poweroff_type type, const char *option)
289 if (type <= 0 || type >= ARRAY_SIZE(poweroff_type_flagpaths))
292 path = poweroff_type_flagpaths[type];
296 fd = open(path, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR);
298 _E("Failed to create '%s'.", path);
303 len = write(fd, option, strlen(option));
305 _E("Failed to store option: %zd", len < 0 ? errno : len);
311 static void poweroff_remove_handle(pid_t pid)
313 struct poweroff_handle *handle;
316 SYS_G_LIST_FOREACH(poweroff_handles, elem, handle) {
317 if (handle->pid == pid)
323 _D("Remove handle pid=%d timeout=%d timeout_id=%d.", handle->pid, handle->timeout, handle->timeout_id);
324 SYS_G_LIST_REMOVE(poweroff_handles, handle);
326 if (handle->timeout_id) {
327 g_source_remove(handle->timeout_id);
329 handle->timeout_id = 0;
335 static gboolean poweroff_wait_timeout_cb(void *data)
337 char timeout[50] = {0,};
338 pid_t pid = (pid_t)((intptr_t)data);
340 poweroff_remove_handle(pid);
342 /* All other processes finished cleanup. Poweroff is now on standby */
343 if (poweroff_stage == POWEROFF_WAIT_OTHERS && SYS_G_LIST_LENGTH(poweroff_handles) == 0) {
344 _D("The last poweroff wait timer for pid %d is expired. Poweroff is now on standby.", pid);
346 CRITICAL_LOG("Starting poweroff sequence.");
348 // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure.
349 snprintf(timeout, sizeof(timeout), "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000);
350 sd_notify(0, timeout);
352 make_power_flag(poweroff_opt.type, poweroff_opt.option);
354 if (disp_plgn->pm_lock_internal)
355 disp_plgn->pm_lock_internal(INTERNAL_LOCK_POWEROFF, LCD_OFF, STAY_CUR_STATE, 0);
358 poweroff_request_shutdown();
360 _D("Poweroff wait timer for pid %d is expired, but keep waiting for others...", pid);
363 return G_SOURCE_REMOVE;
366 static gboolean poweroff_start_timers(void *data)
368 struct poweroff_handle *handle = NULL;
370 bool timer_exist = false;
373 poweroff_stage = POWEROFF_WAIT_OTHERS;
375 SYS_G_LIST_FOREACH(poweroff_handles, l, handle) {
376 pid_alive = kill(handle->pid, 0);
377 if (pid_alive == -1) {
378 _D("Pid(%d) is dead.", handle->pid);
382 _D("Run timer, pid=%d timeout=%d timeout_id=%d.", handle->pid, handle->timeout, handle->timeout_id);
384 handle->timeout_id = g_timeout_add_seconds(handle->timeout,
385 poweroff_wait_timeout_cb,
386 (void *)((intptr_t)(handle->pid)));
392 return G_SOURCE_REMOVE;
394 _D("Handle is NULL.");
396 handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle));
397 if (handle == NULL) {
398 _E("Not enough memory.");
399 return G_SOURCE_REMOVE;
402 handle->pid = getpid();
404 handle->timeout_id = g_timeout_add_seconds(handle->timeout,
405 poweroff_wait_timeout_cb,
406 (void *)((intptr_t)(handle->pid)));
408 if (!handle->timeout_id) {
409 _E("Failed to timer_add.");
411 return G_SOURCE_REMOVE;
414 SYS_G_LIST_APPEND(poweroff_handles, handle);
417 _D("Last Timer: timer_id=%d pid=%d timeout=%d", handle->timeout_id, handle->pid, handle->timeout);
419 return G_SOURCE_REMOVE;
422 static void system_shutdown_send_system_event(void)
427 bundle_add_str(b, EVT_KEY_SYSTEM_SHUTDOWN, EVT_VAL_SYSTEM_SHUTDOWN_TRUE);
428 eventsystem_send_system_event(SYS_EVENT_SYSTEM_SHUTDOWN, b);
432 static int poweroff_option_valid(enum poweroff_type type_e, const char *option)
435 struct power_option *elem;
437 SYS_G_LIST_FOREACH(poweroff_options, l, elem) {
438 if (elem->type != type_e)
441 /* Do not match option
443 if (elem->option == NULL)
445 if (strncmp(elem->option, option, strlen(elem->option)))
448 if (elem->option != NULL)
457 static void poweroff_send_broadcast(int status)
465 _D("Broadcast poweroff %d.", status);
469 /* Need to notify to deviced-vibrator. deviced-vibrator receives ChangeState signal for POWEROFF_TYPE_DIRECT and POWEROFF_TYPE_RESTART */
470 ret_dbus = gdbus_signal_emit(NULL,
471 DEVICED_PATH_POWEROFF,
472 DEVICED_INTERFACE_POWEROFF,
473 SIGNAL_POWEROFF_STATE,
474 g_variant_new("(i)", status));
476 _E("Failed to send dbus signal(%s)", SIGNAL_POWEROFF_STATE);
479 static int power_execute_pid(const char *typename, const char *option)
483 if (poweroff_stage >= POWEROFF_TRIGGERED) {
484 _E("Duplicate poweroff request. Poweroff was already triggered.");
488 enum poweroff_type type_e = poweroff_name_to_type(typename);
489 if (type_e == POWEROFF_TYPE_INVALID) {
490 _E("Failed to get type enum value(%d).", type_e);
494 if (poweroff_option_valid(type_e, option)) {
495 poweroff_opt.type = type_e;
496 free(poweroff_opt.option);
497 poweroff_opt.option = NULL;
499 poweroff_opt.option = strdup(option);
501 _E("Failed to find supported type(%s). option=%s", typename, (option ? option : "NULL"));
505 ret_val = vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, poweroff_opt.type);
507 _E("Failed to set vconf value for power off status: %d", vconf_get_ext_errno());
509 poweroff_stage = POWEROFF_TRIGGERED;
510 if (disp_plgn->update_pm_setting)
511 disp_plgn->update_pm_setting(SETTING_POWEROFF, poweroff_opt.type);
513 /* Poweroff event broadcasting */
514 system_shutdown_send_system_event();
515 poweroff_send_broadcast(poweroff_opt.type);
517 /* Skip running animation if option is silent */
518 if (poweroff_opt.option != NULL && !strcmp(poweroff_opt.option, "silent"))
519 _D("Skip running poweroff animation.");
521 poweroff_start_animation();
523 /* Spare time for AddPowerOffWait requests */
524 g_timeout_add_seconds(1, poweroff_start_timers, NULL);
529 static int power_execute(void *data)
531 return power_execute_pid((char *)data, NULL);
534 static int check_sender_process(GDBusConnection *conn, const char *sender)
538 if (sender == NULL || g_dbus_is_name(sender) == FALSE) {
539 _E("Invalid sender");
543 pid = gdbus_connection_get_sender_pid(conn, sender);
544 if (pid == -1 || kill(pid, 0) == -1) {
545 _E("Process(%d) does not exist, dbus ignored.", pid);
552 static GVariant *dbus_power_handler(GDBusConnection *conn,
553 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
554 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
559 g_variant_get(param, "(s)", &type_str);
561 ret = check_sender_process(conn, sender);
566 CRITICAL_LOG("Poweroff PID(%d) requests %s.", ret, type_str);
567 ret = power_execute_pid(type_str, NULL);
571 return g_variant_new("(i)", ret);
574 static GVariant *dbus_power_option_handler(GDBusConnection *conn,
575 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
576 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
581 g_variant_get(param, "(ss)", &type, &option);
583 ret = check_sender_process(conn, sender);
588 CRITICAL_LOG("Poweroff PID(%d) requests type=%s option=%s.", ret, type, option);
589 ret = power_execute_pid(type, option);
594 return g_variant_new("(i)", ret);
597 /* timer can be added before the stage POWEROFF_WAIT_OTHERS */
598 static GVariant *add_poweroff_time(GDBusConnection *conn,
599 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
600 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
602 struct poweroff_handle *handle;
607 if (poweroff_stage >= POWEROFF_WAIT_OTHERS) {
608 _E("It's too late. Poweroff is already in waiting stage.");
613 ret = check_sender_process(conn, sender);
619 CRITICAL_LOG("PID %d requested to a poweroff timer.", pid);
621 SYS_G_LIST_FOREACH(poweroff_handles, l, handle) {
622 if (handle->pid == pid)
627 poweroff_remove_handle(pid);
629 _D("Make a new handle.");
630 handle = (struct poweroff_handle *)malloc(sizeof(struct poweroff_handle));
631 if (handle == NULL) {
632 _E("Not enough memory.");
638 handle->timeout_id = 0;
639 handle->timeout = POWEROFF_WAIT_MAX;
641 SYS_G_LIST_APPEND(poweroff_handles, handle);
642 _D("Add a new poweroff timer. pid=%d timeout=%d timeout_id=%d)", handle->pid, handle->timeout, handle->timeout_id);
647 return g_variant_new("(i)", ret);
650 static GVariant *remove_poweroff_time(GDBusConnection *conn,
651 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
652 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
654 struct poweroff_handle *handle;
659 ret = check_sender_process(conn, sender);
665 CRITICAL_LOG("PID %d requested to remove poweroff timer.", pid);
667 SYS_G_LIST_FOREACH(poweroff_handles, l, handle) {
668 if (handle->pid == pid)
673 if (handle->timeout_id)
674 g_source_remove(handle->timeout_id);
676 handle->timeout_id = g_timeout_add_seconds(handle->timeout,
677 poweroff_wait_timeout_cb,
678 (void *)((intptr_t)(handle->pid)));
680 _E("Invalid pid(%d).", pid);
685 return g_variant_new("(i)", ret);
688 static const dbus_method_s dbus_methods[] = {
689 { "PowerOff" , "s" , "i", dbus_power_handler },
690 { "PowerOffWithOption", "ss", "i", dbus_power_option_handler },
691 /* Public API device_power_reboot() calls this dbus method. */
692 { "AddPowerOffWait" , NULL, "i", add_poweroff_time },
693 { "RemovePowerOffWait", NULL, "i", remove_poweroff_time },
694 /* Add methods here */
697 static const dbus_interface_u dbus_interface = {
699 .name = DEVICED_INTERFACE_POWEROFF,
700 .methods = dbus_methods,
701 .nr_methods = ARRAY_SIZE(dbus_methods),
704 static int add_poweroff_option(enum poweroff_type type, const char *option)
706 struct power_option *opt;
709 name = poweroff_type_to_name(type);
711 _E("Invalid type(%d).", type);
715 opt = calloc(1, sizeof(struct power_option));
717 _E("Failed to calloc().");
722 opt->option = (option ? strdup(option) : NULL);
724 SYS_G_LIST_APPEND(poweroff_options, opt);
726 _D("Add %s option=%s", name, opt->option);
731 static int load_config(struct parse_result *result, void *user_data)
733 enum poweroff_type type;
736 if (MATCH(result->section, "PowerOff"))
737 type = POWEROFF_TYPE_DIRECT;
738 else if (MATCH(result->section, "Reboot"))
739 type = POWEROFF_TYPE_RESTART;
743 if (!MATCH(result->name, "Option"))
746 ret_val = add_poweroff_option(type, result->value);
748 _E("Failed to add %s option=%s", result->section, result->value);
755 static int booting_done(void *data)
767 static void power_init(void *data)
771 /* init dbus interface */
772 ret_val = gdbus_add_object(NULL, DEVICED_PATH_POWEROFF, &dbus_interface);
774 _E("Failed to init dbus method: %d", ret_val);
776 add_booting_done_handler(NULL);
778 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
780 add_poweroff_option(POWEROFF_TYPE_POWEROFF, NULL);
781 add_poweroff_option(POWEROFF_TYPE_RESTART, NULL);
782 add_poweroff_option(POWEROFF_TYPE_EXIT, NULL);
784 ret_val = config_parse(POWER_CONF_FILE, load_config, NULL);
786 _E("Failed to load power off config: %d", ret_val);
788 poweroff_stage = POWEROFF_DEFAULT;
791 static const struct device_ops power_device_ops = {
792 DECLARE_NAME_LEN(POWER_OPS_NAME),
794 .execute = power_execute,
797 DEVICE_OPS_REGISTER(&power_device_ops)
799 static void __CONSTRUCTOR__ initialize(void)
801 disp_plgn = get_var_display_plugin();
803 _E("Failed to get display plugin variable.");