{"id":202,"date":"2012-02-22T20:11:14","date_gmt":"2012-02-22T19:11:14","guid":{"rendered":"http:\/\/www.sigterm.ch\/?p=202"},"modified":"2012-02-22T20:11:14","modified_gmt":"2012-02-22T19:11:14","slug":"auto-brightness-on-stock-android","status":"publish","type":"post","link":"https:\/\/sigterm.ch\/?p=202","title":{"rendered":"Auto brightness on stock Android (ICS or earlier)"},"content":{"rendered":"<p>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&#8217;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.<!--more--><br \/>\n&nbsp;<\/p>\n<h2><span style=\"color: #000000;\"><strong>Backlight is not decreasing<\/strong><\/span><\/h2>\n<p>I found the responsible source code for this\u00a0in the frameworks\/base\/services\/java\/com\/android\/server\/PowerManagerService.java class.<\/p>\n<pre class=\"brush:java\">private int mHighestLightSensorValue = -1;\n...\nprivate int setScreenStateLocked(boolean on) {\n        int err = Power.setScreenState(on);\n        if (err == 0) {\n            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);\n            if (mUseSoftwareAutoBrightness) {\n                enableLightSensor(on);\n                if (!on) {\n                    \/\/ make sure button and key backlights are off too\n                    mButtonLight.turnOff();\n                    mKeyboardLight.turnOff();\n                    \/\/ clear current value so we will update based on\n                    \/\/ the new conditions when the sensor is reenabled.\n                    mLightSensorValue = -1;\n                    \/\/ reset our highest light sensor value when the\n                    \/\/\u00a0screen turns off\n                    mHighestLightSensorValue = -1;\n                }\n            }\n        }\n        return err;\n    }\n...\nprivate void dockStateChanged(int state) {\n        synchronized (mLocks) {\n            mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED);\n            if (mIsDocked) {\n                mHighestLightSensorValue = -1;\n            }\n            if ((mPowerState &amp; SCREEN_ON_BIT) != 0) {\n                \/\/ force lights recalculation\n                int value = (int)mLightSensorValue;\n                mLightSensorValue = -1;\n                lightSensorChangedLocked(value);\n            }\n        }\n    }\n...\n        \/\/ do not allow light sensor value to decrease\n        if (mHighestLightSensorValue &lt; value) {\n            mHighestLightSensorValue = value;\n        }\n        if (mLightSensorValue != value) {\n            mLightSensorValue = value;\n            if ((mPowerState &amp; BATTERY_LOW_BIT) == 0) {\n                \/\/ use maximum light sensor value seen since screen went on\n                \/\/ for LCD to avoid flicker\n                \/\/ we only do this if we are undocked, since lighting\n                \/\/ should be stable when stationary in a dock.\n                int lcdValue = getAutoBrightnessValue(\n                        (mIsDocked ? value : mHighestLightSensorValue),\n                        mLcdBacklightValues);\n...<\/pre>\n<p>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.<\/p>\n<pre class=\"brush:java\">        \/\/ do not allow light sensor value to decrease\n        if (mHighestLightSensorValue &lt; value) {\n            mHighestLightSensorValue = value;\n        }<\/pre>\n<p>Afterwards mHighestLightSensorValue is used to actually set the new brightness:<\/p>\n<pre class=\"brush:java\"> int lcdValue = getAutoBrightnessValue(\n                        (mIsDocked ? value : mHighestLightSensorValue),\n                        mLcdBacklightValues);<\/pre>\n<p>I fixed this in my build by replacing the last code snip with this one:<\/p>\n<pre class=\"brush:java\">int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);<\/pre>\n<p>So the lcdValue is always corresponding with the light sensor.<br \/>\nI found this code, handling the auto brightness, already in Android 2.2 [froyo] and it&#8217;s still the same in Android 4.0 [ICS]. I did not analyze older code than 2.2, so I can&#8217;t exclude that the behavior was the same&#8230; Google defends their code with a comment saying they want to avoid flickering when the display is on.<br \/>\n&nbsp;<\/p>\n<h2><span style=\"color: #000000;\"><strong>Faster reaction to light sensor values<\/strong><\/span><\/h2>\n<p>Furthermore I replaced the reaction time for the sensor.<\/p>\n<pre class=\"brush:java\">private static final int LIGHT_SENSOR_DELAY = 1000;    \/\/[ms]<\/pre>\n<p>Originally the value was set to 2000. Now the auto brightness adjusting reacts a lot faster.<br \/>\n&nbsp;<\/p>\n<h2><span style=\"color: #000000;\"><strong>Change sensor levels and lcd back light values<\/strong><\/span><\/h2>\n<p>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\u00a0frameworks\/base\/core\/res\/res\/values\/config.xml. If you&#8217;re using an overlay directory for device specific configuration, e.g. device\/samsung\/sgs2\/overlay\/&#8230;, the configuration might be there.<\/p>\n<pre class=\"brush:xml\">&lt;integer-array name=\"config_autoBrightnessLevels\"&gt;\n    &lt;item&gt;15&lt;\/item&gt;\n    &lt;item&gt;150&lt;\/item&gt;\n    &lt;item&gt;1500&lt;\/item&gt;\n    &lt;item&gt;8500&lt;\/item&gt;\n    &lt;item&gt;11000&lt;\/item&gt;\n    &lt;item&gt;15000&lt;\/item&gt;\n&lt;\/integer-array&gt;\n&lt;integer-array name=\"config_autoBrightnessLcdBacklightValues\"&gt;\n    &lt;item&gt;5&lt;\/item&gt;\n    &lt;item&gt;35&lt;\/item&gt;\n    &lt;item&gt;55&lt;\/item&gt;\n    &lt;item&gt;80&lt;\/item&gt;\n    &lt;item&gt;120&lt;\/item&gt;\n    &lt;item&gt;160&lt;\/item&gt;\n    &lt;item&gt;255&lt;\/item&gt;\n&lt;\/integer-array&gt;\n&lt;integer-array name=\"config_autoBrightnessButtonBacklightValues\"&gt;\n    &lt;item&gt;255&lt;\/item&gt;\n    &lt;item&gt;255&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n&lt;\/integer-array&gt;\n&lt;integer-array name=\"config_autoBrightnessKeyboardBacklightValues\"&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n    &lt;item&gt;0&lt;\/item&gt;\n&lt;\/integer-array&gt;<\/pre>\n<p>Remember always to have one more item in\u00a0autoBrightnessLcdBacklightValues,\u00a0autoBrightnessButtonBacklightValues and\u00a0autoBrightnessKeyboardBacklightValues than in\u00a0autoBrightnessLevels. Otherwise you will encounter ArrayIndexOutOfBounds exceptions or the function will return wrong values! Because of the code below.<\/p>\n<pre class=\"brush:java\">private int getAutoBrightnessValue(int sensorValue, int[] values) {\n        try {\n            int i;\n            for (i = 0; i &lt; mAutoBrightnessLevels.length; i++) {\n                if (sensorValue &lt; mAutoBrightnessLevels[i]) {\n                    break;\n                }\n            }\n            return values[i];\n        } catch (Exception e) {\n            \/\/ guard against null pointer or index out of bounds errors\n            Slog.e(TAG, \"getAutoBrightnessValue\", e);\n            return 255;\n        }\n    }<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/sigterm.ch\/?p=202\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[10,11,12,13,16,18,24,26,48,52,55,64,87,88,89,94,95,96,138,139,148],"class_list":["post-202","post","type-post","status-publish","format-standard","hentry","category-android","tag-allow-back-light-decrease","tag-android","tag-android-auto-brightness","tag-android-back-light","tag-android-light-sensor","tag-aosp","tag-auto-brightness","tag-backlight-decrease","tag-froyo","tag-gb","tag-gingerbread","tag-gt-i9100","tag-i9100","tag-ice-cream-sandwich","tag-ics","tag-light-sensor","tag-light-sensor-delay","tag-lightsensor","tag-sgs2","tag-sgsii","tag-stock-android"],"_links":{"self":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/posts\/202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=202"}],"version-history":[{"count":0,"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/posts\/202\/revisions"}],"wp:attachment":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}