2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 #include <ITapiModem.h>
28 #include <tapi_event.h>
29 #include <tapi_common.h>
30 #include <syspopup_caller.h>
31 #include <sys/reboot.h>
35 #include "ss_launch.h"
37 #include "ss_device_handler.h"
38 #include "device-node.h"
39 #include "ss_predefine.h"
40 #include "ss_procmgr.h"
41 #include "ss_vibrator.h"
42 #include "include/ss_data.h"
44 #define PREDEFINE_SO_DIR PREFIX"/lib/ss_predefine/"
46 #define CALL_EXEC_PATH PREFIX"/bin/call"
47 #define LOWMEM_EXEC_PATH PREFIX"/bin/lowmem-popup"
48 #define LOWBAT_EXEC_PATH PREFIX"/bin/lowbatt-popup"
49 #define USBCON_EXEC_PATH PREFIX"/bin/usb-server"
50 #define TVOUT_EXEC_PATH PREFIX"/bin/tvout-selector"
51 #define PWROFF_EXEC_PATH PREFIX"/bin/poweroff-popup"
52 #define MEMPS_EXEC_PATH PREFIX"/bin/memps"
54 /* wait for 5 sec as victim process be dead */
55 #define WAITING_INTERVAL 5
57 #define TVOUT_X_BIN "/usr/bin/xberc"
58 #define TVOUT_FLAG 0x00000001
59 #define MEMPS_LOG_FILE "/var/log/memps"
62 #define POWEROFF_DURATION 2
63 #define POWEROFF_ANIMATION_PATH "/usr/bin/boot-animation"
64 #define POWEROFF_NOTI_NAME "power_off_start"
66 #define WM_READY_PATH "/tmp/.wm_ready"
68 #define LOWBAT_OPT_WARNING 1
69 #define LOWBAT_OPT_POWEROFF 2
70 #define LOWBAT_OPT_CHARGEERR 3
71 #define LOWBAT_OPT_CHECK 4
73 static Ecore_Timer *lowbat_popup_id = NULL;
74 static int lowbat_popup_option = 0;
76 static struct timeval tv_start_poweroff;
77 static void powerdown_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data);
78 static void poweroff_control_cb(keynode_t *in_key, struct ss_main_data *ad);
80 static int ss_flags = 0;
82 static Ecore_Timer *poweroff_timer_id = NULL;
83 static TapiHandle *tapi_handle = NULL;
84 static int power_off = 0;
86 static void make_memps_log(char *file, pid_t pid, char *victim_name)
91 char new_log[NAME_MAX];
92 static pid_t old_pid = 0;
101 if (localtime_r(&now, &cur_tm) == NULL) {
102 PRT_TRACE_ERR("Fail to get localtime");
106 PRT_TRACE("%s_%s_%d_%.4d%.2d%.2d_%.2d%.2d%.2d.log", file, victim_name,
107 pid, (1900 + cur_tm.tm_year), 1 + cur_tm.tm_mon,
108 cur_tm.tm_mday, cur_tm.tm_hour, cur_tm.tm_min,
110 snprintf(new_log, sizeof(new_log),
111 "%s_%s_%d_%.4d%.2d%.2d_%.2d%.2d%.2d.log", file, victim_name,
112 pid, (1900 + cur_tm.tm_year), 1 + cur_tm.tm_mon,
113 cur_tm.tm_mday, cur_tm.tm_hour, cur_tm.tm_min,
116 snprintf(params, sizeof(params), "-f %s", new_log);
117 ret = ss_launch_evenif_exist(MEMPS_EXEC_PATH, params);
122 snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", ret);
123 fp = fopen(buf, "w");
125 fprintf(fp, "%d", (-17));
131 static int lowmem_get_victim_pid()
136 if (device_get_property(DEVICE_TYPE_MEMORY, PROP_MEMORY_VICTIM_TASK, &pid) < 0) {
137 PRT_TRACE_ERR("Get victim task failed");
144 int lowmem_def_predefine_action(int argc, char **argv)
146 int pid, ret, oom_adj;
147 char appname[PATH_MAX];
152 if (!strcmp(argv[0], OOM_MEM_ACT)) {
153 pid = lowmem_get_victim_pid();
154 if (pid > 0 && pid != sysman_get_pid(LOWMEM_EXEC_PATH) && pid != sysman_get_pid(MEMPS_EXEC_PATH)) {
155 if ((sysman_get_cmdline_name(pid, appname, PATH_MAX)) ==
158 ("we will kill, lowmem lv2 = %d (%s)\n",
161 make_memps_log(MEMPS_LOG_FILE, pid, appname);
163 if(get_app_oomadj(pid, &oom_adj) < 0) {
164 PRT_TRACE_ERR("Failed to get oom_adj");
166 PRT_TRACE("%d will be killed with %d oom_adj value", pid, oom_adj);
170 if (oom_adj != OOMADJ_FOREGRD_LOCKED && oom_adj != OOMADJ_FOREGRD_UNLOCKED) {
177 bundle_add(b, "_APP_NAME_", appname);
178 ret = syspopup_launch("lowmem-syspopup", b);
181 PRT_TRACE_EM("popup lauch failed\n");
185 if (set_app_oomadj(ret, OOMADJ_SU) < 0) {
186 PRT_TRACE_ERR("Failed to set oom_adj");
194 int usbcon_def_predefine_action(int argc, char **argv)
199 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
201 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_USB_ONLINE, &val) == 0) {
203 vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS,
204 VCONFKEY_SYSMAN_USB_DISCONNECTED);
205 pm_unlock_state(LCD_OFF, STAY_CUR_STATE);
209 vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS,
210 VCONFKEY_SYSMAN_USB_AVAILABLE);
211 pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
212 pid = ss_launch_if_noexist(USBCON_EXEC_PATH, NULL);
214 PRT_TRACE_ERR("usb predefine action failed\n");
219 PRT_TRACE_ERR("failed to get usb status\n");
223 int earjackcon_def_predefine_action(int argc, char **argv)
227 PRT_TRACE_EM("earjack_normal predefine action\n");
228 if (device_get_property(DEVICE_TYPE_EXTCON, PROP_EXTCON_EARJACK_ONLINE, &val) == 0) {
229 return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, val);
235 int lowbat_popup(void *data)
237 int ret = -1, state = 0;
238 ret = vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &state);
239 if (state == 1 || ret != 0) {
242 if(lowbat_popup_option == LOWBAT_OPT_WARNING) {
243 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
244 } else if(lowbat_popup_option == LOWBAT_OPT_POWEROFF) {
245 bundle_add(b, "_SYSPOPUP_CONTENT_", "poweroff");
246 } else if(lowbat_popup_option == LOWBAT_OPT_CHARGEERR) {
247 bundle_add(b, "_SYSPOPUP_CONTENT_", "chargeerr");
249 bundle_add(b, "_SYSPOPUP_CONTENT_", "check");
252 ret = syspopup_launch("lowbat-syspopup", b);
254 PRT_TRACE_EM("popup lauch failed\n");
258 lowbat_popup_id = NULL;
259 lowbat_popup_option = 0;
262 PRT_TRACE_EM("boot-animation running yet");
269 int lowbat_def_predefine_action(int argc, char **argv)
278 if(lowbat_popup_id != NULL) {
279 ecore_timer_del(lowbat_popup_id);
280 lowbat_popup_id = NULL;
285 if(!strcmp(argv[0],WARNING_LOW_BAT_ACT) || !strcmp(argv[0],CRITICAL_LOW_BAT_ACT)) {
286 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
287 lowbat_popup_option = LOWBAT_OPT_WARNING;
288 } else if(!strcmp(argv[0],POWER_OFF_BAT_ACT)) {
289 bundle_add(b, "_SYSPOPUP_CONTENT_", "poweroff");
290 lowbat_popup_option = LOWBAT_OPT_POWEROFF;
291 } else if(!strcmp(argv[0],CHARGE_ERROR_ACT)) {
292 bundle_add(b, "_SYSPOPUP_CONTENT_", "chargeerr");
293 lowbat_popup_option = LOWBAT_OPT_CHARGEERR;
295 bundle_add(b, "_SYSPOPUP_CONTENT_", "check");
296 lowbat_popup_option = LOWBAT_OPT_CHECK;
299 ret = vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &state);
300 if (state == 1 || ret != 0) {
301 ret = syspopup_launch("lowbat-syspopup", b);
303 PRT_TRACE_EM("popup lauch failed\n");
305 lowbat_popup_option = 0;
309 PRT_TRACE_EM("boot-animation running yet");
310 lowbat_popup_id = ecore_timer_add(1, lowbat_popup, NULL);
316 Eina_Bool powerdown_ap_by_force(void *data)
319 int poweroff_duration = POWEROFF_DURATION;
322 if(tapi_handle != NULL)
324 tel_deinit(tapi_handle);
327 /* Getting poweroff duration */
328 buf = getenv("PWROFF_DUR");
329 if (buf != NULL && strlen(buf) < 1024)
330 poweroff_duration = atoi(buf);
331 if (poweroff_duration < 0 || poweroff_duration > 60)
332 poweroff_duration = POWEROFF_DURATION;
334 gettimeofday(&now, NULL);
335 /* Waiting until power off duration and displaying animation */
336 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
338 gettimeofday(&now, NULL);
341 PRT_TRACE("Power off by force\n");
342 /* give a chance to be terminated for each process */
346 reboot(RB_POWER_OFF);
350 static void powerdown_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
353 int poweroff_duration = POWEROFF_DURATION;
356 if (poweroff_timer_id) {
357 ecore_timer_del(poweroff_timer_id);
358 poweroff_timer_id = NULL;
361 tel_deregister_noti_event(tapi_handle,TAPI_NOTI_MODEM_POWER);
362 tel_deinit(tapi_handle);
365 PRT_TRACE("Power off \n");
367 /* Getting poweroff duration */
368 buf = getenv("PWROFF_DUR");
369 if (buf != NULL && strlen(buf) < 1024)
370 poweroff_duration = atoi(buf);
371 if (poweroff_duration < 0 || poweroff_duration > 60)
372 poweroff_duration = POWEROFF_DURATION;
374 gettimeofday(&now, NULL);
375 /* Waiting until power off duration and displaying animation */
376 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
378 gettimeofday(&now, NULL);
381 /* give a chance to be terminated for each process */
385 reboot(RB_POWER_OFF);
387 static void powerdown_res_cb(TapiHandle *handle, int result, void *data, void *user_data)
389 PRT_TRACE("poweroff command request : %d",result);
391 int poweroff_def_predefine_action(int argc, char **argv)
395 heynoti_publish(POWEROFF_NOTI_NAME);
396 vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void*)poweroff_control_cb);
398 pm_change_state(LCD_NORMAL);
399 system("/etc/rc.d/rc.shutdown &");
402 gettimeofday(&tv_start_poweroff, NULL);
404 ret = tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER, powerdown_ap, NULL);
406 if (ret != TAPI_API_SUCCESS) {
408 ("tel_register_event is not subscribed. error %d\n", ret);
409 powerdown_ap_by_force(NULL);
413 ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF, powerdown_res_cb, NULL);
414 if (ret != TAPI_API_SUCCESS) {
415 PRT_TRACE_ERR("tel_process_power_command() error %d\n", ret);
416 powerdown_ap_by_force(NULL);
419 poweroff_timer_id = ecore_timer_add(15, powerdown_ap_by_force, NULL);
421 powerdown_ap_by_force(NULL);
426 static void enter_flight_mode_cb(TapiHandle *handle, int result, void *data, void *user_data)
428 int bCurFlightMode = 0;
429 if (result != TAPI_POWER_FLIGHT_MODE_ENTER) {
430 PRT_TRACE_ERR("flight mode enter failed %d",result);
432 PRT_TRACE("enter flight mode result : %d",result);
433 if (vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE,&bCurFlightMode) == 0) {
434 PRT_TRACE("Flight Mode is %d", bCurFlightMode);
436 PRT_TRACE_ERR("failed to get vconf key");
441 static void leave_flight_mode_cb(TapiHandle *handle, int result, void *data, void *user_data)
443 int bCurFlightMode = 0;
444 if (result != TAPI_POWER_FLIGHT_MODE_LEAVE) {
445 PRT_TRACE_ERR("flight mode leave failed %d",result);
447 PRT_TRACE("leave flight mode result : %d",result);
448 if (vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE,&bCurFlightMode) == 0) {
449 PRT_TRACE("Flight Mode is %d", bCurFlightMode);
451 PRT_TRACE_ERR("failed to get vconf key");
456 int entersleep_def_predefine_action(int argc, char **argv)
460 pm_change_state(LCD_NORMAL);
463 ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER, enter_flight_mode_cb, NULL);
464 PRT_TRACE_ERR("request for changing into flight mode : %d\n", ret);
466 system("/etc/rc.d/rc.entersleep");
467 pm_change_state(POWER_OFF);
472 int leavesleep_def_predefine_action(int argc, char **argv)
476 pm_change_state(LCD_NORMAL);
479 ret = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE, leave_flight_mode_cb, NULL);
480 PRT_TRACE_ERR("request for changing into flight mode : %d\n", ret);
485 static void restart_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data);
487 Eina_Bool restart_ap_ecore(void *data)
489 restart_ap(tapi_handle,NULL,(void *)-1,NULL);
493 static void restart_ap(TapiHandle *handle, const char *noti_id, void *data, void *user_data)
496 int poweroff_duration = POWEROFF_DURATION;
499 if (poweroff_timer_id) {
500 ecore_timer_del(poweroff_timer_id);
501 poweroff_timer_id = NULL;
505 if(tapi_handle != NULL)
507 tel_deregister_noti_event(tapi_handle,TAPI_NOTI_MODEM_POWER);
508 tel_deinit(tapi_handle);
512 PRT_INFO("Restart\n");
515 buf = getenv("PWROFF_DUR");
516 if (buf != NULL && strlen(buf) < 1024)
517 poweroff_duration = atoi(buf);
518 if (poweroff_duration < 0 || poweroff_duration > 60)
519 poweroff_duration = POWEROFF_DURATION;
520 gettimeofday(&now, NULL);
521 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
523 gettimeofday(&now, NULL);
529 static void restart_ap_by_force(void *data)
532 int poweroff_duration = POWEROFF_DURATION;
535 if (poweroff_timer_id) {
536 ecore_timer_del(poweroff_timer_id);
537 poweroff_timer_id = NULL;
541 if(tapi_handle != NULL)
543 tel_deinit(tapi_handle);
547 PRT_INFO("Restart\n");
550 buf = getenv("PWROFF_DUR");
551 if (buf != NULL && strlen(buf) < 1024)
552 poweroff_duration = atoi(buf);
553 if (poweroff_duration < 0 || poweroff_duration > 60)
554 poweroff_duration = POWEROFF_DURATION;
555 gettimeofday(&now, NULL);
556 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
558 gettimeofday(&now, NULL);
564 int restart_def_predefine_action(int argc, char **argv)
568 pm_change_state(LCD_NORMAL);
569 system("/etc/rc.d/rc.shutdown &");
572 gettimeofday(&tv_start_poweroff, NULL);
575 tel_register_noti_event(tapi_handle, TAPI_NOTI_MODEM_POWER, restart_ap, NULL);
576 if (ret != TAPI_API_SUCCESS) {
578 ("tel_register_event is not subscribed. error %d\n", ret);
579 restart_ap_by_force((void *)-1);
584 ret = tel_process_power_command(tapi_handle, TAPI_PHONE_POWER_OFF, powerdown_res_cb, NULL);
585 if (ret != TAPI_API_SUCCESS) {
586 PRT_TRACE_ERR("tel_process_power_command() error %d\n", ret);
587 restart_ap_by_force((void *)-1);
591 poweroff_timer_id = ecore_timer_add(15, restart_ap_ecore, NULL);
595 int launching_predefine_action(int argc, char **argv)
602 /* current just launching poweroff-popup */
603 ret = syspopup_launch("poweroff-syspopup", NULL);
605 PRT_TRACE_ERR("poweroff popup predefine action failed");
611 int flight_mode_def_predefine_action(int argc, char **argv)
614 int err = TAPI_API_SUCCESS;
615 if (argc != 1 || argv[0] == NULL) {
616 PRT_TRACE_ERR("FlightMode Set predefine action failed");
619 bCurFlightMode = atoi(argv[0]);
620 if (bCurFlightMode == 1) {
621 err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_LEAVE, leave_flight_mode_cb, NULL);
622 } else if (bCurFlightMode == 0) {
623 err = tel_set_flight_mode(tapi_handle, TAPI_POWER_FLIGHT_MODE_ENTER, enter_flight_mode_cb, NULL);
625 if (err != TAPI_API_SUCCESS)
626 PRT_TRACE_ERR("FlightMode tel api action failed %d",err);
631 static void ss_action_entry_load_from_sodir()
634 struct dirent *dentry;
639 dp = opendir(PREDEFINE_SO_DIR);
641 ERR("fail open %s", PREDEFINE_SO_DIR);
645 msg = malloc(sizeof(struct sysnoti));
647 ERR("Malloc failed");
654 while ((dentry = readdir(dp)) != NULL) {
655 if ((ext = strstr(dentry->d_name, ".so")) == NULL)
658 snprintf(tmp, sizeof(tmp), "%s/%s", PREDEFINE_SO_DIR,
662 msg->type = &(dentry->d_name[3]);
663 ss_action_entry_add(msg);
669 static void __tel_init_cb(keynode_t *key_nodes,void *data)
672 bTelReady = vconf_keynode_get_bool(key_nodes);
673 if (bTelReady == 1) {
674 vconf_ignore_key_changed(VCONFKEY_TELEPHONY_READY, (void*)__tel_init_cb);
675 tapi_handle = tel_init(NULL);
676 if (tapi_handle == NULL) {
677 PRT_TRACE_ERR("tapi init error");
680 PRT_TRACE_ERR("tapi is not ready yet");
683 static void poweroff_control_cb(keynode_t *in_key, struct ss_main_data *ad)
686 if (vconf_get_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, &val) != 0)
689 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
690 ss_action_entry_call_internal(PREDEF_POWEROFF, 0);
692 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
693 ss_action_entry_call_internal(PREDEF_PWROFF_POPUP, 0);
698 void ss_predefine_internal_init(void)
701 /* telephony initialize */
704 if (vconf_get_bool(VCONFKEY_TELEPHONY_READY,&bTelReady) == 0) {
705 if (bTelReady == 1) {
706 tapi_handle = tel_init(NULL);
707 if (tapi_handle == NULL) {
708 PRT_TRACE_ERR("tapi init error");
711 vconf_notify_key_changed(VCONFKEY_TELEPHONY_READY, (void *)__tel_init_cb, NULL);
714 PRT_TRACE_ERR("failed to get tapi vconf key");
717 ss_action_entry_add_internal(PREDEF_CALL, call_predefine_action, NULL,
720 ss_action_entry_add_internal(PREDEF_LOWMEM, lowmem_def_predefine_action,
722 ss_action_entry_add_internal(PREDEF_LOWBAT, lowbat_def_predefine_action,
724 ss_action_entry_add_internal(PREDEF_USBCON, usbcon_def_predefine_action,
726 ss_action_entry_add_internal(PREDEF_EARJACKCON,
727 earjackcon_def_predefine_action, NULL,
729 ss_action_entry_add_internal(PREDEF_POWEROFF,
730 poweroff_def_predefine_action, NULL, NULL);
731 ss_action_entry_add_internal(PREDEF_PWROFF_POPUP,
732 launching_predefine_action, NULL, NULL);
733 ss_action_entry_add_internal(PREDEF_REBOOT,
734 restart_def_predefine_action, NULL, NULL);
735 ss_action_entry_add_internal(PREDEF_FLIGHT_MODE,
736 flight_mode_def_predefine_action, NULL, NULL);
737 ss_action_entry_add_internal(PREDEF_HAPTIC, haptic_def_predefine_action,
740 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, (void *)poweroff_control_cb, NULL) < 0) {
741 PRT_TRACE_ERR("Vconf notify key chaneged failed: KEY(%s)", VCONFKEY_SYSMAN_POWER_OFF_STATUS);
743 ss_action_entry_load_from_sodir();
745 /* check and set earjack init status */
746 earjackcon_def_predefine_action(0, NULL);