Why does my Android application drain battery? - android

I've written a simple application that displays some text and a little bit of graphics on screen. I'm using a Nexus 7, this is for an installation, and as such needs to be on continuously as much as 12 hours a day. However, despite being plugged in and charging, my application drains the battery completely in about 8 hours (10-15% / hour).
Apart from the infrequently-changing text and graphics, my application does two things:
It keeps the screen on, at full brightness (via WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); and
It opens two DatagramSockets, one to act as a UDP client, and one to act as a UDP server. These sockets are both opened automatically and managed by the library I'm using, OSCP5. It's open source, so I can hack it as needed, though the less the better. (KISS.)
I've tested the Nexus 7 battery life with no apps running, screen at full brightness, with a tickle every 29 minutes to keep it from sleeping, for a few hours with no battery drain at all. So, signs seem to point to the sockets. I don't have frequent communication on those sockets, they receive approximately a few KB every minute (based on user interaction with another part of the installation).
Is there anything I can do, specifically with the sockets, or any other general testing, to minimize or eliminate the battery drain? I only need to get through 12 hours, but keeping full charge while plugged in doesn't seem like it should be such a tall order...

However, despite being plugged in and charging, my application drains the battery completely in about 8 hours (10-15% / hour).
What do you have the Nexus 7 plugged into? I think it can take advantage of a high-speed charging USB port, the kind you need for most tablets (Android + iPad). I could see your results being more likely if you have this plugged into a garden-variety USB port.
So, signs seem to point to the sockets.
They're certainly a candidate, though since the WiFi radio would probably say on while the device is charging anyway, I'd be a bit surprised. To me, this feels like a CPU issue, where you're busy-waiting or something rather than blocking.
Is there anything I can do, specifically with the sockets, or any other general testing, to minimize or eliminate the battery drain?
I'd see if Traceview points out where you're consuming lots of CPU time. I'd investigate the charging port issue. I'd modify your app to mock the socket work and try to see if your problem persists -- if it does, then the issue isn't the sockets.

Well, keeping the screen on full brightness will really suck down the power. The GPS will do it too; I think those are the two biggest power sinks.
Keeping the network radios busy and keeping the cpu busy will also suck down the power. I hope you're not busy-waiting in any of your software.
Other than that, all I can suggest is that you use the high-power charger that likely came with the tablet. USB data ports are limited to 500mA current, and I've worked with more than one device that can require more than that to keep the battery alive.

Three months and endless head-desk-banging later, it turns out the culprit was my USB run. The total length is around 20'-25', and the length is attenuating the power that gets all the way through the line. Solution: powered USB hub.
So, the answer ended up having nothing to do with Android or programming at all. Sorry, SO.

Related

Triggering an action on multiple devices at the same time

