AutoFrontlight plugin (#2941)

* Add AutoFrontlight plugin

* Add configuration to control autofrontlight feature
pull/2962/head
Hzj_jie 7 years ago committed by Frans de Jonge
parent ed0ba6737e
commit 53eb4dee50

@ -43,10 +43,8 @@ local footerTextGeneratorMap = {
frontlight = function()
if not Device:hasFrontlight() then return "L: NA" end
local powerd = Device:getPowerDevice()
if powerd.is_fl_on ~= nil and powerd.is_fl_on == true then
if powerd.fl_intensity ~= nil then
return ("L: %d%%"):format(powerd.fl_intensity)
end
if powerd:isFrontlightOn() then
return ("L: %d%%"):format(powerd:frontlightIntensity())
else
return "L: Off"
end

@ -38,47 +38,45 @@ function ReaderFrontLight:init()
end
function ReaderFrontLight:onAdjust(arg, ges)
if not Device.hasFrontlight() then return true end
local powerd = Device:getPowerDevice()
if powerd.fl_intensity ~= nil then
logger.dbg("frontlight intensity", powerd.fl_intensity)
local step = math.ceil(#self.steps * ges.distance / self.gestureScale)
logger.dbg("step = ", step)
local delta_int = self.steps[step] or self.steps[#self.steps]
logger.dbg("delta_int = ", delta_int)
local new_intensity
if ges.direction == "north" then
new_intensity = powerd.fl_intensity + delta_int
elseif ges.direction == "south" then
new_intensity = powerd.fl_intensity - delta_int
end
if new_intensity ~= nil then
-- when new_intensity <=0, toggle light off
if new_intensity <= 0 then
powerd:toggleFrontlight()
end
powerd:setIntensity(new_intensity)
if self.view.footer_visible and self.view.footer.settings.frontlight then
self.view.footer:updateFooter()
end
end
logger.dbg("frontlight intensity", powerd:frontlightIntensity())
local step = math.ceil(#self.steps * ges.distance / self.gestureScale)
logger.dbg("step = ", step)
local delta_int = self.steps[step] or self.steps[#self.steps]
logger.dbg("delta_int = ", delta_int)
local new_intensity
if ges.direction == "north" then
new_intensity = powerd:frontlightIntensity() + delta_int
elseif ges.direction == "south" then
new_intensity = powerd:frontlightIntensity() - delta_int
end
if new_intensity == nil then return true end
-- when new_intensity <=0, toggle light off
if new_intensity <= 0 then
powerd:turnOffFrontlight()
else
powerd:setIntensity(new_intensity)
end
if self.view.footer_visible and self.view.footer.settings.frontlight then
self.view.footer:updateFooter()
end
return true
end
function ReaderFrontLight:onShowIntensity()
if not Device.hasFrontlight() then return true end
local powerd = Device:getPowerDevice()
if powerd.fl_intensity ~= nil then
local new_text
if powerd.fl_intensity == 0 then
new_text = _("Frontlight is off.")
else
new_text = T(_("Frontlight intensity is set to %1."), powerd.fl_intensity)
end
UIManager:show(Notification:new{
text = new_text,
timeout = 1.0,
})
local new_text
if powerd:isFrontlightOff() then
new_text = _("Frontlight is off.")
else
new_text = T(_("Frontlight intensity is set to %1."), powerd:frontlightIntensity())
end
UIManager:show(Notification:new{
text = new_text,
timeout = 1.0,
})
return true
end

@ -52,6 +52,7 @@ function Device:new(o)
end
function Device:init()
assert(self ~= nil)
if not self.screen then
error("screen/framebuffer must be implemented")
end
@ -204,4 +205,14 @@ function Device:retrieveNetworkInfo()
end
end
-- Return an integer value to indicate the brightness of the environment. The value should be in
-- range [0, 3].
-- 0: dark.
-- 1: dim, frontlight is needed.
-- 2: bright, frontlight is not needed.
-- 3: dazzling.
function Device:ambientBrightnessLevel()
return 0
end
return Device

@ -8,21 +8,35 @@ local BasePowerD = {
device = nil, -- device object
last_capacity_pull_time = 0, -- timestamp of last pull
is_fl_on = false, -- whether the frontlight is on
}
function BasePowerD:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
assert(o.fl_min < o.fl_max)
if o.init then o:init() end
if o.device and o.device.hasFrontlight() then
o.fl_intensity = o:frontlightIntensityHW()
o:_decideFrontlightState()
if o:isFrontlightOn() then
o:turnOnFrontlightHW()
else
o:turnOffFrontlightHW()
end
end
return o
end
function BasePowerD:init() end
function BasePowerD:toggleFrontlight() end
function BasePowerD:setIntensityHW() end
function BasePowerD:setIntensityHW(intensity) end
function BasePowerD:getCapacityHW() return 0 end
function BasePowerD:isChargingHW() return false end
function BasePowerD:frontlightIntensityHW() return 0 end
function BasePowerD:turnOffFrontlightHW() self:setIntensityHW(self.fl_min) end
function BasePowerD:turnOnFrontlightHW() self:setIntensityHW(self.fl_intensity) end
-- Anything needs to be done before do a real hardware suspend. Such as turn off
-- front light.
function BasePowerD:beforeSuspend() end
@ -30,6 +44,57 @@ function BasePowerD:beforeSuspend() end
-- front light state.
function BasePowerD:afterResume() end
function BasePowerD:isFrontlightOn()
assert(self ~= nil)
return self.is_fl_on
end
function BasePowerD:_decideFrontlightState()
assert(self ~= nil)
assert(self.device.hasFrontlight())
self.is_fl_on = (self.fl_intensity > self.fl_min)
end
function BasePowerD:isFrontlightOff()
return not self:isFrontlightOn()
end
function BasePowerD:frontlightIntensity()
assert(self ~= nil)
if not self.device.hasFrontlight() then return 0 end
if self:isFrontlightOff() then return 0 end
return self.fl_intensity
end
function BasePowerD:toggleFrontlight()
assert(self ~= nil)
if not self.device.hasFrontlight() then return false end
if self:isFrontlightOn() then
return self:turnOffFrontlight()
else
return self:turnOnFrontlight()
end
end
function BasePowerD:turnOffFrontlight()
assert(self ~= nil)
if not self.device.hasFrontlight() then return end
if self:isFrontlightOff() then return false end
self:turnOffFrontlightHW()
self.is_fl_on = false
return true
end
function BasePowerD:turnOnFrontlight()
assert(self ~= nil)
if not self.device.hasFrontlight() then return end
if self:isFrontlightOn() then return false end
if self.fl_intensity == self.fl_min then return false end
self:turnOnFrontlightHW()
self.is_fl_on = true
return true
end
function BasePowerD:read_int_file(file)
local fd = io.open(file, "r")
if fd then
@ -58,10 +123,13 @@ function BasePowerD:normalizeIntensity(intensity)
end
function BasePowerD:setIntensity(intensity)
if intensity == self.fl_intensity then return end
if not self.device.hasFrontlight() then return false end
if intensity == self.fl_intensity then return false end
self.fl_intensity = self:normalizeIntensity(intensity)
self:_decideFrontlightState()
logger.dbg("set light intensity", self.fl_intensity)
self:setIntensityHW()
self:setIntensityHW(self.fl_intensity)
return true
end
function BasePowerD:getCapacity()

@ -133,6 +133,20 @@ function Kindle:usbPlugOut()
self.charging_mode = false
end
function Kindle:ambientBrightnessLevel()
local haslipc, lipc = pcall(require, "liblipclua")
if not haslipc or lipc == nil then return 0 end
local lipc_handle = lipc.init("com.github.koreader.ambientbrightness")
if not lipc_handle then return 0 end
local value = lipc_handle:get_int_property("com.lab126.powerd", "alsLux")
lipc_handle:close()
if type(value) ~= "number" then return 0 end
if value < 10 then return 0 end
if value < 256 then return 1 end
if value < 32768 then return 2 end
return 3
end
local Kindle2 = Kindle:new{
model = "Kindle2",

@ -4,10 +4,7 @@ local BasePowerD = require("device/generic/powerd")
local KindlePowerD = BasePowerD:new{
fl_min = 0, fl_max = 24,
fl_intensity = nil,
lipc_handle = nil,
is_fl_on = false,
}
function KindlePowerD:init()
@ -15,40 +12,29 @@ function KindlePowerD:init()
if haslipc and lipc then
self.lipc_handle = lipc.init("com.github.koreader.kindlepowerd")
end
if self.device.hasFrontlight() then
-- Kindle stock software does not use intensity file directly, so we need to read from its
-- lipc property first.
if self.lipc_handle ~= nil then
self.fl_intensity = self.lipc_handle:get_int_property("com.lab126.powerd", "flIntensity")
else
self.fl_intensity = self:_readFLIntensity()
end
self:_set_fl_on()
end
end
function KindlePowerD:toggleFrontlight()
if not self.device.hasFrontlight() then
return
end
if self:_readFLIntensity() == 0 then
self:setIntensityHW()
function KindlePowerD:frontlightIntensityHW()
if not self.device.hasFrontlight() then return 0 end
-- Kindle stock software does not use intensity file directly, so we need to read from its
-- lipc property first.
if self.lipc_handle ~= nil then
return self.lipc_handle:get_int_property("com.lab126.powerd", "flIntensity")
else
self:_turnOffFL()
return self:_readFLIntensity()
end
end
function KindlePowerD:setIntensityHW()
if self.lipc_handle ~= nil and self.fl_intensity > 0 then
function KindlePowerD:setIntensityHW(intensity)
if self.lipc_handle ~= nil and intensity > 0 then
-- NOTE: We want to bypass setIntensity's shenanigans and simply restore the light as-is
self.lipc_handle:set_int_property("com.lab126.powerd", "flIntensity", self.fl_intensity)
self.lipc_handle:set_int_property(
"com.lab126.powerd", "flIntensity", self.fronglightIntensity())
else
-- NOTE: when fl_intensity is 0, We want to really kill the light, so do it manually
-- NOTE: when intensity is 0, We want to really kill the light, so do it manually
-- (asking lipc to set it to 0 would in fact set it to 1)...
os.execute("echo -n ".. self.fl_intensity .." > " .. self.fl_intensity_file)
os.execute("echo -n ".. intensity .." > " .. self.fl_intensity_file)
end
self:_set_fl_on()
end
function KindlePowerD:getCapacityHW()
@ -76,30 +62,20 @@ function KindlePowerD:__gc()
end
end
function KindlePowerD:_turnOffFL()
-- NOTE: We want to really kill the light, so do it manually (asking lipc to set it to 0 would in fact set it to 1)...
os.execute("echo -n 0 > " .. self.fl_intensity_file)
self.is_fl_on = false
end
function KindlePowerD:_readFLIntensity()
return self:read_int_file(self.fl_intensity_file)
end
function KindlePowerD:_set_fl_on()
self.is_fl_on = (self.fl_intensity > 0)
end
function KindlePowerD:afterResume()
if not self.device.hasFrontlight() then
return
end
if self.is_fl_on then
if self:isFrontlightOn() then
-- Kindle stock software should turn on the front light automatically. The follow statement
-- ensure the consistency of intensity.
self:setIntensityHW()
else
self:_turnOffFL()
self:turnOffFrontlightHW()
end
end

@ -53,9 +53,7 @@ function NickelConf.frontLightLevel.get()
-- FrontLightState config, so don't normalize the value here yet.
return tonumber(new_intensity)
else
-- In NickelConfSpec, require("device") won't return KoboDevice
local powerd = require("device/kobo/powerd")
local fallback_fl_level = powerd.fl_intensity or 1
local fallback_fl_level = 1
assert(NickelConf.frontLightLevel.set(fallback_fl_level))
return fallback_fl_level
end

@ -8,15 +8,8 @@ local KoboPowerD = BasePowerD:new{
-- Do not actively set front light to 0, it may confuse users -- pressing
-- hardware button won't take any effect.
fl_min = 1, fl_max = 100,
fl_intensity = 20,
restore_settings = true,
fl = nil,
-- We will set this value for all kobo models. but it will only be synced
-- with nickel's FrontLightState config if the current nickel firmware
-- supports this config.
is_fl_on = false,
batt_capacity_file = batt_state_folder .. "capacity",
is_charging_file = batt_state_folder .. "status",
}
@ -36,42 +29,24 @@ function KoboPowerD:init()
end
end
function KoboPowerD:toggleFrontlight()
if self.fl ~= nil then
if self.is_fl_on then
self.fl:setBrightness(0)
else
self.fl:setBrightness(self.fl_intensity)
end
self.is_fl_on = not self.is_fl_on
if self.has_fl_state_cfg and KOBO_SYNC_BRIGHTNESS_WITH_NICKEL then
NickelConf.frontLightState.set(self.is_fl_on)
end
function KoboPowerD:_syncNickelConf()
if self.has_fl_state_cfg and KOBO_SYNC_BRIGHTNESS_WITH_NICKEL then
NickelConf.frontLightState.set(self:isFrontlightOn())
NickelConf.frontLightLevel.set(self:frontlightIntensity())
end
end
function KoboPowerD:setIntensityHW()
if self.fl ~= nil then
self.fl:setBrightness(self.fl_intensity)
-- Make sure we persist intensity config in reader setting
G_reader_settings:saveSetting("frontlight_intensity", self.fl_intensity)
if KOBO_SYNC_BRIGHTNESS_WITH_NICKEL then
NickelConf.frontLightLevel.set(self.fl_intensity)
end
-- also keep self.is_fl_on in sync with intensity if needed
local is_fl_on
if self.fl_intensity > 0 then
is_fl_on = true
else
is_fl_on = false
end
if self.is_fl_on ~= is_fl_on then
self.is_fl_on = is_fl_on
if self.has_fl_state_cfg and KOBO_SYNC_BRIGHTNESS_WITH_NICKEL then
NickelConf.frontLightState.set(self.is_fl_on)
end
end
function KoboPowerD:frontlightIntensityHW()
if self.has_fl_state_cfg then
return NickelConf.frontLightLevel.get()
end
return 20
end
function KoboPowerD:setIntensityHW(intensity)
if self.fl == nil then return end
self.fl:setBrightness(self.frontlightIntensity())
self:_syncNickelConf()
end
function KoboPowerD:getCapacityHW()
@ -84,19 +59,15 @@ end
-- Turn off front light before suspend.
function KoboPowerD:beforeSuspend()
if self.fl ~= nil then
self.fl:setBrightness(0)
end
self:turnOffFrontlightHW()
end
-- Restore front light state after resume.
function KoboPowerD:afterResume()
if self.fl ~= nil then
if KOBO_LIGHT_ON_START and tonumber(KOBO_LIGHT_ON_START) > -1 then
self:setIntensity(math.min(KOBO_LIGHT_ON_START, 100))
elseif self.is_fl_on then
self.fl:setBrightness(self.fl_intensity)
end
if KOBO_LIGHT_ON_START and tonumber(KOBO_LIGHT_ON_START) > -1 then
self:setIntensity(math.min(KOBO_LIGHT_ON_START, 100))
elseif self:isFrontlightOn() then
self:turnOnFrontlightHW()
end
end

@ -54,11 +54,13 @@ end
--- Saves a setting.
function LuaSettings:saveSetting(key, value)
self.data[key] = value
return self
end
--- Deletes a setting.
function LuaSettings:delSetting(key)
self.data[key] = nil
return self
end
--- Checks if setting exists.
@ -98,6 +100,7 @@ function LuaSettings:flipNilOrTrue(key)
else
self:delSetting(key)
end
return self
end
--- Flips `nil` or `false` to `true`.
@ -107,6 +110,7 @@ function LuaSettings:flipNilOrFalse(key)
else
self:delSetting(key)
end
return self
end
--- Flips setting to `true`.
@ -116,6 +120,7 @@ function LuaSettings:flipTrue(key)
else
self:saveSetting(key, true)
end
return self
end
--- Flips setting to `false`.
@ -125,11 +130,13 @@ function LuaSettings:flipFalse(key)
else
self:saveSetting(key, true)
end
return self
end
--- Replaces existing settings with table.
function LuaSettings:reset(table)
self.data = table
return self
end
--- Writes settings to disk.
@ -143,6 +150,7 @@ function LuaSettings:flush()
f_out:write("\n")
f_out:close()
end
return self
end
--- Closes settings file.
@ -155,6 +163,7 @@ function LuaSettings:purge()
if self.file then
os.remove(self.file)
end
return self
end
return LuaSettings

@ -299,7 +299,7 @@ function UIManager:scheduleIn(seconds, action)
local usecs = (seconds - s) * MILLION
when[1] = when[1] + s
when[2] = when[2] + usecs
if when[2] > MILLION then
if when[2] >= MILLION then
when[1] = when[1] + 1
when[2] = when[2] - MILLION
end

@ -38,10 +38,7 @@ function FrontLightWidget:init()
local powerd = Device:getPowerDevice()
self.fl_min = powerd.fl_min
self.fl_max = powerd.fl_max
self.fl_cur = powerd.fl_intensity
if self.fl_cur == nil then
self.fl_cur = self.fl_min
end
self.fl_cur = powerd:frontlightIntensity()
local steps_fl = self.fl_max - self.fl_min + 1
self.one_step = math.ceil(steps_fl / 25)
self.steps = math.ceil(steps_fl / self.one_step)

@ -0,0 +1,64 @@
local Device = require("device")
if not Device:isKindle() or
(Device.model ~= "KindleVoyage" and Device.model ~= "KindleOasis") then
return { disabled = true, }
end
local DataStorage = require("datastorage")
local LuaSettings = require("luasettings")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local AutoFrontlight = {
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/autofrontlight.lua"),
settings_id = 0,
enabled = false,
}
function AutoFrontlight:_schedule()
if not self.enabled then
logger.dbg("AutoFrontlight:_schedule() is disabled")
return
end
local settings_id = self.settings_id
logger.dbg("AutoFrontlight:_schedule() @ ", os.time(), ", it should be executed at ", os.time() + 1)
UIManager:scheduleIn(1, function()
self:_action(settings_id)
self:_schedule(self.settings_id)
end)
end
function AutoFrontlight:_action(settings_id)
if settings_id ~= self.settings_id then
logger.dbg("AutoFrontlight:_action(): registered settings_id ",
settings_id,
" does not equal to current one ",
self.settings_id)
return
end
logger.dbg("AutoFrontlight:_action() @ ", os.time())
if Device:ambientBrightnessLevel() <= 1 then
logger.dbg("AutoFrontlight: going to turn on frontlight")
Device:getPowerDevice():turnOnFrontlight()
else
logger.dbg("AutoFrontlight: going to turn off frontlight")
Device:getPowerDevice():turnOffFrontlight()
end
end
function AutoFrontlight:init()
self.enabled = not self.settings:nilOrFalse("enable")
logger.dbg("AutoFrontlight:init() self.enabled: ", self.enabled)
self:_schedule()
end
AutoFrontlight:init()
local AutoFrontlightWidget = WidgetContainer:new{
name = "AutoFrontlight",
}
return AutoFrontlightWidget

@ -0,0 +1,48 @@
describe("AutoFrontlight widget tests", function()
local Device, MockTime
setup(function()
require("commonrequire")
package.unloadAll()
Device = require("device/generic/device"):new()
Device.brightness = 0
Device.hasFrontlight = function() return true end
Device.powerd = require("device/generic/powerd"):new{
frontlight = 0,
}
Device.powerd.frontlightIntensityHW = function()
return 2
end
Device.powerd.setIntensityHW = function(self, intensity)
self.frontlight = intensity
end
Device.ambientBrightnessLevel = function(self)
return self.brightness
end
MockTime = require("mock_time")
MockTime:install()
end)
teardown(function()
MockTime:uninstall()
package.unloadAll()
end)
it("should automatically turn on or off frontlight", function()
local UIManager = require("ui/uimanager")
Device.brightness = 0
MockTime:increase(2)
assert.are.equal(Device:getPowerDevice().frontlight, 2)
Device.brightness = 1
MockTime:increase(2)
assert.are.equal(Device:getPowerDevice().frontlight, 2)
Device.brightness = 2
MockTime:increase(2)
assert.are.equal(Device:getPowerDevice().frontlight, 0)
Device.brightness = 3
MockTime:increase(2)
assert.are.equal(Device:getPowerDevice().frontlight, 0)
end)
end)

@ -0,0 +1,73 @@
describe("AutoFrontlight widget tests", function()
local Device, PowerD, MockTime
setup(function()
require("commonrequire")
package.unloadAll()
MockTime = require("mock_time")
MockTime:install()
PowerD = require("device/generic/powerd"):new{
frontlight = 0,
}
PowerD.frontlightIntensityHW = function()
return 2
end
PowerD.setIntensityHW = function(self, intensity)
self.frontlight = intensity
end
end)
teardown(function()
MockTime:uninstall()
package.unloadAll()
end)
before_each(function()
Device = require("device")
Device.isKindle = function() return true end
Device.model = "KindleVoyage"
Device.brightness = 0
Device.hasFrontlight = function() return true end
Device.powerd = PowerD:new{
device = Device,
}
Device.ambientBrightnessLevel = function(self)
return self.brightness
end
Device.input.waitEvent = function() end
end)
it("should automatically turn on or off frontlight", function()
local UIManager = require("ui/uimanager")
UIManager._run_forever = true
require("luasettings"):
open(require("datastorage"):getSettingsDir() .. "/autofrontlight.lua"):
saveSetting("enable", "true"):
close()
local class = dofile("plugins/autofrontlight.koplugin/main.lua")
local AutoFrontlight = class:new()
AutoFrontlight:init()
Device.brightness = 3
MockTime:increase(1)
UIManager:handleInput()
assert.are.equal(0, Device:getPowerDevice().frontlight)
Device.brightness = 0
MockTime:increase(1)
UIManager:handleInput()
assert.are.equal(2, Device:getPowerDevice().frontlight)
Device.brightness = 1
MockTime:increase(1)
UIManager:handleInput()
assert.are.equal(2, Device:getPowerDevice().frontlight)
Device.brightness = 2
MockTime:increase(1)
UIManager:handleInput()
assert.are.equal(0, Device:getPowerDevice().frontlight)
Device.brightness = 3
MockTime:increase(1)
UIManager:handleInput()
assert.are.equal(0, Device:getPowerDevice().frontlight)
end)
end)

@ -50,3 +50,50 @@ function assertNotAlmostEquals(expected, actual, margin)
.. ', received: ' .. actual
)
end
package.unload = function(module)
if type(module) ~= "string" then return false end
package.loaded[module] = nil
_G[module] = nil
return true
end
package.replace = function(name, module)
if type(name) ~= "string" then return false end
assert(package.unload(name))
package.loaded[name] = module
return true
end
package.reload = function(name)
if type(name) ~= "string" then return false end
assert(package.unload(name))
return require(name)
end
package.unloadAll = function()
local candidates = {
"spec/",
"frontend/",
"plugins/",
"datastorage.lua",
"defaults.lua",
}
local pending = {}
for name, _ in pairs(package.loaded) do
local path = package.searchpath(name, package.path)
if path ~= nil then
for _, candidate in ipairs(candidates) do
if path:find(candidate) == 1 then
table.insert(pending, name)
end
end
end
end
for _, name in ipairs(pending) do
if name ~= "commonrequire" then
assert(package.unload(name))
end
end
return #pending
end

@ -0,0 +1,185 @@
describe("Frontlight function in PowerD", function()
local PowerD, device
setup(function()
require("commonrequire")
PowerD = require("device/generic/powerd"):new{
frontlight = 0,
}
param = {
fl_min = 1,
fl_max = 5,
device = {
hasFrontlight = function() return true end
},
}
end)
before_each(function()
frontlight = param.fl_min
stub(PowerD, "init")
stub(PowerD, "frontlightIntensityHW")
stub(PowerD, "setIntensityHW")
PowerD.setIntensityHW = function(self, intensity)
self.frontlight = intensity
end
spy.on(PowerD, "setIntensityHW")
spy.on(PowerD, "turnOnFrontlightHW")
spy.on(PowerD, "turnOffFrontlightHW")
end)
it("should read frontlight intensity during initialization", function()
PowerD.frontlightIntensityHW.returns(2)
local p = PowerD:new(param)
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.init).is_called(1)
assert.stub(p.frontlightIntensityHW).is_called(1)
end)
test_when_off = function(fl_min)
param.fl_min = fl_min
PowerD.frontlightIntensityHW.returns(fl_min)
local p = PowerD:new(param)
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.init).is_called(1)
assert.stub(p.setIntensityHW).is_called(1)
assert.are.equal(param.fl_min, p.frontlight)
assert.stub(p.frontlightIntensityHW).is_called(1)
assert.spy(p.turnOnFrontlightHW).is_called(0)
assert.spy(p.turnOffFrontlightHW).is_called(1)
-- The intensity is param.fl_min, turnOnFrontlight() should take no effect.
assert.is.falsy(p:turnOnFrontlight())
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.setIntensityHW).is_called(1)
assert.spy(p.turnOnFrontlightHW).is_called(0)
assert.spy(p.turnOffFrontlightHW).is_called(1)
-- Same as the above one, toggleFrontlight() should also take no effect.
assert.is.falsy(p:toggleFrontlight())
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.setIntensityHW).is_called(1)
assert.spy(p.turnOnFrontlightHW).is_called(0)
assert.spy(p.turnOffFrontlightHW).is_called(1)
assert.is.truthy(p:setIntensity(2))
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(2)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(0)
assert.spy(p.turnOffFrontlightHW).is_called(1)
assert.is.falsy(p:turnOnFrontlight())
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(2)
assert.spy(p.turnOnFrontlightHW).is_called(0)
assert.spy(p.turnOffFrontlightHW).is_called(1)
assert.is.truthy(p:turnOffFrontlight())
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.setIntensityHW).is_called(3)
assert.are.equal(param.fl_min, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(0)
assert.spy(p.turnOffFrontlightHW).is_called(2)
assert.is.truthy(p:turnOnFrontlight())
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(4)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(1)
assert.spy(p.turnOffFrontlightHW).is_called(2)
assert.is.truthy(p:toggleFrontlight())
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.setIntensityHW).is_called(5)
assert.are.equal(param.fl_min, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(1)
assert.spy(p.turnOffFrontlightHW).is_called(3)
assert.is.truthy(p:toggleFrontlight())
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(6)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(2)
assert.spy(p.turnOffFrontlightHW).is_called(3)
end
test_when_on = function(fl_min)
assert(fl_min < 2)
param.fl_min = fl_min
PowerD.frontlightIntensityHW.returns(2)
local p = PowerD:new(param)
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.init).is_called(1)
assert.stub(p.setIntensityHW).is_called(1)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(1)
assert.spy(p.turnOffFrontlightHW).is_called(0)
assert.is.falsy(p:setIntensity(2))
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(1)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(1)
assert.spy(p.turnOffFrontlightHW).is_called(0)
assert.is.falsy(p:turnOnFrontlight())
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(1)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(1)
assert.spy(p.turnOffFrontlightHW).is_called(0)
assert.is.truthy(p:turnOffFrontlight())
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.setIntensityHW).is_called(2)
assert.are.equal(param.fl_min, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(1)
assert.spy(p.turnOffFrontlightHW).is_called(1)
assert.is.truthy(p:toggleFrontlight())
assert.are.equal(2, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOn())
assert.stub(p.setIntensityHW).is_called(3)
assert.are.equal(2, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(2)
assert.spy(p.turnOffFrontlightHW).is_called(1)
assert.is.truthy(p:toggleFrontlight())
assert.are.equal(0, p:frontlightIntensity())
assert.is.truthy(p:isFrontlightOff())
assert.stub(p.setIntensityHW).is_called(4)
assert.are.equal(param.fl_min, p.frontlight)
assert.spy(p.turnOnFrontlightHW).is_called(2)
assert.spy(p.turnOffFrontlightHW).is_called(2)
end
it("should turn on and off frontlight when the frontlight was off", function()
test_when_off(0)
end)
it("should turn on and off frontlight when the minimum level is 1 and frontlight was off",
function() test_when_off(1) end)
it("should turn on and off frontlight when the frontlight was on", function()
test_when_on(0)
end)
it("should turn on and off frontlight when the minimum level is 1 and frontlight was on",
function() test_when_on(1) end)
end)

@ -0,0 +1,45 @@
local MockTime = {
original_os_time = os.time,
original_util_time = nil,
value = os.time(),
}
function MockTime:install()
assert(self ~= nil)
local util = require("ffi/util")
if self.original_util_time == nil then
self.original_util_time = util.gettime
assert(self.original_util_time ~= nil)
end
os.time = function() return self.value end
util.gettime = function() return self.value, 0 end
end
function MockTime:uninstall()
assert(self ~= nil)
local util = require("ffi/util")
os.time = self.original_os_time
if self.original_util_time ~= nil then
util.gettime = self.original_util_time
end
end
function MockTime:set(value)
assert(self ~= nil)
if type(value) ~= "number" then
return false
end
self.value = math.floor(value)
return true
end
function MockTime:increase(value)
assert(self ~= nil)
if type(value) ~= "number" then
return false
end
self.value = math.floor(self.value + value)
return true
end
return MockTime

@ -61,7 +61,7 @@ bar=baz
fd:close()
NickelConf._set_kobo_conf_path(fn)
assert.Equals(NickelConf.frontLightLevel.get(), 20)
assert.Equals(NickelConf.frontLightLevel.get(), 1)
assert.Equals(NickelConf.frontLightState.get(), nil)
os.remove(fn)

Loading…
Cancel
Save