Bad CompSci: Android Wallpaper Crash

There’s a bug with some Android phone models that will cause the phone to brick itself by applying a specific wallpaper.

It’s making the rounds on the Internet because, of course, the bug is ridiculous and silly, and also because tech blogs love a good story about anything that can kill or freeze a phone. Granted, this is worse than usual because it renders phones unbootable, but these stories spread like crazy because nobody wants their phone ruined.

People who know enough to be dangerous have already weighed in on the situation, offering a plausible-sounding explanation involving color spaces and rounding errors, such as the one given in the above video. You see, the wallpaper in question is using a non-sRGB color space and, according to the most common explanation, Android hits a bug when trying to convert it to sRGB. This kills the phone.

It sounds complicated enough to be true. Presenting color is a hard problem, so it sounds conceivable that there could be an edge case, gone unnoticed for years, that could brick your phone… right?

Actually, there’re a few problems with this explanation. For one thing, it’s possible to view the wallpaper anywhere else in Android – web browser, Twitter client, picture gallery – without so much as crashing the application, let alone bricking the phone. This is hand waved away by suggesting that the conversion process only takes place when the picture is set as the phone’s wallpaper, but why should that be? While the phone’s screen may not be capable of giving a true representation of the entire non-sRGB color space, Android seems capable enough of displaying what it can without any issues.

What else could be going on that would treat wallpaper images differently than any other image? Fortunately, Android is open source, so all we have to do is look at the code to discover where exactly this bug is happening, so we can figure out why it’s happening.

// TODO: Fine tune the performance here, tracking on b/123615079.
int[] histogram = new int[256];
for (int row = 0; row < height; row++) {
    for (int col = 0; col < width; col++) {
        int pixel = grayscale.getPixel(col, row);
        int y = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel);
        histogram[y]++;
    }
}

For context, the rounding error that’s causing the bug is happening on the line that’s computing the value of y. The code is combining some already-rounded RGB values without clamping the final value as a safeguard against floating-point inaccuracies. So, for some specific values of red, green, and blue, it’s possible that histogram[y] will attempt to access the 257th element, which results in an ArrayIndexOutOfBounds exception. If that exception isn’t caught, it will crash the application.

The reason this has nothing to do with color spaces is that, no matter which color space you’re working in, the red, green, and blue values will still be stored in the range 0-255. It’s just that those values represent a larger or smaller spectrum depending on the color space. That’s why falsely converting images from a smaller color space to a larger one can result in more vibrant images: colors that were closer together are now represented as being further apart, so the image looks more colorful and surreal.

However, this bug still would have been encountered, sRGB or no sRGB, because the above code has nothing to do with color spaces, only the red, green, and blue values of each pixel.

So what’s this histogram function for anyway? Turns out it’s part of a larger algorithm for computing thresholds, or edges, in an image. And what’s that for?

When an Android phone is unlocked, a brief transition is played to fade the background in. That transition relies on image threshold data to make the fade-in look – to use the technical term – nice. Since this extra computation only happens to wallpaper images, looking at the image in an app is safe, but setting it as your wallpaper isn’t. This also explains why some Android phones are immune while others are impacted: not all brands use the stock unlock transition.

Unfortunately, the “color space” explanation has already taken root. More than likely, someone opened the image in Photoshop and noticed that the color space was “weird,” never bothered to check their assumptions (how common are non-sRGB images?) nor to dig into the incongruities of the explanation (why doesn’t the phone choke on it in any other circumstance?) so now we’re stuck with this example of Bad CompSci.