如何阅读“adb shell dumpsys alarm”输出

87

我在设置闹钟时遇到了问题,不知道如何正确设置,并且也不太理解取消和重新安排闹钟的机制。

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

我知道我这里要求的解释很多,所以如果有人能提供关于“adb shell dumpsys alarm”详细解释的链接,我会非常感激。

以下是问题:

  1. 待处理的闹钟批次:23

    a. ‘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}}

    a. ‘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’是否表示此闹钟由于手机睡眠状态而未延迟?
    i. ‘operation=PendingIntent{...}’代表将由闹钟触发的挂起意图,我猜测。

  3. 广播引用计数:0

    a. 这是什么?

  4. Top Alarms:

    a. 这是什么?

  5. +47s271ms 运行,0次唤醒,2个警报:com.username.weatherinfo
      act=com.username.receivers.CyclicWeatherUpdater.WEATHER_UPDATE_ACTION
        cmp={com.username.weatherinfo/com.username.receivers.CyclicWeatherUpdater}

    a. '+47s271ms' 是指此警报将在47秒后触发吗?
    b. '0次唤醒' 意味着警报从未被触发过吗?
    c. '2个警报' 是什么意思?
    d. 'com.username.weatherinfo' 是指包名,该包名在上下文字段中为挂起的意图提供了吗?
    e. 'act' 表示发送给意图的操作是什么?
    f. 'cmp' 是什么?我看到它由包名和类名组成 - 但它们从哪里获取?从意图构造函数中获取吗?
    g. 为什么某些警报只有 'act' 或只有 'cmp' 的部分?我认为没有 'cmp' 字段的警报是用于隐式广播意图的。但是,为什么有些警报没有 'act' 字段?

  6. Alarm Stats:

    a. 这是什么?


假设您已经阅读了AlarmManager的API文档,那么我的下一步可能是阅读一些相关的AOSP源代码:https://android.googlesource.com/platform/frameworks/base/+/kitkat-mr2.2-release/services/java/com/android/server/AlarmManagerService.java(这是kitkat版本,似乎已经移动或更改)。 - Chris Stratton
@ChrisStratton - 如果他读过AlarmManager文档,他就不会问一半的问题了。在棒棒糖中,“核心服务”已经移动到“core”子文件夹中 - https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/AlarmManagerService.java - Alex P.
3
@Alex P. 请不要给那个人的建议发表无意义的评论,而是指引我至少找到 API 文档中我所提出的六个问题中的一个答案。根据你的评论,应该很容易找到至少三个答案。请帮我找到答案,而不是再次提供解释。谢谢。 - Eugene Shtoka
3个回答

198

我知道这个帖子有些旧了,但是答案并不容易找到,可能会有用。我花了很多时间研究这些消息的含义。

问题1: 批次

Pending alarm batches: 23

警报被分成批次。 如文档所述
从API 19开始,传递给此方法的触发时间被视为不精确:该警报将不会在此时间之前传递,但可能被延迟并在稍后的时间传递。操作系统将使用此策略,在整个系统中“批量”地收集警报,最大程度地减少设备需要“唤醒”的次数,并最小化电池使用。通常,计划在不久的将来的警报不会像计划在遥远的将来的警报那样被推迟。
每个批次可能有多个警报。在这种情况下,有23个批次的警报,这意味着可能安排了许多超过23个的警报。在dumpsys alarm输出中,描述每个批次的行如下:
Batch{4293d3a8 num=1 start=1369361 end=1407261}:

其中:

  • 4293d3a8 是与该批次关联的内部 ID。
  • num=1 表示该批次中警报的数量。在这种情况下,该批次中只有一个警报。
  • startend 数字表示自系统上次重启以来经过的毫秒数,如此帖子所述,并且大致表示应触发该批次中警报的时间窗口。

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是设置闹钟的类的包名。
  • 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。(我不得不深入研究AlarmManager.java源代码才能弄清楚这一点。)
  • repeatInterval=900000表示闹钟重复的时间间隔,例如每900000毫秒或15分钟一次。0的值意味着闹钟不重复。
  • count=指的是应该触发闹钟的次数,但由于某种原因没有被触发的次数。0是一个很好的数字。>0表示闹钟由于某种原因被跳过了。
  • operation=PendingIntent{...}是对由闹钟触发的PendingIntent的引用。根据PendingIntent是使用getServicegetBroadcastgetActivity还是getActivities实例化的,闹钟将启动服务、发送广播或启动一个或多个活动。

问题3: 广播引用计数

要了解此项和其他输出项目,我必须深入研究AlarmManagerService.java源代码

为了使某些闹钟工作,设备必须被唤醒,并且在所有必要的广播发送完之前不应该回到睡眠状态。内部变量mBroadcastRefCount初始化为0,并随着需要发送的广播排队而增加。每次广播发送后,它会递减,当它回到0时,wakeLock被释放,设备可以回到睡眠状态。

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

问题4: 顶部闹钟

这是按总累计时间排名的前十个闹钟,可用于查找消耗最多系统资源的闹钟,例如查找可能导致电池寿命缩短的进程。

问题5:警报统计

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

问题6:警报统计条目

警报统计条目的外观如下:

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 消息。有时不明显地如何将闹钟批处理在一起,有时很难在所需的时间精确触发服务或活动。希望这对于试图调试其闹钟的人们是有用的参考。


5
作为一个曾经也为闹钟烦恼的人,这里有两个提示:
调试Shell输出:
- 当看到负数或者巨大的时间(例如:-2hr57m20s311ms,14d5hr23m07s500ms)时,这是因为我混淆了时钟类型(例如:RTC和ELAPSED)。文档中已经很清楚了,“RTC_WAKEUP: Alarm time in System.currentTimeMillis()”https://developer.android.com/reference/android/app/AlarmManager.html#RTC_WAKEUP - 在实时取消闹钟(创建后),使用cancel方法,如果您安排了一个待处理的意图,则需要同时使用alarmManager.cancel(pendingIntent) 和 pendingIntent.cancel()

4

虽然morphatic的答案已经足够了解,但我创建了一个开源项目,通过GUI以视觉化的方式展示相同的信息。我认为这可能对他人有用,因为首先它对我很有用。

https://github.com/Dottorhouse/DumpsysAlarm


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接