Disabling Screen-Off Animation In Android

I am impressed by the amazing progress Android’s UI has made since its inception. With each iteration, likewise in software as in hardware, its usability and aesthetics have steadily improved to the point where I can now confidently buy one for my mom to replace the iPhone I recommended to her only last year.

On the other hand, one particular "feature" I intensely dislike is the screen-off animation that emulates the brief white flash you see when an old CRT TV monitor is powering off. Introduced in Gingerbread (2.3), it seems not to bother most people as much as it bothers me, and even seems to be quite popular (e.g., this thread).

I was glad to learn though that a number of people find it as annoying as I do, for example in this thread and this bug.

As a CyanogenMod fan, I was quite happy with the straightforward checkbox in the Settings app in CyanogenMod 9 that toggled whether to play this animation. In CM10, this option was removed, but there was an easy hack involving changing window animation scale in the developer settings, as explained in the second link above.

So when I updated to CM10.1 M1, I was very unpleasantly surprised to find that this hack does not work any more either. I tried to immediately downgrade to CM10, but then discovered that doing so requires a full data wipe (of course…). A quick search pulled up this thread which proposes a simple prop edit, but the following posts in the thread suggest mixed results.

So, stuck with CM10.1, and really disgusted at this turn of events, I finally decided to put on my hax0r gloves and get this annoying "feature" out of my face once and for all.

Poking Around

I went to androidxref.com and started searching the Android source code for "screen off animation". (OK, I actually started out with grep, but it didn’t take me long to realize androidxref.com was about sixty million times faster - it’s really pretty cool.)

I quickly found why changing the window animation scale in Jelly Bean 4.1 (and CM10) disables the screen-off animation. The two snippets of of code implementing this behavior are at line 470 and line 2228 of PowerManagerService.java.

In Jelly Bean 4.2 (and CM10.1), however, these parts of the code have been completely refactored. The snippet of code that launches the screen-off animation is now found at line 704 of DisplayPowerController.java. Note that this new DisplayPowerController class has been factored out of the old PowerManagerService class, and both have moved into a separate power sub-directory.

The Hacking

Disclaimer: I am NOT responsible for anything that happens to your phone or you or your house or your relationship with your wife if you follow the instructions down here. If you don’t know what you’re doing and are scared of bricking your phone, just give up and go watch Superbowl. Please.

What did not change, I found, is that this code gets packaged into /system/framework/services.jar on the Android system. So, let’s take a look at this file as found in the CM10.1 image on my phone:

# Copy services.jar from phone to current directory.
adb pull /system/framework/services.jar
# Disassemble.
apktool d services.jar

(apktool is a tool that extracts and disassembles Android APK/JAR files, and is available for Linux, Windows and OS X.) This produces a directory, services.jar.out, which contains the disassembled code of services.jar we just pulled from a connected phone. I dived into the DisplayPowerController code and edited the else clause at line 704 to essentially just say setScreenOn(false); directly instead of running the animation first. If you look at the dissassembled code, you’d realize Dalvik bytecode is really quite readable and easy to hack, especially since the line number hints allow you to directly map a line in the Java source code to the corresponding Dalvik instructions. I just had the Java source file on androidxref.com open in a browser tab for reference and killed instructions line by line. You can download my patch here and apply it like this:

patch -d services.jar.out -Np1 < path/to/disable_screen_off_animation.patch

(For CM10.1 nightlies (after the MR1.1 merge) and CM10.1 M2, use this patch instead. The same piece of code was shuffled around to line 777. For CM10.1 M3, use this patch instead.)

Now re-assemble the code and push it back on to the device:

# Re-assemble modified sources as services-mod.jar.
apktool b services.jar.out services-mod.jar
# Copy services-mod.jar to /sdcard/ on phone.
adb push services-mod.jar /sdcard/
# Remount /system partition as read-write in order to modify it.
adb shell su -c 'mount -o rw,remount /system'
# Overwrite original services.jar on phone with services-mod.jar as root.
adb shell su -c 'cp /sdcard/services-mod.jar /system/framework/services.jar'
# Reboot phone for this to take effect.
adb reboot

When the phone reboots, it will say Android is upgrading and will rebuild Dalvik cache for each application, so it might take a while. But hey, it’s worth it.

Parting Words

The final product, if you just want to replace the services.jar on your phone, is here:

  • CyanogenMod 10.1 M1 - tested on Galaxy Nexus (maguro) and Nexus S (crespo), should work on other phones as well (can’t promise - let me know):

  • CyanogenMod 10.1 M2 - tested on Galaxy Nexus (maguro), should work on other phones as well (can’t promise - let me know):

  • CyanogenMod 10.1 M3 - tested on Galaxy Nexus (maguro), should work on other phones as well (can’t promise - let me know):

  • CyanogenMod 10.1 RC1 - tested on Galaxy Nexus (maguro), should work on other phones as well (can’t promise - let me know):

  • Stock 4.2.2 (takju/JDQ39) - for "takju" factory image from Google

  • Stock 4.2.2 (yakju/JDQ39) - for "yakju" factory image from Google

Apply the services-mod.jar to your phone like this (obviously assuming you have adb working and root):

# Copy services-mod.jar to /sdcard/ on phone.
adb push services-mod.jar /sdcard/
# Remount /system partition as read-write in order to modify it.
adb shell su -c 'mount -o rw,remount /system'
# Overwrite original services.jar on phone with services-mod.jar as root.
adb shell su -c 'cp /sdcard/services-mod.jar /system/framework/services.jar'
# Reboot phone for this to take effect.
adb reboot

Or, I suppose, you could just use ES File Explorer with root mode enabled, mount /system as read-write and copy the file to /system/framework/services.jar on the phone.

Note that a reboot is needed after you replace the services.jar whatever you do, and upon the first reboot the "Android is upgrading" dialog will pop up.

About the author

I am a software engineer by profession and a passionate technology geek in my free time.