80321e81bcdf6921f8a29a6b54cd55c16fe6fa1a
[framework/system/deviced.git] / src / power / power-handler.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <unistd.h>
21 #include <time.h>
22 #include <limits.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <vconf.h>
26 #include <assert.h>
27 #include <limits.h>
28 #include <vconf.h>
29 #include <fcntl.h>
30 #include <sys/reboot.h>
31 #include <sys/time.h>
32 #include <mntent.h>
33 #include <sys/mount.h>
34 #include <device-node.h>
35 #include "dd-deviced.h"
36 #include "core/log.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"
52
53 #define SIGNAL_NAME_POWEROFF_POPUP      "poweroffpopup"
54 #define SIGNAL_BOOTING_DONE             "BootingDone"
55
56 #define PREDEF_PWROFF_POPUP             "pwroff-popup"
57 #define PREDEF_INTERNAL_POWEROFF        "internal_poweroff"
58
59 #define POWEROFF_NOTI_NAME              "power_off_start"
60 #define POWEROFF_DURATION               2
61 #define MAX_RETRY                       2
62
63 #define SYSTEMD_STOP_POWER_OFF                          4
64
65 #define SIGNAL_POWEROFF_STATE   "ChangeState"
66
67 #define POWEROFF_POPUP_NAME     "poweroff-syspopup"
68 #define UMOUNT_RW_PATH "/opt/usr"
69
70
71 struct popup_data {
72         char *name;
73         char *key;
74 };
75
76 static struct timeval tv_start_poweroff;
77
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)
82 {
83         if (telephony)
84                 return;
85         telephony = find_device("telephony");
86         _I("telephony (%d)", telephony);
87 }
88
89 static void telephony_start(void)
90 {
91         telephony_init();
92         if (telephony)
93                 telephony->start();
94 }
95
96 static void telephony_stop(void)
97 {
98         if (telephony)
99                 telephony->stop();
100 }
101
102 static int telephony_exit(void *data)
103 {
104         if (!telephony)
105                 return -EINVAL;
106         telephony->exit(data);
107         return 0;
108 }
109
110 static void poweroff_popup_edbus_signal_handler(void *data, DBusMessage *msg)
111 {
112         DBusError err;
113         char *str;
114         int val = 0;
115
116         if (dbus_message_is_signal(msg, DEVICED_INTERFACE_NAME, SIGNAL_NAME_POWEROFF_POPUP) == 0) {
117                 _E("there is no power off popup signal");
118                 return;
119         }
120
121         dbus_error_init(&err);
122
123         if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
124                 _E("there is no message");
125                 return;
126         }
127
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;
136         if (val == 0) {
137                 _E("not supported message : %s", str);
138                 return;
139         }
140         vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val);
141 }
142
143 static void booting_done_edbus_signal_handler(void *data, DBusMessage *msg)
144 {
145         if (!dbus_message_is_signal(msg, DEVICED_INTERFACE_CORE, SIGNAL_BOOTING_DONE)) {
146                 _E("there is no bootingdone signal");
147                 return;
148         }
149
150         device_notify(DEVICE_NOTIFIER_BOOTING_DONE, (void *)TRUE);
151         telephony_init();
152 }
153
154 static void poweroff_send_broadcast(int status)
155 {
156         static int old = 0;
157         char *arr[1];
158         char str_status[32];
159
160         if (old == status)
161                 return;
162
163         _D("broadcast poweroff %d", status);
164
165         old = status;
166         snprintf(str_status, sizeof(str_status), "%d", status);
167         arr[0] = str_status;
168
169         broadcast_edbus_signal(DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF,
170                         SIGNAL_POWEROFF_STATE, "i", arr);
171 }
172
173 static void poweroff_stop_systemd_service(void)
174 {
175         char buf[256];
176         _D("systemd service stop");
177         umount2("/sys/fs/cgroup", MNT_FORCE |MNT_DETACH);
178 }
179
180 static void poweroff_start_animation(void)
181 {
182         char params[128];
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);
187 }
188
189 static void poweroff_control_cb(keynode_t *in_key, struct main_data *ad)
190 {
191         int val;
192         int ret;
193         int recovery;
194
195         telephony_start();
196
197         if (vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &val) != 0)
198                 return;
199
200         recovery = val;
201
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;
209                 else
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);
213         }
214
215         if (val == VCONFKEY_SYSMAN_POWER_OFF_DIRECT || val == VCONFKEY_SYSMAN_POWER_OFF_RESTART)
216                 poweroff_send_broadcast(val);
217
218         switch (val) {
219         case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
220                 device_notify(DEVICE_NOTIFIER_POWEROFF, (void *)val);
221                 notify_action(PREDEF_POWEROFF, 0);
222                 break;
223         case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
224                 notify_action(PREDEF_PWROFF_POPUP, 0);
225                 break;
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);
232                 else
233                         notify_action(PREDEF_REBOOT, 0);
234                 break;
235         }
236
237         if (update_pm_setting)
238                 update_pm_setting(SETTING_POWEROFF, val);
239 }
240
241 /* umount usr data partition */
242 static void unmount_rw_partition()
243 {
244         int retry = 0;
245         sync();
246         if (!mount_check(UMOUNT_RW_PATH))
247                 return;
248         while (1) {
249                 switch (retry++) {
250                 case 0:
251                         /* Second, kill app with SIGTERM */
252                         _I("Kill app with SIGTERM");
253                         terminate_process(UMOUNT_RW_PATH, false);
254                         sleep(3);
255                         break;
256                 case 1:
257                         /* Last time, kill app with SIGKILL */
258                         _I("Kill app with SIGKILL");
259                         terminate_process(UMOUNT_RW_PATH, true);
260                         sleep(1);
261                         break;
262                 default:
263                         if (umount2(UMOUNT_RW_PATH, 0) != 0) {
264                                 _I("Failed to unmount %s", UMOUNT_RW_PATH);
265                                 return;
266                         }
267                         _I("%s unmounted successfully", UMOUNT_RW_PATH);
268                         return;
269                 }
270                 if (umount2(UMOUNT_RW_PATH, 0) == 0) {
271                         _I("%s unmounted successfully", UMOUNT_RW_PATH);
272                         return;
273                 }
274         }
275 }
276
277 static void powerdown(void)
278 {
279         static int wait = 0;
280         struct timeval now;
281         int poweroff_duration = POWEROFF_DURATION;
282         int check_duration = 0;
283         char *buf;
284
285         if (power_off == 1) {
286                 _E("during power off");
287                 return;
288         }
289         telephony_stop();
290         vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
291         power_off = 1;
292         sync();
293
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) {
302                 if (wait == 0) {
303                         _I("wait poweroff %d %d", check_duration, poweroff_duration);
304                         wait = 1;
305                 }
306                 usleep(100000);
307                 gettimeofday(&now, NULL);
308                 check_duration = now.tv_sec - tv_start_poweroff.tv_sec;
309                 if (check_duration < 0)
310                         break;
311         }
312         unmount_rw_partition();
313 }
314
315 static void restart_by_mode(int mode)
316 {
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");
321         else
322                 reboot(RB_AUTOBOOT);
323 }
324
325 int internal_poweroff_def_predefine_action(int argc, char **argv)
326 {
327         int ret;
328         const struct device_ops *display_device_ops;
329
330         telephony_start();
331
332         display_device_ops = find_device("display");
333         if (!display_device_ops) {
334                 _E("Can't find display_device_ops");
335                 return -ENODEV;
336         }
337
338         display_device_ops->exit(NULL);
339         sync();
340
341         gettimeofday(&tv_start_poweroff, NULL);
342
343         ret = telephony_exit(PREDEF_POWEROFF);
344
345         if (ret < 0) {
346                 powerdown_ap(NULL);
347                 return 0;
348         }
349         return ret;
350 }
351
352 int do_poweroff(int argc, char **argv)
353 {
354         return internal_poweroff_def_predefine_action(argc, argv);
355 }
356
357 int poweroff_def_predefine_action(int argc, char **argv)
358 {
359         int retry_count = 0;
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");
364                         retry_count++;
365                         continue;
366                 }
367                 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
368                 return 0;
369         }
370         return -1;
371 }
372
373 static int hall_ic_status(void)
374 {
375         if (!hall_ic)
376                 return HALL_IC_OPENED;
377         return hall_ic->status();
378 }
379
380 int launching_predefine_action(int argc, char **argv)
381 {
382         struct popup_data *params;
383         static const struct device_ops *apps = NULL;
384         int val;
385
386         val = hall_ic_status();
387         if (val == HALL_IC_CLOSED) {
388                 _I("cover is closed");
389                 return 0;
390         }
391         if (apps == NULL) {
392                 apps = find_device("apps");
393                 if (apps == NULL)
394                         return 0;
395         }
396         params = malloc(sizeof(struct popup_data));
397         if (params == NULL) {
398                 _E("Malloc failed");
399                 return -1;
400         }
401         params->name = POWEROFF_POPUP_NAME;
402         apps->init((void *)params);
403         free(params);
404         return 0;
405 }
406
407 int restart_def_predefine_action(int argc, char **argv)
408 {
409         int ret;
410         int data = 0;
411
412         const struct device_ops *display_device_ops;
413         poweroff_start_animation();
414         telephony_start();
415
416         display_device_ops = find_device("display");
417         if (!display_device_ops) {
418                 _E("Can't find display_device_ops");
419                 return -ENODEV;
420         }
421
422         pm_change_internal(getpid(), LCD_NORMAL);
423         display_device_ops->exit(NULL);
424         sync();
425
426         gettimeofday(&tv_start_poweroff, NULL);
427
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);
434         else
435                 ret = telephony_exit(PREDEF_REBOOT);
436
437         if (ret < 0) {
438                 restart_ap((void *)data);
439                 return 0;
440         }
441         return ret;
442 }
443
444 int restart_recovery_def_predefine_action(int argc, char **argv)
445 {
446         int ret;
447         char *param[1];
448         char status[32];
449
450         snprintf(status, sizeof(status), "%d", SYSTEMD_STOP_POWER_RESTART_RECOVERY);
451         param[0] = status;
452
453         return restart_def_predefine_action(1, param);
454 }
455
456 int restart_fota_def_predefine_action(int argc, char **argv)
457 {
458         int ret;
459         char *param[1];
460         char status[32];
461
462         snprintf(status, sizeof(status), "%d", SYSTEMD_STOP_POWER_RESTART_FOTA);
463         param[0] = status;
464
465         return restart_def_predefine_action(1, param);
466 }
467
468 int reset_resetkey_disable(char *name, enum watch_id id)
469 {
470         _D("force reset power resetkey disable to zero");
471         return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, 0);
472 }
473
474 static DBusMessage *edbus_resetkeydisable(E_DBus_Object *obj, DBusMessage *msg)
475 {
476         DBusMessageIter iter;
477         DBusMessage *reply;
478         int val, ret;
479
480         ret = dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &val,
481                         DBUS_TYPE_INVALID);
482         if (!ret) {
483                 _E("there is no message");
484                 ret = -EINVAL;
485                 goto error;
486         }
487
488         ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_RESETKEY_DISABLE, val);
489         if (ret < 0)
490                 goto error;
491
492         if (val)
493                 register_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE, reset_resetkey_disable);
494         else
495                 unregister_edbus_watch(msg, WATCH_POWER_RESETKEY_DISABLE);
496
497         _D("get power resetkey disable %d, %d", val, ret);
498
499 error:
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);
503         return reply;
504 }
505
506 static int reset_wakeupkey(char *name, enum watch_id id)
507 {
508         _D("force reset wakeupkey to zero");
509         return device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, 0);
510 }
511
512 static DBusMessage *edbus_set_wakeup_key(E_DBus_Object *obj, DBusMessage *msg)
513 {
514         DBusMessageIter iter;
515         DBusMessage *reply;
516         int val, ret;
517
518         ret = dbus_message_get_args(msg, NULL,
519                         DBUS_TYPE_INT32, &val,
520                         DBUS_TYPE_INVALID);
521         if (!ret) {
522                 _E("there is no message");
523                 ret = -EINVAL;
524                 goto error;
525         }
526
527         ret = device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_KEY, val);
528         if (ret < 0)
529                 goto error;
530
531         if (val)
532                 register_edbus_watch(msg, WATCH_POWER_WAKEUPKEY, reset_wakeupkey);
533         else
534                 unregister_edbus_watch(msg, WATCH_POWER_WAKEUPKEY);
535
536         _D("set power wakeup key %d %d", val, ret);
537
538 error:
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);
542         return reply;
543 }
544
545 static DBusMessage *dbus_power_handler(E_DBus_Object *obj, DBusMessage *msg)
546 {
547         DBusError err;
548         DBusMessageIter iter;
549         DBusMessage *reply;
550         pid_t pid;
551         int ret;
552         int argc;
553         char *type_str;
554
555         dbus_error_init(&err);
556
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");
561                 ret = -EINVAL;
562                 goto out;
563         }
564
565         if (argc < 0) {
566                 _E("message is invalid!");
567                 ret = -EINVAL;
568                 goto out;
569         }
570
571         pid = get_edbus_sender_pid(msg);
572         if (kill(pid, 0) == -1) {
573                 _E("%d process does not exist, dbus ignored!", pid);
574                 ret = -ESRCH;
575                 goto out;
576         }
577
578         telephony_start();
579
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);
586
587 out:
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);
591
592         return reply;
593 }
594
595 void powerdown_ap(void *data)
596 {
597         _I("Power off");
598         powerdown();
599         reboot(RB_POWER_OFF);
600 }
601
602 void restart_ap(void *data)
603 {
604         _I("Restart %d", (int)data);
605         powerdown();
606         restart_by_mode((int)data);
607 }
608
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 */
616 };
617
618 static void power_init(void *data)
619 {
620         int bTelReady = 0;
621         int ret;
622
623         /* init dbus interface */
624         ret = register_edbus_method(DEVICED_PATH_POWER, edbus_methods, ARRAY_SIZE(edbus_methods));
625         if (ret < 0)
626                 _E("fail to init edbus method(%d)", ret);
627
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);
638
639         register_action(PREDEF_INTERNAL_POWEROFF,
640                                      internal_poweroff_def_predefine_action, NULL, NULL);
641
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);
644         }
645
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,
651                     SIGNAL_BOOTING_DONE,
652                     booting_done_edbus_signal_handler);
653         hall_ic = find_device(HALL_IC_NAME);
654 }
655
656 static const struct device_ops power_device_ops = {
657         .priority = DEVICE_PRIORITY_NORMAL,
658         .name     = "power",
659         .init     = power_init,
660 };
661
662 DEVICE_OPS_REGISTER(&power_device_ops)