Jeff Sharkey

Android SurfaceFlinger tricks for fun and profit

Some Android phones are now shipping with OLED displays, such as Nexus One, the Droid Incredible, and the Samsung Galaxy. Organic LED displays have separate pixel elements for each color channel (red, green, and blue), and each channel has a different efficiency.

Take, for example, the Nexus One. If powering only the red pixels at full intensity draws a current “i”, then powering all green pixels draws “1.5i”, and all blue pixels “2i”. (These ratios are derived from empirical measurements, and don’t hold in all cases.) Also, it’s worth noting that OLED displays don’t have backlights like LCD, meaning that darker colors draw less power.

If you could power only the red pixels you could save quite a bit of power.

So I started poking around SurfaceFlinger, the low-level window compositer on Android. I brushed off my OpenGL skills and after a few hours I had simple proof-of-concept. A couple hours later I had several filters between red-only and full-color:

I plugged the phone into an industrial power meter which takes very accurate current measurements, and started looking at the power needed for various color modes:

Baseline (mA) Default (mA) Red-only (mA) Green-only (mA) Blue-only (mA) Amber (mA) Salmon (mA)
Launcher 86.4 148.4 40.0 58.4 86.5 64.3 66.3
Browser 86.4 344.5 96.7 145.2 194.0 156.5 148.7
Maps 86.4 286.5 95.1 131.9 156.7 139.0 132.9
Settings 86.4 41.0 14.3 19.1 19.9 20.3 20.5
Email 86.4 337.1 94.4 142.4 187.1 153.6 146.2
Gallery 86.4 140.4 78.6 83.1 90.1 90.3 87.8

Average % of Default, OLED-only 35% 46% 56% 49% 48%
Best-case % of Default, including overall system baseline 42% 54% 65% 56% 55%

All measurements taken in airplane mode with GPS disabled. “Baseline” is the current used when showing Launcher with a SurfaceFlinger mask causing all pixels to be rendered black. (That is, everything along the pipeline was being exercised except the actual OLED pixels.)

Filtering to show only red pixels only requires 35% of the original baseline OLED panel current, on average. Adding back the baseline current, the best case overall is about 42% of the original system current, effectively doubling the battery life. Also, showing only red pixels doubles as an awesome night vision mode, perfect for astronomy. :)

If you’d like some other colors added back in, the amber and salmon filters can help, while still offering about 56% of the original system current. It’s also worth noting that the Nexus One OLED display uses a PenTile pixel layout, giving it twice as many directly-addressable green pixels as red and blue. Thus the Green-only filter results in the visually sharpest text.

(The video above is also available on YouTube.)

The actual SurfaceFlinger patch is straightforward, mostly living in LayerBase::drawWithOpenGL(). There is another patch to Development that adds options in Dev Tools for controlling it at runtime. It also reads from the sf.render_effect system property at boot.

The patches are contributed to the AOSP under the Apache 2.0 license, and cleanly apply to the freshly released froyo branch. Feel free to integrate them into your own tree to experiment, but note that you’ll need SurfaceFlinger to render in OpenGL mode, which might not be possible without specific hardware drivers.

The phone isn’t any less responsive when using these filters, but visually it can take time for your eyes to adjust. It’s more of a geeky hack, but hopefully you’ll find it useful.