LibreShift / red-moon

Android screen filter app for night time phone use.
GNU General Public License v3.0
657 stars 81 forks source link

Dim in a more intelligent way #122

Open smichel17 opened 7 years ago

smichel17 commented 7 years ago

Motivation / Premise

There's two ways to dim the screen.

  1. Turn down the backlight
  2. Show a partially transparent black overlay (ie, use the filter).

Given the choice, I think I would always rather start with the backlight, and only engage the filter when the backlight reaches 0.

The problem

This is actually a hard problem to solve:

I am not planning on working on this any time soon, but I am interested in feedback. Would you find the proposal below acceptable? What do you find useful or not about Red Moon's current brightness/dim controls? Is there anything you wish Red Moon could do, or that you never want it to do?

Proposal

The problem with doing this is that if the user switches to a darker profile, turns up the brightness, and repeats that several times, we could reach a profile at maximum darkness without actually dimming the screen at all. So solve that, we need to:

For example:

There's one final problem: unless the brightness is already at the minimum when the user turns it on, we'll never be able to reach the minimum. So, instead of raising/lowering a fixed amount, we need to scale it by whatever the initial brightness is.

Conclusion

I believe this implementation, while complex, will respect all the user's wishes.


Note: I will keep this comment up to date, but comments below reflect my thoughts at the time, not now.

mirh commented 7 years ago

Also, why not hooking into KCAL, or using a driver like CF.lumen?

smichel17 commented 7 years ago

See #20

smichel17 commented 7 years ago

Currently thinking it might make sense to replace lower brightness with settings to control the system brightness. A couple ways we could do that:

  1. An app-wide toggle for whether to control system brightness. If it's enabled, add per-filter:
    • A toggle to control whether automatic brightness is enabled
    • A slider to control the brightness level
  2. Same as 1, but the toggle for controlling system brightness is per-filter.
  3. Same as 2, but combine the two toggles into a list, ie Control brightness: [Off / Fixed / Auto]
    • If it's set to Off, the brightness slider disappears.
smichel17 commented 7 years ago

Here's another one. It's more clever than the others. Maybe too clever.


A simpler version is to do the same as the above, but not try to change the automatic (adaptive) backlight setting -- leave that for users to toggle manually. This would sacrifice some functionality, but might be worth it in simplicity and usefulness.

mirh commented 7 years ago

A toggle to control whether automatic brightness is enabled

If any, it should be natural to just stick to it if user had it enabled. I mean.. Provided ALS curves are exposed to programs I guess? Ok wrong assumption. And I guess adaptive brightness introduced in L further complicates the situation.

...

In other news I found https://github.com/fython/Blackbulb

If it's above halfway, it'll control the backlight brightness.

I'd say 1/4 imo. Or at least because on my phone minimum brightness is already pretty low.

smichel17 commented 7 years ago

If any, it should be natural to just stick to it if user had it enabled.

Right now, Lower brightness, if enabled, turns automatic* brightness off and sets the brightness level to 0. My point was, if we don't offer a way to turn off automatic brightness, we're losing functionality. Maybe we're okay with that, but any time you take away something that people might rely on, you need to think very hard about it, first. That's another reason why I'm often hesitant to add features/settings that I'm not sure we want to keep.

*ie, adaptive brightness. I use the names I do because that's what they're called in the code.

In other news I found https://github.com/fython/Blackbulb

Thank you for reminding me of this. I'd been meaning to look into how it's able to work without overlay permission (turns out, the filter is masquerading as a temporary notification).

I really like how simple their interface is, although they don't have separate controls for color/intensity/dim, profiles, a timer, or the ability to automatically pause in secure apps.

It looks like they proxy all their calls to the filtering service through a call to a tile receiver. Not sure why that is, but maybe related to #142.

I'd say 1/4 imo. Or at least because on my phone minimum brightness is already pretty low.

1/2 was just an example; If I end up going this route, I'll play around with it to see what value feels good.

smichel17 commented 7 years ago

Stray thought: Would it make sense to combine this with the button backlight setting? It would be nice if that setting had some effect on all devices, as I don't really like a useless setting sitting around.

smichel17 commented 7 years ago

I updated the top comment with a proposal.

smichel17 commented 7 years ago

Copying the reply from @wavexx in #191 so I don't forget it:

I'm not sure all of this is needed. I agree that changing brightness should dim/[un]dim before changing the backlight when going under 0.

Ideally "dim" just doubles the dynamic range of the brightness, so that 0-50% is from maximum to zero dim (keeping backlight to 0), and 50-100% is zero backlight to 100% (keeping dim at 0).

If you could remap the system backlight control to this, then switching filters would be trivial (the current brightness is absolute). I have no experience with android development, so I cannot comment if that's actually doable.

However, when I switch off the filter, just restore whatever brightness was set before turning it on.

My specific use-case is super-simple: I just want darker, at night. I just use "dim", with the timer.

I do agree that this would be ideal. Unfortunately, it is impossible to change the behavior of the system brightness control. I also don't know of any way for an app to be notified when the user changes the brightness, although we can periodically check what the brightness is and react accordingly -- this might have an impact on battery usage, but we can minimize that if Pause in excluded apps is enabled.

