如何读取 "adb shell dumpsys alarm" 输出

How to read "adb shell dumpsys alarm" output

我正在努力正确设置闹钟,并了解取消和重新安排闹钟的机制。

我发现有一个 adb 命令可以检索设备上安排的所有警报,但我没有找到说明输出格式的文档。

我明白,我在这里要求很多解释,所以如果有人能抛出一个 link 并详细解释 "adb shell dumpsys alarm",我将不胜感激。

那么问题来了:

  1. Pending alarm batches: 23

    一个。 “23”是当前活动的预定闹钟的数量吗?

  2. Batch{4293d3a8 num=1 start=1369361 end=1407261}:
      RTC #0: Alarm{4293d358 type 1 com.android.chrome}
        type=1 whenElapsed=1369361 when=+19s304ms window=-1 repeatInterval=0 count=0
        operation=PendingIntent{429e4500: PendingIntentRecord{429dbbc8 com.android.chrome broadcastIntent}}

    一个。什么是 'num=1'、'start=1369361' 和 'end=1407261'?
    b.我假设 'RTC' 代表 RTC 警报。
    C。 “#0”代表什么?
    d. 'type=1' 是什么意思?
    e. 'when=+19s304ms'的意思是19秒后会触发警报吗?
    F。 'window=-1' 是什么意思?
    G。 'repeatInterval=0' 是否意味着这是非重复警报?
    H。 'count=0' 是否意味着由于 phone 睡眠状态而未推迟此警报?
    一世。 'operation=PendingIntent{...}' 代表未决意图,我认为它将由警报触发。

  3. Broadcast ref count: 0

    一个。这是什么?

  4. Top Alarms:

    一个。这是什么?

  5. +47s271ms running, 0 wakeups, 2 alarms: com.username.weatherinfo
      act=com.username.receivers.CyclicWeatherUpdater.WEATHER_UPDATE_ACTION
        cmp={com.username.weatherinfo/com.username.receivers.CyclicWeatherUpdater}

    一个。 '+47s271ms' 是否意味着此警报将在 47 秒内触发?
    b.什么是“0 次唤醒”——从未触发警报?
    C。什么是“2闹钟”?
    d. 'com.username.weatherinfo' 是否代表包的名称,它在上下文字段中被赋予待处理的意图?
    e. 'act' 是指为意图发送的操作吗?
    F。什么是 'cmp'?我明白了,它由包名和 class 名称组成 - 但它们是从哪里获取的?来自意图构造函数? G。为什么部分报警只有'act'或只有'cmp'?我假设,没有 'cmp' 字段的警报用于隐式广播意图。然而,为什么会有没有'act'字段的警报?

  6. Alarm Stats:

    一个。这是什么?

我知道这个线程很旧,但答案不容易找到,但可能会有用。我花了很多时间弄清楚这些消息的含义。

Q1:批次

Pending alarm batches: 23

警报被组织成批次。 As described in the documentation:

Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.

每批可能有多个警报。在这种情况下,有 23 批次 警报,这意味着计划的警报可能远不止 23 个。在 dumpsys alarm 输出中,描述每个批次的行如下所示:

Batch{4293d3a8 num=1 start=1369361 end=1407261}:

其中:

  • 4293d3a8 是与批次关联的内部 ID。
  • num=1是这批报警的个数。在这种情况下,批次中只有一个警报。
  • startend数字表示自系统上次重启以来经过的毫秒数described in this post,也大致表示window的应触发批次中的警报的时间。

Q2:警报

每个警报都由三行描述,如下所示:

RTC #0: Alarm{4293d358 type 1 com.android.chrome} 
    type=1 whenElapsed=1369361 when=+19s304ms window=-1 repeatInterval=0 count=0
    operation=PendingIntent{429e4500: PendingIntentRecord{429dbbc8 com.android.chrome broadcastIntent}}

