ANR 分析一般步骤与方法

关于 ANR 问题的已经存在很多文档了,本文尝试从另一个纬度展开描述,实现快速上手处理一个 ANR 问题。

ANR 主要有以下 4 种类型

Activity ANR---InputDispatchingTimedOut应用程序主线程在 5 秒内没有完成用户的 input 事件,目前部分小米机型是8秒超时Input event dispatching timed out
Service ANR---ServiceTimeout应用程序没有执行完成 service 的 bind/create/start/destroy/unbind 操作前台服务 20 秒超时,后台服务 200 秒超时Timeout executing service
Broadcast ANR---BroadcastTimeout应用程序在规定时间内没有执行完成 onReceive 操作前台广播 10 秒超时,后台广播 60 秒超时Timeout of broadcast BroadcastRecord
ContentProvider ANR---ContentProviderTimeout应用程序在 10 秒内没有执行完成 ContentProvider 相关操作timeout publishing content providers

分析步骤

  1. 确定 ANR 类型和时间点

搜索 am_anr 关键字,注意这个关键字和 ANR in 的区别,system log 中的 ANR in 会打印应用的调用栈信息,可能会有延迟,所以这个时候已经不是关键点,因此 event log 中 am_anr 相对较为准确。这里找列举了两种 anr 的类型,从上面的信息我们可以看到,发生 anr 的时间、pid 信息、包名、以及类型,我们有了这些信息可以进行下一步分析。

10-15 02:46:33.441 1477 24601 I am_anr : [0,23888,com.xiaomi.account,818429509,Input dispatching timed out (Application does not have a focused window)]
 
09-21 21:51:48.519 1666 6390 I am_anr : [0,5901,com.xiaomi.account,818429509,executing service com.xiaomi.account/com.xiaomi.mipush.sdk.MessageHandleService]
  1. 检查 CPU 信息

搜索 ANR in 关键字,检查系统负载是否正常。在 system log 中,会打印在 anr 发生前后一个时间段的 CPU 使用情况来辅助分析。因为此信息具有一定的时间滞后性,有时不能和 anr 发生时间完全匹配,这个信息也只能当作一点参考,CPU 的统计方法是一段时间内不同进程或线程在用户态和内核态分配 CPU 时间片/统计总时间,如果当前是8核心,那么攒满则是800%,这里列出一些主要的参数。

ANR inANR in com.xiaomi.account (com.xiaomi.account/.ui.UserDetailInfoActivity)
PID23888
ReasonInput dispatching timed out (Application does not have a focused window)
LoadLoad: 22.36 / 18.09 / 17.23 三个数字分别是1分钟、5分钟、15分钟内系统的平均负荷 当CPU完全空闲的时候,平均负荷为0;当CPU工作量饱和的时候,平均负荷为1,通过Load可以判断系统负荷是否过重
/proc/pressure/memory----- Output from /proc/pressure/memory ----- some avg10=52.70 avg60=55.21 avg300=58.94 total=17016471911 full avg10=12.26 avg60=23.90 avg300=35.61 total=10514083300 ----- End output from /proc/pressure/memory ----- avg10、avg60、avg300 分别代表 10s、60s、300s 的时间周期内的阻塞时间百分比total 是总累计时间,以毫秒为单位some 这一行,代表至少有一个任务在某个资源上阻塞的时间占比full 这一行,代表所有的非 idle 任务同时被阻塞的时间占比,这期间 cpu 被完全浪费,会带来严重的性能问题 我们以 IO 的 some 和 full 来举例说明,假设在 60 秒的时间段内,系统有两个 task,在 60 秒的周期内的运行情况如下图所示: img 红色阴影部分表示任务由于等待 IO 资源而进入阻塞状态。Task A 和 Task B 同时阻塞的部分为 full,占比 16.66%;至少有一个任务阻塞(仅 Task B 阻塞的部分也计算入内)的部分为 some,占比 50%。通过这些阻塞占比数据,我们可以看到短期以及中长期一段时间内各种资源的压力情况。
CPU usageCPU usage from 24140ms to 0ms ago 96% 1477/system_server: 60% user + 36% kernel / faults: 60091 minor 15157 major … … CPU usage from 150ms to 658ms later 159% 1477/system_server: 102% user + 57% kernel / faults: 1048 minor 60 major … …

