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 "dd-deviced.h"
37 #include "core/launch.h"
38 #include "core/queue.h"
39 #include "core/device-handler.h"
40 #include "core/device-notifier.h"
41 #include "core/predefine.h"
42 #include "core/data.h"
43 #include "core/common.h"
44 #include "core/devices.h"
45 #include "proc/proc-handler.h"
46 #include "display/poll.h"
47 #include "display/setting.h"
48 #include "core/edbus-handler.h"
49 #include "display/core.h"
50 #include "power-handler.h"
51 #include "hall/hall-handler.h"
53 #define SIGNAL_NAME_POWEROFF_POPUP "poweroffpopup"
54 #define SIGNAL_BOOTING_DONE "BootingDone"
56 #define PREDEF_PWROFF_POPUP "pwroff-popup"
57 #define PREDEF_INTERNAL_POWEROFF "internal_poweroff"
59 #define POWEROFF_NOTI_NAME "power_off_start"
60 #define POWEROFF_DURATION 2
63 #define SYSTEMD_STOP_POWER_OFF 4
65 #define SIGNAL_POWEROFF_STATE "ChangeState"
67 #define POWEROFF_POPUP_NAME "poweroff-syspopup"
68 #define UMOUNT_RW_PATH "/opt/usr"
76 static struct timeval tv_start_poweroff;
78 static int power_off = 0;
79 static const struct device_ops *telephony;
80 static const struct device_ops *hall_ic = NULL;
81 static void telephony_init(void)
85 telephony = find_device("telephony");
86 _I("telephony (%d)", telephony);
89 static void telephony_start(void)
96 static void telephony_stop(void)
102 static int telephony_exit(void *data)
106 telephony->exit(data);
110 static void poweroff_popup_edbus_signal_handler(void *data, DBusMessage *msg)
116 if (dbus_message_is_signal(msg, DEVICED_INTERFACE_NAME, SIGNAL_NAME_POWEROFF_POPUP) == 0) {
117 _E("there is no power off popup signal");
121 dbus_error_init(&err);
123 if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
124 _E("there is no message");
128 if (strncmp(str, PREDEF_PWROFF_POPUP, strlen(PREDEF_PWROFF_POPUP)) == 0)
129 val = VCONFKEY_SYSMAN_POWER_OFF_POPUP;
130 else if (strncmp(str, PREDEF_POWEROFF, strlen(PREDEF_POWEROFF)) == 0)
131 val = VCONFKEY_SYSMAN_POWER_OFF_DIRECT;
132 else if (strncmp(str, PREDEF_REBOOT, strlen(PREDEF_REBOOT)) == 0)
133 val = VCONFKEY_SYSMAN_POWER_OFF_RESTART;
134 else if (strncmp(str, PREDEF_FOTA_REBOOT, strlen(PREDEF_FOTA_REBOOT)) == 0)
135 val = SYSTEMD_STOP_POWER_RESTART_FOTA;
137 _E("not supported message : %s", str);
140 vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val);
143 static void booting_done_edbus_signal_handler(void *data, DBusMessage *msg)
145 if (!dbus_message_is_signal(msg, DEVICED_INTERFACE_CORE, SIGNAL_BOOTING_DONE)) {
146 _E("there is no bootingdone signal");
150 device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE);
154 static void poweroff_send_broadcast(int status)
163 _D("broadcast poweroff %d", status);
166 snprintf(str_status, sizeof(str_status), "%d", status);
169 broadcast_edbus_signal(DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF,
170 SIGNAL_POWEROFF_STATE, "i", arr);
173 static void poweroff_stop_systemd_service(void)
176 _D("systemd service stop");
177 umount2("/sys/fs/cgroup", MNT_FORCE |MNT_DETACH);
180 static void poweroff_start_animation(void)
183 snprintf(params, sizeof(params), "/usr/bin/boot-animation --stop --clear");
184 launch_app_cmd_with_nice(params, -20);
185 launch_evenif_exist("/usr/bin/sound_server", "--poweroff");
186 device_notify(DEVICE_NOTIFIER_POWEROFF_HAPTIC, NULL);
189 static void poweroff_control_cb(keynode_t *in_key, struct main_data *ad)
197 if (vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &val) != 0)
202 if (val == SYSTEMD_STOP_POWER_OFF ||
203 val == SYSTEMD_STOP_POWER_RESTART ||
204 val == SYSTEMD_STOP_POWER_RESTART_RECOVERY ||
205 val == SYSTEMD_STOP_POWER_RESTART_FOTA) {
206 poweroff_stop_systemd_service();
207 if (val == SYSTEMD_STOP_POWER_OFF)
208 val = VCONFKEY_SYSMAN_POWER_OFF_DIRECT;
210 val = VCONFKEY_SYSMAN_POWER_OFF_RESTART;
211 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
212 vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val);
215 if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART)
216 poweroff_send_broadcast(val);
219 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
220 device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val);
221 notify_action(PREDEF_POWEROFF, 0);
223 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
224 notify_action(PREDEF_PWROFF_POPUP, 0);
226 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
227 device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val);
228 if (recovery == SYSTEMD_STOP_POWER_RESTART_RECOVERY)
229 notify_action(PREDEF_RECOVERY, 0);
230 else if (recovery == SYSTEMD_STOP_POWER_RESTART_FOTA)
231 notify_action(PREDEF_FOTA_REBOOT, 0);
233 notify_action(PREDEF_REBOOT, 0);
237 if (update_pm_setting)
238 update_pm_setting(SETTING_POWEROFF, val);
241 /* umount usr data partition */
242 static void unmount_rw_partition()
246 if (!mount_check(UMOUNT_RW_PATH))
251 /* Second, kill app with SIGTERM */
252 _I("Kill app with SIGTERM");
253 terminate_process(UMOUNT_RW_PATH, false);
257 /* Last time, kill app with SIGKILL */
258 _I("Kill app with SIGKILL");
259 terminate_process(UMOUNT_RW_PATH, true);
263 if (umount2(UMOUNT_RW_PATH, 0) != 0) {
264 _I("Failed to unmount %s", UMOUNT_RW_PATH);
267 _I("%s unmounted successfully", UMOUNT_RW_PATH);
270 if (umount2(UMOUNT_RW_PATH, 0) == 0) {
271 _I("%s unmounted successfully", UMOUNT_RW_PATH);
277 static void powerdown(void)
281 int poweroff_duration = POWEROFF_DURATION;
282 int check_duration = 0;
285 if (power_off == 1) {
286 _E("during power off");
290 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
294 buf = getenv("PWROFF_DUR");
295 if (buf != NULL && strlen(buf) < 1024)
296 poweroff_duration = atoi(buf);
297 if (poweroff_duration < 0 || poweroff_duration > 60)
298 poweroff_duration = POWEROFF_DURATION;
299 gettimeofday(&now, NULL);
300 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
301 while (check_duration < poweroff_duration) {
303 _I("wait poweroff %d %d", check_duration, poweroff_duration);
307 gettimeofday(&now, NULL);
308 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
309 if (check_duration < 0)
312 unmount_rw_partition();
315 static void restart_by_mode(int mode)
317 if (mode == SYSTEMD_STOP_POWER_RESTART_RECOVERY)
318 launch_evenif_exist("/usr/sbin/reboot", "recovery");
319 else if (mode == SYSTEMD_STOP_POWER_RESTART_FOTA)
320 launch_evenif_exist("/usr/sbin/reboot", "fota");
325 int internal_poweroff_def_predefine_action(int argc, char **argv)
328 const struct device_ops *display_device_ops;
332 display_device_ops = find_device("display");
333 if (!display_device_ops) {
334 _E("Can't find display_device_ops");
338 display_device_ops->exit(NULL);
341 gettimeofday(&tv_start_poweroff, NULL);
343 ret = telephony_exit(PREDEF_POWEROFF);
352 int do_poweroff(int argc, char **argv)
354 return internal_poweroff_def_predefine_action(argc, argv);
357 int poweroff_def_predefine_action(int argc, char **argv)
360 poweroff_start_animation();
361 while (retry_count < MAX_RETRY) {
362 if (notify_action(PREDEF_INTERNAL_POWEROFF, 0) < 0) {
363 _E("failed to request poweroff to deviced");
367 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
373 static int hall_ic_status(void)
376 return HALL_IC_OPENED;
377 return hall_ic->status();
380 int launching_predefine_action(int argc, char **argv)
382 struct popup_data *params;
383 static const struct device_ops *apps = NULL;
386 val = hall_ic_status();
387 if (val == HALL_IC_CLOSED) {
388 _I("cover is closed");
392 apps = find_device("apps");
396 params = malloc(sizeof(struct popup_data));
397 if (params == NULL) {
401 params->name = POWEROFF_POPUP_NAME;
402 apps->init((void *)params);
407 int restart_def_predefine_action(int argc, char **argv)
412 const struct device_ops *display_device_ops;
413 poweroff_start_animation();
416 display_device_ops = find_device("display");
417 if (!display_device_ops) {
418 _E("Can't find display_device_ops");
422 pm_change_internal(getpid(), LCD_NORMAL);
423 display_device_ops->exit(NULL);
426 gettimeofday(&tv_start_poweroff, NULL);
428 if (argc == 1 && argv)
429 data = atoi(argv[0]);
430 if (data == SYSTEMD_STOP_POWER_RESTART_RECOVERY)
431 ret = telephony_exit(PREDEF_RECOVERY);
432 else if (data == SYSTEMD_STOP_POWER_RESTART_FOTA)
433 ret = telephony_exit(PREDEF_FOTA_REBOOT);
435 ret = telephony_exit(PREDEF_REBOOT);
438 restart_ap((void *)data);
444 int restart_recovery_def_predefine_action(int argc, char **argv)
450 snprintf(status, sizeof(status), "%d", SYSTEMD_STOP_POWER_RESTART_RECOVERY);
453 return restart_def_predefine_action(1, param);
456 int restart_fota_def_predefine_action(int argc, char **argv)
462 snprintf(status, sizeof(status), "%d", SYSTEMD_STOP_POWER_RESTART_FOTA);
465 return restart_def_predefine_action(1, param);
468 int reset_resetkey_disable(char *name, enum watch_id id)
470 _D("force reset power resetkey disable to zero");
471 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, 0);
474 static DBusMessage *edbus_resetkeydisable(E_DBus_Object *obj, DBusMessage *msg)
476 DBusMessageIter iter;
480 ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &val,
483 _E("there is no message");
488 ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, val);
493 register_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE, reset_resetkey_disable);
495 unregister_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE);
497 _D("get power resetkey disable %d, %d", val, ret);
500 reply = dbus_message_new_method_return(msg);
501 dbus_message_iter_init_append(reply, &iter);
502 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
506 static int reset_wakeupkey(char *name, enum watch_id id)
508 _D("force reset wakeupkey to zero");
509 return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, 0);
512 static DBusMessage *edbus_set_wakeup_key(E_DBus_Object *obj, DBusMessage *msg)
514 DBusMessageIter iter;
518 ret = dbus_message_get_args(msg, NULL,
519 DBUS_TYPE_INT32, &val,
522 _E("there is no message");
527 ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, val);
532 register_edbus_watch(msg, WATCH_POWER_WAKEUPKEY, reset_wakeupkey);
534 unregister_edbus_watch(msg, WATCH_POWER_WAKEUPKEY);
536 _D("set power wakeup key %d %d", val, ret);
539 reply = dbus_message_new_method_return(msg);
540 dbus_message_iter_init_append(reply, &iter);
541 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
545 static DBusMessage *dbus_power_handler(E_DBus_Object *obj, DBusMessage *msg)
548 DBusMessageIter iter;
555 dbus_error_init(&err);
557 if (!dbus_message_get_args(msg, &err,
558 DBUS_TYPE_STRING, &type_str,
559 DBUS_TYPE_INT32, &argc, DBUS_TYPE_INVALID)) {
560 _E("there is no message");
566 _E("message is invalid!");
571 pid = get_edbus_sender_pid(msg);
572 if (kill(pid, 0) == -1) {
573 _E("%d process does not exist, dbus ignored!", pid);
580 if(strncmp(type_str, PREDEF_REBOOT, strlen(PREDEF_REBOOT)) == 0)
581 restart_def_predefine_action(0, NULL);
582 else if(strncmp(type_str, PREDEF_RECOVERY, strlen(PREDEF_RECOVERY)) == 0)
583 restart_recovery_def_predefine_action(0, NULL);
584 else if(strncmp(type_str, PREDEF_PWROFF_POPUP, strlen(PREDEF_PWROFF_POPUP)) == 0)
585 launching_predefine_action(0, NULL);
588 reply = dbus_message_new_method_return(msg);
589 dbus_message_iter_init_append(reply, &iter);
590 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
595 void powerdown_ap(void *data)
599 reboot(RB_POWER_OFF);
602 void restart_ap(void *data)
604 _I("Restart %d", (int)data);
606 restart_by_mode((int)data);
609 static const struct edbus_method edbus_methods[] = {
610 { "setresetkeydisable", "i", "i", edbus_resetkeydisable },
611 { "SetWakeupKey", "i", "i", edbus_set_wakeup_key },
612 { PREDEF_REBOOT, "si", "i", dbus_power_handler },
613 { PREDEF_RECOVERY, "si", "i", dbus_power_handler },
614 { PREDEF_PWROFF_POPUP, "si", "i", dbus_power_handler },
615 /* Add methods here */
618 static void power_init(void *data)
623 /* init dbus interface */
624 ret = register_edbus_method(DEVICED_PATH_POWER, edbus_methods, ARRAY_SIZE(edbus_methods));
626 _E("fail to init edbus method(%d)", ret);
628 register_action(PREDEF_POWEROFF,
629 poweroff_def_predefine_action, NULL, NULL);
630 register_action(PREDEF_PWROFF_POPUP,
631 launching_predefine_action, NULL, NULL);
632 register_action(PREDEF_REBOOT,
633 restart_def_predefine_action, NULL, NULL);
634 register_action(PREDEF_RECOVERY,
635 restart_recovery_def_predefine_action, NULL, NULL);
636 register_action(PREDEF_FOTA_REBOOT,
637 restart_fota_def_predefine_action, NULL, NULL);
639 register_action(PREDEF_INTERNAL_POWEROFF,
640 internal_poweroff_def_predefine_action, NULL, NULL);
642 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void *)poweroff_control_cb, NULL) < 0) {
643 _E("Vconf notify key chaneged failed: KEY(%s)", VCONFKEY_SYSMAN_POWER_OFF_STATUS);
646 register_edbus_signal_handler(DEVICED_OBJECT_PATH, DEVICED_INTERFACE_NAME,
647 SIGNAL_NAME_POWEROFF_POPUP,
648 poweroff_popup_edbus_signal_handler);
649 register_edbus_signal_handler(DEVICED_PATH_CORE,
650 DEVICED_INTERFACE_CORE,
652 booting_done_edbus_signal_handler);
653 hall_ic = find_device(HALL_IC_NAME);
656 static const struct device_ops power_device_ops = {
657 .priority = DEVICE_PRIORITY_NORMAL,
662 DEVICE_OPS_REGISTER(&power_device_ops)