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.
30 #include <sys/reboot.h>
33 #include <sys/mount.h>
34 #include <device-node.h>
35 #include <journal/system.h>
36 #include "dd-deviced.h"
38 #include "core/launch.h"
39 #include "core/device-handler.h"
40 #include "core/device-notifier.h"
41 #include "core/common.h"
42 #include "core/devices.h"
43 #include "proc/proc-handler.h"
44 #include "display/poll.h"
45 #include "display/setting.h"
46 #include "core/edbus-handler.h"
47 #include "display/core.h"
48 #include "power-handler.h"
49 #include "hall/hall-handler.h"
51 #define SIGNAL_NAME_POWEROFF_POPUP "poweroffpopup"
52 #define SIGNAL_BOOTING_DONE "BootingDone"
54 #define POWEROFF_NOTI_NAME "power_off_start"
55 #define POWEROFF_DURATION 2
58 #define SYSTEMD_STOP_POWER_OFF 4
60 #define SIGNAL_POWEROFF_STATE "ChangeState"
62 #define POWEROFF_POPUP_NAME "poweroff-syspopup"
63 #define UMOUNT_RW_PATH "/opt/usr"
65 static void poweroff_control_cb(keynode_t *in_key, void *data);
72 static struct timeval tv_start_poweroff;
74 static int power_off = 0;
75 static const struct device_ops *telephony = NULL;
76 static const struct device_ops *hall_ic = NULL;
78 static void telephony_init(void)
80 FIND_DEVICE_VOID(telephony, "telephony");
81 _I("telephony (%d)", telephony);
84 static void telephony_start(void)
87 device_start(telephony);
90 static void telephony_stop(void)
92 device_stop(telephony);
95 static int telephony_exit(void *data)
99 ret = device_exit(telephony, data);
103 static int systemd_manager_object(const char *opt, char **param)
105 return dbus_method_async("org.freedesktop.systemd1",
106 "/org/freedesktop/systemd1",
107 "org.freedesktop.systemd1.Manager",
112 static int systemd_manager_object_start_unit(char **param)
114 return systemd_manager_object("StartUnit", param);
117 static int systemd_manager_object_stop_unit(char **param)
119 return systemd_manager_object("StopUnit", param);
122 static int stop_systemd_journald(void)
124 char *journal_socket[2] = { "systemd-journald.socket", "replace" };
125 char *journal_service[2] = { "systemd-journald.service", "replace" };
129 ret = systemd_manager_object_stop_unit(journal_socket);
131 _E("failed to stop 'systemd-journald.socket'");
134 ret |= systemd_manager_object_stop_unit(journal_service);
136 _E("failed to stop 'systemd-journald.service'");
143 static int hall_ic_status(void)
147 ret = device_get_status(hall_ic);
149 return HALL_IC_OPENED;
153 static void poweroff_start_animation(void)
156 snprintf(params, sizeof(params), "/usr/bin/boot-animation --stop --clear");
157 launch_app_cmd_with_nice(params, -20);
158 launch_evenif_exist("/usr/bin/sound_server", "--poweroff");
159 device_notify(DEVICE_NOTIFIER_POWEROFF_HAPTIC, NULL);
162 int previous_poweroff(void)
165 static const struct device_ops *display_device_ops = NULL;
169 FIND_DEVICE_INT(display_device_ops, "display");
171 display_device_ops->exit(NULL);
174 gettimeofday(&tv_start_poweroff, NULL);
176 ret = telephony_exit(POWER_POWEROFF);
185 static int poweroff(void)
188 poweroff_start_animation();
189 while (retry_count < MAX_RETRY) {
190 if (previous_poweroff() < 0) {
191 _E("failed to request poweroff to deviced");
195 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
201 static int pwroff_popup(void)
203 struct popup_data *params;
204 static const struct device_ops *apps = NULL;
207 val = hall_ic_status();
208 if (val == HALL_IC_CLOSED) {
209 _I("cover is closed");
213 FIND_DEVICE_INT(apps, "apps");
215 params = malloc(sizeof(struct popup_data));
216 if (params == NULL) {
220 params->name = POWEROFF_POPUP_NAME;
221 apps->init((void *)params);
226 static int power_reboot(int type)
230 const struct device_ops *display_device_ops = NULL;
231 poweroff_start_animation();
234 FIND_DEVICE_INT(display_device_ops, "display");
236 pm_change_internal(getpid(), LCD_NORMAL);
237 display_device_ops->exit(NULL);
240 gettimeofday(&tv_start_poweroff, NULL);
242 if (type == SYSTEMD_STOP_POWER_RESTART_RECOVERY)
243 ret = telephony_exit(POWER_RECOVERY);
244 else if (type == SYSTEMD_STOP_POWER_RESTART_FOTA)
245 ret = telephony_exit(POWER_FOTA);
247 ret = telephony_exit(POWER_REBOOT);
250 restart_ap((void *)type);
256 static int power_execute(void *data)
260 if (strncmp(POWER_POWEROFF, (char *)data, POWER_POWEROFF_LEN) == 0)
262 else if (strncmp(PWROFF_POPUP, (char *)data, PWROFF_POPUP_LEN) == 0)
263 ret = pwroff_popup();
264 else if (strncmp(POWER_REBOOT, (char *)data, POWER_REBOOT_LEN) == 0)
265 ret = power_reboot(VCONFKEY_SYSMAN_POWER_OFF_RESTART);
266 else if (strncmp(POWER_RECOVERY, (char *)data, POWER_RECOVERY_LEN) == 0)
267 ret = power_reboot(SYSTEMD_STOP_POWER_RESTART_RECOVERY);
268 else if (strncmp(POWER_FOTA, (char *)data, POWER_FOTA_LEN) == 0)
269 ret = power_reboot(SYSTEMD_STOP_POWER_RESTART_FOTA);
270 else if (strncmp(INTERNAL_PWROFF, (char *)data, INTERNAL_PWROFF_LEN) == 0)
271 ret = previous_poweroff();
276 static void poweroff_popup_edbus_signal_handler(void *data, DBusMessage *msg)
282 if (dbus_message_is_signal(msg, DEVICED_INTERFACE_NAME, SIGNAL_NAME_POWEROFF_POPUP) == 0) {
283 _E("there is no power off popup signal");
287 dbus_error_init(&err);
289 if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
290 _E("there is no message");
294 if (!strncmp(str, PWROFF_POPUP, PWROFF_POPUP_LEN))
295 val = VCONFKEY_SYSMAN_POWER_OFF_POPUP;
296 else if (!strncmp(str, POWER_POWEROFF, POWER_POWEROFF_LEN))
297 val = SYSTEMD_STOP_POWER_OFF;
298 else if (!strncmp(str, POWER_REBOOT, POWER_REBOOT_LEN))
299 val = SYSTEMD_STOP_POWER_RESTART;
300 else if (!strncmp(str, POWER_FOTA, POWER_FOTA_LEN))
301 val = SYSTEMD_STOP_POWER_RESTART_FOTA;
303 _E("not supported message : %s", str);
306 vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val);
309 static int booting_done(void *data)
322 static void booting_done_edbus_signal_handler(void *data, DBusMessage *msg)
326 if (!dbus_message_is_signal(msg, DEVICED_INTERFACE_CORE, SIGNAL_BOOTING_DONE)) {
327 _E("there is no bootingdone signal");
330 done = booting_done(NULL);
334 _I("signal booting done");
335 device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE);
338 static void poweroff_send_broadcast(int status)
347 _D("broadcast poweroff %d", status);
350 snprintf(str_status, sizeof(str_status), "%d", status);
353 broadcast_edbus_signal(DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF,
354 SIGNAL_POWEROFF_STATE, "i", arr);
357 static void poweroff_stop_systemd_service(void)
360 _D("systemd service stop");
361 umount2("/sys/fs/cgroup", MNT_FORCE |MNT_DETACH);
364 static void poweroff_control_cb(keynode_t *in_key, void *data)
372 if (vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &val) != 0)
377 if (val == SYSTEMD_STOP_POWER_OFF ||
378 val == SYSTEMD_STOP_POWER_RESTART ||
379 val == SYSTEMD_STOP_POWER_RESTART_RECOVERY ||
380 val == SYSTEMD_STOP_POWER_RESTART_FOTA) {
381 pm_lock_internal(INTERNAL_LOCK_POWEROFF, LCD_OFF, STAY_CUR_STATE, 0);
382 poweroff_stop_systemd_service();
383 if (val == SYSTEMD_STOP_POWER_OFF)
384 val = VCONFKEY_SYSMAN_POWER_OFF_DIRECT;
386 val = VCONFKEY_SYSMAN_POWER_OFF_RESTART;
387 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
388 vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val);
391 if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART)
392 poweroff_send_broadcast(val);
395 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
396 device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val);
399 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
402 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
403 device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val);
404 power_reboot(recovery);
408 if (update_pm_setting)
409 update_pm_setting(SETTING_POWEROFF, val);
412 /* umount usr data partition */
413 static void unmount_rw_partition()
418 if (!mount_check(UMOUNT_RW_PATH))
424 /* Second, kill app with SIGTERM */
425 _I("Kill app with SIGTERM");
426 terminate_process(UMOUNT_RW_PATH, false);
430 /* Last time, kill app with SIGKILL */
431 _I("Kill app with SIGKILL");
432 terminate_process(UMOUNT_RW_PATH, true);
436 if (umount2(UMOUNT_RW_PATH, 0) != 0) {
437 _I("Failed to unmount %s", UMOUNT_RW_PATH);
440 _I("%s unmounted successfully", UMOUNT_RW_PATH);
443 if (umount2(UMOUNT_RW_PATH, 0) == 0) {
444 _I("%s unmounted successfully", UMOUNT_RW_PATH);
450 static void powerdown(void)
454 int poweroff_duration = POWEROFF_DURATION;
455 int check_duration = 0;
458 if (power_off == 1) {
459 _E("during power off");
462 journal_system_shutdown();
463 /* if this fails, that's OK */
464 stop_systemd_journald();
466 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
470 buf = getenv("PWROFF_DUR");
471 if (buf != NULL && strlen(buf) < 1024)
472 poweroff_duration = atoi(buf);
473 if (poweroff_duration < 0 || poweroff_duration > 60)
474 poweroff_duration = POWEROFF_DURATION;
475 gettimeofday(&now, NULL);
476 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
477 while (check_duration < poweroff_duration) {
479 _I("wait poweroff %d %d", check_duration, poweroff_duration);
483 gettimeofday(&now, NULL);
484 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
485 if (check_duration < 0)
489 unmount_rw_partition();
493 static void restart_by_mode(int mode)
495 if (mode == SYSTEMD_STOP_POWER_RESTART_RECOVERY)
496 launch_evenif_exist("/usr/sbin/reboot", "recovery");
497 else if (mode == SYSTEMD_STOP_POWER_RESTART_FOTA)
498 launch_evenif_exist("/usr/sbin/reboot", "fota");
503 int reset_resetkey_disable(char *name, enum watch_id id)
505 _D("force reset power resetkey disable to zero");
506 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, 0);
509 static DBusMessage *edbus_resetkeydisable(E_DBus_Object *obj, DBusMessage *msg)
511 DBusMessageIter iter;
515 ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &val,
518 _E("there is no message");
523 ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, val);
528 register_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE, reset_resetkey_disable);
530 unregister_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE);
532 _D("get power resetkey disable %d, %d", val, ret);
535 reply = dbus_message_new_method_return(msg);
536 dbus_message_iter_init_append(reply, &iter);
537 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
541 static int reset_wakeupkey(char *name, enum watch_id id)
543 _D("force reset wakeupkey to zero");
544 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, 0);
547 static DBusMessage *edbus_set_wakeup_key(E_DBus_Object *obj, DBusMessage *msg)
549 DBusMessageIter iter;
553 ret = dbus_message_get_args(msg, NULL,
554 DBUS_TYPE_INT32, &val,
557 _E("there is no message");
562 ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, val);
567 register_edbus_watch(msg, WATCH_POWER_WAKEUPKEY, reset_wakeupkey);
569 unregister_edbus_watch(msg, WATCH_POWER_WAKEUPKEY);
571 _D("set power wakeup key %d %d", val, ret);
574 reply = dbus_message_new_method_return(msg);
575 dbus_message_iter_init_append(reply, &iter);
576 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
580 static DBusMessage *dbus_power_handler(E_DBus_Object *obj, DBusMessage *msg)
583 DBusMessageIter iter;
590 dbus_error_init(&err);
592 if (!dbus_message_get_args(msg, &err,
593 DBUS_TYPE_STRING, &type_str,
594 DBUS_TYPE_INT32, &argc, DBUS_TYPE_INVALID)) {
595 _E("there is no message");
601 _E("message is invalid!");
606 pid = get_edbus_sender_pid(msg);
607 if (kill(pid, 0) == -1) {
608 _E("%d process does not exist, dbus ignored!", pid);
615 if(!strncmp(type_str, POWER_REBOOT, POWER_REBOOT_LEN))
616 ret = power_reboot(VCONFKEY_SYSMAN_POWER_OFF_RESTART);
617 else if(!strncmp(type_str, POWER_RECOVERY, POWER_RECOVERY_LEN))
618 ret = power_reboot(SYSTEMD_STOP_POWER_RESTART_RECOVERY);
619 else if(!strncmp(type_str, PWROFF_POPUP, PWROFF_POPUP_LEN))
620 ret = pwroff_popup();
623 reply = dbus_message_new_method_return(msg);
624 dbus_message_iter_init_append(reply, &iter);
625 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
630 void powerdown_ap(void *data)
634 reboot(RB_POWER_OFF);
637 void restart_ap(void *data)
639 _I("Restart %d", (int)data);
640 journal_system_device_reboot((int)data);
642 restart_by_mode((int)data);
645 static const struct edbus_method edbus_methods[] = {
646 { "setresetkeydisable", "i", "i", edbus_resetkeydisable },
647 { "SetWakeupKey", "i", "i", edbus_set_wakeup_key },
648 { POWER_REBOOT, "si", "i", dbus_power_handler },
649 { POWER_RECOVERY, "si", "i", dbus_power_handler },
650 { PWROFF_POPUP, "si", "i", dbus_power_handler },
651 /* Add methods here */
654 static void power_init(void *data)
659 /* init dbus interface */
660 ret = register_edbus_method(DEVICED_PATH_POWER, edbus_methods, ARRAY_SIZE(edbus_methods));
662 _E("fail to init edbus method(%d)", ret);
664 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void *)poweroff_control_cb, NULL) < 0) {
665 _E("Vconf notify key chaneged failed: KEY(%s)", VCONFKEY_SYSMAN_POWER_OFF_STATUS);
668 register_edbus_signal_handler(DEVICED_OBJECT_PATH, DEVICED_INTERFACE_NAME,
669 SIGNAL_NAME_POWEROFF_POPUP,
670 poweroff_popup_edbus_signal_handler);
671 register_edbus_signal_handler(DEVICED_PATH_CORE,
672 DEVICED_INTERFACE_CORE,
674 booting_done_edbus_signal_handler);
675 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
677 hall_ic = find_device(HALL_IC_NAME);
680 static const struct device_ops power_device_ops = {
681 .priority = DEVICE_PRIORITY_NORMAL,
682 .name = POWER_OPS_NAME,
684 .execute = power_execute,
687 DEVICE_OPS_REGISTER(&power_device_ops)