为什么WakefulIntentService会检查START_FLAG_REDELIVERY?

时间:2013-02-04 03:18:08

标签: android android-service android-lifecycle wakelock commonsware-cwac

来自WakefileIntentService.javaCWAC Wakeful library代码包含:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    PowerManager.WakeLock lock = getLock(this.getApplicationContext());
    if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) {
        lock.acquire();
    }
    super.onStartCommand(intent, flags, startId);
    return(START_REDELIVER_INTENT);
}

为什么代码检查START_FLAG_REDELIVERY - 什么阻止了以下情况?

    调用
  1. onStartCommand()并获取锁定。
  2. 系统在完成之前终止服务。
  3. 系统使用START_FLAG_REDELIVERY重新传递意图,对已经锁定的锁定进行另一次acquire()调用。
  4. 服务完成并拨打release()一次。
  5. 由于获得两次但仅发布一次,引用计数锁仍然永久保留。

3 个答案:

答案 0 :(得分:1)

如果服务被终止,则其执行进程终止,稍后当它重新启动时,不再保持锁定。您可以在此snippit中看到锁只是保存在静态变量中。

synchronized private static PowerManager.WakeLock getLock(Context context) {
    if (lockStatic == null) {
      PowerManager mgr=
          (PowerManager)context.getSystemService(Context.POWER_SERVICE);

      lockStatic=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
      lockStatic.setReferenceCounted(true);
    }

    return(lockStatic);
  }

https://groups.google.com/forum/?fromgroups=#!topic/android-developers/w8BdsI1BVdA

答案 1 :(得分:0)

这似乎是为了在进程被终止后重新获取锁,但是当另一个intentservice已经运行了一个锁时,在这种情况下它需要增加重新传递的意图的引用计数,因为原始锁定来自旧流程中的sendWakefulWork()不再存在。

由于没有处理START_FLAG_RETRY,这似乎很奇怪,我为此打开了问题https://github.com/commonsguy/cwac-wakeful/issues/10

答案 2 :(得分:0)

  

是什么阻止了以下情况?

您的方案意味着Android将终止该服务并保留WakeLock未完成的服务。我知道不会出现这种情况。 Android终止进程,而不是服务,操作系统有责任在此时发布任何获取的WakeLock

  

由于没有处理START_FLAG_RETRY,这似乎很奇怪,我为此打开了问题https://github.com/commonsguy/cwac-wakeful/issues/10

正如我在该问题中所指出的,虽然START_FLAG_REDELIVERY有适当的文档,但START_FLAG_RETRY却没有。我不知道什么时候会被使用。我不知道WakeLock的状态是基于那些没有记录的原因。等等。偶尔出现意外睡眠的风险要比无意中保持CPU无限启动要好得多。