July 30, 2014

Google I/O 2009: Getting a Charge with Android

google_io_091Next up is Jeff Sharkey’s presentation on “Coding for Life – Battery Life, That Is”. Where Dan Morrill focused on performance in terms of speed, Jeff focused on performance in terms of battery  lifespan.

Jeff presented some interesting figures on power use, presumably working off a G1-style device. The LCD takes 90mA, more even than the CPU running at full tilt. The worst, though, are the radios, which can easily chew up 200mA when in use by an app above and beyond any other power use by the device. So while a device sitting in airplane mode could run for 24 days, we can only play YouTube videos for about 3.4 hours, due to LCD use, CPU use, and using WiFi or 3G for data transfer.

These figures get scary when you consider what it means for background processing. An app that wakes up every 10 minutes and runs for 8 seconds to poll data from the Internet (using about 350mA during those few seconds) cuts the user’s battery life in half. So, building apps that use wakeup alarms via AlarmManager can really eat up the battery.

The bulk of Jeff’s presentation was focused on how to do all of this better.

For example, in terms of networking, you might want to check the network you are on and perhaps delay work until you get on a faster network. Slow radios chew up power similar to fast radios, but since we use them for less time (for the same amount of data transfer), fewer mAh hours are burned if we can wait for a faster network connection.

Another area of potential power savings is in data parsing. Converting XML into a DOM is more expensive than XmlPullParser, for example. If you have control over both sides of the communication, you might consider a binary format, such as Google’s Protocol Buffers. On the other hand, depending on your app, you may spend so little time doing data parsing that it is not worth the optimization.

As one might expect, wakelocks (covered in an earlier Building ‘Droids post) can be expensive, particularly if you forget them and never release them. If you are using them for a foreground application to keep the screen on (e.g., for video playback), rather than manually dealing with wakelocks, consider using the android:keepScreenOn attribute in your layout XML to let Android handle the wakelocks for you, so long as your activity is visible. Or, specify a timeout, such that the wakelock will be automatically released if you forget to release it yourself.

Garbage collection chews up battery life, and so recycling objects whenever possible is a benefit for battery life as well as CPU speed (e.g., frame rates in games). Use object pools, re-use StringBuffer/StringBuilder objects, and so on. In effect, whenever you use the new operator, think of whether there is an existing object you can safely re-use.

Another point Jeff made comes in the form of services for background processing. It is easy to think of these as something that should be running all the time, like Windows services or Linux daemons. That is a simple mental model, but it does not truly map to what Android is aimed for. Rather, consider services to be short-term background actions, triggered by activities, or AlarmManager, or other system events. In particular, if possible, use IntentService (new to Android 1.5), which abstracts away the background thread and starting/stopping the short-term services, simplifying your code. But, as noted earlier, be careful about using AlarmManager for “wakeup” style events, since you are at that point forcing the device to wake up and consume more battery than it might otherwise use.