My app holds a partial wakelock (to ensure the CPU keeps running) and also uses a proximity wake lock to turn the screen off if the user holds the phone near their face. The app plays audio to the user using its own native threads and the OpenSLES api.
The problem I have is that when the proximity sensor triggers and the screen turns off the CPU appears to slow down and the native threads can no-longer keep up and the audio stutters.
Anyone know what's going on here and if there's anything I can do about it?
Regards
Phil
What I really needed was a high performance wifi lock - it was actually the wifi that was the problem, not the CPU.
See http://developer.android.com/reference/android/net/wifi/WifiManager.html#WIFI_MODE_FULL_HIGH_PERF
Related
I'm working on an app that uses a MediaPlayer object to play H.264 MP4 videos from a WallpaperService as it is a live wallpaper app. Battery drain occurs while the device (Nexus 5, Android 6.0.1) is idle and sleeping if I pause/stop the MediaPlayer with mediaPlayer.pause() or mediaPlayer.stop(). The drain is about 3-7%/hour as tested multiple times overnight. As soon as I release the media player with mediaPlayer.release(), the battery drain goes back to a more normal 1%/hour. I pause/stop the mediaPlayer when onVisibilityChanged calls false. The phone is reporting to be going to sleep in both the stock Android battery chart and Better Battery Stats.
How can this battery drain be explained if the CPU is going into a sleep state successfully?
EDIT: Something new I've discovered is that when calling mediaPlayer.setSurface(null) right before mediaPlayer.pause(), the idle battery use comes back to normal. I can then do mediaPlayer.setSurface(surface) to set it back before mediaPlayer.start(). The problem is there's some black artifacting for a couple of seconds after restarting.
I can't give you a precise answer but can give you what to look for. I suspect what is going on is that pause() is checking for events frequently enough to keep the processor from entering the deeper sleep/C-states. In contrast, stop() doesn't need to check for events and so allows the processor to enter a deep sleep state. I wrote an article on sleep states some years back.
I suspect that the writers of the function decided to check more frequently than is necessary. This is a very common mistake due to the developers thinking that shorter sleeps / more frequent checking result in better response (which it almost never does). You can check this by using a processor power monitor that actually checks the hardware sleep states. Unfortunately, most don't and only check for processor independent "equivalents".
So let's get back to your question: What can you do about it. I can give you some advice but none of it is very satisfying:
Check for an API or data structure that allows you to set the
checking interval for pause(). By the way, I don't know of any.
Write your own. Of course, this complicates writing platform independent apps
Use an alternative media player that has done this correctly
Hammer on google until it's fixed
Like I said, none of this is very satisfying. By the way, searching the net, I found evidence that this has happened more than once with new Android releases.
Good luck and let us know what happens.
It is a well known issue that many Android phones switch off the accelerometer when the screen goes off. However something seems to have changed with Android Fit (the app). Fit keeps counting steps even when the screen goes off. If Fit is installed, then events are raised for step counting within the Fit environment and I am able to capture them using
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
.setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
I have tested this on a Samsung S4 and on a Oneplus One and in both cases the steps are counted.
How do they do that? What Android classes do they use?
My understanding is that the available method introduced since Kitkat is to implement a SensorEventListener. For example theelfismike provides code that implements this. However on many phones the step counting stops when the screen goes off. Interestingly the counting does not seem to stop if the Google Fit app is installed (hence I guess they keep the accelerometer on).
Am I missing something? Is the functionality of keeping counting steps after screen off available to the mortal programmers?
Thanks!
As Ilja said, your code runs even after the screen gets turned off. But in this case I guess we need a little different answer.
They definitely use a Service that keeps a wakelock and they query the sensors for data. Important part here is holding the wakelock - you have to prevent the device from going into sleep during lifetime of your service - if you don't want to miss some data.
But this approach will be drain the battery really fast, because in order to detect steps you need to process quite a lot of data from sensors.
Thats why there is sensor batching. That allows you to get continuous sensor data even without keeping the device awake. It basically stores the sensor events in a hw based queue right in the chip itself and only sends them to your app (service,..) at predefined intervals in batches. This allows you to do a 24/7 monitoring without draining the battery significantly. Please note that only supported chipsets can do that (you can find details in Android docs), in case of older phones you need to fallback to the hideous wakelock keeping method in order to get your data.
You can also just use Google Fit APIs, but this would only work when there're both Google Fit + Google Play Services installed on the device with monitoring turned on.
Every normal Thread is keep on working when the screen goes off or when the Activity lost its focus...but when the activity gets killed then all thread are killed...
However you can use services for longrunning tasks like asking the accelerometer for example
I have an application which records audio via microphone and directly encodes the raw PCM-data to MP3 via LAME (configured for most performance), before sending that stream via HTTP.
On my Galaxy S5, it's working flawlessly while screen is ON, but seconds after turning the screen OFF, the process get's struggling due to lack of CPU.
I'm using all known required options to prevent the device from sleeping and theoretically it's working as the CPU does not sleep, but just scaling the CPU too low:
service is running in foreground-state
I have a WIFI_MODE_FULL_HIGH_PERF-lock
and a PARTIAL_WAKE_LOCK to prevent the CPU from sleeping
priority of all affected threads is set to android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
The application is theoretically working very well and used on hundred of thousand devices meanwhile.
But if the user is using the MP3-encoder + screen off, there is a chance that the CPU doesn't deliver enough power anymore to encode + stream the data smooth.
The CPU-governor of my S5 is "interactive" - if I set it to "performance", the problem is gone.
Anybody an idea how to prevent Android from sleeping, without using root to change the governor all the time the app is in use?
I am currently working on an app that utilizes the light sensors to perform a task in my service. I used the examples from this site as my base:
Android Light Sensor
The sensors work perfectly when my tablet is plugged into the computer to debug. However, if I run the same code without it being plugged in, the response is super slow, and some times never triggers at all.
Can anyone suggest why the performance is hindered when the device is by itself?
EDIT:
I SHOULD HAVE NOTED THAT I AM TRYING TO READ THE SENSOR WITH THE DEVICE OFF. I FOUND THAT THE PROBLEM WAS THAT THE SENSOR WAS SHUTTING DOWN WHEN THE DEVICE SLEPT. PLEASE SEE MY ANSWER BELOW.
Thanks,
josh
Sometimes this is just a device issue, many have been reported as acting slow to light/proximity sensors. As far as the anomaly of the sensors responding normally when it is plugged in; maybe your device sensors simply respond faster when there is a power source.
I'd say look through your options with changing the rate
In:
https://developer.android.com/reference/android/hardware/SensorManager.html
rate rate of events. This is only a hint to the system. events may be received faster or slower than the specified rate. Usually events
are received faster. The value must be one of SENSOR_DELAY_NORMAL,
SENSOR_DELAY_UI, SENSOR_DELAY_GAME, or SENSOR_DELAY_FASTEST.
So I would imagine adding SENSOR_DELAY_FASTEST may help you.
Also, I refer you to Android SENSOR_DELAY_FASTEST isn't fast enough post.
I found that the cause of the trouble was the device shutting the CPU down, which resulted in delay or non-reading of the light sensor.
Adding a partial wake lock did fix the problem, but at the cost of high battery usage. If anyone has any suggestions as to how I can continue monitoring the light sensor with the device off without the Wake Lock I would greatly appreciate it.
Hey, I finished my code and everything works as it should but I'm wondering since smartphones have limited battery, CPU .. How can I check if my application will run good on older phones? and how can I check if my app consumes the phones battery?
Thanks
The only way to really know it to test the app in the phones.
That said, you can profile it and make educated guesses based on how CPU-intensive is your app, for how long is it running, if you have services using cpu continuously, etc.
There are a few things to consider:
The main battery drain is the screen. If you keep any kind of screen lock (even dim), it will destroy the battery.
Any other lock (wifi, etc.), will induce battery drain. Do you use them? Do you need them? Do you release them as soon as they're not needed?
Do you have hardware listeners (e.g., location, accelerometer), unregister them as soon as they're not needed
Take a look at this video: http://www.google.com/events/io/2009/sessions/CodingLifeBatteryLife.html
Also take a look on
http://developer.android.com/guide/developing/debugging/debugging-tracing.html