Recently I stumbled across Androids auto brightness feature/bug. On all Android phones I ever possessed, the auto brightness was working as expected. When you enter a brighter area the display gets brighter. Returning back to a darker zone the display gets dimmed. On my own AOSP(Android Open Source Project)-build my phone display never got dimmed. When a certain brightness level was reached the display stayed on this level, even if I covered the light sensor. The brightness remained so until the phone got locked and/or the phone display went off. I tested this behavior on three Google phones: Nexus One, Nexus S and on the Galaxy Nexus. On other phones I could not reproduce this. All phones I’ve tested were on their original software. The fact detecting this on Google phones (AOSP builds) but not on others tells me that many phone providers (e.g. Samsung) are not happy with it and changed this behavior by themselves.
Backlight is not decreasing
I found the responsible source code for this in the frameworks/base/services/java/com/android/server/PowerManagerService.java class.
private int mHighestLightSensorValue = -1; ... private int setScreenStateLocked(boolean on) { int err = Power.setScreenState(on); if (err == 0) { mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0); if (mUseSoftwareAutoBrightness) { enableLightSensor(on); if (!on) { // make sure button and key backlights are off too mButtonLight.turnOff(); mKeyboardLight.turnOff(); // clear current value so we will update based on // the new conditions when the sensor is reenabled. mLightSensorValue = -1; // reset our highest light sensor value when the // screen turns off mHighestLightSensorValue = -1; } } } return err; } ... private void dockStateChanged(int state) { synchronized (mLocks) { mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED); if (mIsDocked) { mHighestLightSensorValue = -1; } if ((mPowerState & SCREEN_ON_BIT) != 0) { // force lights recalculation int value = (int)mLightSensorValue; mLightSensorValue = -1; lightSensorChangedLocked(value); } } } ... // do not allow light sensor value to decrease if (mHighestLightSensorValue < value) { mHighestLightSensorValue = value; } if (mLightSensorValue != value) { mLightSensorValue = value; if ((mPowerState & BATTERY_LOW_BIT) == 0) { // use maximum light sensor value seen since screen went on // for LCD to avoid flicker // we only do this if we are undocked, since lighting // should be stable when stationary in a dock. int lcdValue = getAutoBrightnessValue( (mIsDocked ? value : mHighestLightSensorValue), mLcdBacklightValues); ...
In the copied code we see the mLightSensorValue never gets smaller. Its restored to -1 when the class get initialized, the phone gets locked, phone display is off or when ever the phone receives a dockingEvent.
// do not allow light sensor value to decrease if (mHighestLightSensorValue < value) { mHighestLightSensorValue = value; }
Afterwards mHighestLightSensorValue is used to actually set the new brightness:
int lcdValue = getAutoBrightnessValue( (mIsDocked ? value : mHighestLightSensorValue), mLcdBacklightValues);
I fixed this in my build by replacing the last code snip with this one:
int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
So the lcdValue is always corresponding with the light sensor.
I found this code, handling the auto brightness, already in Android 2.2 [froyo] and it’s still the same in Android 4.0 [ICS]. I did not analyze older code than 2.2, so I can’t exclude that the behavior was the same… Google defends their code with a comment saying they want to avoid flickering when the display is on.
Faster reaction to light sensor values
Furthermore I replaced the reaction time for the sensor.
private static final int LIGHT_SENSOR_DELAY = 1000; //[ms]
Originally the value was set to 2000. Now the auto brightness adjusting reacts a lot faster.
Change sensor levels and lcd back light values
Finally I changed the sensor triggers for the auto brightness, intended to have more levels and reach better battery life. As you may notice I took pretty low lcdBacklightValues. This configuration is hardly depending on your phone, I use this values on my Samsung Galaxy SII (GT-I9100). You find the configuration in frameworks/base/core/res/res/values/config.xml. If you’re using an overlay directory for device specific configuration, e.g. device/samsung/sgs2/overlay/…, the configuration might be there.
<integer-array name="config_autoBrightnessLevels"> <item>15</item> <item>150</item> <item>1500</item> <item>8500</item> <item>11000</item> <item>15000</item> </integer-array> <integer-array name="config_autoBrightnessLcdBacklightValues"> <item>5</item> <item>35</item> <item>55</item> <item>80</item> <item>120</item> <item>160</item> <item>255</item> </integer-array> <integer-array name="config_autoBrightnessButtonBacklightValues"> <item>255</item> <item>255</item> <item>0</item> <item>0</item> <item>0</item> <item>0</item> <item>0</item> </integer-array> <integer-array name="config_autoBrightnessKeyboardBacklightValues"> <item>0</item> <item>0</item> <item>0</item> <item>0</item> <item>0</item> <item>0</item> <item>0</item> </integer-array>
Remember always to have one more item in autoBrightnessLcdBacklightValues, autoBrightnessButtonBacklightValues and autoBrightnessKeyboardBacklightValues than in autoBrightnessLevels. Otherwise you will encounter ArrayIndexOutOfBounds exceptions or the function will return wrong values! Because of the code below.
private int getAutoBrightnessValue(int sensorValue, int[] values) { try { int i; for (i = 0; i < mAutoBrightnessLevels.length; i++) { if (sensorValue < mAutoBrightnessLevels[i]) { break; } } return values[i]; } catch (Exception e) { // guard against null pointer or index out of bounds errors Slog.e(TAG, "getAutoBrightnessValue", e); return 255; } }
Whoa, great walkthrough of the AOSP brightness code. Thanks.
I’m porting AOSP/CyanogenMod 9 to the Samsung Galaxy Tab 7 Plus and brightness stuff is easier than RIL so… that’s where I started!
Hi,
Is there a way of changing this on an existing ROM? I have one installed which I like very much, the only thing bugging me is the extremely slow reaction time of the Light sensor… 🙁
Thanks!
Hi,
Is there a way of changing this on an existing ROM? I have one installed which I like very much, the only thing bugging me is the extremely slow reaction time of the Light sensor… 🙁
Thanks!
@Andre: I’m afraid that’s not possible. This must be changed in the source code. You could suggest the change to your ROM developers, maybe they will integrate into the next release.
@Andre: I’m afraid that’s not possible. This must be changed in the source code. You could suggest the change to your ROM developers, maybe they will integrate into the next release.
Hello:
great slove the auto brightness issue on Android ics,
but in Jelly bean it have different code
in PowerManagerService.java
Hello:
great slove the auto brightness issue on Android ics,
but in Jelly bean it have different code
in PowerManagerService.java
@lemon
I did not check the code on JellyBean or later yet. This post is only valid for ICS or earlier…
@lemon
I did not check the code on JellyBean or later yet. This post is only valid for ICS or earlier…