Jeff Mixon

Just another WordPress site. Literally.

RSS Feed

Examining build.prop tweaks for Android ICS: A comprehensive guide (Part 1)

Android build.prop file

Android devices are great. They can easily be hacked and tweaked to seemingly no end. There’s a lot of great info out there detailing step-by-step instructions on how to perform various enhancements to your particular device. Unfortunately, there is also a fair amount of misinformation being disseminated via forums and blogs that can have a very negative effect on your device. Just because you can change something doesn’t necessarily mean you should. In this guide, I will walk through various common Android build.prop settings and evaluate whether or not you should actually change them on your Android ICS device, MythBusters style.

windowsmgr.max_events_per_sec – BUSTED

As the name implies, this property specifies how quickly the system is allowed to process certain events before throttling occurs. Specifically, this property is used by the InputDispatcher when processing screen touch and movement events. This value will really only come in to play with extremely rapid touch events, such as swiping or scrolling. The default value for this property is 90, and Google explains why:

// This number equates to the refresh rate * 1.5. The rate should be at least
// equal to the screen refresh rate. We increase the rate by 50% to compensate for
// the discontinuity between the actual rate that events come in at (they do
// not necessarily come in constantly and are not handled synchronously).
// Ideally, we would use Display.getRefreshRate(), but as this does not necessarily
// return a sensible result, we use '60' as our default assumed refresh rate.
result = 90;

Many build.prop tweaks set this value to 300, but it seems this is a bad idea. As Google points out, Android maxes out at 60fps. The default value is already allow for a possible max_events_per_sec of 90. Even if you allow for 300 max_events_per_sec, you’ll only ever see 60 of these events in any given second. Therefore, any value much higher than 90 is unlikely to have any noticeable impact on your experience in general. Additionally, setting this value too high can starve other UI events that need to get processed, viz. touch inputs. You’re not likely to feel like your device is running very smoothly when it is busy processing thousands of scroll events instead of responding immediately to you clicking to try and open a link or an app. There may be some specific scenarios where increasing this value does appear to improve system feedback, but changing this value for all UI events across the board will likely cause more problems than it will solve.

dalvik.vm.heapgrowthlimit and dalvik.vm.heapsize - BUSTED
Android devices are getting buffer every day and along with that, the amount of RAM devices have available has increased significantly. Devices with 1GB of RAM are now common; some are even equipped with 2GB already.

This is one property that has cropped up recently in various build.prop recommendations for ICS. Typical suggested values range from “48m” all the way up to “256m”, likely motivated by the common misconception that more is better. The real purpose of this property is much less obvious than one might initially guess. It is also another one you should probably avoid changing.

In ICS, the dalvik.vm.heapgrowthlimit property takes over as the effective dalvik.vm.heapsize property. Applications will be restricted to the value set by this property by default. Google has this to say about it:

// The largest size we permit the heap to grow.  This value allows
// the user to limit the heap growth below the maximum size.  This
// is a work around until we can dynamically set the maximum size.
// This value can range between the starting size and the maximum
// size but should never be set below the current footprint of the
// heap.

An indeed, we can see this enforced in several places in the Heap and HeapSource structures. Including:

if (overhead + HEAP_MIN_FREE >= hs->maximumSize) {
        LOGE_HEAP("No room to create any more heaps "
                  "(%zd overhead, %zd max)",
                  overhead, hs->maximumSize);
        return false;
    }
 
    heap.maximumSize = hs->growthLimit - overhead;

As we see here, the heap’s maximum size is determined by the growthLimit variable on the HeapSource structure. We can also see a check to ensure there is enough total heap space available to begin with before attempting to create the new heap. At first blush, it looks like like growthLimit (dalvik.vm.heapgrowthlimit) is redundant and synonymous with maxiumSize (dalvik.vm.heapsize). It seems that could set the dalvik.vm.heapgrowthlimit to 64M and the dalvik.vm.heapsize to 256M and only the growthLimit value would be used to govern a heap’s maximum size. That’s where this interesting method comes in:

/*
* Removes any growth limits.  Allows the user to allocate up to the
* maximum heap size.
*/
void dvmClearGrowthLimit()
{
    ...
    gHs->growthLimit = gHs->maximumSize;
    size_t overhead = oldHeapOverhead(gHs, false);
    gHs->heaps[0].maximumSize = gHs->maximumSize - overhead;
    gHs->heaps[0].limit = gHs->heaps[0].base + gHs->heaps[0].maximumSize;
    ...
}

