Abstract

Android* applications may increase battery consumption significantly if they use wakelocks improperly. In this document, we will give some hints and tips on how to identify No Sleep bugs related to wakelock misuse.

1. Introduction

Limiting battery power consumption is essential for smartphones. To get the best autonomy possible, Android OS is designed to opportunistically go into sleep mode as soon as it detects no user activity on the system. Some applications require the device to stay on even if there is no user interaction for a long time. Examples of this are watching a video, listening to music, using GPS, and playing a game. Android provides such a mechanism for the OS or applications in order to keep the device awake. This mechanism is called a wakelock.

The introduction of such a mechanism puts the responsibility of managing the component’s activities on the application developer. If used incorrectly, the application can drain the battery significantly even when the application is not running in the foreground.

2. Wakelock

2.1. What is it?

A wakelock is a software mechanism to control the power state of the host device. The Android OS exports explicit power management handles and APIs to specify when a particular component needs to stay on, or awake, until it is explicitly released from duty.

The wakelock mechanism is implemented in two levels: user and kernel. The figure shows the internal design of Android wakelock implementation. The user wakelock can be utilized by either high-level OS services or applications and is provided by the power management service. It allows an application to control the power state of the device. A kernel wakelock is held by the OS kernel or a driver. A user wakelock is mapped to a kernel wakelock. Any active kernel-level wakelock prevents the system from being suspended to RAM state, which is the highest power saving state for mobile devices.

2.2. Android User Wakelocks

The Android framework exports the wakelock mechanism through the PowerManager Wakelock API and identifies four types of user wakelocks:

Wakelocks can be acquired to force some of the components (CPU, screen, and keyboard) to stay awake.

Use special caution with the PARTIAL_WAKE_LOCK as the CPU will continue to run regardless of any display timeouts or the state of the screen and even if the user presses the power button. This may lead to silent power drain as the phone looks like it is in standby mode (screen is off), but is actually fully awake.

In all other wakelocks, the user can still put the device to sleep using the power button. All wakelocks, except partial wakelocks, will be implicitly released after the power button is pressed.

2.3. Android Kernel Wakelocks

Kernel wakelocks are low-level wakelocks held by the kernel. They can be acquired/ released internally from the kernel. As such, application developers have less direct control on them, but an application’s behaviour can indirectly trigger these wakelocks and increase battery consumption inadvertently.

Here are examples of kernel wakelocks.

Wlan_rx: Held by the kernel when data is sent or received over Wi-Fi*.

PowerManagerService: Is the container for all partial wakelocks.

Sync: Held while the sync process is running.

Alarm_rtc: Handles the alarm (when an application or process checks periodically on something).

Main: Keeps the kernel awake. This is the last one to be released when the system goes to suspend mode.

2.4. No-Sleep bugs

The application has to release every wakelock it acquires at some point to allow the system to go back to a deep sleep mode. This acquire/release mechanism may lead to some bugs if the wakelock is never released. A wakelock remains held even if the application holding it is not running in the foreground anymore. A wakelock is released when it is explicitly released by a release call or if the application is actually killed (force close). Leaving some wakelocks held prevents the system from going into deep sleep mode even if there is no activity, significantly increasing the power drain and silently reducing the battery autonomy. This is called a No-Sleep bug. Due to the event-driven nature of Android, developers may not think of all the code paths that their applications had acquired wakelocks and, therefore, need to close. This type of bug is called a No-Sleep bug code path.

Another occurrence of this type of bug is when the release happens before the wakelock has been effectively acquired. This can happen in multithreaded code where the acquisition and release of the wakelock happen in different threads. This is called a No-Sleep bug race condition.

The last issue is the No-sleep dilation, where the wakelock is acquired longer than what is actually necessary.

Why are these issues important to look at? According to a study made by P. Vekris: “55% of 328 applications using wakelocks do not follow our policies for no-sleep bugs” [2012]. Some major applications have been released with No-Sleep bugs. So developers need to be aware of this specific point in order for their applications to run optimally.

