From e5bf0d66eb492d2f0d0f03f40a46811d8d2d8fc1 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 12 Nov 2020 15:28:54 +0000 Subject: [PATCH] powersave - document som things and add screen blank override for pwrsv add a screen power save mode than overrides regular powersave (bug is subordinat to forced power save). --- src/bin/e_powersave.c | 66 +++++++++++++++++++++++----- src/bin/e_powersave.h | 40 ++++++++++------- src/bin/e_screensaver.c | 7 ++- src/bin/e_sys.c | 33 +++++++------- src/modules/cpufreq/e_mod_main.c | 4 +- src/modules/temperature/e_mod_main.c | 5 ++- 6 files changed, 105 insertions(+), 50 deletions(-) diff --git a/src/bin/e_powersave.c b/src/bin/e_powersave.c index 0844e909f..d7fcdb83f 100644 --- a/src/bin/e_powersave.c +++ b/src/bin/e_powersave.c @@ -12,6 +12,8 @@ struct _E_Powersave_Sleeper { Ecore_Pipe *pipe; int fd; + Eina_Bool go E_BITFIELD; + Eina_Bool free_requested E_BITFIELD; }; /* local subsystem functions */ @@ -30,11 +32,13 @@ static Eina_List *deferred_actions = NULL; static Ecore_Timer *deferred_timer = NULL; static E_Powersave_Mode powersave_mode = E_POWERSAVE_MODE_LOW; static E_Powersave_Mode powersave_mode_force = E_POWERSAVE_MODE_NONE; +static E_Powersave_Mode powersave_mode_screen = E_POWERSAVE_MODE_NONE; static double defer_time = 5.0; static Eina_Bool powersave_force = EINA_FALSE; static Eina_List *powersave_sleepers = NULL; static Eina_Bool powersave_deferred_suspend = EINA_FALSE; static Eina_Bool powersave_deferred_hibernate = EINA_FALSE; +static Eina_Bool powersave_screen = EINA_FALSE; /* externally accessible functions */ EINTERN int @@ -99,6 +103,7 @@ e_powersave_mode_set(E_Powersave_Mode mode) else if (mode > e_config->powersave.max) mode = e_config->powersave.max; if (powersave_mode == mode) return; + printf("PWSAVE %i/%i\n", (int)mode, (int)E_POWERSAVE_MODE_FREEZE); powersave_mode = mode; if (powersave_force) return; @@ -110,6 +115,7 @@ E_API E_Powersave_Mode e_powersave_mode_get(void) { if (powersave_force) return powersave_mode_force; + if (powersave_screen) return powersave_mode_screen; return powersave_mode; } @@ -117,6 +123,7 @@ E_API void e_powersave_mode_force(E_Powersave_Mode mode) { if (mode == powersave_mode_force) return; + printf("PWSAVE FORCE %i/%i\n", (int)mode, (int)E_POWERSAVE_MODE_FREEZE); powersave_force = EINA_TRUE; powersave_mode_force = mode; _e_powersave_event_change_send(powersave_mode_force); @@ -127,6 +134,7 @@ E_API void e_powersave_mode_unforce(void) { if (!powersave_force) return; + printf("PWSAVE UNFORCE\n"); powersave_force = EINA_FALSE; if (powersave_mode_force != powersave_mode) { @@ -136,6 +144,34 @@ e_powersave_mode_unforce(void) powersave_mode_force = E_POWERSAVE_MODE_NONE; } +E_API void +e_powersave_mode_screen_set(E_Powersave_Mode mode) +{ + if (mode == powersave_mode_screen) return; + printf("PWSAVE SCREEN SET %i/%i\n", (int)mode, (int)E_POWERSAVE_MODE_FREEZE); + powersave_screen = EINA_TRUE; + powersave_mode_screen = mode; + if (!powersave_force) + { + _e_powersave_event_change_send(powersave_mode_screen); + _e_powersave_mode_eval(); + } +} + +E_API void +e_powersave_mode_screen_unset(void) +{ + if (!powersave_screen) return; + printf("PWSAVE SCREEN UNSET\n"); + powersave_screen = EINA_FALSE; + if ((!powersave_force) && (powersave_mode_screen != powersave_mode)) + { + _e_powersave_event_change_send(powersave_screen); + _e_powersave_mode_eval(); + } + powersave_mode_screen = E_POWERSAVE_MODE_NONE; +} + E_API E_Powersave_Sleeper * e_powersave_sleeper_new(void) { @@ -159,12 +195,12 @@ e_powersave_sleeper_free(E_Powersave_Sleeper *sleeper) { if (!sleeper) return; ecore_pipe_del(sleeper->pipe); - powersave_sleepers = eina_list_remove(powersave_sleepers, sleeper); eina_freeq_ptr_add(eina_freeq_main_get(), sleeper, free, sizeof(*sleeper)); + powersave_sleepers = eina_list_remove(powersave_sleepers, sleeper); } E_API void -e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval) +e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval, Eina_Bool allow_save) { double timf; unsigned int tim; @@ -174,8 +210,20 @@ e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval) char buf[1] = { 1 }; if (!sleeper) return; - if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE) timf = 3600; - else timf = (double)poll_interval / 8.0; + if (allow_save) + { + if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE) + timf = 3600.0; + else if (e_powersave_mode_get() == E_POWERSAVE_MODE_EXTREME) + timf = (double)poll_interval / 2.0; + else if (e_powersave_mode_get() == E_POWERSAVE_MODE_HIGH) + timf = (double)poll_interval / 4.0; + else + timf = (double)poll_interval / 8.0; + } + else + timf = (double)poll_interval / 8.0; + FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&exfds); @@ -191,12 +239,11 @@ e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval) { if (read(sleeper->fd, buf, 1) < 0) fprintf(stderr, "%s: ERROR READING FROM FD\n", __func__); - return; + if (buf[0] == 1) // was woken up by mainloop to do another poll + return; } else if (ret == 0) - { - return; - } + return; } } @@ -331,8 +378,7 @@ _e_powersave_event_change_send(E_Powersave_Mode mode) { E_Event_Powersave_Update *ev; - printf("CHANGE PW SAVE MODE TO %i / %i\n", - (int)mode, E_POWERSAVE_MODE_EXTREME); + printf("PWSAVE TO %i/%i\n", (int)mode, (int)E_POWERSAVE_MODE_FREEZE); ev = E_NEW(E_Event_Powersave_Update, 1); ev->mode = mode; ecore_event_add(E_EVENT_POWERSAVE_UPDATE, ev, _e_powersave_event_update_free, NULL); diff --git a/src/bin/e_powersave.h b/src/bin/e_powersave.h index de52d1ee1..1d419b9fb 100644 --- a/src/bin/e_powersave.h +++ b/src/bin/e_powersave.h @@ -2,12 +2,12 @@ typedef enum _E_Powersave_Mode { - E_POWERSAVE_MODE_NONE, - E_POWERSAVE_MODE_LOW, - E_POWERSAVE_MODE_MEDIUM, - E_POWERSAVE_MODE_HIGH, - E_POWERSAVE_MODE_EXTREME, - E_POWERSAVE_MODE_FREEZE + E_POWERSAVE_MODE_NONE, // no powersaving + E_POWERSAVE_MODE_LOW, // normal power management - AC plugged in + E_POWERSAVE_MODE_MEDIUM, // lots of battery available but not on AC + E_POWERSAVE_MODE_HIGH, // have enough battery but good to save powwr + E_POWERSAVE_MODE_EXTREME, // low on battery save more + E_POWERSAVE_MODE_FREEZE // really try and do as little as possible } E_Powersave_Mode; typedef struct _E_Powersave_Deferred_Action E_Powersave_Deferred_Action; @@ -23,25 +23,38 @@ extern E_API int E_EVENT_POWERSAVE_CONFIG_UPDATE; struct _E_Event_Powersave_Update { - E_Powersave_Mode mode; + E_Powersave_Mode mode; }; EINTERN int e_powersave_init(void); EINTERN int e_powersave_shutdown(void); +// do this thing somw time later - how much later depends on power save mode +// this is done in the mainloop E_API E_Powersave_Deferred_Action *e_powersave_deferred_action_add(void (*func) (void *data), const void *data); E_API void e_powersave_deferred_action_del(E_Powersave_Deferred_Action *pa); E_API void e_powersave_mode_set(E_Powersave_Mode mode); E_API E_Powersave_Mode e_powersave_mode_get(void); +// force is used by e's system core to use "connected standby" where the system +// should be aslpee but not regular suspend - soits still alive but it needs +// to try and be as idle as possible E_API void e_powersave_mode_force(E_Powersave_Mode mode); E_API void e_powersave_mode_unforce(void); -E_API E_Powersave_Sleeper *e_powersave_sleeper_new(void); -E_API void e_powersave_sleeper_free(E_Powersave_Sleeper *sleeper); +// used by screen saving/blanking to set a specific power mode when screens +// are off/not visible +E_API void e_powersave_mode_screen_set(E_Powersave_Mode mode); +E_API void e_powersave_mode_screen_unset(void); + E_API void e_powersave_defer_suspend(void); E_API void e_powersave_defer_hibernate(void); E_API void e_powersave_defer_cancel(void); + +// sleepers are meant to be used in threads polling for things. create in +// mainloop then use and sleep in a thread, +E_API E_Powersave_Sleeper *e_powersave_sleeper_new(void); +E_API void e_powersave_sleeper_free(E_Powersave_Sleeper *sleeper); // the below function is INTENDED to be called from a thread -E_API void e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval); +E_API void e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval, Eina_Bool allow_save); /* FIXME: in the powersave system add things like pre-loading entire files * int memory for pre-caching to avoid disk spinup, when in an appropriate @@ -53,12 +66,5 @@ E_API void e_powersave_sleeper_sleep(E_Powersave_Sleeper /* FIXME: in powersave mode also reduce ecore timer precision, so timers * will be dispatched together and system will wakeup less. */ -/* FIXME: in powersave mode also add the ability to change screenblanker - * preferences when in powersave mode as well as check in the screensaver - * has kicked in */ - -/* FIXME: in powersave mode also if screenblanker has kicked in be able to - * auto-suspend etc. etc. */ - #endif #endif diff --git a/src/bin/e_screensaver.c b/src/bin/e_screensaver.c index f12f2eed0..c28439c50 100644 --- a/src/bin/e_screensaver.c +++ b/src/bin/e_screensaver.c @@ -237,6 +237,7 @@ _e_screensaver_handler_desk_show_cb(void *data EINA_UNUSED, int type EINA_UNUSED static Eina_Bool _e_screensaver_idle_timer_cb(void *d EINA_UNUSED) { + e_powersave_mode_screen_set(E_POWERSAVE_MODE_FREEZE); ecore_event_add(E_EVENT_SCREENSAVER_ON, NULL, NULL, NULL); screensaver_idle_timer = NULL; return EINA_FALSE; @@ -452,7 +453,10 @@ e_screensaver_eval(Eina_Bool saver_on) if (!_screensaver_ignore) { if (!e_screensaver_on_get()) - ecore_event_add(E_EVENT_SCREENSAVER_ON, NULL, NULL, NULL); + { + e_powersave_mode_screen_set(E_POWERSAVE_MODE_FREEZE); + ecore_event_add(E_EVENT_SCREENSAVER_ON, NULL, NULL, NULL); + } } } return; @@ -485,6 +489,7 @@ e_screensaver_eval(Eina_Bool saver_on) { if (e_screensaver_on_get()) { + e_powersave_mode_screen_unset(); e_screensaver_update(); ecore_event_add(E_EVENT_SCREENSAVER_OFF, NULL, NULL, NULL); } diff --git a/src/bin/e_sys.c b/src/bin/e_sys.c index ec894fec9..27ef39733 100644 --- a/src/bin/e_sys.c +++ b/src/bin/e_sys.c @@ -988,23 +988,20 @@ _e_sys_cb_acpi_event(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { E_Event_Acpi *ev = event; - if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE) + if (((ev->type == E_ACPI_TYPE_LID) && + (ev->status == E_ACPI_LID_OPEN)) || + (ev->type == E_ACPI_TYPE_POWER) || + (ev->type == E_ACPI_TYPE_SLEEP)) { - if (((ev->type == E_ACPI_TYPE_LID) && - (ev->status == E_ACPI_LID_OPEN)) || - (ev->type == E_ACPI_TYPE_POWER) || - (ev->type == E_ACPI_TYPE_SLEEP)) + if (_e_sys_acpi_handler) { - if (_e_sys_acpi_handler) - { - ecore_event_handler_del(_e_sys_acpi_handler); - _e_sys_acpi_handler = NULL; - } - e_powersave_mode_unforce(); - ecore_timer_add(1.0, _e_sys_resume_delay, NULL); - // XXX: need some way of, at the system level, restoring - // system and devices back to running normally + ecore_event_handler_del(_e_sys_acpi_handler); + _e_sys_acpi_handler = NULL; } + e_powersave_mode_unforce(); + ecore_timer_add(0.5, _e_sys_resume_delay, NULL); + // XXX: need some way of, at the system level, restoring + // system and devices back to running normally } return ECORE_CALLBACK_PASS_ON; } @@ -1026,11 +1023,11 @@ _e_sys_suspend_delay(void *data EINA_UNUSED) else { if (_e_sys_acpi_handler) - ecore_event_handler_del(_e_sys_acpi_handler); + ecore_event_handler_del(_e_sys_acpi_handler); _e_sys_acpi_handler = - ecore_event_handler_add(E_EVENT_ACPI, - _e_sys_cb_acpi_event, - NULL); + ecore_event_handler_add(E_EVENT_ACPI, + _e_sys_cb_acpi_event, + NULL); e_powersave_mode_force(E_POWERSAVE_MODE_FREEZE); // XXX: need some system way of forcing the system into a very low // power level with as many devices suspended as possible. below is diff --git a/src/modules/cpufreq/e_mod_main.c b/src/modules/cpufreq/e_mod_main.c index ea92f995a..4d60c60f2 100644 --- a/src/modules/cpufreq/e_mod_main.c +++ b/src/modules/cpufreq/e_mod_main.c @@ -1323,7 +1323,7 @@ static void _cpufreq_cb_frequency_check_done(void *data, Ecore_Thread *th EINA_UNUSED) { Thread_Config *thc = data; - e_powersave_sleeper_free(thc->sleeper); + if (thc->sleeper) e_powersave_sleeper_free(thc->sleeper); free(thc); } @@ -1342,7 +1342,7 @@ _cpufreq_cb_frequency_check_main(void *data, Ecore_Thread *th) else _cpufreq_status_free(status); if (ecore_thread_check(th)) break; - e_powersave_sleeper_sleep(thc->sleeper, thc->interval); + e_powersave_sleeper_sleep(thc->sleeper, thc->interval, EINA_TRUE); } } diff --git a/src/modules/temperature/e_mod_main.c b/src/modules/temperature/e_mod_main.c index 8ecd02c9a..36443f7b5 100644 --- a/src/modules/temperature/e_mod_main.c +++ b/src/modules/temperature/e_mod_main.c @@ -51,7 +51,7 @@ static void _temperature_thread_free(Tempthread *tth) { eina_stringshare_del(tth->sensor_name); - e_powersave_sleeper_free(tth->sleeper); + if (tth->sleeper) e_powersave_sleeper_free(tth->sleeper); free(tth->extn); free(tth); } @@ -260,6 +260,7 @@ _temperature_face_shutdown(const Eina_Hash *hash EINA_UNUSED, const void *key EI Config_Face *inst; inst = hdata; + // XXX: sleeper free if (inst->th) ecore_thread_cancel(inst->th); if (inst->sensor_name) eina_stringshare_del(inst->sensor_name); if (inst->id) eina_stringshare_del(inst->id); @@ -294,7 +295,7 @@ _temperature_check_main(void *data, Ecore_Thread *th) if (ptemp != temp) ecore_thread_feedback(th, (void *)((long)temp)); ptemp = temp; if (ecore_thread_check(th)) break; - e_powersave_sleeper_sleep(tth->sleeper, tth->poll_interval); + e_powersave_sleeper_sleep(tth->sleeper, tth->poll_interval, EINA_TRUE); } }