A nosy look into LiveWallpapers.apk

It first seemed that the Galaxy wallpaper was implemented in C + OpenGL (with Java calls, of course). From our tests, using Canvas was not an option, since there were just too many particles for poor humble Canvas.

And it also looked like it was using the NDK, I thought upon reading this post.

Then somebody at that forum suggested they are implemented with Processing, which made me kind of laugh internally. But the very same source he used (Romain Guy’s blog post about live wallpapers) denies that and gives some details about the Android implementation:

The prototypes are written in Processing. I did port Processing to Android to run live wallpapers and performance was not on par with what we wanted, so we implemented something called RenderScript #

Digging deeper, I downloaded the /system/apps/LiveWallpaper.apk file from the phone to my computer (using the DDMS perspective from within Eclipse), uncompressed it (it’s a ZIP file in disguise) and inspected its contents to see if I could locate where was the code the guy in the first post shown. And I indeed could :-)

The .rs files (for “RenderScript”, I deduct) are all in res/raw. They have names such as galaxy.rs, grass.rs, nexus.rs and so on. And they look like this:

#pragma version(1)
#pragma stateVertex(PVBkOrtho)
#pragma stateRaster(parent)
#pragma stateFragment(PFBackground)
#pragma stateStore(PFSBackground)

#define ELLIPSE_RATIO 0.892f

#define PI 3.1415f
#define TWO_PI 6.283f
#define ELLIPSE_TWIST 0.023333333f

float angle;

/**
 * Script initialization. Called automatically.
 */

void init() {
    angle = 50.0f;
}

/**
 * Helper function to generate the stars.
 */

float randomGauss() {
    float x1;
    float x2;
    float w = 2.f;

    while (w >= 1.0f) {
        x1 = 2.0f * randf2(0.0f, 1.0f) - 1.0f;
        x2 = 2.0f * randf2(0.0f, 1.0f) - 1.0f;
        w = x1 * x1 + x2 * x2;
    }

    w = sqrtf(-2.0 * logf(w) / w);
    return x1 * w;
}

float gSpeed[12000];

/**
 * Generates the properties for a given star.
 */

void createParticle(struct Particles_s *part, int idx, float scale) {
    float d = fabsf(randomGauss()) * State->galaxyRadius * 0.5f + randf(64.0f);
    float id = d / State->galaxyRadius;
    float z = randomGauss() * 0.4f * (1.0f - id);
    float p = -d * ELLIPSE_TWIST;

    int r,g,b,a;
    if (d < State->galaxyRadius * 0.33f) {
        r = (int) (220 + id * 35);
        g = 220;
        b = 220;
    } else {
        r = 180;
        g = 180;
        b = (int) clampf(140.f + id * 115.f, 140.f, 255.f);
    }
    // Stash point size * 10 in Alpha
    a = (int) (randf2(1.2f, 2.1f) * 60);
    part->color = r | g<<8 | b<<16 | a<<24;

    if (d > State->galaxyRadius * 0.15f) {
        z *= 0.6f * (1.0f - id);
    } else {
        z *= 0.72f;
    }

    // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
    d = mapf(-4.0f, State->galaxyRadius + 4.0f, 0.0f, scale, d);

    part->position.x = randf(TWO_PI);
    part->position.y = d;
    gSpeed[idx] = randf2(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;

    part->position.z = z / 5.0f;
}

// etc

It might be baptised as RenderScript but it no doubt smells like C from a couple of miles away: #pragma’s, #define’s, struct’s and ->’s for pointing to members? You can’t help thinking it’s C, no matter how hard you try.

More deductions: either this RenderScript uses a gcc compiler in the very phone (not that unlikely since it’s a Linux system after all?) or it parses the contents of the script on loading time. Then it’s “just” a wrapper for OpenGL calls and generally cumbersome stuff such as preparing textures, vertex shaders etc (I can see something related to vertex shaders in the galaxy wallpaper, for example).

I’ve copy-pasted the full galaxy.rs source code into a gist, just in case you want to see the whole thing but don’t have a phone and a DDMS environment handy :-)

City Ambient EP (Live at BCN)

Comments

  • The source code is publicly available at android.git.kernel.org, no need to unpack apks :) Also RenderScript is not quite C. It’s very similar, but it’s not a scripting language, and it’s not compiled with GCC. On currently released phones it uses a custom compiler called ACC (available in our source tree) but we’ve replaced it with LLVM internally and added a lot of nice features (built in support for vectors, etc.) I’ve also talked about RenderScript at Devoxx 09 and you can find the slides + video at parleys.com.

  • Well, thank you for the heads up, Romain! The info is much appreciated!

    It seems I wasn’t nosy enough… Of course the wallpapers are published — I found the source here as you said.

    I’ll watch your Devoxx conference to learn more about this RenderScript thingie, it looks very interesting!

    One thing though, it’s odd that the conference is not available at Google Tech talks channel or something. I’m pretty sure it would get way more exposure.

    Thanks again :-)