如果持有它的应用程序或服务被杀死,Android 操作系统是否会释放唤醒锁? [英] Does the Android OS release a wakelock if the app or service holding it is killed?

查看:32
本文介绍了如果持有它的应用程序或服务被杀死,Android 操作系统是否会释放唤醒锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有关于唤醒锁的问题.在如下所示的情况下,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 操作系统是否会释放唤醒锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