diff --git a/frontend/device/cervantes/device.lua b/frontend/device/cervantes/device.lua index 63e0cc822..4384f7b65 100644 --- a/frontend/device/cervantes/device.lua +++ b/frontend/device/cervantes/device.lua @@ -48,6 +48,7 @@ local Cervantes = Generic:new{ hasWifiManager = yes, canReboot = yes, canPowerOff = yes, + canSuspend = yes, home_dir = "/mnt/public", -- do we support usb mass storage? diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index 61e79befd..02bb58766 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -68,7 +68,7 @@ local Device = { canToggleChargingLED = no, canUseWAL = yes, -- requires mmap'ed I/O on the target FS canRestart = yes, - canSuspend = yes, + canSuspend = no, canStandby = no, canPowerSaveWhileCharging = no, total_standby_time = 0, -- total time spent in standby diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 0a83a4e44..956803abe 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -133,6 +133,8 @@ local Kindle = Generic:new{ canModifyFBInfo = yes, -- NOTE: Newer devices will turn the frontlight off at 0 canTurnFrontlightOff = yes, + -- NOTE: Via powerd.toggleSuspend + canSuspend = yes, home_dir = "/mnt/us", -- New devices are REAGL-aware, default to REAGL isREAGL = yes, diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua index f1e43704f..bd4c82ece 100644 --- a/frontend/device/kobo/device.lua +++ b/frontend/device/kobo/device.lua @@ -72,6 +72,7 @@ local Kobo = Generic:new{ canStandby = no, -- will get updated by checkStandby() canReboot = yes, canPowerOff = yes, + canSuspend = yes, -- most Kobos have X/Y switched for the touch screen touch_switch_xy = true, -- most Kobos have also mirrored X coordinates @@ -1076,6 +1077,11 @@ function Kobo:resume() self:setupChargingLED() end +function Kobo:usbPlugOut() + -- Reset the unexpected wakeup shenanigans, since we're no longer charging, meaning power savings are now critical again ;). + self.unexpected_wakeup_count = 0 +end + function Kobo:saveSettings() -- save frontlight state to G_reader_settings (and NickelConf if needed) self.powerd:saveSettings() diff --git a/frontend/device/remarkable/device.lua b/frontend/device/remarkable/device.lua index d49239963..43b100596 100644 --- a/frontend/device/remarkable/device.lua +++ b/frontend/device/remarkable/device.lua @@ -37,6 +37,7 @@ local Remarkable = Generic:new{ hasOTAUpdates = yes, canReboot = yes, canPowerOff = yes, + canSuspend = yes, isTouchDevice = yes, hasFrontlight = no, hasSystemFonts = yes, diff --git a/frontend/device/sdl/device.lua b/frontend/device/sdl/device.lua index f2bf05b49..28cb08b7d 100644 --- a/frontend/device/sdl/device.lua +++ b/frontend/device/sdl/device.lua @@ -67,7 +67,7 @@ local Device = Generic:new{ hasEinkScreen = no, hasSystemFonts = yes, canSuspend = no, - canStandby = yes, + canStandby = no, startTextInput = SDL.startTextInput, stopTextInput = SDL.stopTextInput, canOpenLink = getLinkOpener, @@ -120,9 +120,12 @@ local Emulator = Device:new{ hasNaturalLightApi = yes, hasWifiToggle = yes, hasWifiManager = yes, + -- Not really, Device:reboot & Device:powerOff are not implemented, so we just exit ;). canPowerOff = yes, canReboot = yes, + -- NOTE: Via simulateSuspend canSuspend = yes, + canStandby = no, } local UbuntuTouch = Device:new{ @@ -337,11 +340,13 @@ function Emulator:simulateSuspend() local Screensaver = require("ui/screensaver") Screensaver:setup() Screensaver:show() + self.screen_saver_mode = true end function Emulator:simulateResume() local Screensaver = require("ui/screensaver") Screensaver:close() + self.screen_saver_mode = false end -- fake network manager for the emulator diff --git a/frontend/device/sony-prstux/device.lua b/frontend/device/sony-prstux/device.lua index 438138e35..2f442210e 100644 --- a/frontend/device/sony-prstux/device.lua +++ b/frontend/device/sony-prstux/device.lua @@ -17,6 +17,7 @@ local SonyPRSTUX = Generic:new{ hasWifiManager = yes, canReboot = yes, canPowerOff = yes, + canSuspend = yes, usbPluggedIn = false, home_dir = nil, } diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index f6d1b4f66..cee934237 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -64,6 +64,11 @@ local Screensaver = { default_screensaver_message = _("Sleeping"), } +-- Remind emulator users that Power is bound to F2 +if Device:isEmulator() then + Screensaver.default_screensaver_message = Screensaver.default_screensaver_message .. "\n" .. _("(Press F2 to resume)") +end + function Screensaver:_getRandomImage(dir) if not dir then return nil diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index 6a9854cd2..5a7e53410 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -173,6 +173,7 @@ function UIManager:init() self.event_handlers["Light"] = function() Device:getPowerDevice():toggleFrontlight() end + -- USB plug events with a power-only charger self.event_handlers["Charging"] = function() self:_beforeCharging() -- NOTE: Plug/unplug events will wake the device up, which is why we put it back to sleep. @@ -182,11 +183,13 @@ function UIManager:init() end self.event_handlers["NotCharging"] = function() -- We need to put the device into suspension, other things need to be done before it. + Device:usbPlugOut() self:_afterNotCharging() if Device.screen_saver_mode then self:suspend() end end + -- USB plug events with a data-aware host self.event_handlers["UsbPlugIn"] = function() self:_beforeCharging() -- NOTE: Plug/unplug events will wake the device up, which is why we put it back to sleep. @@ -200,6 +203,7 @@ function UIManager:init() end self.event_handlers["UsbPlugOut"] = function() -- We need to put the device into suspension, other things need to be done before it. + Device:usbPlugOut() self:_afterNotCharging() if Device.screen_saver_mode then self:suspend() @@ -382,6 +386,14 @@ function UIManager:init() Device:simulateResume() self:_afterResume() end + self.event_handlers["PowerRelease"] = function() + -- Resume if we were suspended + if Device.screen_saver_mode then + self:resume() + else + self:suspend() + end + end end end @@ -1782,11 +1794,11 @@ Executes all the operations of a suspension (i.e., sleep) request. This function usually puts the device into suspension. ]] function UIManager:suspend() - if Device:isCervantes() or Device:isKobo() or Device:isSDL() or Device:isRemarkable() or Device:isSonyPRSTUX() then + if self.event_handlers["Suspend"] then self.event_handlers["Suspend"]() elseif Device:isKindle() then Device.powerd:toggleSuspend() - elseif Device.isPocketBook() and Device.canSuspend() then + elseif Device:canSuspend() then Device:suspend() end end @@ -1801,7 +1813,7 @@ function UIManager:resume() -- invalidate the last battery capacity pull time so that we get up to date data immediately. Device:getPowerDevice():invalidateCapacityCache() - if Device:isCervantes() or Device:isKobo() or Device:isSDL() or Device:isRemarkable() or Device:isSonyPRSTUX() then + if self.event_handlers["Resume"] then self.event_handlers["Resume"]() elseif Device:isKindle() then self.event_handlers["OutOfSS"]() diff --git a/plugins/autosuspend.koplugin/main.lua b/plugins/autosuspend.koplugin/main.lua index ae6ce99af..29554b749 100644 --- a/plugins/autosuspend.koplugin/main.lua +++ b/plugins/autosuspend.koplugin/main.lua @@ -1,12 +1,7 @@ local Device = require("device") -if not Device:isCervantes() and - not Device:isKindle() and - not Device:isKobo() and - not Device:isRemarkable() and - not Device:isSDL() and - not Device:isSonyPRSTUX() and - not Device:isPocketBook() then +-- If a device can power off or go into standby, it can also suspend ;). +if not Device:canSuspend() then return { disabled = true, } end @@ -46,6 +41,7 @@ function AutoSuspend:_enabledStandby() end function AutoSuspend:_enabled() + -- NOTE: Plugin is only enabled if Device:canSuspend(), so we can elide the check here return self.auto_suspend_timeout_seconds > 0 end @@ -64,10 +60,11 @@ function AutoSuspend:_schedule(shutdown_only) -- On devices with an auxiliary battery, we only care about the auxiliary battery being charged... local powerd = Device:getPowerDevice() if Device:hasAuxBattery() and powerd:isAuxBatteryConnected() then - is_charging = powerd:isAuxCharging() + is_charging = powerd:isAuxCharging() and not powerd:isAuxCharged() else - is_charging = powerd:isCharging() + is_charging = powerd:isCharging() and not powerd:isCharged() end + -- We *do* want to make sure we attempt to go into suspend/shutdown again while *fully* charged, though. if PluginShare.pause_auto_suspend or is_charging then suspend_delay_seconds = self.auto_suspend_timeout_seconds shutdown_delay_seconds = self.autoshutdown_timeout_seconds @@ -134,8 +131,6 @@ function AutoSuspend:init() -- Disabled, until the user opts in. self.auto_standby_timeout_seconds = G_reader_settings:readSetting("auto_standby_timeout_seconds", -1) - if Device:isPocketBook() and not Device:canSuspend() then return end - -- We only want those to exist as *instance* members self.is_standby_scheduled = false self.going_to_suspend = false @@ -178,7 +173,6 @@ end -- NOTE: event_hook takes care of overloading this to unregister the hook, too. function AutoSuspend:onCloseWidget() logger.dbg("AutoSuspend: onCloseWidget") - if Device:isPocketBook() and not Device:canSuspend() then return end self:_unschedule() self.task = nil @@ -346,10 +340,21 @@ end function AutoSuspend:onUnexpectedWakeupLimit() logger.dbg("AutoSuspend: onUnexpectedWakeupLimit") + -- Should be unnecessary, because we should *always* follow onSuspend, which already does this... + -- Better safe than sorry, though ;). + self:_unschedule() -- Only re-engage the *shutdown* schedule to avoid doing the same dance indefinitely. self:_restart() end +function AutoSuspend:onNotCharging() + logger.dbg("AutoSuspend: onNotCharging") + -- Make sure both the suspend & shutdown timers are re-engaged on unplug, + -- in case we hit an UnexpectedWakeupLimit during the charge cycle... + self:_unschedule() + self:_start() +end + -- time_scale: -- 2 ... display day:hour -- 1 ... display hour:min @@ -464,6 +469,7 @@ function AutoSuspend:pickTimeoutValue(touchmenu_instance, title, info, setting, end function AutoSuspend:addToMainMenu(menu_items) + -- Device:canSuspend() check elided because it's a plugin requirement menu_items.autosuspend = { sorting_hint = "device", checked_func = function() @@ -489,7 +495,7 @@ function AutoSuspend:addToMainMenu(menu_items) {60, 24*3600}, 1) end, } - if Device:canPowerOff() or Device:isEmulator() then + if Device:canPowerOff() then menu_items.autoshutdown = { sorting_hint = "device", checked_func = function()