问题描述
我有关于唤醒锁的问题.在如下所示的情况下,Android 操作系统是否会释放唤醒锁(PARTIAL_WAKE_LOCK
,如果您需要指定)以防止唤醒锁被保留并浪费电池,直到关闭电源(而不是睡眠).
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).
案例 1-a:
应用程序在它的一个线程中获得了唤醒锁(没有超时选项)(请认为在这种情况下这是合理的)并且它被设计为在关键任务完成时释放唤醒锁.App 可以被 taskmanager 或臭名昭著的 taskkiller 杀死,并且 app 没有机会让其线程释放唤醒锁.那个唤醒锁会发生什么?
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?
案例 1-b:
(如果案例 1-a 的答案是是的,别担心",那么请忽略此案例.)与案例 1-a 相同,但应用程序为唤醒锁提供了超时选项,例如 3 秒.此超时选项是否保持有效?
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?
案例 2-a:
请想象有一个由 AlarmManager(通过广播接收器)启动的服务,并且该服务已获得唤醒锁(无超时选项).此服务旨在使唤醒锁获取时间最短.但不幸的是,由于内存不足,Android OS 选择了终止此服务.(我不知道在获取唤醒锁时操作系统是否会终止服务,但我猜操作系统不在乎.但我希望操作系统稍后会释放唤醒锁.)那个唤醒锁会发生什么?
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?
案例 2-b:
(如果案例 2-a 的答案是是的,别担心",那么请忽略此案例.)与案例 2-a 相同,但服务为唤醒锁提供了超时选项,例如 3 秒.此超时选项是否保持有效?
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?
推荐答案
WakeLock 实现概述
当我们使用 pm.newWakeLock
创建一个新的唤醒锁时,PowerManager
只是创建一个新的 WakeLock 对象并返回.WakeLock 对象不是绑定器对象,因此不能通过多个进程使用.但是,在该 WakeLock 对象中,它包含一个名为 mToken 的 Binder 对象.
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();
}
因此,当您对该 WakeLock 对象调用获取或释放时,它实际上将该令牌传递给 PowerManagerService
.
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;
}
}
查看获取或释放唤醒锁时 PowerManagerService
的工作原理将帮助您回答问题.
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);
}
...
}
...
}
关键语句是lock.linkToDeath(wakeLock, 0);
.那个 lock
正是我们之前提到的 mToken.如果此绑定器消失,此方法会注册接收者(wakeLock
)以获取通知.如果这个活页夹对象意外消失(通常是因为它的宿主进程已被终止),那么 binderDied
方法将在接收者上被调用.
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.
注意PowerManagerService
中的WakeLock与PowerManager
中的WakeLock不同,它是IBinder.DeathRecipient
的实现.所以看看它的 binderDied
方法.
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);
}
handleWakeLockDeath
将释放唤醒锁.
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();
}
}
所以我认为在您的问题中的两种情况下,答案都是不要担心.至少在 Android 4.2(代码出处)中,确实如此.此外,PowerManager
中的 WakeLock 类有一个 finalize 方法,但这不是您问题的关键.
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.
这篇关于如果持有它的应用程序或服务被杀死,Android 操作系统是否会释放唤醒锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!