这里主要关注几个参数来确定是否是系统资源耗尽或者其余进程过度占用导致我们自己业务产生 anr。

  1. 检查内存信息

搜索 /proc/meminfo 检查内存信息,这里我尽量补充了一些信息,我们只需要关注红色标记的数据即可。

------ (cat /proc/meminfo) in 90s ------
MemTotal:        3747684 kB 所有可用RAM大小
MemFree:           82500 kB 当前系统空闲的内存大小 LowFree + HighFree 系统层面
MemAvailable:    1134732 kB 应用程序可用内存 MemAvailable≈MemFree+Buffers+Cached
Buffers:            2660 kB 用来给文件做缓冲大小
Cached:           972828 kB 被高速缓冲存储器(cache memory)用的内存的大小
SwapCached:        32640 kB 被高速缓冲存储器(cache memory)用的交换空间的大小
Active:           791176 kB 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小
Inactive:        1033660 kB 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径
Active(anon):     368260 kB 活跃的与文件无关的内存(比如进程的堆栈,用malloc申请的内存)
Inactive(anon):   596716 kB 非活跃的与文件无关的内存(比如进程的堆栈,用malloc申请的内存)
Active(file):     422916 kB 活跃的与文件关联的内存(比如程序文件、数据文件所对应的内存页)
Inactive(file):   436944 kB 非活跃的与文件关联的内存(比如程序文件、数据文件所对应的内存页)
Unevictable:       66784 kB
Mlocked:           66784 kB
SwapTotal:       2306044 kB 交换空间的总大小
SwapFree:         854604 kB 未被使用交换空间的大小
Dirty:              1188 kB 等待被写回到磁盘的内存大小
Writeback:             0 kB 正在被写回到磁盘的内存大小
AnonPages:        910312 kB 未映射页的内存大小
Mapped:           707912 kB 设备和文件等映射的大小
Shmem:             49912 kB
KReclaimable:     325856 kB
Slab:             404288 kB 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗
SReclaimable:     127612 kB 可收回Slab的大小
SUnreclaim:       276676 kB 不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)
KernelStack:       66016 kB 常驻内存,每一个用户线程都会分配一个kernel stack(内核栈)
ShadowCallStack:   16572 kB
PageTables:        99760 kB 管理内存分页页面的索引表的大小
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     4179884 kB
Committed_AS:   99241124 kB
VmallocTotal:   262930368 kB
VmallocUsed:      161964 kB
VmallocChunk:          0 kB
Percpu:            10784 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
CmaTotal:         688128 kB
CmaFree:           27336 kB
[cat: 0.012s elapsed]
  1. 检查 Low Memory Killer

Android的Low Memory Killer基于Linux的OOM机制,通过在用户空间中指定了一组内存临界值,定时按照配置的策略检查判断进程oom_adj,当其中的某个值与进程描述中的oom_adj值在同一范围时,该进程将被Kill掉,Low Memory Killer通过检查oom_adj和占用的内存大小来杀死不必要的进程释放其内存。oom_adj 代表进程的优先级,数值越高,优先级越低,越容易被杀死;

oom_adj:代表进程的优先级, 数值越大,优先级越低,越容易被杀。取值范围[-16, 15]
oom_score_adj: 取值范围[-1000, 1000]
oom_score:linux oom才会使用。

搜索关键字 lowmemorykiller 我们检查一下是否内存紧张触发了 kill,如果 anr 时间段发生大量 kill 则表示很有可能此次 anr 与资源不足有关。