其中:

  • 第一部分是RTC_WAKEUPRTCELAPSED_WAKEUPELAPSED中的一个,表示报警的type,对应0-3的整数值,分别
  • #0 是批次中的警报数,其中数字从 0 到 n-1,其中 n 是批次中的警报数。如果您的警报与其他警报一起批处理,则未来最远的“when=”定义将触发批处理中的所有警报的时间。
  • 4293d358 是与警报关联的内部 ID 号
  • com.android.chrome是设置闹钟class的包名
  • type=1,报警类型,见上面第一个项目符号
  • whenElapsed=1369361指自系统启动后触发此警报的毫秒数(大约)
  • when=+19s304ms表示在调用dumpsys alarm后的19秒,304毫秒后触发。同样,像+2d13h29m03s882ms这样的值指的是未来2天13小时29分钟...的相对时间
  • window= 指的是与警报批处理方法有关的两个内部常量之一。 AlarmManager.WINDOW_EXACT=0 并在使用 setExact()setAlarmClock() 安排闹钟时设置。 AlarmManager.WINDOW_HEURISTIC=-1 并在使用 setInexactRepeating() 安排闹钟时设置。否则,该值由 API 版本确定。对于 API < 19 (KitKat),使用 WINDOW_EXACT,对于 API >= 19,使用 WINDOW_HEURISTIC。 (我不得不 dig into the AlarmManager.java source code 弄明白了。)
  • repeatInterval=900000 是警报重复的频率,例如每 900000 毫秒或 15 分钟。值为 0 表示警报不重复。
  • count=指的是警报应该被触发的次数,但是由于某些原因,不是。 0在这里是一个很好的数字。 >0 表示由于某种原因跳过了警报。
  • operation=PendingIntent{...} 是对由警报触发的 PendingIntent 的引用。根据 PendingIntent 是否使用 getServicegetBroadcastgetActivitygetActivities 实例化,警报将启动服务、发送广播或启动一项或多项活动。

Q3:广播引用计数

要了解这个和之后的其他输出项目,我必须 dig into the AlarmManagerService.java source code

为了使某些警报起作用,必须唤醒设备,并且在发送所有必要的广播之前不应返回休眠状态。内部变量 mBroadcastRefCount 初始化为 0,并随着要发送的广播排队而递增。随着每个广播的发送,它会递减,当它回到 0 时,wakeLock 被释放,设备可以重新进入睡眠状态。

Broadcast Ref Count: 0 只是表示在 dumpsys alarm 是 运行 时,它没有在发送任何广播。

Q4:热门警报

这是按报警代码累计总时间降序排列的前十个报警运行。这可用于查找消耗最多系统资源的警报,例如查找可能导致耗尽电池寿命的过程。

Q5:警报统计

此部分显示自系统上次重新启动以来具有 运行 的所有警报的统计信息。在这里您可以查看您过去设置的警报是否已被触发,它们是否唤醒了 phone 等。接下来将介绍这些条目的格式。

Q6:警报统计条目

警报统计条目如下所示:

com.example.someapp +1s857ms running, 0 wakeups:
    +1s817ms 0 wakes 83 alarms: cmp={com.example.someapp/com.example.someapp.someservice}
    +40ms 0 wakes 1 alarms: cmp={com.example.someapp/com.example.someapp.someotherservice}

第一行的位置:

  • com.example.someapp是触发报警的进程的包名
  • +1s857ms running 是进程消耗的总系统时间
  • 0 wakeups 是设备被这些警报之一唤醒的次数

然后之后的每一行都指的是已设置的警报之一,其中:

  • +1s817ms 是系统消耗的总时间
  • 0 wakes是设备被唤醒的次数
  • 83 alarms为报警触发次数;对于重复警报,这只会 >1
  • cmp={...}触发警报时启动的服务

或者,如果警报触发广播,条目可能如下所示:

android +4m51s566ms running, 281 wakeups:
    +2m46s583ms 0 wakes 1224 alarms: act=android.intent.action.TIME_TICK
    +1m25s624ms 89 wakes 89 alarms: act=android.content.syncmanager.SYNC_ALARM
    +52s898ms 0 wakes 41 alarms: act=com.android.server.action.NETWORK_STATS_POLL
    ...

与:

  • act=... 是广播的意向名称

警报可能同时具有 cmp={...}act=... 条目,这意味着警报既广播了意图又启动了服务。

总结

使用 adb shell dumpsys alarm 的输出调试 android 警报可能很棘手,并且没有中心位置可以完整解释 dumpsys 消息。警报如何一起批处理并不总是很明显,有时很难获得服务或 activity 在需要时准确触发。希望这对尝试调试警报的人有帮助。

作为一个也被警报困扰的人,这里有两个提示:

调试shell输出:

  • 看到负数或大量时间(例如 -2hr57m20s311ms、14d5hr23m07s500ms)是因为我混淆了时钟类型(例如 RTC 与 ELAPSED)。这在文档中很清楚,“RTC_WAKEUP: Alarm time in System.currentTimeMillis()https://developer.android.com/reference/android/app/AlarmManager.html#RTC_WAKEUP

  • 实时(创建后)取消警报。使用取消,如果您安排了一个待处理的意图,则需要:alarmManager.cancel(pendingIntent)pendingIntent.cancel()

尽管 morphatic 的答案就是您需要知道的全部内容,但我已经为 GUI 创建了一个开源项目,以可视化方式显示相同的信息。我认为它可能对其他人有用,因为它首先对我有用。

https://github.com/Dottorhouse/DumpsysAlarm