This method effectively removes any limitation set by dalvik.vm.heapgrowthlimit and sets the maximum heap size to the value defined by dalvik.vm.heapsize (or the hard-coded default of 16M). This method is wired up straight to the Dalvik runtime implementation as a native call and we can see it defined here:

static void Dalvik_dalvik_system_VMRuntime_clearGrowthLimit(const u4* args, JValue* pResult)
{
    dvmClearGrowthLimit();
    RETURN_VOID();
}
 
...
 
const DalvikNativeMethod dvm_dalvik_system_VMRuntime[] = {
...
    { "clearGrowthLimit", "()V",
        Dalvik_dalvik_system_VMRuntime_clearGrowthLimit },
...
};

And if we keep chasing this rabbit “up” the rabbit hole, we can see it finally in action here in the ActivityThread Java class:

if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
        }

This flag is set by a relatively new attribute (API level 11) which you can add to the application element in an Android application’s manifest file.

So what does this all mean? The dalvik.vm.heapgrowthlimit property limits how large an Android application’s heap can get before garbage collection has to be attempted. The dalvik.vm.heapsize property defines an absolute maximum for the heap size for an application even when the largeHeap flag is set in the manifest. Google’s motivation behind doing this was clearly to limit the heap size to a reasonable amount for most applications, but also give some flexibility to app developers who know they’re going to need the largest heap size possible to run their application.

Should you change this setting? Probably not. The ICS default for a phone with (at least) 1024MB of RAM is 64m. You can check your specific phone’s value as the hardware vendor can override this themselves when they build the ROM. But don’t let the disparity between 1024 and 64 bother you; most mobile apps should not have any problems with 64MB of heap size unless the developers are naughty. When this limit is reached, a garbage collection routine will remove obsolete objects from memory reducing the heap size down considerably in most cases. It is extremely unlikely raising this value to reduce GC routines will have any perceptible effect. If anything, it could cause other apps or the general system to suffer from too many stale objects sulking around in memory. Garbage collection will inevitably occur either way, and when it does, the size of the heap will likely have a direct impact on the cost of the routine.

The point is, it is impossible for a user to optimize for every application using this system-wide setting. This responsibility falls on application developers to optimize their applications, not users. The largeHeap flag was created to allow developers to do just that. If you do feel compelled to experiment with this setting regardless, be mindful that an application could have up to two heaps at once. Thus, the heap growth limit value should always be, at most, a little less than half of the maximum allowable heap size.

debug.performance.tuning – BUSTED

This property doesn’t appear to exist in the ICS code base. Incidentally, I also don’t see it in Gingerbread (2.3.6). It’s possible this value is specific to only certain custom implementations of Android, such as Cyanogenmod, but as far as I can tell, this one does nothing.

video.accelerate.hw – BUSTED

Again, this one appears to do nothing in ICS.

persist.adb.notify – CONFIRMED