... ...
10-30 12:04:00.266 706 706 I lowmemorykiller: Kill 'com.miui.voiceassist:core' (25453), uid 10174, oom_score_adj 100 to free 44536kB rss, 50280kB swap; reason: device is in direct reclaim and thrashing (62%)
10-30 12:04:00.365 706 706 I lowmemorykiller: Kill 'com.xiaomi.xmsf' (25155), uid 10173, oom_score_adj 100 to free 43064kB rss, 50368kB swap; reason: cw
10-30 12:04:03.210 706 706 I lowmemorykiller: Kill 'com.xiaomi.bluetooth' (25354), uid 1002, oom_score_adj 500 to free 45944kB rss, 52212kB swap; reason: device is in direct reclaim and thrashing (566%)
10-30 12:04:05.736 706 706 I lowmemorykiller: Kill 'com.miui.home' (25022), uid 10130, oom_score_adj 0 to free 105092kB rss, 52188kB swap; reason: device is in direct reclaim and thrashing (509%) 
10-30 12:04:06.099 706 706 I lowmemorykiller: Kill 'com.miui.analytics' (25618), uid 10131, oom_score_adj 250 to free 41756kB rss, 48076kB swap; reason: device is in direct reclaim and thrashing (41%) 
... ...

经过前面几个步骤的分析,我们现在初步掌握了 发生 anr 的类型、设备的 CPU、内存等使用信息。如果此时 CPU的负载较高、内存使用上也出现问题并伴随有多个 APP 的 anr,那么我就到此就可以确定此次 anr 与当前设备相关,与业务的关系较小。如果没有上述情况,或者想进一步确定是否是自身业务引起,我们继续搜索信息。

  1. Trace 文件

"main" prio=5 tid=1 Native
  | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72f7f1f0 self=0xb4000070e6659be0
  | sysTid=19801 nice=0 cgrp=foreground sched=0/0 handle=0x72b68664f8
  | state=S schedstat=( 17151346322 43291363904 44264 ) utm=1344 stm=370 core=1 HZ=100
  | stack=0x7fcef42000-0x7fcef44000 stackSize=8188KB
  | held mutexes=
  native: #00 pc 00000000000a7eac  /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+12) (BuildId: 2594db063b42cfbc24ddfd230657b4cf)
  native: #01 pc 0000000000017cfc  /system/lib64/libutils.so (android::Looper::pollInner(int)+192) (BuildId: 6cc789a5db76fed354200c8693268976)
  native: #02 pc 0000000000017bd8  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+116) (BuildId: 6cc789a5db76fed354200c8693268976)
  native: #03 pc 0000000000165cc0  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+48) (BuildId: 18fc2a1014c9edf08cbe44845c39623f)
  at android.os.MessageQueue.nativePollOnce(Native method)
  at android.os.MessageQueue.next(MessageQueue.java:341)
  at android.os.Looper.loopOnce(Looper.java:168)
  at android.os.Looper.loop(Looper.java:299)
  at android.app.ActivityThread.main(ActivityThread.java:8109)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:974)

main: 主线程标识,如果是子线程,那么命名应该是“Thread-X”的格式,x表示线程id,逐步递增。

prio:线程优先级,默认5

tid:tid 不是县城id,是线程唯一标识

group:线程组名称

sCount:该线程被挂起次数

dsCount:线程被调试器刮起的次数

obj:对象地址

self:该线程Native的地址

sysTid:是线程号(主线程号同进程号相同)

nice:线程的调度优先级

sched:分别标志了线程的调度策略和优先级

cgrp:调度归属组

handle:线程处理函数的地址

state:调度状态

schedstat:三个值分别表示线程cpu上执行的时间、线程的等待时间和线程执行的时间长度,0无意义

utm:线程用户态下使用的时间值(单位是jiffies)

stm:内核态下的调度时间值

core:最后执行这个线程的cpu核的序号

案例

主线程被其他线程lock,导致死锁

DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 s=0 obj=0x400143a8
  | sysTid=691 nice=0 sched=0/0 handle=-1091117924
  at java.lang.Object.wait(Native Method)
  - waiting on <0x1cd570> (a android.os.MessageQueue)
  at java.lang.Object.wait(Object.java:195)
  at android.os.MessageQueue.next(MessageQueue.java:144)
  at android.os.Looper.loop(Looper.java:110)
  at android.app.ActivityThread.main(ActivityThread.java:3742)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
  at dalvik.system.NativeStart.main(Native Method)
 
