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 <ITapiModem.h>
32 #include <tapi_event.h>
33 #include <tapi_common.h>
34 #include <syspopup_caller.h>
35 #include <sys/reboot.h>
38 #include <sys/mount.h>
39 #include "dd-deviced.h"
41 #include "core/launch.h"
42 #include "core/queue.h"
43 #include "core/device-handler.h"
44 #include "device-node.h"
45 #include "core/predefine.h"
46 #include "core/data.h"
47 #include "core/common.h"
48 #include "core/devices.h"
49 #include "proc/proc-handler.h"
50 #include "display/poll.h"
51 #include "display/setting.h"
53 #define SIGNAL_NAME_POWEROFF_POPUP "poweroffpopup"
55 #define PREDEF_ENTERSLEEP "entersleep"
56 #define PREDEF_LEAVESLEEP "leavesleep"
57 #define PREDEF_POWEROFF "poweroff"
58 #define PREDEF_REBOOT "reboot"
59 #define PREDEF_PWROFF_POPUP "pwroff-popup"
60 #define PREDEF_INTERNAL_POWEROFF "internal_poweroff"
61 #define PREDEF_FLIGHT_MODE "flightmode"
63 #define POWEROFF_NOTI_NAME "power_off_start"
64 #define POWEROFF_DURATION 2
67 static struct timeval tv_start_poweroff;
69 static Ecore_Timer *poweroff_timer_id = NULL;
70 static TapiHandle *tapi_handle = NULL;
71 static int power_off = 0;
73 static void poweroff_popup_edbus_signal_handler(void *data, DBusMessage *msg)
79 if (dbus_message_is_signal(msg, INTERFACE_NAME, SIGNAL_NAME_POWEROFF_POPUP) == 0) {
80 _E("there is no power off popup signal");
84 dbus_error_init(&err);
86 if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
87 _E("there is no message");
91 if (strncmp(str, PREDEF_PWROFF_POPUP, strlen(PREDEF_PWROFF_POPUP)) == 0)
92 val = VCONFKEY_SYSMAN_POWER_OFF_POPUP;
93 else if (strncmp(str, PREDEF_POWEROFF, strlen(PREDEF_POWEROFF)) == 0)
94 val = VCONFKEY_SYSMAN_POWER_OFF_DIRECT;
95 else if (strncmp(str, PREDEF_POWEROFF, strlen(PREDEF_REBOOT)) == 0)
96 val = VCONFKEY_SYSMAN_POWER_OFF_RESTART;
98 _E("not supported message : %s", str);
101 vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, val);
104 static void poweroff_control_cb(keynode_t *in_key, struct ss_main_data *ad)
107 if (vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &val) != 0)
110 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
111 ss_action_entry_call_internal(PREDEF_POWEROFF, 0);
113 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
114 ss_action_entry_call_internal(PREDEF_PWROFF_POPUP, 0);
116 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
117 ss_action_entry_call_internal(PREDEF_REBOOT, 0);
121 if (update_pm_setting)
122 update_pm_setting(SETTING_POWEROFF, val);
125 static void remount_ro()
128 const char* table = "/etc/mtab";
129 const char mmtpoint[10][64];
131 int r = -1, foundmount=0;
133 fp = setmntent(table, "r");
138 while (mnt=getmntent(fp)) {
139 if (foundmount >= 10)
141 if (!strcmp(mnt->mnt_type, "ext4") && strstr(mnt->mnt_opts, "rw")) {
142 memset(mmtpoint[foundmount], 0, 64);
143 strncpy(mmtpoint[foundmount], mnt->mnt_dir, 63);
150 snprintf(buf, sizeof(buf), "fuser -c %s -k -15", mmtpoint[foundmount]);
152 umount2(mmtpoint[foundmount], MNT_DETACH);
156 static void enter_flight_mode_cb(TapiHandle *handle, int result, void *data, void *user_data)
158 int bCurFlightMode = 0;
159 if (result != TAPI_POWER_FLIGHT_MODE_ENTER) {
160 _E("flight mode enter failed %d",result);
162 _D("enter flight mode result : %d",result);
163 if (vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE,&bCurFlightMode) == 0) {
164 _D("Flight Mode is %d", bCurFlightMode);
166 _E("failed to get vconf key");
171 static void leave_flight_mode_cb(TapiHandle *handle, int result, void *data, void *user_data)
173 int bCurFlightMode = 0;
174 if (result != TAPI_POWER_FLIGHT_MODE_LEAVE) {
175 _E("flight mode leave failed %d",result);
177 _D("leave flight mode result : %d",result);
178 if (vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE,&bCurFlightMode) == 0) {
179 _D("Flight Mode is %d", bCurFlightMode);
181 _E("failed to get vconf key");
186 int flight_mode_def_predefine_action(int argc, char **argv)
189 int err = TAPI_API_SUCCESS;
190 if (argc != 1 || argv[0] == NULL) {
191 _E("FlightMode Set predefine action failed");
194 bCurFlightMode = atoi(argv[0]);
195 if (bCurFlightMode == 1) {
196 err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE, leave_flight_mode_cb, NULL);
197 } else if (bCurFlightMode == 0) {
198 err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER, enter_flight_mode_cb, NULL);
200 if (err != TAPI_API_SUCCESS)
201 _E("FlightMode tel api action failed %d",err);
206 static void __tel_init_cb(keynode_t *key_nodes,void *data)
209 bTelReady = vconf_keynode_get_bool(key_nodes);
210 if (bTelReady == 1) {
211 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_READY, (void*)__tel_init_cb);
212 tapi_handle = tel_init(NULL);
213 if (tapi_handle == NULL) {
214 _E("tapi init error");
217 _E("tapi is not ready yet");
221 Eina_Bool powerdown_ap_by_force(void *data)
224 int poweroff_duration = POWEROFF_DURATION;
227 if(tapi_handle != NULL)
229 tel_deinit(tapi_handle);
232 /* Getting poweroff duration */
233 buf = getenv("PWROFF_DUR");
234 if (buf != NULL && strlen(buf) < 1024)
235 poweroff_duration = atoi(buf);
236 if (poweroff_duration < 0 || poweroff_duration > 60)
237 poweroff_duration = POWEROFF_DURATION;
239 gettimeofday(&now, NULL);
240 /* Waiting until power off duration and displaying animation */
241 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
243 gettimeofday(&now, NULL);
246 _I("Power off by force");
247 /* give a chance to be terminated for each process */
251 reboot(RB_POWER_OFF);
255 static void powerdown_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
258 int poweroff_duration = POWEROFF_DURATION;
261 if (poweroff_timer_id) {
262 ecore_timer_del(poweroff_timer_id);
263 poweroff_timer_id = NULL;
266 tel_deregister_noti_event(tapi_handle,TAPI_NOTI_MODEM_POWER);
267 tel_deinit(tapi_handle);
273 /* Getting poweroff duration */
274 buf = getenv("PWROFF_DUR");
275 if (buf != NULL && strlen(buf) < 1024)
276 poweroff_duration = atoi(buf);
277 if (poweroff_duration < 0 || poweroff_duration > 60)
278 poweroff_duration = POWEROFF_DURATION;
280 gettimeofday(&now, NULL);
281 /* Waiting until power off duration and displaying animation */
282 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
284 gettimeofday(&now, NULL);
287 /* give a chance to be terminated for each process */
291 reboot(RB_POWER_OFF);
293 static void powerdown_res_cb(TapiHandle *handle, int result, void *data, void *user_data)
295 _D("poweroff command request : %d",result);
299 int internal_poweroff_def_predefine_action(int argc, char **argv)
303 display_device_ops.exit(NULL);
304 system("/usr/lib/system-server/shutdown.sh &");
307 gettimeofday(&tv_start_poweroff, NULL);
309 ret = tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER, powerdown_ap, NULL);
311 if (ret != TAPI_API_SUCCESS) {
312 _E("tel_register_event is not subscribed. error %d", ret);
313 powerdown_ap_by_force(NULL);
317 ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF, powerdown_res_cb, NULL);
318 if (ret != TAPI_API_SUCCESS) {
319 _E("tel_process_power_command() error %d\n", ret);
320 powerdown_ap_by_force(NULL);
323 poweroff_timer_id = ecore_timer_add(15, powerdown_ap_by_force, NULL);
325 powerdown_ap_by_force(NULL);
330 static void restart_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data);
332 Eina_Bool restart_ap_ecore(void *data)
334 restart_ap(tapi_handle,NULL,(void *)-1,NULL);
338 static void restart_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
341 int poweroff_duration = POWEROFF_DURATION;
344 if (poweroff_timer_id) {
345 ecore_timer_del(poweroff_timer_id);
346 poweroff_timer_id = NULL;
350 if(tapi_handle != NULL)
352 tel_deregister_noti_event(tapi_handle,TAPI_NOTI_MODEM_POWER);
353 tel_deinit(tapi_handle);
358 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
362 buf = getenv("PWROFF_DUR");
363 if (buf != NULL && strlen(buf) < 1024)
364 poweroff_duration = atoi(buf);
365 if (poweroff_duration < 0 || poweroff_duration > 60)
366 poweroff_duration = POWEROFF_DURATION;
367 gettimeofday(&now, NULL);
368 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
370 gettimeofday(&now, NULL);
377 static void restart_ap_by_force(void *data)
380 int poweroff_duration = POWEROFF_DURATION;
383 if (poweroff_timer_id) {
384 ecore_timer_del(poweroff_timer_id);
385 poweroff_timer_id = NULL;
388 if(tapi_handle != NULL) {
389 tel_deinit(tapi_handle);
397 buf = getenv("PWROFF_DUR");
398 if (buf != NULL && strlen(buf) < 1024)
399 poweroff_duration = atoi(buf);
400 if (poweroff_duration < 0 || poweroff_duration > 60)
401 poweroff_duration = POWEROFF_DURATION;
402 gettimeofday(&now, NULL);
403 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
405 gettimeofday(&now, NULL);
412 int entersleep_def_predefine_action(int argc, char **argv)
416 pm_change_internal(getpid(), LCD_NORMAL);
417 system("/usr/lib/system-server/shutdown.sh &");
420 ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER, enter_flight_mode_cb, NULL);
421 _I("request for changing into flight mode : %d", ret);
423 system("/etc/rc.d/rc.entersleep");
424 pm_change_internal(getpid(), POWER_OFF);
429 int poweroff_def_predefine_action(int argc, char **argv)
433 heynoti_publish(POWEROFF_NOTI_NAME);
435 while (retry_count < MAX_RETRY) {
436 if (ss_action_entry_call_internal(PREDEF_INTERNAL_POWEROFF, 0) < 0) {
437 _E("failed to request poweroff to system_server");
441 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
447 int launching_predefine_action(int argc, char **argv)
454 /* current just launching poweroff-popup */
455 if (predefine_control_launch("poweroff-syspopup", NULL, 0) < 0) {
456 _E("poweroff-syspopup launch failed");
462 int leavesleep_def_predefine_action(int argc, char **argv)
466 pm_change_internal(getpid(), LCD_NORMAL);
469 ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE, leave_flight_mode_cb, NULL);
470 _I("request for changing into flight mode : %d", ret);
475 int restart_def_predefine_action(int argc, char **argv)
479 heynoti_publish(POWEROFF_NOTI_NAME);
480 pm_change_internal(getpid(), LCD_NORMAL);
481 display_device_ops.exit(NULL);
482 system("/etc/rc.d/rc.shutdown &");
485 gettimeofday(&tv_start_poweroff, NULL);
488 tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER, restart_ap, NULL);
489 if (ret != TAPI_API_SUCCESS) {
490 _E("tel_register_event is not subscribed. error %d", ret);
491 restart_ap_by_force((void *)-1);
496 ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF, powerdown_res_cb, NULL);
497 if (ret != TAPI_API_SUCCESS) {
498 _E("tel_process_power_command() error %d", ret);
499 restart_ap_by_force((void *)-1);
503 poweroff_timer_id = ecore_timer_add(15, restart_ap_ecore, NULL);
507 static void power_init(void *data)
511 if (vconf_get_bool(VCONFKEY_TELEPHONY_READY,&bTelReady) == 0) {
512 if (bTelReady == 1) {
513 tapi_handle = tel_init(NULL);
514 if (tapi_handle == NULL) {
515 _E("tapi init error");
518 vconf_notify_key_changed(VCONFKEY_TELEPHONY_READY, (void *)__tel_init_cb, NULL);
521 _E("failed to get tapi vconf key");
524 ss_action_entry_add_internal(PREDEF_ENTERSLEEP,
525 entersleep_def_predefine_action, NULL,
527 ss_action_entry_add_internal(PREDEF_POWEROFF,
528 poweroff_def_predefine_action, NULL, NULL);
529 ss_action_entry_add_internal(PREDEF_PWROFF_POPUP,
530 launching_predefine_action, NULL, NULL);
531 ss_action_entry_add_internal(PREDEF_LEAVESLEEP,
532 leavesleep_def_predefine_action, NULL,
534 ss_action_entry_add_internal(PREDEF_REBOOT,
535 restart_def_predefine_action, NULL, NULL);
537 ss_action_entry_add_internal(PREDEF_INTERNAL_POWEROFF,
538 internal_poweroff_def_predefine_action, NULL, NULL);
540 ss_action_entry_add_internal(PREDEF_FLIGHT_MODE,
541 flight_mode_def_predefine_action, NULL, NULL);
543 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void *)poweroff_control_cb, NULL) < 0) {
544 _E("Vconf notify key chaneged failed: KEY(%s)", VCONFKEY_SYSMAN_POWER_OFF_STATUS);
547 register_edbus_signal_handler(OBJECT_PATH, INTERFACE_NAME,
548 SIGNAL_NAME_POWEROFF_POPUP,
549 (void *)poweroff_popup_edbus_signal_handler);
550 register_edbus_signal_handler(OBJECT_PATH, INTERFACE_NAME,
551 SIGNAL_NAME_LCD_CONTROL,
552 (void *)lcd_control_edbus_signal_handler);
555 const struct device_ops power_device_ops = {