@ -5,7 +5,6 @@ if not Device:canSuspend() then
return { disabled = true , }
end
local Event = require ( " ui/event " )
local Math = require ( " optmath " )
local NetworkMgr = require ( " ui/network/manager " )
local PluginShare = require ( " pluginshare " )
@ -34,8 +33,6 @@ local AutoSuspend = WidgetContainer:extend{
task = nil ,
kindle_task = nil ,
standby_task = nil ,
leave_standby_task = nil ,
wrapped_leave_standby_task = nil ,
going_to_suspend = nil ,
}
@ -109,10 +106,10 @@ function AutoSuspend:_start()
end
end
function AutoSuspend : _start_standby ( )
function AutoSuspend : _start_standby ( sleep_in )
if self : _enabledStandby ( ) then
logger.dbg ( " AutoSuspend: start standby timer at " , time.format_time ( self.last_action_time ) )
self : _schedule_standby ( )
self : _schedule_standby ( sleep_in )
end
end
@ -201,14 +198,6 @@ function AutoSuspend:init()
self.standby_task = function ( )
self : _schedule_standby ( )
end
self.leave_standby_task = function ( )
-- Only if we're not already entering suspend...
if self.going_to_suspend then
return
end
UIManager : broadcastEvent ( Event : new ( " LeaveStandby " ) )
end
-- Make sure we only have an AllowStandby handler when we actually want one...
self : toggleStandbyHandler ( self : _enabledStandby ( ) )
@ -235,7 +224,6 @@ function AutoSuspend:onCloseWidget()
self : _unschedule_standby ( )
self.standby_task = nil
self.leave_standby_task = nil
end
function AutoSuspend : onInputEvent ( )
@ -252,17 +240,13 @@ function AutoSuspend:_unschedule_standby()
self.is_standby_scheduled = false
end
-- Make sure we don't trigger a ghost LeaveStandby event...
if self.leave_standby_task then
logger.dbg ( " AutoSuspend: unschedule leave standby task " )
UIManager : unschedule ( self.leave_standby_task )
end
end
function AutoSuspend : _schedule_standby ( )
function AutoSuspend : _schedule_standby ( sleep_in )
sleep_in = sleep_in or self.auto_standby_timeout_seconds
-- Start the long list of conditions in which we do *NOT* want to go into standby ;).
if not Device : canStandby ( ) then
if not Device : canStandby ( ) or self.going_to_suspend then
return
end
@ -292,7 +276,7 @@ function AutoSuspend:_schedule_standby()
standby_delay_seconds = self.auto_standby_timeout_seconds
else
local now = UIManager : getElapsedTimeSinceBoot ( )
standby_delay_seconds = s elf.auto_standby_timeout_seconds - time.to_number ( now - self.last_action_time )
standby_delay_seconds = s leep_in - time.to_number ( now - self.last_action_time )
-- If we blow past the deadline on the first call of a scheduling cycle,
-- make sure we don't go straight to allowStandby, as we haven't called preventStandby yet...
@ -302,7 +286,7 @@ function AutoSuspend:_schedule_standby()
-- or if the only input events we consumed did not trigger an InputEvent event (woken up by gyro events),
-- meaning self.last_action_time is further in the past than it ought to.
-- Delay by the full amount to avoid further bad scheduling interactions.
standby_delay_seconds = s elf.auto_standby_timeout_seconds
standby_delay_seconds = s leep_in
end
end
@ -360,8 +344,7 @@ function AutoSuspend:onSuspend()
UIManager : preventStandby ( )
end
-- And make sure onLeaveStandby, which will come *after* us if we suspended *during* standby,
-- won't re-schedule stuff right before entering suspend...
-- Make sure that we don't re-schedule standby *after* us if we suspended *during* standby,
self.going_to_suspend = true
end
@ -386,20 +369,6 @@ function AutoSuspend:onResume()
self : _start_standby ( )
end
function AutoSuspend : onLeaveStandby ( )
logger.dbg ( " AutoSuspend: onLeaveStandby " )
-- Unschedule suspend and shutdown, as the realtime clock has ticked
self : _unschedule ( )
-- Reschedule suspend and shutdown (we'll recompute the delay based on the last user input, *not* the current time).
-- i.e., the goal is to behave as if we'd never unscheduled it, making sure we do *NOT* reset the delay to the full timeout.
self : _start ( )
-- Assuming _start didn't send us straight to onSuspend (i.e., we were woken from standby by the scheduled suspend task!)...
if not self.going_to_suspend then
-- Reschedule standby, too (we're guaranteed that no standby task is currently scheduled, hence the lack of unscheduling).
self : _start_standby ( )
end
end
function AutoSuspend : onUnexpectedWakeupLimit ( )
logger.dbg ( " AutoSuspend: onUnexpectedWakeupLimit " )
-- Should be unnecessary, because we should *always* follow onSuspend, which already does this...
@ -649,7 +618,6 @@ function AutoSuspend:AllowStandbyHandler()
end
if wake_in >= 3 then -- don't go into standby, if scheduled wakeup is in less than 3 secs
UIManager : broadcastEvent ( Event : new ( " EnterStandby " ) )
logger.dbg ( " AutoSuspend: entering standby with a wakeup alarm in " , wake_in , " s " )
-- This obviously needs a matching implementation in Device, the canonical one being Kobo.
@ -657,29 +625,28 @@ function AutoSuspend:AllowStandbyHandler()
logger.dbg ( " AutoSuspend: left standby after " , time.format_time ( Device.last_standby_time ) , " s " )
-- We delay the LeaveStandby event (our onLeaveStandby handler is responsible for rescheduling everything properly),
-- to make sure UIManager will consume the input events that woke us up first
-- (in case we were woken up by user input, as opposed to an rtc wake alarm)!
-- (This ensures we'll use an up to date last_action_time, and that it only ever gets updated from *user* input).
-- NOTE: While UIManager consumes scheduled tasks before input events, we do *NOT* have to rely on tickAfterNext,
-- NOTE: UIManager consumes scheduled tasks before input events,
-- solely because of where we run inside an UI frame (via UIManager:_standbyTransition):
-- we're neither a scheduled task nor an input event, we run *between* scheduled tasks and input polling.
-- That means we go straight to input polling when returning, *without* a trip through the task queue
-- (c.f., UIManager:_checkTasks in UIManager:handleInput).
UIManager : nextTick ( self.leave_standby_task )
UIManager : shiftScheduledTasksBy ( - Device.last_standby_time ) -- correct scheduled times by last_standby_time
-- Since we go straight to input polling, and that our time spent in standby won't have affected the already computed
-- input polling deadline (because MONOTONIC doesn't tick during standby/suspend),
-- tweak said deadline to make sure poll will return immediately, so we get a chance to run through the task queue ASAP.
-- This ensures we get a LeaveStandby event in a timely fashion,
-- even when there isn't actually any user input happening (e.g., woken up by the rtc alarm).
-- This shouldn't prevent us from actually consuming any pending input events first,
-- because if we were woken up by user input, those events should already be in the evdev queue...
UIManager : consumeInputEarlyAfterPM ( true )
-- When we exit this method, we are sure that the input polling deadline is zero (consumeInputEarly).
-- UIManager will check newly scheduled tasks before going to input polling again (with a new deadline).
self : _start_standby ( ) -- Schedule the next standby check in the future.
else
if not self.going_to_suspend then
self : _start_standby ( )
end
-- When we exit this method, we are sure that the input polling deadline is approximately `wake_in`.
-- So it is safe to schedule another task a bit later.
self : _start_standby ( wake_in + 0.1 ) -- Schedule the next standby check 0.1 seconds after the next calculated wakeup time.
end
end