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

use*_*128 63 android adb alarmmanager

我正在努力设置正确的警报,并了解取消和重新安排警报的机制.

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

我明白了,我在这里要求很多解释,所以如果有人会抛出一个关于"adb shell dumpsys alarm"的详细解释的链接,我将非常感激.

那么,这里有一些问题:

  1. 待批警报:23

    一个.'23'是否有许多当前活动的预定警报?

  2. 批量{4293d3a8 num = 1 start = 1369361 end = 1407261}:
      RTC#0:报警{4293d358类型1 com.android.chrome}
        类型= 1 whenElapsed = 1369361当= + 19s304ms窗口= -1 repeatInterval = 0 count = 0
        操作= PendingIntent {429e4500:PendingIntentRecord {429dbbc8 com.android.chrome broadcastIntent}}

    一个.什么是'num = 1','start = 1369361'和'end = 1407261'?
    湾 我认为'RTC'代表RTC警报.
    C.'#0'代表什么?
    d.什么意思'type = 1'?
    即 'when = + 19s304ms'是否意味着警报将在19秒内触发?
    F.什么意思'window = -1'?
    G.'repeatInterval = 0'意味着这是非重复警报吗?
    H."count = 0"意味着由于手机睡眠状态,此警报未被推迟吗?
    一世.'operation = PendingIntent {...}'代表待处理的意图,我将假设将由警报触发.

  3. 广播引用计数:0

    一个.这是什么?

  4. 热门警报:

    一个.这是什么?

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

    一个."+ 47s271ms"是否意味着此警报将在47秒内触发?
    湾 什么是'0唤醒' - 警报从未被触发?
    C.什么是'2报警'?
    d.'com.username.weatherinfo'代表包的名称,是否在上下文字段中提供给挂起的意图?
    即 '行为'是否意味着行动,是为意图而发送的?
    F.什么是'cmp'?我看,它是由包名和类名组成的 - 但是它们从哪里开始?从意图构造函数?G.为什么部分警报只有'行为'或只有'cmp'?我假设没有'cmp'字段的警报是用于隐式广播意图.然而,为什么没有"行为"字段会发出警报?

  6. 报警统计:

    一个.这是什么?

mor*_*tic 153

我意识到这个线程很老,但答案不容易找到,并且可能有用.我花了很多时间来研究这些消息的含义.

Q1:批次

Pending alarm batches: 23
Run Code Online (Sandbox Code Playgroud)

警报按批次组织.如文档中所述:

从API 19开始,传递给此方法的触发时间被视为不精确:警报将不会在此时间之前传递,但可能会延迟并在稍后传递.操作系统将使用此策略在整个系统中将警报"批处理"在一起,从而最大限度地减少设备需要"唤醒"并最大限度地减少电池使用的次数.一般而言,只要在将来安排的警报,就不会延迟在不久的将来安排的警报.

每批可能有多个警报.在这种情况下,有23 警报,这意味着可能会安排超过23个警报.在dumpsys alarm输出中,描述每个批次的行如下所示:

Batch{4293d3a8 num=1 start=1369361 end=1407261}:
Run Code Online (Sandbox Code Playgroud)

其中:

  • 4293d3a8 是与批次关联的内部标识.
  • 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}}
Run Code Online (Sandbox Code Playgroud)

其中:

  • 的第一部分,这是一个RTC_WAKEUP,RTC,ELAPSED_WAKEUP,或ELAPSED,表示type警报的和分别对应于整数值0-3,
  • #0是批处理,其中数字是从0到内报警的数量n-1,其中n在批量报警的数量.如果您的警报与其他人进行批处理,则将来最远的"when ="定义批次中所有警报将被触发的时间.
  • 4293d358 是与警报关联的内部标识号
  • com.android.chrome 是设置警报的类的包名称
  • type=1,报警的类型,见上面的第一个子弹
  • whenElapsed=1369361 是指自系统启动以来触发此警报的毫秒数(大约)
  • when=+19s304ms表示警报将在19秒内触发,距离dumpsys alarm调用时间为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使用实例化getService,getBroadcast,getActivity,或者getActivities,报警器就会启动一个服务,发送广播,或启动一项或多项活动.

Q3:广播参考计数

为了找到这个和其他输出项后我不得不深入研究AlarmManagerService.java源代码.

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

Broadcast Ref Count: 0只是意味着在dumpsys alarm运行时,它不是在发送任何广播的过程中.

Q4:热门警报

这是警报代码运行的总聚合时间按降序排列的前十个警报.这可用于查找消耗最大量系统资源的警报,例如,查找可能因故障而耗尽电池寿命的过程.

Q5:警报统计

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

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}
Run Code Online (Sandbox Code Playgroud)

在第一行中的位置:

  • 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
    ...
Run Code Online (Sandbox Code Playgroud)

有:

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

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

摘要

使用输出调试android警报adb shell dumpsys alarm可能很棘手,并且没有dumpsys完整解释消息的中心位置.警报如何被批处理并不总是很明显,有时很难在需要时准确地触发服务或活动.希望这对于试图调试警报的人来说是有用的参考.


Jas*_*son 5

作为一个也在吵闹闹钟的人,这里有两个提示:

调试shell输出:

  • 看到负或巨大的时间(如-2hr57m20s311ms,14d5hr23m07s500ms),是因为我感到困惑的时钟(如RTC所经过的)类型.这在文档中很明确," RTC_WAKEUP: Alarm time in System.currentTimeMillis()" https://developer.android.com/reference/android/app/AlarmManager.html#RTC_WAKEUP

  • 实时取消警报(创建后).使用取消,如果您计划挂起的意图需要:alarmManager.cancel(pendingIntent)pendingIntent.cancel()