Обзор реализации WakeLock
Когда мы используем pm.newWakeLock
для создания нового wakelock, PowerManager
просто создает новый объект WakeLock и возвращает. Объект WakeLock не является объектом связывания, поэтому его нельзя использовать в нескольких процессах. Однако в этом объекте WakeLock он содержит объект Binder с именем mToken.
WakeLock(int flags, String tag) {
mFlags = flags;
mTag = tag;
mToken = new Binder();
}
Поэтому, когда вы вызываете acqu или release для этого объекта 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
, когда приобретение или освобождение от вейк-блокировки поможет вам ответить на ваш вопрос.
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
освободит этот будильник.
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 есть метод finalize в PowerManager
, но это не ключ к вашему вопросу.