如果持有的应用程序或服务被杀死,Android OS是否会释放Wakelock?
-
11-10-2019 - |
题
我对Wakelock有疑问。在下面显示的情况下,do android os释放wakelock(PARTIAL_WAKE_LOCK
如果您需要指定)防止Wakelock获取并浪费电池,直到关闭电源(不睡觉)。
案例1-A:
App已在其一个线程之一中获取了Wakelock(W/O超时选项)(在这种情况下,请认为它是合理的),并且在完成关键任务时旨在释放Wakelock。应用程序可以被Taskmanager或臭名昭著的任务杀死,并且App没有机会让其线程释放Wakelock。那挥杆怎么办?
案例1-B:
(如果对案例1-A的答案是“是的,请放心”,请忽略此情况。)与案例1-A相同,但是App给Wakelock提供了超时选项,例如3秒。此超时选项保持有效吗?
案例2-A:
请想象,AlarmManager(通过广播接收器)启动了一项服务,该服务已获得Wakelock(W/O超时选项)。该服务旨在使Wakelock获得最低时间。但不幸的是,Android OS选择了这项服务以杀死记忆紧缩。 (我不知道在获得Wakelock时是否会杀死OS,但我想OS不在乎。但是我希望OS稍后会释放Wakelock。)Wakelock会发生什么?
案例2-B:
(如果对案例2-A的答案是“是的,请不要担心”,请忽略此情况。)与案例2-A相同,但是服务给Wakelock提供了超时选项,例如3秒。此超时选项保持有效吗?
解决方案
Wakelock实施概述
当我们使用时 pm.newWakeLock
为了创建一个新的Wakelock, PowerManager
只需创建一个新的Wakelock对象并返回即可。 Wakelock对象不是粘合剂对象,因此不能通过多个过程使用它。但是,在该Wakelock对象中,它包含一个名为Mtoken的粘合剂对象。
WakeLock(int flags, String tag) {
mFlags = flags;
mTag = tag;
mToken = new Binder();
}
因此,当您致电在此Wakelock对象上获取或释放时,它实际上将令牌传递给 PowerManagerService
.
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
mHandler.removeCallbacks(mReleaser);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
}
}
看看如何 PowerManagerService
获取或释放Wakelock时可以帮助您回答问题。
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
方法将被接收到收件人。
请注意,Wakelock在 PowerManagerService
与Wakelock不同 PowerManager
, ,这是 IBinder.DeathRecipient
. 。因此请查看其 binderDied
方法。
@Override
public void binderDied() {
PowerManagerService.this.handleWakeLockDeath(this);
}
这 handleWakeLockDeath
将释放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();
}
}
因此,我认为在您的问题中,答案是不用担心的。至少在Android 4.2(代码来源)中,这是真的。此外,在Wakelock类中有一个最终确定方法 PowerManager
, ,但这不是您问题的关键。
其他提示
我认为(我不确定这一点)Android系统不会让Wakelocks保持杀死的过程。当它用Sigkill杀死一个过程时,最有可能消除了该过程所持有的任何Wakelocks。
否则,正如您所说,撞车事故将导致电话总是醒着,我没有观察到。