I'm trying to trigger an action inside my Android app on multiple devices at the exact same time (or with the lowest delay/shift possible).
The devices are strictly similar (brand, model, version), plugged via USB to a Macbook Pro. I have 4 devices so far but the final solution will include many more so I need a solution that works with a lot of devices.
I have tried using sockets (Socket.io and regular WS) over Wifi and USB, but the delay slightly increases for each device so the action is not triggered in sync.
I also tried sending a broadcast UDP packet over USB, this gives way better results but seems very inconsistent: the max delay goes from 10 to a 100ms.
Syncing clocks was another option I was considering but not sure how accurate can it get across many devices (and NTP seems tricky on Android)
Any idea or pattern to address this kind of requirements? Thanks!
EDIT
So after doing some tests, the most accurate option was to sync the devices clocks using NTP as suggested by Sam Mason (I'm using this library). I managed to get an average 5ms shift between my 4 devices.
first some observations:
mobile devices tend to power down NICs aggressively to conserve power (I'm not sure how much this is affected by whether they are currently charging)
they also throttle their CPU frequency if they're not being used and it can take a while (i.e. milliseconds) to get them back up to speed. given that your devices are all the "same" the variance in your measurements would probably be dominated by other apps also running
measuring the delay in apps responding seems non-trivial, doing this via a network might increase variance because all devices are contesting each other (note that USB is a "serial bus" so this applies here as well). depending on how much this matters it might be worth setting up a video camera and watch their screens
that said, I'd be tempted to rely on their clocks to do this. NTP sync can be great (e.g. sub-millisecond precision is pretty easy) but probably not for mobile devices (I'd assume Android NTP clients care more about power and anything less than a few seconds is fine for humans). that said, their clocks should be pretty stable, so have your clients check in (randomly so there's less network contention, and do it a few times so the NIC is properly powered up). the clients can use this to figure out how long until the "event", then sleep until a few milliseconds before this. they can then wake up and do a busy loop checking the time (to make sure the CPU is powered up) and then continue at the appropriate time

When does the device go to sleep?

I saw a great speech from Commonsware's Mark about multithreading and using wakeful services yesterday at AppsWorld London. He recommends using WakefulIntentService or WakeFulBroadcastReceiver in some situations to ensure your app will be able to continue some long processing and prevent the device to go to sleep.
I have an app that does some background processing regularly when the device screen is off. I use AlarmManager to have it get the stuff done regularly.
Since I have a large user base (200.000 active users), I get to see all kind of weird cases when users send me some logfile. Among others I could see that on some devices after the alarm will be triggered, the app starts doing his job and then suddenly just doesn't do anything for many seconds, or even minutes (no entry in the logfile for a while). I assume this is because the phone goes to sleep.
What bugs me is that this happens only on some devices, for instance it would happen a lot on Samsung SGS2+, but not on SGS2, SGS3 or SGS4.
So what I'm wondering is: what is the policy to decide when to put the phone to sleep? Is it Android deciding or is it lower at the Linux level?
How much tweaking from the manufacturer is allowed? Shouldn't the sleep policy be part of the Android Compatibility definition?
Extra question: Are there some levels of being asleep, like several levels of CPU speed, or is it just boolean sleeping / not sleeping?
what is the policy to decide when to put the phone to sleep?
Generally speaking, if nothing is holding a WakeLock, the device is free to go into "opportunistic suspend" mode, where the CPU stops executing instructions.
Is it Android deciding or is it lower at the Linux level?
The Linux kernel -- via Android extensions originally, now rolled into the stock kernel -- handles opportunistic suspend. Userland apps, like SDK apps, can use WakeLock to block opportunistic suspend..
In terms of how the kernel is configured in terms of opportunistic suspend, I have no idea.
Shouldn't the sleep policy be part of the Android Compatibility definition?
Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise.
Are there some levels of being asleep, like several levels of CPU speed, or is it just boolean sleeping / not sleeping?
From the standpoint of an Android SDK app, and with respect to the CPU, right now, it is "boolean sleeping/not sleeping", as compared to Intel SpeedStep-style CPU frequency changes. Certain multi-core CPUs may turn on and off cores to save power, but this is generally independent from opportunistic suspend.

Does Android lower the download rate when the screen turns off?

I observed that I can download a file faster if I use wget with the screen on application,
that acquires a screen dim wake lock than doing the same without this application and
having the screen turned off.. I downloaded exactly the same file (from my apache web server) and the time is almost two times faster when I used the screen on application. To download the file I use a ported versions of wget.. And here is my question:
Does Android lower the download rate when the screen turns off?
Or due to the fact that the screen on app acquires a wake lock, forces the CPU to be always on, so more CPU cycles are spent for the download process.. I am a little bit confused..
Short answer is yes, Android sometimes does lower the download rate when the screen turns off. According to this Android bug report (starred by 90 users),
It seems that, even with "Wifi Sleep Policy" set to "Never", the wifi on some Android devices will enter Power Save mode (a.k.a. PSP mode) when the screen turns off.
PSP mode apparently causes the wifi device to sleep, but wake up periodically and ask its access point to deliver packets that were addressed to to the device while it was asleep. This necessarily causes additional, "spiky" network latency. This additional latency means that some network-oriented applications experience problems when the screen turns off.
This more or less correlates with the behavior you're describing. This issue affects only some phones, not all, and only some versions of Android. I suggest you visit the bug report above, there is a long discussion of this issue.
How to solve this issue
There is a workaround for Android 2.3 at least: You need to acquire WIFI_MODE_HIGH_PERF lock:
In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode WIFI_MODE_FULL but it operates at high performance with minimum packet loss and low packet latency even when the device screen is off. This mode will consume more power and hence should be used only when there is a need for such an active connection.
CPU clock scaling in Android
Android is based on Linux kernel, and uses CPUFreq Governors to adjust CPU frequency to conserve the battery. Exact policies and frequencies vary from vendor to vendor and are subject to change. There are also utilities that let you adjust these policies, but they all require rooted phone. Usually, Android phones lower CPU frequency and use "powersave" governor when the screen is turned off.
However, I don't think network traffic on a phone is CPU-bound. That is, even when in power-safe mode, network throughput is a bottleneck, not CPU speed.

How to stop an android device from being charged programmatically?

Is there an Android API for stop charging even though physically the charging is on?
Reading previous answers, it looks like there's no way to do this exclusively in software. However, it should be relatively easy to do it with a little hardware help - i.e. by using any Bluetooth- or WiFi-enabled smart electrical switch with open API. The phone could then switch the charger on or off programmatically whenever it feels like it.
Is there an Android API for stop charging even though physically the charging is on?
AFAIK no.
Justification:
android.intent.action.BATTERY_CHANGED is a protected intent that can only be sent by the system. Therefore you cannot duplicate or override the functionality.
You guys are all missing the point - the purpose of limiting charging is to increase battery lifespan by keeping it away from fully charged conditions (and near empty but that's a different issue). If you anticipate needing a full charge then tell it to charge to 100.
If you can't set a charge limit then the battery would rarely be idle and ideally charged when on the charger. It probably requires device level support though.
https://play.google.com/store/apps/details?id=es.guille.stopcharge uses echo "0" > /sys/class/power_supply/battery/device/charge. It works for me on a nexus 4 (rooted), as long as the device isn't fully charged (in a charging state).
Also relevant: https://android.stackexchange.com/questions/15001/how-can-i-avoid-the-battery-charging-when-connected-via-usb
Contrary to some answers indicating it's not possible, it is, indeed possible with ROOT. You can find some apps on the Play Store that will allow you to do this (with root permission, of course).
The best app that works on every phone I've tried it on is Battery Charge Limit. You can download it from the Play Store or the XDA discussion thread. The app is under active development so, if you find that your phone isn't supported, just submit an issue on its GitHub page.
NB: I am not the developer of this application.
This is unfortunately not possible. Android only have read APIs for battery data.
Battery charging control is internal to the Android kernel and battery IC modules. Manufacturers do change it from time to time, like HTC is having small cycles from 95-100% (a bad idea IMO), Samsung does stop charges as soon as it reaches 100%, but I've never seen a device able to stop charging before 100% to reduce battery aging :(.
At best if we're lucky, a sysfs interface might help do that, but it requires root and will differ from device to device.
Just to add to this. Samsung phones do not stop charging after 100%. As far as I'm aware they "trickle" charge past this point however they recommend you do not charge your phone past 100% for over 1 hour. Battery manufacturers like Anker also state the same so the idea of stopping the charge at 100% would be really useful. The risks of leaving the phone on charge are battery bloat and eventually cell rupture. I wasn't aware of this to start off with an killed my samsung battery within 3 months of owning the phone.
To expand on the original question. I've noticed some kernels allow fast charging. If they are able to alter the charge rate up could we alter the charge rate down (trickle) to meet a desired finish time (when your morning alarm goes off)??
I have installed a timer on the AC receptacle where I plug my Moto E's charger into. After guestimating how much time the battery needs to charge to about 85%, I set the timer. This is not my idea of a solution, but at least it keeps my phone from being charged to 100%, as I usually err on the short side when setting the timer.
I dont think there would be such an api. If it does exist it needs to be supported by the device manufacture as its not a pure OS lever feature. The same reason would make it a bad idea to use it as not all devices will support it.
That being said it would be a bad idea to use/implement it , mobile devices are not built to directly run from the power supply and a user will not plug in the cable if he/she did not want to actually charge the device.

Android debugging -> battery drains

Have you noticed a significant battery drain when debugging Android application on the phone?
Also, does a lot of Log.d() messages drains the battery?
Not really.
Is not your phone connected to your PC, and thus charging, while you perform debugging?
Every operation on Android drains battery, but I do not think Logging drain battery more than, say, drawing screen updates.
Yes! I just started debugging my Android apps on my phone (Motorola Droid) rather than on the emulator a few days ago because it's so much faster. Since then my battery life has become abysmal. Of course it doesn't get drained while I'm actually debugging because at that time the phone is connected to my PC and is charging from it. But the rest of the day my battery seems to drain much faster than it used to. When I look at the Battery Use screen in Settings it indicates that "Android OS" is using a significant amount of battery, far more than it ever did in the past. I have no idea what is causing this or how to fix it.
If your definition of "debugging Android application on the phone" is: you test your application while your phone is connected to your PC, then no. Your phone will charge all the time and the battery will get charged faster than it will drain, so you shouldn't have any worries.
On the other hand, if your phone isn't connected to PC, and you are calling Log.d() a LOT, let's say, 1,000,000 times in a loop, then yes, this will put a strain on your battery, since you will generate a lot of string statements that will appear under Logcat's logs and old logs will have to be discarded. Don't overdo it with logging messages.

Categories

Resources