2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 <ITapiPower.h>
28 #include <TapiEvent.h>
29 #include <TapiCommon.h>
30 #include <syspopup_caller.h>
31 #include <sys/reboot.h>
35 #include "ss_launch.h"
37 #include "ss_device_handler.h"
38 #include "ss_device_plugin.h"
39 #include "ss_predefine.h"
40 #include "ss_procmgr.h"
41 #include "include/ss_data.h"
43 #define PREDEFINE_SO_DIR PREFIX"/lib/ss_predefine/"
45 #define CALL_EXEC_PATH PREFIX"/bin/call"
46 #define LOWMEM_EXEC_PATH PREFIX"/bin/lowmem-popup"
47 #define LOWBAT_EXEC_PATH PREFIX"/bin/lowbatt-popup"
48 #define USBCON_EXEC_PATH PREFIX"/bin/usb_setting"
49 #define TVOUT_EXEC_PATH PREFIX"/bin/tvout-selector"
50 #define PWROFF_EXEC_PATH PREFIX"/bin/poweroff-popup"
51 #define MEMPS_EXEC_PATH PREFIX"/bin/memps"
53 /* wait for 5 sec as victim process be dead */
54 #define WAITING_INTERVAL 5
56 #define TVOUT_X_BIN "/usr/bin/xberc"
57 #define TVOUT_FLAG 0x00000001
58 #define MEMPS_LOG_FILE "/var/log/memps"
61 #define POWEROFF_DURATION 2
62 #define POWEROFF_ANIMATION_PATH "/usr/bin/boot-animation"
63 #define POWEROFF_NOTI_NAME "power_off_start"
65 #define VCONFKEY_TESTMODE_LOW_BATT_POPUP "db/testmode/low_batt_popup"
67 #define LOWBAT_OPT_WARNING 1
68 #define LOWBAT_OPT_POWEROFF 2
69 #define LOWBAT_OPT_CHARGEERR 3
70 #define LOWBAT_OPT_CHECK 4
72 static Ecore_Timer *lowbat_popup_id = NULL;
73 static int lowbat_popup_option = 0;
75 static struct timeval tv_start_poweroff;
76 static void powerdown_ap(TelTapiEvent_t *event, void *data);
78 static int ss_flags = 0;
80 static unsigned int power_subscription_id = 0;
82 static void make_memps_log(char *file, pid_t pid, char *victim_name)
87 char new_log[NAME_MAX];
88 static pid_t old_pid = 0;
96 cur_tm = (struct tm *)malloc(sizeof(struct tm));
98 PRT_TRACE_ERR("Fail to memory allocation");
102 if (localtime_r(&now, cur_tm) == NULL) {
103 PRT_TRACE_ERR("Fail to get localtime");
107 PRT_TRACE("%s_%s_%d_%.4d%.2d%.2d_%.2d%.2d%.2d.log", file, victim_name,
108 pid, (1900 + cur_tm->tm_year), 1 + cur_tm->tm_mon,
109 cur_tm->tm_mday, cur_tm->tm_hour, cur_tm->tm_min,
111 snprintf(new_log, sizeof(new_log),
112 "%s_%s_%d_%.4d%.2d%.2d_%.2d%.2d%.2d.log", file, victim_name,
113 pid, (1900 + cur_tm->tm_year), 1 + cur_tm->tm_mon,
114 cur_tm->tm_mday, cur_tm->tm_hour, cur_tm->tm_min,
117 snprintf(params, sizeof(params), "-f %s", new_log);
118 ret = ss_launch_evenif_exist(MEMPS_EXEC_PATH, params);
123 snprintf(buf, sizeof(buf), "/proc/%d/oom_adj", ret);
124 fp = fopen(buf, "w");
126 fprintf(fp, "%d", (-17));
133 static int lowmem_get_victim_pid()
138 if (0 > plugin_intf->OEM_sys_get_memnotify_victim_task(&pid)) {
139 PRT_TRACE_ERR("Get victim task failed");
146 int lowmem_def_predefine_action(int argc, char **argv)
148 int pid, ret, oom_adj;
149 char appname[PATH_MAX];
154 if (!strcmp(argv[0], OOM_MEM_ACT)) {
155 pid = lowmem_get_victim_pid();
156 if (pid > 0 && pid != sysman_get_pid(LOWMEM_EXEC_PATH) && pid != sysman_get_pid(MEMPS_EXEC_PATH)) {
157 if ((sysman_get_cmdline_name(pid, appname, PATH_MAX)) ==
160 ("we will kill, lowmem lv2 = %d (%s)\n",
163 make_memps_log(MEMPS_LOG_FILE, pid, appname);
165 if(get_app_oomadj(pid, &oom_adj) < 0) {
166 PRT_TRACE_ERR("Failed to get oom_adj");
168 PRT_TRACE("%d will be killed with %d oom_adj value", pid, oom_adj);
172 if (oom_adj >= OOMADJ_BACKGRD_UNLOCKED) {
179 bundle_add(b, "_APP_NAME_", appname);
180 ret = syspopup_launch("lowmem-syspopup", b);
183 PRT_TRACE_EM("popup lauch failed\n");
187 if (set_app_oomadj(ret, OOMADJ_SU) < 0) {
188 PRT_TRACE_ERR("Failed to set oom_adj");
193 PRT_TRACE_EM("making memps log for low memory\n");
194 make_memps_log(MEMPS_LOG_FILE, 1, "LOWMEM_WARNING");
200 int usbcon_def_predefine_action(int argc, char **argv)
205 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
207 if (plugin_intf->OEM_sys_get_jack_usb_online(&val) == 0) {
209 vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS,
210 VCONFKEY_SYSMAN_USB_DISCONNECTED);
211 pm_unlock_state(LCD_OFF, STAY_CUR_STATE);
213 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
214 if(bat_state < VCONFKEY_SYSMAN_BAT_NORMAL) {
217 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
219 ret = syspopup_launch("lowbat-syspopup", b);
221 PRT_TRACE_EM("popup lauch failed\n");
228 vconf_set_int(VCONFKEY_SYSMAN_USB_STATUS,
229 VCONFKEY_SYSMAN_USB_AVAILABLE);
230 pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
231 pid = ss_launch_if_noexist(USBCON_EXEC_PATH, NULL);
233 PRT_TRACE_ERR("usb predefine action failed\n");
238 PRT_TRACE_ERR("failed to get usb status\n");
242 int earjackcon_def_predefine_action(int argc, char **argv)
246 PRT_TRACE_EM("earjack_normal predefine action\n");
247 if (plugin_intf->OEM_sys_get_jack_earjack_online(&val) == 0) {
248 return vconf_set_int(VCONFKEY_SYSMAN_EARJACK, val);
254 int lowbat_popup(void *data)
256 int ret = -1, state = 0;
257 ret = vconf_get_int("memory/boot-animation/finished", &state);
258 if (state == 1 || ret != 0) {
261 if(lowbat_popup_option == LOWBAT_OPT_WARNING) {
262 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
263 } else if(lowbat_popup_option == LOWBAT_OPT_POWEROFF) {
264 bundle_add(b, "_SYSPOPUP_CONTENT_", "poweroff");
265 } else if(lowbat_popup_option == LOWBAT_OPT_CHARGEERR) {
266 bundle_add(b, "_SYSPOPUP_CONTENT_", "chargeerr");
268 bundle_add(b, "_SYSPOPUP_CONTENT_", "check");
271 ret = syspopup_launch("lowbat-syspopup", b);
273 PRT_TRACE_EM("popup lauch failed\n");
277 lowbat_popup_id = NULL;
278 lowbat_popup_option = 0;
281 PRT_TRACE_EM("boot-animation running yet");
288 int lowbat_def_predefine_action(int argc, char **argv)
297 if(lowbat_popup_id != NULL) {
298 ecore_timer_del(lowbat_popup_id);
299 lowbat_popup_id = NULL;
304 if(!strcmp(argv[0],WARNING_LOW_BAT_ACT) || !strcmp(argv[0],CRITICAL_LOW_BAT_ACT)) {
305 bundle_add(b, "_SYSPOPUP_CONTENT_", "warning");
306 lowbat_popup_option = LOWBAT_OPT_WARNING;
307 } else if(!strcmp(argv[0],POWER_OFF_BAT_ACT)) {
308 bundle_add(b, "_SYSPOPUP_CONTENT_", "poweroff");
309 lowbat_popup_option = LOWBAT_OPT_POWEROFF;
310 } else if(!strcmp(argv[0],CHARGE_ERROR_ACT)) {
311 bundle_add(b, "_SYSPOPUP_CONTENT_", "chargeerr");
312 lowbat_popup_option = LOWBAT_OPT_CHARGEERR;
314 bundle_add(b, "_SYSPOPUP_CONTENT_", "check");
315 lowbat_popup_option = LOWBAT_OPT_CHECK;
318 ret = vconf_get_int("memory/boot-animation/finished", &state);
319 if (state == 1 || ret != 0) {
320 ret = syspopup_launch("lowbat-syspopup", b);
322 PRT_TRACE_EM("popup lauch failed\n");
324 lowbat_popup_option = 0;
328 PRT_TRACE_EM("boot-animation running yet");
329 lowbat_popup_id = ecore_timer_add(1, lowbat_popup, NULL);
335 Eina_Bool powerdown_ap_by_force(void *data)
338 int poweroff_duration = POWEROFF_DURATION;
341 /* Getting poweroff duration */
342 buf = getenv("PWROFF_DUR");
343 if (buf != NULL && strlen(buf) < 1024)
344 poweroff_duration = atoi(buf);
345 if (poweroff_duration < 0 || poweroff_duration > 60)
346 poweroff_duration = POWEROFF_DURATION;
348 gettimeofday(&now, NULL);
349 /* Waiting until power off duration and displaying animation */
350 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
352 gettimeofday(&now, NULL);
355 PRT_TRACE("Power off by force\n");
357 /* give a chance to be terminated for each process */
360 reboot(RB_POWER_OFF);
364 static void powerdown_ap(TelTapiEvent_t *event, void *data)
367 int poweroff_duration = POWEROFF_DURATION;
370 if (power_subscription_id) {
371 tel_deregister_event(power_subscription_id);
372 power_subscription_id = 0;
374 PRT_TRACE("Power off \n");
376 /* Getting poweroff duration */
377 buf = getenv("PWROFF_DUR");
378 if (buf != NULL && strlen(buf) < 1024)
379 poweroff_duration = atoi(buf);
380 if (poweroff_duration < 0 || poweroff_duration > 60)
381 poweroff_duration = POWEROFF_DURATION;
383 gettimeofday(&now, NULL);
384 /* Waiting until power off duration and displaying animation */
385 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
387 gettimeofday(&now, NULL);
391 /* give a chance to be terminated for each process */
394 reboot(RB_POWER_OFF);
397 int poweroff_def_predefine_action(int argc, char **argv)
401 heynoti_publish(POWEROFF_NOTI_NAME);
403 pm_change_state(LCD_NORMAL);
404 system("/etc/rc.d/rc.shutdown &");
407 gettimeofday(&tv_start_poweroff, NULL);
409 tel_register_event(TAPI_EVENT_POWER_PHONE_OFF,
410 &power_subscription_id,
411 (TelAppCallback) & powerdown_ap, NULL);
412 if (ret != TAPI_API_SUCCESS) {
414 ("tel_register_event is not subscribed. error %d\n", ret);
415 powerdown_ap_by_force(NULL);
419 ret = tel_process_power_command(TAPI_PHONE_POWER_OFF);
420 if (ret != TAPI_API_SUCCESS) {
421 PRT_TRACE_ERR("tel_process_power_command() error %d\n", ret);
422 powerdown_ap_by_force(NULL);
429 static void restart_ap(TelTapiEvent_t *event, void *data);
431 Eina_Bool restart_ap_ecore(void *data)
433 restart_ap(NULL, (void *)-1);
437 static void restart_ap(TelTapiEvent_t *event, void *data)
440 int poweroff_duration = POWEROFF_DURATION;
443 if (power_subscription_id) {
444 tel_deregister_event(power_subscription_id);
445 power_subscription_id = 0;
448 PRT_INFO("Restart\n");
451 buf = getenv("PWROFF_DUR");
452 if (buf != NULL && strlen(buf) < 1024)
453 poweroff_duration = atoi(buf);
454 if (poweroff_duration < 0 || poweroff_duration > 60)
455 poweroff_duration = POWEROFF_DURATION;
456 gettimeofday(&now, NULL);
457 while (now.tv_sec - tv_start_poweroff.tv_sec < poweroff_duration) {
459 gettimeofday(&now, NULL);
465 int restart_def_predefine_action(int argc, char **argv)
469 pm_change_state(LCD_NORMAL);
470 system("/etc/rc.d/rc.shutdown &");
473 gettimeofday(&tv_start_poweroff, NULL);
476 tel_register_event(TAPI_EVENT_POWER_PHONE_OFF,
477 &power_subscription_id,
478 (TelAppCallback) & restart_ap, NULL);
479 if (ret != TAPI_API_SUCCESS) {
481 ("tel_register_event is not subscribed. error %d\n", ret);
482 restart_ap(NULL, (void *)-1);
486 ret = tel_process_power_command(TAPI_PHONE_POWER_OFF);
487 if (ret != TAPI_API_SUCCESS) {
488 PRT_TRACE_ERR("tel_process_power_command() error %d\n", ret);
489 restart_ap(NULL, (void *)-1);
496 int launching_predefine_action(int argc, char **argv)
503 /* current just launching poweroff-popup */
504 ret = syspopup_launch("poweroff-syspopup", NULL);
506 PRT_TRACE_ERR("poweroff popup predefine action failed");
512 static void ss_action_entry_load_from_sodir()
515 struct dirent *dentry;
520 dp = opendir(PREDEFINE_SO_DIR);
522 ERR("fail open %s", PREDEFINE_SO_DIR);
526 msg = malloc(sizeof(struct sysnoti));
528 ERR("Malloc failed");
535 while ((dentry = readdir(dp)) != NULL) {
536 if ((ext = strstr(dentry->d_name, ".so")) == NULL)
539 snprintf(tmp, sizeof(tmp), "%s/%s", PREDEFINE_SO_DIR,
543 msg->type = &(dentry->d_name[3]);
544 ss_action_entry_add(msg);
551 void ss_predefine_internal_init(void)
553 ss_action_entry_add_internal(PREDEF_LOWMEM, lowmem_def_predefine_action,
555 ss_action_entry_add_internal(PREDEF_LOWBAT, lowbat_def_predefine_action,
557 ss_action_entry_add_internal(PREDEF_USBCON, usbcon_def_predefine_action,
559 ss_action_entry_add_internal(PREDEF_EARJACKCON,
560 earjackcon_def_predefine_action, NULL,
562 ss_action_entry_add_internal(PREDEF_POWEROFF,
563 poweroff_def_predefine_action, NULL, NULL);
564 ss_action_entry_add_internal(PREDEF_PWROFF_POPUP,
565 launching_predefine_action, NULL, NULL);
566 ss_action_entry_add_internal(PREDEF_REBOOT,
567 restart_def_predefine_action, NULL, NULL);
569 ss_action_entry_load_from_sodir();
571 /* check and set earjack init status */
572 earjackcon_def_predefine_action(0, NULL);