"Binder Thread #3" prio=5 tid=15 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x434e7758
  | sysTid=734 nice=0 sched=0/0 handle=1733632
  at dalvik.system.NativeStart.run(Native Method)
  ... ...
 
"Binder Thread #2" prio=5 tid=13 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x1cd570
  | sysTid=696 nice=0 sched=0/0 handle=1369840
  at dalvik.system.NativeStart.run(Native Method)
  ... ...
 
"Binder Thread #1" prio=5 tid=11 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433aca10
  | sysTid=695 nice=0 sched=0/0 handle=1367448
  at dalvik.system.NativeStart.run(Native Method)
  ... ...

从日志来看 主线程 main 在 waiting <0x1cd570> , 检索发现 Binder Thread #2 的 obj 地址为 <0x1cd570>,而该 binder 进程某种原因导致阻塞,这里不在分析堆栈。

关键词搜索

  1. Slow Operation /am_lifecycle_sample
  2. Slow Looper main
  3. Slow Binder /binder_sample
  4. dvm_lock_sample

常见原因

  1. 主线程binder耗时
  2. 主线程i/o耗时
  3. 死锁
  4. 主线程等锁耗时(自线程持锁耗时,持锁sleep等)
  5. activity resume慢/焦点窗口切换慢/窗口绘制慢(针对Input anr)
  6. 主线程有太多消息要执行,导致对应组件消息执行delay。
  7. 主线程前面的消息执行耗时,导致后面的消息delay。
  8. 跟手机当时状态有关,内存/cpu等
  9. startForeground未在Service的onStartCommand中执行

案例

  1. i/o 耗时

io耗时导致110消息执行时间过长,导致Receiver消息迟迟得不到执行

06-30 15:11:11.411 1000 1895 8935 I am_anr :[0,5831,com.android.settings,952745541,Broadcast of Intent { act=android.hardware.usb.action.USB_STATE flg=0x31000010 cmp=com.android.settings/.connecteddevice.usb.UsbModeChooserReceiver(has extras) }]
06-30 15:11:16.453 1000 5831 5831 I am_lifecycle_sample: [0,com.android.settings,110,14998]
06-30 15:11:16.454 1000 5831 5831 W Looper : PerfMonitor longMsg :seq=2 plan=15:11:01.454 late=2ms wall=14998ms running=77ms runnable=55ms io=14144ms h=android.app.ActivityThread$H w=110 procState=2
06-30 15:11:16.469 1000 5831 5831 D UsbModeChooserReceiver: action = android.hardware.usb.action.USB_STATE
  1. 主线程等锁耗时

发生ANR的8s内,home主线程有等锁11s,导致input事件未被及时处理。

02-07 16:24:51.941 1000 1237 8731 I am_anr :[0,1855,com.miui.home,953794117,Input dispatching timed out (com.miui.home/com.miui.home.recents.settings.NavigationBarTypeActivity, 1d271ca com.miui.home/com.miui.home.recents.settings.NavigationBarTypeActivity (server) is not responding. Waited 8000ms for FocusEvent(hasFocus=false))]
02-07 16:24:52.566 10074 1855 1855 I dvm_lock_sample: [com.miui.home,1,main,11259,Launcher.java,7312,void com.miui.home.launcher.Launcher.bindAppsChanged(java.util.List, java.util.List, java.util.List),LauncherModel.java,1468,void com.miui.home.launcher.LauncherModel$LoaderTask.run(),100]

子线程sleep,导致主线程耗时

  1. “QueueTaskManager[PersistentAppTaskManager[PeriodicUpdateTaskTaskManager]]” prio=5 tid=20 Sleeping
  2. group=“main” sCount=1 ucsCount=0 flags=1 obj=0x12c81cd8 self=0xb400007203f390f0