When I came up with the proposal, I was thinking, "What are the options with the controls we have? Which of those is the best?" This comment got me thinking, "What's the ideal? How close can we get to that?" It was a very useful change of mindset and has given me some new ideas -- thanks :)

wavexx commented 7 years ago

On Thu, Sep 28 2017, smichel17 wrote:

I do agree that this would be ideal. Unfortunately, it is impossible to change the behavior of the system brightness control. I also don't know of any way for an app to be notified when the user changes the brightness, although we can periodically check what the brightness is and react accordingly -- this might have an impact on battery usage, but we can minimize that if Pause in excluded apps is enabled.

Could you get at least increase/decrease brightness events? (as opposed to sliding the brightness control, which I assume generates absolute values).

When I came up with the proposal, I was thinking, "What are the options with the controls we have? Which of those is the best?" This comment got me thinking, "What's the ideal? How close can we get to that?" It was a very useful change of mindset and has given me some new ideas -- thanks :)

But if you did include the backlight level in the filter settings, as opposed to just "lower to 0", it would be just a setting like the other. When changing the backlight, just update the preset value as well.

I never had more than one filter, but if I had more in addition, I wouldn't want the current brightness to influence my "dark reading" preset where I want the backlight to be always zero.

smichel17 commented 7 years ago

Could you get at least increase/decrease brightness events? (as opposed to sliding the brightness control, which I assume generates absolute values).

Nope, there's no interface at all for apps to interact with the backlight brightness that I'm aware of, aside from getting and setting the backlight values (which is done the same way you'd change any other system setting, like toggling the wifi).

But if you did include the backlight level in the filter settings, as opposed to just "lower to 0", it would be just a setting like the other. When changing the backlight, just update the preset value as well.

If possible I'd like to integrate backlight controls without increasing the number of settings. At its core, Red Moon has a pretty simple function and its design should reflect that. There are ways to do what you want without adding settings, though (for example, making the Lower backlight option multiple choice and/or combining it with Hardware button backlight).

I never had more than one filter, but if I had more in addition, I wouldn't want the current brightness to influence my "dark reading" preset where I want the backlight to be always zero.

Noted. I think the current proposal is better than any previous version, but not good enough to build, yet.

mirh commented 7 years ago

Nope, there's no interface at all for apps to interact with the backlight brightness that I'm aware of

That sounds something the kernel would care\handle https://github.com/torvalds/linux/blob/master/include/linux/backlight.h any new idea?

smichel17 commented 7 years ago

I haven't read 100% of the android documentation so it's possible there's a callback I missed somewhere, but it seems unlikely.

It's probably possible with root -- almost anything is. However, such things are typically undocumented and might be a ton of work to implement.

wavexx commented 7 years ago

On Fri, Sep 29 2017, mirh wrote:

That sounds something the kernel would care/handle https://github.com/torvalds/linux/blob/master/include/linux/backlight.h any idea?

Under vanilla linux, yes. Unified leds and backlight control is available on KMS drivers (and some others) via /proc/. Events (user and system driven) are also emitted via ACPI.

However, this might tell very little on what android actually does/has under the hood.

mirh commented 7 years ago

ARM certainly gives no fucks to ACPI... Though something else in the kernel might or might not be exposed

Again, I guess this is yet another time one of those "perfect with root - horrible pretension to be even working without" situations

AdamNiederer commented 6 years ago

Nope, there's no interface at all for apps to interact with the backlight brightness that I'm aware of

I know Lux manages to do it; the system brightness slider is entirely disabled when Lux is enabled, and one can control the system brightness and overlay opacity from the notification or the slider within the app. It targets android 5, but it's worked on 4.x in the past as well. Maybe that'll help narrow down the search or give a reversal target.

I'm pretty sure the core mechanism of action doesn't require any additional permissions, either. It asks for usage access for some unrelated features.

mirh commented 6 years ago

I'm not sure what you actually meant with "entirely disabled" (always stuck on the same setting, is not technically "disabled"), but yes there is this stupid thing since the first version of android.

It's not what dev was talking about, if you just proceeded reading the reminder of the following sentence. Could instead this or this be of any help?

smichel17 commented 6 years ago

This issue has gotten long enough that I think it's pretty unfocused.

I'm traveling this week but when I get back, I'll close this and make a new issue with a summary of the parts here that are still relevant, with some screenshots to clarify the problems.

smichel17 commented 5 years ago

Copying @decadent's comment from #21 so I don't lose it when I go to summarize this issue

I have to disagree that this can be trusted to the system's automatic brightness control. I don't know about the situation in stock Android or custom ROMs, but phone vendors' brightness algorithms are rather deficient in all phones that I've used. There are already several apps to correct this, e.g. Lux and CF.lumen, and a slew of 'dark filters' to lower the brightness below the minimum. Bundling both brightness and red filter control in one app makes all the sense.

Moreover, ambient brightness measurements can help the functionality of the red filter. E.g. if I step into a mall at night, strong red filter isn't of much use to me under the fluorescent lights: I have to disable it to see the screen.

However, I don't know about the power usage and optimization factors here. Since the system already measures the brightness anyway, I would hope that there's an event-subscription API instead of polling, or that measurements of the app instead of those of the system wouldn't make much difference. And the feature could be optional, to satisfy the power-conscious users.