3. Identifying No Sleep bugs

The no sleep bug can be tackled in two ways: either a static analysis doing a code path scanning or dynamically at run time. In this paper we will focus on run-time analysis.

This method does not guarantee you’ll find all the wakelocks bugs in an application. It will however help you spot some wakelock issues if they occur during run time. To identify a wakelock issue, you need to follow a code path where the wakelock is not released. Testing an application against no sleep bugs involves manipulating the application, trying different ways to exit it, at different places in the application to see if a wakelock persists.

In some cases, it may be necessary to prevent the system from going into deep sleep even if the application is not in the foreground anymore. An application may need to perform a task in the background. This is the case, for example, if the application has to perform a long download: a video or game dataset. The application may be put in the background by the user while it’s downloading, but the phone should stay awake until the download is completed. In that case, the application may hold a wakelock until the download is completed. Of course, you should check that the wakelock is released at some point. For example, if the phone loses network connection in the middle of a download, the phone should not remain awake if the action cannot be performed anymore.

In summary, identifying a No Sleep bug is very context dependent. There is no predefined criterion that allows someone to easily identify this issue. Only common sense can assess these types of bugs.

3.1. Using adb

The tools to look at wakelocks are shell commands. For most users it is very professional, so we don’t discuss how to use it here.

3.2. Using OnePowerGuard Pro Application

OnePowerGuard Pro* is an Android app that you can download on https://www.onexuan.com. It collects information that allows you to spot battery drain, especially wakelock issues.

First, by clicking the “Battery Doctor ” button, you can check the Deep Sleep, the Battery Total Time, Radio Type, Data Conn, Screen Brightnesses, Screen On, Signal Scanning Time, Active Phone Call, wifi on, WiFi Running, Total Received and Total Send. Ideally, most of the time, the phone should be in Deep Sleep if it is not in use.

You can check the battery info and what happened every time. When the phone is in an emergency, they will be marked red.

Then you can check the kernel wakelocks. You can check the time spent within each kernel wakelock type as well as the count. High time or high counts may be symptomatic of a problem. From this report you cannot link a hotspot to a specific application or process but you can spot a specific behaviour that may be triggered by a specific application.

In the Kernel Wakelock report, the line “vbus_present”, “main”, “PowerManagerService” aggregates the time spent in user wakelocks. If this line shows a hot spot, you can drill down by checking the Partial Wakelock report.

Most of the time, the partial wakelock refers to the application that holds it. It’s a great help to find the culprit. Though some times, some activities may be launched by other apps. For example, a game may play sound through the AudioOut channel assigned to the Android Media gallery. If not coded properly, it would be the game’s fault for not closing the sound channel. It is never the Android Gallery’s fault.

The AlarmManager may signal that wake ups were caused by alarms or that an application has made numerous alarm modifications. You may want to check the Alarm section

Network entry can be useful if you suspect some high traffic on the network. The multipdp/svnet-dormancy kernel wakelock may indicate that you also have some high network usage.

4. Test Case

Let’s consider a real case. I stay in a place where Wifi signal is poor, From a user standpoint, everything looks fine. After a few minutes we check it with OnePowerGuard Pro. On the “Kernel Wakelocks” screen, you can see that the “PowerManagerService” and “deleted_wake_locks” make more the time and the count

Now let’s look at the Partial wakelocks. We can see that one partial wakelocks remain despite the fact that there is no activity. One is the ConnectivityService, which means that This wakelock is held during transition between data connections.

5. Conclusion

Wakelocks are very useful and powerful tools. But if misused, they can have a very negative effect on the device battery life, considerably impacting the user experience. It is important for developers to check during QA that their code is not causing any No Sleep bugs. They should consider using the available tools to analyse the battery impact of their application in real life usage and try to limit their impact on the customer device as much as possible.