PowerManager newWakeLock.acquire() not working as expected - android

I want my app to keep the CPU running but turn the screen off to minimise power wastage.
Previous posts on this subject suggest the following approach:
mPm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.WAKE_LOCK_TAG);
mWakeLock.acquire(); //keep CPU running, turn screen off
The manifest contains:
<uses-permission android:name="android.permission.WAKE_LOCK" />
In my innocence I expected that on acquiring the lock the screen would go off immediately but nothing happened.
The earlier posts I have read never seem to overcome this problem, did anyone succeed? Is there anything else I must do?

It would be more efficient in another way to use this within the onCreate method of the activity:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
That is a better way to use wake-locks in a efficient manner.

The wake lock does not turn off the screen. Normally, when the screen goes off, your application pauses because the CPU is put to sleep. If you have PARTIAL_WAKE_LOCK, your app will continue to run and the CPU will be active even when the screen goes off (due to auto or manual sleeping). Only use this if you really need to continue processing data after the screen is off. You mention you are concerned about minimizing power usage, acquiring a wake lock of any kind can cause waster power. It is wise to follow this warning from the PowerManager docs
Device battery life will be significantly affected by the use of this
API. Do not acquire PowerManager.WakeLocks unless you really need
them, use the minimum levels possible, and be sure to release them as
soon as possible.
So it is good idea to evaluate why you think you need a wake lock for your task. If you think it is too save power, it isn't.

Related

Android: When is WakeLock needed?

If I have an IntentService that simply updates the SharedPreference, is a (partial) WakeLock needed?
I understand that a WakeLock keeps the CPU awake, but when is it needed?
If you need to keep the CPU running in order to complete some work before the device goes to sleep, you can use a PowerManager system service feature called wake locks. Wake locks allow your application to control the power state of the host device.
Creating and holding wake locks can have a dramatic impact on the host device's battery life. Thus you should use wake locks only when strictly necessary and hold them for as short a time as possible. For example, you should never need to use a wake lock in an activity.
One legitimate case for using a wake lock might be a background service that needs to grab a wake lock to keep the CPU running to do work while the screen is off. Again, though, this practice should be minimized because of its impact on battery life.
Unfortunately, some poorly-coded, malicious, or simply buggy apps might create an abnormal amount of undesirable wakelocks. Other apps require constant Internet access in order to operate in a normal fashion - Facebook and Messenger are probably the most popular representatives. They persistently request information from the web (the so-called "polling" for new events), which is causing subsequent wakelocks.
In other cases, an update to a given app can also cause certain issues, which usually result in partial wakelocks. The latter keep your CPU constantly humming in the background, sometimes without your knowledge, and prevent your device from "going to sleep". That's a pretty substantial prerequisite for anomalous battery drain. Thus, it is advisable to regularly monitor the wakelocks on your device and see which of your apps go harsh on our system's resources.
Read more at:
What-are-wakelocks-how-they-affect-the-battery-life-of-your-Android-device-and-how-to-Greenify
Reference: https://developer.android.com/training/scheduling/wakelock.html
It is needed when you don't want CPU to sleep when user locks the screen for example.
If you have an IntentService without acquired WakeLock it will pause after a while if user locks the screen and it will continue its work when user wakes a device. With WakeLock acquired your service will work even if the screen is locked.
As #My God mentioned, it impacts on battery life a lot, so, use it only when you really need to finish some operation and you cannot wait till user wakes a device.

For which kinds of work I need to use CPU WAKE_LOCK in Sleep Mode?

For which kinds of work I need to use CPU WAKE LOCK ? For example in Sleep Mode I am using TelephonyManager getCellLocation(), should I use PARTIAL_WAKE_LOCK in this case or not? I didn't find this info in the documentation. P.S. TelephonyManager has different API implementation on different devices so for me it looks tricky. Thanks.
**Flag Value CPU Screen Keyboard**
PARTIAL_WAKE_LOCK On* Off Off
SCREEN_DIM_WAKE_LOCK On Dim Off
SCREEN_BRIGHT_WAKE_LOCK On Bright Off
FULL_WAKE_LOCK On Bright Bright
Incase you keep getting the location regularly even when the phone screen is turned off, use a partial wake lock to do so. From the above table we can see that a partial wake lock only keeps the CPU on while screen and keyboard is off(you dont require them as you just want to get location). Anyways refer to the below link for more info on WAKE LOCKS
http://developer.android.com/reference/android/os/PowerManager.html
Also refer to this question on SO, can be helpful
How can I keep my Android service running when the screen is turned off?
After some investigation looks like for all operations that can not be triggered from Manifest using system intents.

Is it possible to detect motion when screen is off?

