手动释放定时唤醒锁

时间:2014-02-28 16:16:58

标签: android wakelock

在我的后台服务中,我使用acquire()(不带参数)获取部分唤醒锁定,并在我不再需要它时手动释放它。

那时,一些Xperia用户抱怨Xperia的Stamina模式出现问题。我发现了这篇文章:Optimizing for Sony's Stamina Mode

  
      
  1. 不要使用唤醒锁   唤醒锁通常对功耗非常不利,因为它们使整个Android系统保持清醒状态。如果使用了唤醒锁定,请确保它们是定时唤醒锁定,以便长时间不存在所采用的唤醒锁定。为唤醒锁定时间,以便在任务完成后释放它。您可以在Java Monday的示例中看到它。
  2.   

所以我开始使用定时唤醒锁(使用acquire(timeout)代替acquire())。问题在于发布。我仍在手动发布,因为在大多数情况下,我不会比超时到期更快地需要锁定。

问题是自动释放。我会解释一下。定时获取是以这种方式实现的(取自android-19来源):

public void acquire(long timeout) {
    synchronized (mToken) {
        acquireLocked();
        mHandler.postDelayed(mReleaser, timeout);
    }
}

mReleaser初始化如下(来自android-19来源):

private final Runnable mReleaser = new Runnable() {
    public void run() {
        release();
    }
};

如果不再保持锁定,release()会抛出RuntimeException:

public void release(int flags) {
    synchronized (mToken) {
        if (!mRefCounted || --mCount == 0) {
            mHandler.removeCallbacks(mReleaser);
            if (mHeld) {
                try {
                    mService.releaseWakeLock(mToken, flags);
                } catch (RemoteException e) {
                }
                mHeld = false;
            }
        }
        if (mCount < 0) {
            throw new RuntimeException("WakeLock under-locked " + mTag);
        }
    }
}

所以问题是,当我手动释放它时,它仍然会在超时到期后尝试自动释放它,并且唤醒锁被锁定不足。

问题是:我怎样才能使用定时唤醒锁定,同时能够在超时到期之前手动释放它?

2 个答案:

答案 0 :(得分:1)

作为解决方案(或解决方法 - 如果有人知道更好的解决方案,请发表评论)唤醒没有参考计数器的锁:

mWakeLock.setReferenceCounted(false);

这可以防止锁定不足

答案 1 :(得分:0)

在您复制的代码中,突出显示的行会删除当引用计数降为零时由acquire添加的回调,因此假设您正在获取然后每次获取只释放一次,那么您应该没问题。如果你实际上达到超时,你怎么知道停止手动释放...

if (!mRefCounted || --mCount == 0) {
   mHandler.removeCallbacks(mReleaser);           /// This removes the callback
   if (mHeld) {
        try {
            mService.releaseWakeLock(mToken, flags);
        } catch (RemoteException e) {
        }
        mHeld = false;
    }
}
相关问题