Android suspend

By | February 26, 2013

In order to save battery android suspends whenever the screen is locked or after a certain timeout. Suspend shuts down the CPU and “non-essential” radios such as WiFi and GPS but not the AlarmManager, GSM and CDMA[2]. When applications need to perform important updates they can require that the CPU stays ON, this is achieved using either wake_locks directly or through the use of PowerManager or WindowManager (not very pretty keep screen ON trick). There are java and C apis to work with the wake_locks.

Wake_lock in Java

The access to the android wake_locks can be done using PowerManager. Bellow its a use case:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, “My Tag”);
wl.acquire();
..screen will stay on during this section..
wl.release();

Note that you can set any of the following lock types:

wake_lock types CPU Screen Keyboard
PARTIAL ON* OFF OFF
SCREEN DIM ON Dim OFF
SCREEN BRIGHT ON Brigth OFF
FULL ON Brigth Brigth

Wake_lock in C

Using the C api:

#include <linux/wakelock.h>

void wake_lock_init(struct wake_lock *lock, int type, const char *name)

void wake_lock_timeout(struct wake_lock *lock, long timeout)

void wake_lock(struct wake_lock *lock)

void wake_unlock(struct wake_lock *lock)
I found at least the following two lock types:

As far as I know there are only two types of wake lock in C:

  • WAKE_LOCK_SUSPEND – prevents system from suspending
  • WAKE_LOCK_IDLE – not sure about this one, I think it is supposed to prevent the system from going idle(?!)

Another way to access the wake_locks can be by accessing some /proc/ and /sys/ files such as the following:

  • /proc/wake_locks – lists the current wake_locks (name, count, expire_count, active_count, wake_count, total_time, sleep_time, max_time, last_change).
  • /sys/power/state – indicates the current system state.

Debugging can be accomplished by setting the following mask:

echo 15 > /sys/module/wake_lock/parameter/debug_mask

Theoretically to check if a device is going into deep sleep, one can use the method bellow. Unfortunately this did not work for me.

mkdir debugfs

mount -t debugfs none /debugfs

cat /debugfs/suspend/deesleep_count

Issues with wake_lock

The problem with a partial wake_lock is that although it might not directly consume power, it allows other applications to consume it while they should not be running. So battery life also depends greatly on the other apps running on the phone. Also due to this problem, android developers have redone the cpu consumption reporting system in order for it to attribute more blame to applications holding the wake_lock:

“…the reporting of this has been greatly improved in 2.3.  Now while you are holding a partial wake lock (while the screen is off), you will get 50% of the blame for all CPU during that time.  This makes it very likely that your app will show up on the CPU usage list.  I think you can assume that as 2.3 gets on more devices, you will get increasingly complaints from users as they start seeing your app to blame, instead of just having a nebulous experience of their battery life being poorer than it seems it should be with no clear cause.” [11]

Keeping services alive

Android suspends and kills applications quite often, some devices have a maximum of 15 background processes. An application can fall on the LRU list or also be killed if there is excessive memory consumption. In order for an android service to keep running, one has to define it as a foreground activity (startForeground method()) so the “system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory” [11]. Even this is not totally secure and I haven’t quite understood if this services aren’t killed as well after a 30 minute period.

From andoid:

The Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes. To determine which processes to keep and which to kill, the system places each process into an “importance hierarchy” based on the components running in the process and the state of those components. Processes with the lowest importance are eliminated first, then those with the next lowest importance, and so on, as necessary to recover system resources.

There are five levels in the importance hierarchy. The following list presents the different types of processes in order of importance (the first process is most important and is killed last):

  1. Foreground process

  2. A process that is required for what the user is currently doing. A process is considered to be in the foreground if any of the following conditions are true:Generally, only a few foreground processes exist at any given time. They are killed only as a last resort—if memory is so low that they cannot all continue to run.

    1. It hosts an Activity that the user is interacting with (the Activity‘s onResume() method has been called).

    2. It hosts a Service that’s bound to the activity that the user is interacting with.

    3. It hosts a Service that’s running “in the foreground”—the service has called startForeground().

    4. It hosts a Service that’s executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).

    5. It hosts a BroadcastReceiver that’s executing its onReceive() method.

  3. Generally, at that point, the device has reached a memory paging state, so killing some foreground processes is required to keep the user interface responsive.Generally, only a few foreground processes exist at any given time. They are killed only as a last resort—if memory is so low that they cannot all continue to run. Generally, at that point, the device has reached a memory paging state, so killing some foreground processes is required to keep the user interface responsive.

Making sure one application runs indefinitely as a background service even if the system goes to sleep is non trivial. Android does not encourage this behavior nor that it support it conveniently. Which makes sense, since most applications do not need to be running all the time and it avoids the misuse of resources.

References:
[1] Awesome suspend allround tutorial – http://arunmurthy.blogspot.com.es/2012/04/some-tips-on-android-suspendresume.html
[2] What happens with android suspend – http://stackoverflow.com/questions/5120185/android-sleep-standby-mode
[3] Android PowerManager – http://developer.android.com/reference/android/os/PowerManager.html
[4] Using wake_lock from C – http://elinux.org/Android_Power_Management
[5] How to prevent wake_locks and rationale behind it – http://forum.xda-developers.com/showthread.php?t=1878828
[6] AlarmReceiver- http://stackoverflow.com/questions/8713361/keep-a-service-running-even-when-phone-is-asleep
[7] Using WindowManager for preventing suspend – http://stackoverflow.com/questions/4628058/partial-wakelock-for-3g-in-android
[8] PowerManager – http://developer.android.com/reference/android/os/PowerManager.html
[9] Screen ON hack – http://stackoverflow.com/questions/4628058/partial-wakelock-for-3g-in-android
[10] Start in foreground – http://stackoverflow.com/questions/3856767/android-keeping-a-background-service-alive-preventing-process-death
[11] Very nice read about wake_locks – https://groups.google.com/forum/?fromgroups=#!topic/android-developers/Tg7_sUL8Ec4
[12] Mandatory check, Android power management – http://www.slideshare.net/jerrinsg/android-power-management

Leave a Reply