Make UIManager track prevent/allowStandby state. (#6558)

Conversely, Trapper and plugins report standby interruptibility.
reviewable/pr6559/r2
ezdiy 4 years ago committed by GitHub
parent 4cff623244
commit fd31bcc5fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -306,6 +306,11 @@ function Device:info()
return self.model
end
-- Hardware specific method for UI to signal allowed/disallowed standby.
-- The device is allowed to enter standby only from within waitForEvents,
-- and only if allowed state is true at the time of waitForEvents() invocation.
function Device:setAutoStandby(isAllowed) end
-- Hardware specific method to handle usb plug in event
function Device:usbPlugIn() end

@ -43,8 +43,10 @@ function Trapper:wrap(func)
-- Catch and log any error happening in func (an error happening
-- in a coroutine just aborts silently the coroutine)
local pcalled_func = function()
UIManager:preventStandby()
-- we use xpcall as it can give a whole stacktrace, unlike pcall
local ok, err = xpcall(func, debug.traceback)
UIManager:allowStandby()
if not ok then
logger.warn("error in wrapped function:", err)
return false

@ -37,6 +37,8 @@ local UIManager = {
_refresh_func_stack = {},
_entered_poweroff_stage = false,
_exit_code = nil,
_prevent_standby_count = 0,
_prev_prevent_standby_count = 0,
event_hook = require("ui/hook_container"):new()
}
@ -80,12 +82,11 @@ function UIManager:init()
end)
end
if Device:isPocketBook() then
-- Only fg/bg state plugin notifiers, not real power event.
self.event_handlers["Suspend"] = function()
self:_beforeSuspend()
Device:onPowerEvent("Power")
end
self.event_handlers["Resume"] = function()
Device:onPowerEvent("Power")
self:_afterResume()
end
end
@ -1198,6 +1199,11 @@ function UIManager:handleInput()
wait_us = math.min(wait_us or math.huge, self.ZMQ_TIMEOUT)
end
-- If allowed, entering standby (from which we can wake by input) must trigger in response to event
-- this function emits (plugin), or within waitEvent() right after (hardware).
-- Anywhere else breaks preventStandby/allowStandby invariants used by background jobs while UI is left running.
self:_standbyTransition()
-- wait for next event
local input_event = Input:waitEvent(wait_us)
@ -1301,6 +1307,35 @@ function UIManager:resume()
end
end
-- Release standby lock once. We're done with whatever we were doing in the background.
-- Standby is re-enabled only after all issued prevents are paired with allowStandby for each one.
function UIManager:allowStandby()
assert(self._prevent_standby_count > 0, "allowing standby that isn't prevented; you have an allow/prevent mismatch somewhere")
self._prevent_standby_count = self._prevent_standby_count - 1
end
-- Prevent standby, ie something is happening in background, yet UI may tick.
function UIManager:preventStandby()
self._prevent_standby_count = self._prevent_standby_count + 1
end
-- Allow/prevent calls above can interminently allow standbys, but we're not interested until
-- the state change crosses UI tick boundary, which is what self._prev_prevent_standby_count is tracking.
function UIManager:_standbyTransition()
if self._prevent_standby_count == 0 and self._prev_prevent_standby_count > 0 then
-- edge prevent->allow
logger.dbg("allow standby")
Device:setAutoStandby(true)
self:broadcastEvent(Event:new("AllowStandby"))
elseif self._prevent_standby_count > 0 and self._prev_prevent_standby_count == 0 then
-- edge allow->prevent
logger.dbg("prevent standby")
Device:setAutoStandby(false)
self:broadcastEvent(Event:new("PreventStandby"))
end
self._prev_prevent_standby_count = self._prevent_standby_count
end
function UIManager:flushSettings()
self:broadcastEvent(Event:new("FlushSettings"))
end

@ -1,4 +1,5 @@
local logger = require("logger")
local UIManager = require("ui/uimanager")
local CommandRunner = {
pio = nil,
@ -41,6 +42,7 @@ function CommandRunner:start(job)
"sh plugins/backgroundrunner.koplugin/luawrapper.sh " ..
"\"" .. self.job.executable .. "\""
logger.dbg("CommandRunner: Will execute command " .. command)
UIManager:preventStandby()
self.pio = io.popen(command)
end
@ -71,6 +73,7 @@ function CommandRunner:poll()
self.job.result = 222
end
end
UIManager:allowStandby()
self.pio:close()
self.pio = nil
self.job.end_sec = os.time()

@ -544,6 +544,8 @@ function BookInfoManager:collectSubprocesses()
local pid = self.subprocesses_pids[i]
if util.isSubProcessDone(pid) then
table.remove(self.subprocesses_pids, i)
-- Prevent has been issued for each bg task spawn, we must allow for each death too.
UIManager:allowStandby()
else
i = i + 1
end
@ -621,6 +623,9 @@ function BookInfoManager:extractInBackground(files)
logger.warn("Failed lauching background extraction sub-process (fork failed)")
return false -- let caller know it failed
end
-- No straight control flow exists for background task completion here, so we bump prevent
-- counter on each task, and undo that inside collectSubprocesses() zombie reaper.
UIManager:preventStandby()
table.insert(self.subprocesses_pids, task_pid)
self.subprocesses_last_added_ts = util.gettime()

Loading…
Cancel
Save