This one disable the USB debugging notification when you have your device connected to a computer. We can see this used here:

        private void updateAdbNotification() {
            if (mNotificationManager == null) return;
            final int id = com.android.internal.R.string.adb_active_notification_title;
            if (mAdbEnabled && mConnected) {
                if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;

This is a good one to disable (set to “0″) if you want to declutter your notification bar.

persist.sys.purgeable_assets – BUSTED

This one claims to free up memory, however it is nowhere to be found in the Android code base. This one is a patch made to Cyanogenmod 7 to do some Bitmap hackery. It may not even exist in CM9. Unless you are running CM7, or possibly CM9, this property has no effect.

persist.sys.use_dithering – BUSTED

Another Cyanogenmod-specific property. This will have no effect on stock ICS.

dalvik.vm.execution-mode – BUSTED

This property can set the execution mode of the Dalvik VM. The VM can run in three modes: fast, portable, and very likely JIT. It is possible to compile Android without JIT support, but the default is to include it. In general, JIT is the execution mode you are going to want on your device. This is why you will see most build.prop files setting this property to “init:jit”. However, this is unnecessary since the default execution mode is JIT:

#if defined(WITH_JIT)
    gDvm.executionMode = kExecutionModeJit;
#else
...

As I mentioned before, WITH_JIT compiler flag is set by default in ICS, thus there is no need to define this setting in your build.prop. If WITH_JIT flag was set to false, setting the execution mode to JIT would have no effect anyway.

dalvik.vm.dexopt-flags – PLAUSIBLE

This property can set various options that affect how the Dalvik runtime performs optimization and verification. Suggested values range from turning bytecode verification off completely to enabling object registry mapping and precise garbage collection. Setting “v=n” will turn off bytecode verification, which while in all practicality is unlikely to cause any problems directly, it is a severe violation of the whole Java trust and security model.

On the other hand, setting “m=y” will turn on the register map for tracking objects to garbage collect. Incidentally, this also enables “precise” garbage collection, which, as you may have guessed is a slightly more accurate way to track objects for garbage collection. By accurate we mean less likely to falsely identify an object as still in use when in fact it is no longer being used. This would, in theory, be a more efficient mechanism to free up unused objects, and thus increase available memory (RAM).

Enabling precise GC seems like a good idea as long as your device has the muscle to spare, but I can not find enough information to know for sure what the total implication is to using precise GC versus conservative. I suspect it likely a trade-off of more cpu cycles per collection to obtain more free RAM. You will have to decide which one is more important to you based on your device capabilities and personal tolerance levels. This is assuming that the difference will even be perceptible in a real-world environment, which I suspect would be less than profound, if any at all.

ro.media.dec.jpeg.memcap – BUSTED

This property is one of many that promises to make your audio and visual experience better. Unfortunately, not only is it only related to JPEG decompression, it is completely unused in ICS (and Gingerbread for that matter) and has no effect on your device.

At first, it looks kind of promising:

// Key to lookup the size of memory buffer set in system property
static const char KEY_MEM_CAP[] = "ro.media.dec.jpeg.memcap";

Ok, cool. The property exists at least. However, that’s the only place this is referenced. The KEY_MEM_CAP is never used anywhere. If we look a little closer, we’ll come across this:

/* Check if the memory cap property is set.
   If so, use the memory size for jpeg decode.
*/
static void overwrite_mem_buffer_size(j_decompress_ptr cinfo) {
#ifdef ANDROID_LARGE_MEMORY_DEVICE
    cinfo->mem->max_memory_to_use = 30 * 1024 * 1024;
#else
    cinfo->mem->max_memory_to_use = 5 * 1024 * 1024;
#endif
}

This looks like exactly where this property should be used, but isn’t. The value is clearly hardcoded here. In fact, if we look up the Skia project source tree on Google code, we can see that the latest version has this variable commented out now with the following comment:

/* For non-ndk builds we could look at the system's jpeg memory cap and use it
 * if it is set. However, for now we will use the NDK compliant hardcoded values
 */
//#include <cutils/properties.h>
//static const char KEY_MEM_CAP[] = "ro.media.dec.jpeg.memcap";

ro.media.enc.hprof.vid.bps – CONFIRMED

This one is generally grouped together as a general “media” enhancement tweak. This particular property controls the “high” bit rate at which videos are encoded using the Android stock camera application. That means if you are using a third party camera app, this setting will have no effect. Let’s take a look at the snippet.

mVideoBitrate = getInt("ro.media.enc.hprof.vid.bps",
                               "ro.media.enc.lprof.vid.bps",
                               360000, 192000);

While the default values may seem very low, these are very unlikely to ever be necessary. When a device manufacturer deploys the production ROM, they will define many properties in a different property file (viz. “system.prop”), which will contain values specific to the hardware. Those values are going to be used instead of the hard coded ones we see here.

For example, if I launch a shell on a Galaxy S3 and run the following command:

getprop ro.media.enc.hprof.vid.bps

I will get a value back of “12000000″, even though I do not have this property defined in my build.prop. This is because it was defined in the default.prop file by Samsung knowing the capabilities of the device and the camera.

This setting can definitely be useful if these values are important to you, just be sure you’re not setting the value to the same (or worse yet lower!) than what is already defined on your device. While you’re at it, you may want to tweak some of the other values:

ro.media.enc.hprof.aud.bps
ro.media.enc.hprof.codec.vid
ro.media.enc.hprof.codec.aud
ro.media.enc.hprof.aud.hz

The names are pretty self-explanatory, but you can find out more info about each one with a little bit of Google’ing.

Summary

The build.prop file is a powerful tool for root users to modify the behavior of various aspects of the Android experience. However, there are no secret values here that are going to instantly make your phone run faster, better, smarter, or more efficiently. In fact, if you don’t know what you are doing, you can actually decrease the performance of your device. Over time I will investigate more build.prop properties to determine which ones can actually enhance your Android experience and which ones only create a placebo effect.

Series NavigationExamining build.prop tweaks for Android ICS: A comprehensive guide (Part 2) >>
Tags: , , , , , , .
  • Trackbacks
  • Comments
  • bfoster68
    July 24, 2012

    Love the detail Jeff. looking forward to Part 2

  • User
    July 31, 2012

    Hi, nice write up! I was wondering if you had any thoughts about the following under ICS:

    ro.kernel.android.checkjni=0
    ro.kernel.checkjni=0
    ro.config.nocheckin=1

    Thanks!

    • Jeff
      July 31, 2012

      I’ll definitely include them in my Part 2 post. Thanks!

  • Arrancamos
    August 2, 2012

    Great Jeff, I’m writting a tweak tool that lets you take backups of build.prop & gps.conf and change their values with a recommended option, so the user just do some clicks and changes are made easy. It is useful for me because I used to change ROMs like I do with my underwear ^^

    of course it lets you save/load/restore original tweaks/settings respectively.

    So man, hope you keep investigating about this because my spare time it’s not enough.

  • Pete10
    August 22, 2012

    Nice overview, waiting for the next part. Will it also cover some init.rc commands (setprop net.tcp…)?

  • Mr. S
    September 14, 2012

    Your code formatting looks a little broken: there are instances of > and < in some of the snippets.

    Great write-up, however!

  • Crack
    October 8, 2012

    Great! Looking forward to part 2!

  • oreo
    October 14, 2012

    Wow, great guide! Lemme suggest all the 3G tweaks, classes and the net.tcp.buffersizes for part 2, and the power collapse/sleep mode/fast dormancy ones!

    Also does setting google DNS (8.8.8.8 8.8.4.4)help?

    • oreo
      October 14, 2012

      I think a huge collection of all those is stored here: http://forum.xda-developers.com/showthread.php?t=1887997
      There’s the ones you already covered, all the other “most used” ones and a LOT of tweaks I didn’t even know they existed.

      • Jeff
        October 15, 2012

        Thanks for the link. I’m putting together a list for Part 2 now so I’ll definitely try and hit some of those you mentioned.

  • Andrea Budelacci
    October 22, 2012

    Hi,
    is there a way to disable/enable the spell_check_enable via build.prop ?

  • Fo
    October 29, 2012

    wow this is the most helpful build.prop article for ics so far! Great job!

    +1 for mythbustering this file :D

  • AnhNguyen
    November 4, 2012

    Where is the part2 ? thanks for good information

  • Jeff
    November 5, 2012

    Part 2 is up!

  • cheryl
    January 17, 2013

    Thanks your site came up quick on Google!

  • Leo
    February 10, 2013

    Hi Jeff.
    I’d like to ask you: Does this build.prop tweaks explanatory article of yours apply to/for smartphones running Gingerbread 2.3.4?

    Or nothing of this has to do with GB and it only is for ICS?

    I’d like to read it all, anyway, but I’d like to know if it will be fine to use these tweaks for GB. Partially? None at all? Only specific ones? Please do try to help me :(

    My phone is the Xperia Pro (Mk16, rooted) running Stock GB 2.3.4. It works so fine (gaming, browsing, multimedia, etc) that I think no tweak could ever improve its beautiful performance. So I’m reading about this build.prop tweakings just to get knowledge to experiment and see.

    I hope to get an answer from you soon : ) And if it not applies, please do try to make something like this for GB :(

    Leo.

    • Jeff
      February 11, 2013

      Leo, All these tweaks are from the perspective of Ice Cream Sandwich. Most, if not all, of the findings still apply in Jelly Bean as well. However, Gingerbread code base is significantly different than ICS and I’m not really looking through it very thoroughly as I go through various properties. However, I do point out a few times that after a cursory inspection of GB code, many of these properties don’t existing in GB either.

  • Guilherme
    February 23, 2013

    Everywhere on XDA they post those tweaks like its going to make a miracle. Thanks for sharing your invaluable knowledge with us Jeff.

  • gUmz
    January 30, 2014

    Hello could you please make a review of Build.prop for Jelly Bean. Many thanks

    [WORDPRESS HASHCASH] The poster sent us ’0 which is not a hashcash value.

  • GB
    May 24, 2014

    thx for sharing knowledge

Leave a Reply

*