应用程序结束时是否会释放wakelock

14 篇文章 1 订阅
2 篇文章 0 订阅

http://stackoverflow.com/questions/4697873/does-the-android-os-release-a-wakelock-if-the-app-or-service-holding-it-is-kille

10




I have question about wakelock. In cases shown below, does android OS release wakelock (PARTIAL_WAKE_LOCK if you need to specify) to prevent wakelock was left acquired and wasting battery until turning power off (not sleep).


Case 1-a:
App has acquired wakelock (w/o timeout option) in one of its threads (please think it is reasonable in this case) and it was designed to release wakelock when critical task was finished. App can be killed by taskmanager or notorious taskkiller, and app has no chance to let its thread release wakelock. What happens to that wakelock?


Case 1-b:
(If answer to case 1-a is "Yes, don't worry", then please ignore this case.) Same as case 1-a but app gave timeout option to wakelock, say 3 seconds. Is this timeout option kept valid?


Case 2-a:
Please imagine there is a service which was started by AlarmManager (via Broadcast receiver) and the service has acquired a wakelock (w/o timeout option). This service is designed to make wakelock-acquired-time minimum. But unfortunately, Android OS picked this service to kill due to memory crunch. (I don't know if OS won't kill service when wakelock is acquired, but I guess OS doesn't care. But I hope OS will release wakelock later.) What happens to that wakelock?


Case 2-b:
(If answer to case 2-a is "Yes, don't worry", then please ignore this case.) Same as case 2-a but service gave timeout option to wakelock, say 3 seconds. Is this timeout option kept valid?
android android-source wakelock kill-process android-wake-lock
shareimprove this question

edited Apr 28 '13 at 2:02
StarPinkER
6,63611648

asked Jan 15 '11 at 3:51
Tomcat
4351025

add a comment
3 Answers
active oldest votes
up vote 13 down vote accepted



WakeLock Implementation Overview


When we use pm.newWakeLock to create a new wakelock, the PowerManager simply creates a new WakeLock object and returns. The WakeLock object is not a binder object, so it cannot be used through multiple processes. However, in that WakeLock object, it contains a Binder object named mToken.


    WakeLock(int flags, String tag) {
        mFlags = flags;
        mTag = tag;
        mToken = new Binder();
    }


So when you call acquire or release on this WakeLock object, it actually passes that token to PowerManagerService.


    private void acquireLocked() {
        if (!mRefCounted || mCount++ == 0) {
            mHandler.removeCallbacks(mReleaser);
            try {
                mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);
            } catch (RemoteException e) {
            }
            mHeld = true;
        }
    }


Look at how PowerManagerService works when acquiring or releasing a wakelock will help you answer your question.


void acquireWakeLockInternal(IBinder lock, int flags, String tag, WorkSource ws,
        int uid, int pid) {
    synchronized (mLock) {
        ...
        WakeLock wakeLock;
        int index = findWakeLockIndexLocked(lock);
        if (index >= 0) {
            ...
            // Update existing wake lock.  This shouldn't happen but is harmless.
            ...
        } else {
            wakeLock = new WakeLock(lock, flags, tag, ws, uid, pid);
            try {
                lock.linkToDeath(wakeLock, 0);
            } catch (RemoteException ex) {
                throw new IllegalArgumentException("Wake lock is already dead.");
            }
            notifyWakeLockAcquiredLocked(wakeLock);
            mWakeLocks.add(wakeLock);
        }
        ...
    }
    ...
}


The key statement is the lock.linkToDeath(wakeLock, 0);. That lock is exactly the mToken we mentioned before. This method registers the recipient (the wakeLock) for a notification if this binder goes away. If this binder object unexpectedly goes away (typically because its hosting process has been killed), then the binderDied method will get called on the recipient.



Notice that the WakeLock in PowerManagerService is different from the WakeLock in PowerManager, it is an implementation of IBinder.DeathRecipient. So check out its binderDied method.


    @Override
    public void binderDied() {
        PowerManagerService.this.handleWakeLockDeath(this);
    }


The handleWakeLockDeath will release that wakelock.


private void handleWakeLockDeath(WakeLock wakeLock) {
    synchronized (mLock) {
        ...
        int index = mWakeLocks.indexOf(wakeLock);
        if (index < 0) {
            return;
        }


        mWakeLocks.remove(index);
        notifyWakeLockReleasedLocked(wakeLock);


        applyWakeLockFlagsOnReleaseLocked(wakeLock);
        mDirty |= DIRTY_WAKE_LOCKS;
        updatePowerStateLocked();
    }
}


So I think in both cases in your question, the answer is don't worry. At least in Android 4.2 (where the code comes from), it is true. Moreover, there is a finalize method on the WakeLock class in PowerManager, but this is not the key to your question.



结论是会释放wakelock。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值