Code Pollution: Background Becomes Foreground

In the Code Pollution series, I’ll be writing about topics where a coding anti-pattern may work tactically for an individual application, but strategically will be bad for Android as a whole, just as pollution may benefit one firm while harming many others.

In previous posts, I complained loudly about trying to write services that remain in memory all of the time, and extolled the virtues of using AlarmManager to convert those services into scheduled tasks (a la Linux cron jobs). That advice is still very valid, but there is one scenario that the previous posts do not take into account.

But, first, a word (or, perhaps, several words) about games.

Real-time games, like the ever-popular first-person shooter (FPS) genre, aim to push a high “frame rate”. The faster the frame rate, the smoother the animations will appear. Game developers go to great lengths to make sure their application does not stall unexpectedly due to its own code — for example, developers will avoid generating garbage and will try to run the garbage collector only at safe times.

That is all fine and well, but a persistent concern for game developers on Android is the impacts that external forces have on their frame rates. For example, a year ago, the big concern was garbage collection going on in other processes — garbage collection takes CPU time, even if that work is being done in a totally separate Linux process from the game itself.

To counteract this, the core Android team made some improvements in Android 1.6, relegating all background processing to a class that is capped in terms of CPU utilization, leveraging some Linux process and thread control frameworks. Garbage collection in those background processes will no longer hog the CPU. Hence, games can run with minimal interference…so long as background processing stays in the background.

What has come to light recently is that there are still circumstances when code that was in the background class will be promoted to the foreground, at least briefly, to prevent operating system stalls. The two documented scenarios are:

  • BroadcastReceiver objects will be brought to the foreground for the onReceive() call
  • Services will be brought to the foreground for onCreate(), onStart(), and onDestroy()

Hence, while normal background processing is CPU-capped, any processing done in the two areas shown above will be in the foreground class and could steal more significant CPU time from the game.

SEE ALSO:   CALLING ALL DEVELOPERS: Udemy kicks off 2016 with $10 online courses

And this is where the AlarmManager pattern comes in.

AlarmManager triggers a BroadcastReceiver to get control, in onReceive(), at the time an alarm goes off…which could be in the middle of a game. If that receiver attempts to do significant work in onReceive() itself, it will impact the frame rates of games being played at that time. You have long been encouraged to keep onReceive() calls short — this is just another reason to keep these to the millisecond range, not several seconds.

The best pattern, overall, for using AlarmManager is to use the BroadcastReceiver as a bridge to an IntentService. The IntentService will do whatever significant work there is in a background thread, one that should remain part of the background class and therefore will not harm game play. The downside is that the IntentService may wind up being created, started, and destroyed, and those specific operations will run in foreground priority. So long as you do not add any logic of your own to those three callbacks — relying instead on IntentService’s stock implementation — the effect should be minimal…but there will still be an effect.

The ideal solution would be for your background code to realize that a time-sensitive foreground operation is underway, so you can perhaps disable your alarms outright, or at least dial back their frequency. This could be accomplished in the operating system, but it could also be done as a community standard. We could come up with a pair of broadcast actions (e.g., GAME_ON, GAME_OFF) that everyone aims to honor. A game would broadcast GAME_ON before the game begins; those implementing alarms would respond by disabling those alarms. Similarly, the game would broadcast GAME_OFF to notify background work to resume normal operation. We would need to work out the mechanics of handling the case where GAME_OFF was not broadcast, due to crashes or evil developers.

SEE ALSO:   Did Google Shoot itself in the Foot with Nexus One?

Regardless, for those of you who use AlarmManager, please do what you can to make sure that you do as little work as possible in the foreground windows of background processes. Our ability to frag rests in your hands.

  • Rene

    I can picture myself happily reading an entire book of these gems!

  • b87

    nice article but i think that most of the readers would just skip it… separate thread for development articles would be nice on androidguys…

  • Josh

    This was a good read. I'm just starting as an Android developer so tips like this really help me get an understanding of best practices I should work towards.

    The GAME_ON/OFF idea is good in theory, but I'm sure people would abuse the GAME_ON broadcast to ensure their non-game apps run faster at the expense of other background applications.

    • Mark Murphy

      Agreed, though there may be social ways to deal with that, with "blame screens" akin to the battery usage monitor. In other words, don't block the undesired behavior, but provide mechanisms to help users find out about undesired behavior.

  • Mark

    I wouldn't call it GAME_ON since it is probably relevant to any app that needs to run at near top-speed (many games do not need this BTW).

    It feels like something that should be handled in the Android framework.

    For example, a "game" could ping the android framework every, say, second, its doing a top-speed task and so the framework knows how to prioritise CPU accordingly.

    I prefer the pinging compared to a sign-on, sign-off approach because you don't have to worry about games that forget to "sign off" etc.

  • cool go android developer.. 🙂