Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WakeLock finalized while still held

Tags:

The pm and keepScreenOn variables are globally defined.

I grab the PowerManager.WakeLock in my OnCreate method:

pm = (PowerManager) getSystemService(Context.POWER_SERVICE); keepScreenOn = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_LOCK,"tpd"); 

in my onStart, onResume, and onRestart I grab the lock with

if (keepScreenOn == null) {     keepScreenOn = pm.newakeLock(PowerManager,SCREEN_BRIGHT_LOCK,"tpd"); } keepScreenOn.acquire(); 

in my onDestroy, onPause, and onStop I release the lock with:

if (keepScreenOn != null) {   keepScreenOn.release();   keepScreenOn = null } 

After my app exits I get a failure screen and adb complains that

java.lang.Exception: WakeLock finalized while still held: tpd

Tracing shows that I released the lock before exit. What have I missed?

There is no way out of the app without crossing at least one of onPause, onStop, or onDestroy. I can see that the app called release() as often as it called acquire() so even though the wakelock is reference counted it should still have zero refs.

like image 364
Tim Daly Avatar asked May 07 '11 11:05

Tim Daly


1 Answers

Ok I believe I found the problem.

The WakeLock is reference counted. That means that if a second acquire() happens it will just bump the reference count. Every call to acquire() needs to be protected by a call to isHeld() as in:

if ((keepScreenOn != null) &&           // we have a WakeLock     (keepScreenOn.isHeld() == false)) {  // but we don't hold it    keepScreenOn.acquire(); } 

I had assumed that acquire() on a lock I held did nothing so multiple acquire() calls caused the problem. Since the reference count is not zero the GC throws an error.

like image 102
Tim Daly Avatar answered Sep 28 '22 19:09

Tim Daly