Battery Drain

Android Programs and Drivers are designed to consume almost to no power when your Andoid device screen is turned off. The device enters a so called Deep Sleep mode. This saves the battery and makes the device work longer on a single charge.

However the Deep Sleep mode could be disturbed by bad behaviour of Programs and or Drivers. When the device is in Deep Sleep mode every once in a while some processes need to do something, like polling for e-mail or Whatsapp messages. This causes a so called WakeLock. The Deep Sleep mode is interrupted and the device uses more battery.

WakeLock

If your device uses much more Battery than you expect, or gets even hot, you have a WakeLock problem on your device.

To check this is very simple. Leave your device screen off for an hour. Then goto Settings > Battery > Click on the graph.

On the right you see a Dutch Battery screen. Look at the horizontal blue line "Wakker". If there is too much blue when your Screen On (line below) is off you have a problem.

Google Play Services NlpWakelock

The most heard problem is massive wakelock time from a service called NlpWakelock. It stands for Network Location Provider and is used by the Google Play Service.

This problem beheaviour occurs when Wifi is set for "always on" and you have choosen to "Use Wifi..." in the Location Service settings. Switch that off and use gps only. Gps doesn't consume very much power on Android!

Also in the advanced Wifi settings at "Keep Wifi on during Sleep" avoid "Always On" and choose "Only when plugged in" or "Never".

If you need Wifi nlp you can try to Stop and clear the data of the Google Play Services at Application Settings.

Just found another "Google Play Service" problem. It has to do with Portable Fitness Wear. The Wear Service keeps waking up your device (every 15 minutes).

But most don't have any wearable fitness device. What is the point Google? Bug? Some disable the service for now with Disable Service app from the store:

UserPresenceService (com.google.android.gms.auth.be.proximity.authorization.userpresence.UserPresenceService)

Note: version 6.5.87 of Google Play Service seem to have solved it (25 nov 2014)

Note2: To clear all settings for Google Play Services you can goto Apps and stop and Clear data fro both Google Play Services and Google Services Framework.

Data from Google Play Services is also stored in the gservices db from Google Services Framework!

If that fails and you have rooted phone do this:

    • adb shell

    • su

  • stop

    • rm -r /data/data/com.google.android.gms

    • rm -r /data/data/com.google.android.gsf

    • sync

    • reboot

    • Google Play Services will take a few minutes, be patient

You may have to remove and add your Google account again from the Android Settings menu.

Disable Google Play Services is not a good idea: pm disable com.google.android.gms

Android and newer gapps (store, maps, gmail etc) need Google Play Services nowadays.

Finding Wakelock problem

Now you know you have a Wakelock problem you need to find out what is causing it.

There is a small free app in the Play Store called Wakelock Detector or use BetterBatteryStats (both only root)

If you run it it will collect the number of Wakelocks since you turned the device on. You see per application how many Wakelocks occurred and the total time. In this example the FM radio was recording. So that continued after the screen turned off.

Next is Gmail that checked for e-mail 9 times.

Without rooted phone

If you have adb access you can use dumpsys batteryinfo or batterystats to find the responsible process causing wakelocks.

Like dumpsys batteryinfo|grep "Wake lock"

You can also use dumpsys alarm or dumpsys | grep -C 1 wakeups to find more info on wakelocks.

Look at the Alarm Stats for Alarm Manage. You cannot escape the android.intent.action.TIME_TICK.

More Wakelock info can be found in logcat. You can use this command: logcat -d | grep 'WakeLock start' | sort

That will give you the pid and use ps <pid> to find the process responsible for that wakelock.

Newer Android versions als have the /proc/wakelock file. You can view this text file with cat /proc/wakelock

More info here from intel.

dumpsys batteryinfo shows:

Per-PID Stats:

PID 422 wake time: +6m49s763ms

PID 422 wake time: +32s210ms

PID 723 wake time: +16s405ms

PID 151 wake time: +11s206ms

PID 422 wake time: +172ms

PID 422 wake time: +20s373ms

PID 422 wake time: +5s424ms

PID 2505 wake time: +28s52ms

PID 2522 wake time: +5s774ms

PID 2690 wake time: +26s715ms

PID 422 wake time: +3s135ms

PID 11887 wake time: +1m20s633ms

PID 422 wake time: +8m53s148ms

PID 11501 wake time: +59s733ms

PID 2505 wake time: +339ms

PID 2690 wake time: +602ms

PID 422 wake time: +6s532ms

PID 2522 wake time: +3s493ms