sysTid=7700 nice=0 cgrp=default sched=0/0 handle=0x700d385cb0
state=S schedstat=( 136187002 10009767 89 ) utm=9 stm=4 core=4 HZ=100
stack=0x700d282000-0x700d284000 stackSize=1039KB
held mutexes=
at java.lang.Thread.sleep(Native method)
sleeping on <0x05379990> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:451)
locked <0x05379990> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:356)
at com.xiaomi.finddevice.adapter.PersistentStroageImpl.getStorageService(PersistentStroageImpl.java:116)
at com.xiaomi.finddevice.adapter.PersistentStroageImpl.readTinyData(PersistentStroageImpl.java:37)
at com.xiaomi.finddevice.common.PersistentStroage.readTinyData(PersistentStroage.java:42)
at com.xiaomi.finddevice.v2.FindDeviceStorage.getStatus(FindDeviceStorage.java:290)
at com.xiaomi.finddevice.v2.FindDeviceStatusManagerInternal.get(FindDeviceStatusManagerInternal.java:61)
locked <0x0c4caf24> (a java.lang.Class<com.xiaomi.finddevice.v2.FindDeviceStatusManagerInternal>)
at com.xiaomi.finddevice.v2.update.PeriodicUpdateTask$DeviceCredentialUpdateSubTask.doDeviceCredentialUpdate(PeriodicUpdateTask.java:87)
at com.xiaomi.finddevice.v2.update.PeriodicUpdateTask$DeviceCredentialUpdateSubTask.run(PeriodicUpdateTask.java:78)
at com.xiaomi.finddevice.common.task.PersistentAppTaskBuilder$2.run(PersistentAppTaskBuilder.java:108)
at com.xiaomi.finddevice.common.task.PersistentAppTaskManager.doRunTask(PersistentAppTaskManager.java:367)
at com.xiaomi.finddevice.common.task.PersistentAppTaskManager.onRunTask(PersistentAppTaskManager.java:338)
at com.xiaomi.finddevice.common.task.PersistentAppTaskManager.access$100(PersistentAppTaskManager.java:19)
at com.xiaomi.finddevice.common.task.PersistentAppTaskManager$1.run(PersistentAppTaskManager.java:600)
at com.xiaomi.finddevice.common.task.QueueTaskManager.runTaskLoop(QueueTaskManager.java:295)
at com.xiaomi.finddevice.common.task.QueueTaskManager.access$000(QueueTaskManager.java:17)
at com.xiaomi.finddevice.common.task.QueueTaskManager$1.run(QueueTaskManager.java:198)
at java.lang.Thread.run(Thread.java:920)
 
"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 ucsCount=0 flags=1 obj=0x71d62f88 self=0xb400007203ef8be0
  | sysTid=7677 nice=0 cgrp=default sched=0/0 handle=0x7343c944f8
  | state=S schedstat=( 326449768 42522457 280 ) utm=25 stm=7 core=6 HZ=100
  | stack=0x7fc292e000-0x7fc2930000 stackSize=8188KB
  | held mutexes=
  at com.xiaomi.finddevice.v2.FindDeviceStatusManagerInternal.get(FindDeviceStatusManagerInternal.java:-1)
  - waiting to lock <0x0c4caf24> (a java.lang.Class<com.xiaomi.finddevice.v2.FindDeviceStatusManagerInternal>) held by thread 20
  at com.xiaomi.finddevice.v2.FindDeviceStatusManagerService.onCreate(FindDeviceStatusManagerService.java:49)
  at android.app.ActivityThread.handleCreateService(ActivityThread.java:4639)
  at android.app.ActivityThread.access$1900(ActivityThread.java:275)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2178)
  at android.os.Handler.dispatchMessage(Handler.java:106)
  at android.os.Looper.loopOnce(Looper.java:210)
  at android.os.Looper.loop(Looper.java:299)
  at android.app.ActivityThread.main(ActivityThread.java:8290)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1073)
  1. binder 耗时

app查询另一个进程的content provider,binder耗时5s多