My app simply need to detect any motion of the device while screen is off.
I know that accelerometer is used for this task but it don't work while screen is off in all devices. this is a list of devices http://www.saltwebsites.com/2012/android-accelerometers-screen-off
so is there a way of taking accelerometer sensor data while screen is off that works on all devices?
or is there a way to detect motion using another sensors?
Partial Wake Lock is all you need to access accelerometer readings while the screen is off.
You can use it like this:
private PowerManager.WakeLock mWakeLock;
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();
And after you're done, just release the lock:
mWakeLock.release();
If you obtain accelerometer data in a Service, you could simply acquire lock in it's onCreate() and release in onDestroy().
Yes you can use accelerometer in the background or when screen is off
but you need to hold a WakeLock [Link] to prevent the device from sleeping.
If you need to detect if the device is still or if it started moving again you might be interested in Recognizing the User's Current Activity from Google Services.
After a quick research I found that most of android devices does not send the accelarometer events when the screen is off. To know more about this bug please take a look on here. Also here too.
When the screen is off the CPU goes to sleep and you cannot capture events without taking a partial wakelock. I suggest you to take a partial wakelock when you call the onPause and release it onResume. Be careful with wakelocks they make your phone drain a really big amount of energy, you should manage them carefully.
PS: You have to acquire the wakelock in the onPause method because if you try to call it somewhere else you might not be able to gain it because the CPU may be already shutted down.

Are wake_locks automatically released when an Activity/Service holding it is terminated or finishes?

I know that it is best practice to release a wake_lock as soon as it is no more needed, but what happens if the Activity or Service, for example, that has acquired it finishes or is stopped before you release the lock? Is it automatically released by the system? I think the system should release them automatically in that case, but I can not find anything on the API docs..
EDIT: added more info
Looking at the PowerManager.WakeLock documentation, I've seen that the wake_locks are reference counted by default (read setReferenceCounted here), i.e. if we retrieve a wake lock in an activity with PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "myWakeLock"); wl.acquire(); and then the reference variable wl that holds it goes out of scope, then the wake lock is released because its reference count goes to zero... is it right?
EDIT: wrong understanding above
I think I've misunderstood the reference count concept above... it should mean that if I acquire twice the lock and release it only once, then the reference count is 1 and the lock is not yet released. If it is not reference counted, then I can acquire x times and then with a single release it is released.
There seems to be a lot of misinformation spread on the web about this. WakeLocks as exposed in the Android API have a pretty complex lifecycle and there is really no other way than be super diligent about managing it.
If an Activity or Service stops without you releasing a wakelock the state is undefined. If you inspect the code (https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/PowerManager.java, search for "class WakeLock") you will see that they are released when they are garbage collected.
This, "when they are garbage collected", however, is an extremely loose statement. In practice it seems that devices pre-Lollipop er really slow to GC the wakelocks (we can pretend it's not happening at all for practical purposes), but on post-Lollipop devices with the ART runtime it seems that stray WakeLocks are garbage collected within a few seconds.
On your questions about reference counting, you can see in the Android code that the lock is released disregarding what count it has.
If you do a blame on the Android code you can also see that it has not changed much over the years - so it all comes down to how the GC behaves. So you need to be diligent, store the lock in a field on your activity/service and release/acquire in sensible places in the app lifecycle. But if at all possible you should not be using a wakelock, but just the Force Screen On trick that Gatekeeper links to in one of the other answers.
Only if the process is destroyed then will the wakelocks be released. Just by finishing the service / Activity wake_lock will not be released.
I believe this answer will help you leaps and bounds Force Screen On
The PowerManager API states that you should release a wakelock as soon as possible, using the PowerManager API is known for draining more battery. Also in it API it states:
*If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers and even after the user presses the power
button. In all other wakelocks, the CPU will run, but the user can
still put the device to sleep using the power button.
http://developer.android.com/reference/android/os/PowerManager.html
As detailed in this answer if the process is killed then yes the wakelock is released. But if the service or activity finishes normally without releasing the answer should be no.

PARTIAL_WAKE_LOCK when recording sensor data

I am recording sensor data such as Accelerometer, Orientation, Gyroscope. This data writes to a file onSensorChanged update every so often.
My problem is when I put the phone into standby that the sensor data stops writing to file. So I done some research and decided to set it up using PowerManager and using the wake lock
PARTIAL_WAKE_LOCK: I just can't get it working.
SCREEN_DIM_WAKE_LOCK: My code will work grand.
From what I read up on there seems to be a problem with using PARTIAL_WAKE_LOCK.
I can't seem to find a definite answer on whether or not there is a problem with it still or there isn't. I even tried some of the hack approaches people have suggested such as using an itent to capture when screen is off and then unregistering the sensors and registering them again. But this solution didn't work. From what I can gather it seems inconsistant if it will work or not and seems phone dependant. I have tried my code on both a HTC Wildfire running Android2.2 and Nexus S running Android2.3.
My application is an app that is basically ran in the background with a long running service. So having PARTIAL_WAKE_LOCK is important with battery life.
This is only defined to work as of Android 2.3. Prior to that the platform would explicitly turn off all sensors when the screen turns off in order to reduce battery use.
This is a pretty old question, I'll still answer it as pretty much all the devices today are beyond 2.3
Create a background service and use the Partial Lock Wake in the following manner:
First take care of the permissions (in the manifest file):
<uses-permission android:name="android.permission.WAKE_LOCK" />
Then, most preferably use this in the Application file, or wherever:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
if(/*condition*/) {
wakeLock.acquire(); //keep CPU awake
} else {
wakeLock.release(); //disable keep CPU awake
}
Although it is a pretty cool feature, it drains your battery life, hence use it responsibly.

Categories

Resources