PID 422 wake time: +339ms

PID 31786 wake time: +94ms

PID 1126 wake time: +35ms

PID 30364 wake time: +94ms

PID 531 wake time: +413ms

PID 32641 wake time: +6m38s447ms

PID 1893 wake time: +637ms

PID 2505 wake time: +10s987ms

PID 422 wake time: +780ms

Now PID 422 can be found with: ps|grep 422

system 422 149 493688 79952 ffffffff 4027bb94 S system_server

To find last cpu usage (and battery consumption and minor/major page faults) use dumpsys cpuinfo

Load: 11.03 / 11.05 / 12.38

CPU usage from 58447ms to 21204ms ago:

94% 35/kswapd0: 0% user + 94% kernel

3.8% 32530/com.google.android.gm: 3.3% user + 0.5% kernel

0.3% 422/system_server: 0.3% user + 0% kernel / faults: 74 minor

.....

0% 1007/thermald: 0% user + 0% kernel / faults: 95 minor

253% TOTAL: 9.8% user + 243% kernel

We have a VM memory configuration problem with kswapd0 using so much cpu. Over 94% the last 30 seconds. Later more about kswapd0.

Digging deeper

With dumpsys batteryinfo|grep "Wake lock" I found a massive wake lock problem for vbus (micro usb charging)

Finding what causing it is very hard. It has something todo with battery, usb and power manager.

It was time to dig deeper with: grep -C 10 -i vbus /proc/kmsg

(end the command with CTRL+\ ENTER)

Now you get much more info on what is happening during this vbus wake lock.

Freezing the apps

Android comes with system apps, phone manufacturers add a few of their own too. Not all are usefull.

More running apps consume more battery. Take a look at your installed applications and Freeze unneeded/unused aplications.

Note:

If you cannot Freeze / Disable an application you need to root the phone and rename the apk of that application in the /system/app folder (don't remove the apk but rename it. Add .OFF to the original filename:

Example: Browser.apk becomes Browser.apk.OFF

Disable auto updates and notifications in apps

Some packages like Google PlayStore, Maps and Youtube keep running as a service to provide updates and notifications. For more battery life you better disable notifications and auto updates. This can be done in each app, generally in the Settings menu. You can check if their services stop running in Android settings menu > Apps then tab Active.

Wifi sleep timeout

Save more power if you set the Wifi connection to go to sleep when the screen turns off. The default time before it Wifi is shut down is 15 minutes.

You can set this Wifi sleep timeout if you have a rooted device. This example sets it to 300000 msec, 5 minutes.

In adb shell:

sqlite3 /data/data/com.android.providers.settings/databases/settings.db "INSERT INTO secure (name, value) VALUES ('wifi_idle_ms', '300000');"

content insert --uri content://settings/secure --bind name:s:wifi_idle_ms --bind value:i:300000

settings put secure wifi_idle_ms 300000

Note: Android 4.2+ has it in the global settings table.

Linux processes and high cpu

Apart from Android apps the underlying Linux processes can also cause high cpu and thus excessive battery usage. These don't show in the Android Battery stats.

For example keep an eye on the kswapd0 process (use top -m 1). It could be using very high cpu if you misconfigure memory management. This will be hours at 80% or more.

PID PR CPU% S #THR VSS RSS PCY UID Name

35 0 80% R 1 0K 0K root kswapd0

1455 0 2% S 20 384964K 91784K bg u0_a0 com.nng.igoprimoisr.javaclient

32525 0 2% R 1 1152K 424K root top

931 0 1% S 5 6016K 456K root /system/bin/mpdecision

428 1 1% S 118 503360K 77156K fg system system_server

This kswapd lock issue, causing high cpu and battery drain, will occur on devices without swap device. You can beat it by changing VM settings.

dumpsys batteryinfo|grep -C 1 kswapd0

Proc kswapd0:

CPU: 0ms usr + 39m 6s 0ms krn

The kswapd solution that worked for me was:

  • vm.swappiness to 60 (default 60)

  • OOM ADJ levels 0,1,2,4,9,15

    • OOM MB levels not too low (advised: 6144,8192,10240,12288,14336,16384 which are 24,32,40,48,56,64 MB)

  • vm.min_free_kbytes to 4096 (or higher)

  • vm.overcommit_memory to 1 (default 0)

  • vm.overcommit_ratio to 50 (default 60)

You can also disabling OOM all together (disarm it):

echo 9999 > /sys/module/lowmemorykiller/parameters/adj # OOM adj level for process to kill

echo 1 > /sys/module/lowmemorykiller/parameters/minfree # kill if free mem reaches (4kb blocks)

Disable Kernel Samepage Merging (KSM) since it has little memory gain and cost you battery due to constant cpu usage (about 5%)

Edit your build.prop and set :ro.config.ksm.support=false or put this in your install-recovery.sh: echo 0 > /sys/kernel/mm/ksm/run

Or change the parameters to be less aggressive:

pages_to_scan 20 and sleep_millisecs 7000 (which is default anyway without init.rc settings)

From /init.rc:

on property:ro.config.ksm.support=true

write /sys/kernel/mm/ksm/pages_to_scan 100

write /sys/kernel/mm/ksm/sleep_millisecs 500

write /sys/kernel/mm/ksm/run 1

You can monitor the device cpu state with a builtin option in the Developer options section. Scroll down and select Show CPU usage. It will overlay CPU consuming running processes with a load bar for each process. Keep it running for a few days to keep an eye on kswapd0 for example.

Auto Airplane mode at night

Another way to save battery is to switch to flightmode at night. There are a lot of programs to do that. Like ES Task Manager: Battery > Others

Cyanogen Mod Roms have that in the Alarms / Time settings.

GSM instead of CDMA

Default your phone will be on the in CDMA mode or GSM/CDMA automode. It will prefer the CDMA/UMTS network (HSPDA/3G) which is fast for data connections. But CDMA uses much more battery the GSM. If you don't need very fast connections switch to GSM only mode. The data will be 1G or Edge, which is enough for Whatsapp and e-mail.

CPU's and governor

The governor looks at how much cpu you request from the device and scales up and down. On sigle core cpu's there is only the cpu frequency to adjust. When having a multi cpu device cores can switch on and off too. On single core the "ondemand" governer will do a good job. On multicore devices I recommend the "hotplug" governor. (if you use stock rom)

Another way to save battery is to limit the cpu frequency to a max value (underclock) or to switch of cpu cores, or both. My experience is that switching off cpu cores doesn't help much. Underclocking does save battery at the cost of a little performance.

Example from a /etc/install-recovery.sh file:

# set max cpu lower than the max 1.209 Ghz on a quad core

echo 1 > /sys/devices/system/cpu/cpu1/online

echo 1 > /sys/devices/system/cpu/cpu2/online

echo 1 > /sys/devices/system/cpu/cpu3/online

echo 754000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

echo hotplug > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

Check for available frequencies the file /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies and for the governors

/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors (root access needed)

Reset the battery statistics

From an adb shell you can reset the battery statistics. Use this command: dumpsys batteryinfo --reset or for newer Android dumpsys batterystats --reset

Throttle Service polling

The Throttle Service (data bandwidth) is polling every 600 seconds by default. This causes wakelocks. You can increase it polling by setting this time to 3600 or 86400.

You need a SQLite editor on your rooted device. Edit the settings db and go to the secure or on newer versions the global table. Add a new record called throttle_polling_sec and set it to 3600.

Reboot. Setting it to 0 will never let your phone sleep! Bad idea.

I have not found a way to disable this android.net.IThrottleManager service from the command line. The am command only provides the startservice option.

The ThrottleService is started with /system/bin/system_server at boot.

dumpsys throttle

The threshold is 0, after which you experince throttling to 300kbps

Current period is 2682000 seconds long and ends in 783077 seconds.

Polling every 86400 seconds

Current Throttle Index is 0

mMaxNtpCacheAge=86400000

Period[0] - read:0, written:0

Period[1] - read:0, written:0

Period[2] - read:0, written:0

Period[3] - read:0, written:0

Period[4] - read:0, written:0

Period[5] - read:0, written:0

Edit: you can disable the throttle service with this command: setprop persist.bandwidth.enable 0 or ndc bandwidth disable

Bluetooth park state mod (Bluez stack)

I noticed that bluetooth consumed a lot of battery on my phone when I started using it all day. Then I learned that the bluetooth "park state" feature was switched off for compatibility reasons by Samsung. You can find this setting in /etc/bluetooth/main.conf

The variable is called DefaultLinkPolicy. Mine was set to 7 (so without the park state feature)

Set it to 15: role switch(0x0001), hold mode(0x0002), sniff mode(0x0004) and park state(0x0008)

DefaultLinkPolicy=15

and test if your carkit or headset is still working well over a few days. You will notice way less battery drain on your phone.

...