06-25 16:30:49.584 1000 1894 16604 I am_anr :[0,6171,com.miui.cloudservice,818429509,Input dispatching timed out (com.miui.cloudservice/com.miui.cloudservice.ui.MiCloudMainActivity, 7cfa4a0 com.miui.cloudservice/com.miui.cloudservice.ui.MiCloudMainActivity(server) is not responding. Waited 5002ms for FocusEvent(hasFocus=false))]
06-25 16:30:49.872 10141 6171 6171 W BpBinder: PerfMonitor binderTransact : time = 5416ms interface=android.content.IContentProvider code=1
06-25 16:30:49.893 10141 6171 6171 W Activity: Slow Operation: Activity com.miui.cloudservice/.ui.ShareLocationProxyActivity onCreate took 5440ms

对端进程pid为7467,isLocked持锁5s多,导致isOpen等锁

outgoing transaction: from 6171: 6171 to 7467:14336 context:binder code: 1 duration: 5.12 s
06-25 16:30:49.871 9810 7467 14336 W aomi.finddevic: Long monitor contention with owner IntentService[FindDeviceAsyncControlService] (16551) at boolean com.xiaomi.finddevice.v2.FindDeviceStatusManagerInternal.isLocked(android.content.Context(FindDeviceStatusManagerInternal.java:85) waiters=1 in boolean com.xiaomi.finddevice.v2.FindDeviceStatusManagerInternal.isOpen() for 5.415s
  1. 窗口绘制慢

12-07 18:23:28.203 19559 19559 I wm_on_resume_called: [0,com.miui.extraphoto.motionphoto.MotionPhotoActivity,RESUME_ACTIVITY,1]
12-07 18:23:28.203 19559 19559 I wm_on_top_resumed_gained_called: [40246013,com.miui.extraphoto.motionphoto.MotionPhotoActivity,topWhenResuming]
12-07 18:23:35.209 2307 19883 I am_anr : [0,19559,com.miui.extraphoto,551075397,Input dispatching timed out (Application does not have a focused window)]

mDrawState 状态不是HAS_DRAWN,窗口未绘制完成,无法响应input key事件

mDisplayId=0 rootTaskId=3250 mSession=Session{8d1dcab 19559:u0a10082} mClient=android.os.BinderProxy@f1c0c6
    mOwnerUid=10082 showForAllUsers=false package=com.miui.extraphoto appop=NONE
    mAttrs={(0,0)(fillxfill) sim=
 
{adjust=pan forwardNavigation}
layoutInDisplayCutoutMode=shortEdges ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x10302fe
      fl=LAYOUT_IN_SCREEN FULLSCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED TRANSLUCENT_STATUS DRAWS_SYSTEM_BAR_BACKGROUNDS
      pfl=NO_MOVE_ANIMATION FORCE_DRAW_STATUS_BAR_BACKGROUND USE_BLAST FIT_INSETS_CONTROLLED
      vsysui=LAYOUT_STABLE LAYOUT_FULLSCREEN
      bhv=SHOW_TRANSIENT_BARS_BY_SWIPE
      fitSides=}
  ......
    WindowStateAnimator{6f89c4e com.miui.extraphoto/com.miui.extraphoto.motionphoto.MotionPhotoActivity}:
      mSurface=Surface(name=com.miui.extraphoto/com.miui.extraphoto.motionphoto.MotionPhotoActivity)/@0x9ce816f
      Surface: shown=false layer=0 alpha=1.0 rect=(0.0,0.0)  transform=(1.0, 0.0, 0.0, 1.0)
      mDrawState=DRAW_PENDING      mLastHidden=true // mDrawState 状态不是HAS_DRAWN,窗口未绘制完成
      mEnterAnimationPending=false      mSystemDecorRect=[0,0][0,0]
    mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
    isOnScreen=true
    isVisible=true

以上只是简单的分析 ANR 步骤和方法,以及一些信息表示的意义,本意是加强对 ANR 信息的理解,提高分析解决 ANR 问题的速度。