我对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。

否则,正如您所说,撞车事故将导致电话总是醒着,我没有观察到。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top