记录一次三方App ANR分析过程

Monkey 测试出现多次com.google.android.apps.adm ANR

1.在Monkey error中查看com.google.android.apps.adm ANR时候的cpu loading,cpu loading都比较低,大概在20%-30%,应该跟系统负载无关。

// NOT RESPONDING: com.google.android.apps.adm (pid 28188) Time Longth Since Monkey Start: 271764
ANR in com.google.android.apps.adm (com.google.android.apps.adm/.activities.MainActivity)
PID: 28188
Reason: Input dispatching timed out (Application does not have a focused window)
Parent: com.google.android.apps.adm/.activities.MainActivity

CPU usage from 2ms to 7270ms later (2024-07-05 19:08:47.419 to 2024-07-05 19:08:54.688):
27% TOTAL: 13% user + 12% kernel + 0.7% iowait + 0.8% irq + 0.2% softirq

2.分析了两次ANR,发现都是com.google.android.apps.adm的MainActivity的绘制存在异常,导致input超时。

第一份:

012-0707_160625--0707_194326\traces\07-07_175635--anr_2024-07-07-17-56-28-145.log
----- pid 1746 at 2024-07-07 17:56:27.963584411+0800 -----
Cmd line: com.google.android.apps.adm
主线程没有异常
"main" prio=5 tid=1 Native
  | group="main" sCount=1 ucsCount=0 flags=1 obj=0x725686d8 self=0xb4000074f1e3bc00
  | sysTid=1746 nice=-20 cgrp=top-app sched=0/0 handle=0x759a6484f8
  
  at android.os.MessageQueue.nativePollOnce(Native method)
  at android.os.MessageQueue.next(MessageQueue.java:335)
  at android.os.Looper.loopOnce(Looper.java:162)
  at android.os.Looper.loop(Looper.java:294)
  at android.app.ActivityThread.main(ActivityThread.java:8376)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:640)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:982)
  
  
E:\project\E6707SM\HS63L011XA4617000204\ylog\ap\1\012-0707_160625--0707_194326\2-android.log
InputDispatcher等待MainActivity的Window,从17:56:22.890 开始等待5000ms
M0B2C2D  07-07 17:56:22.890  1145  1281 W InputDispatcher: Waiting because no window has focus but ActivityRecord{a911d67 u0 com.google.android.apps.adm/.activities.MainActivity t7305 d0} may eventually add a window when it finishes starting up. Will wait for 5000ms
MainActivity的OnResumed方法被调用
E0B2C38  07-07 17:56:22.951  1746  1746 I wm_on_resume_called: [177282407,com.google.android.apps.adm.activities.MainActivity,RESUME_ACTIVITY,7]
栈顶
E0B2C69  07-07 17:56:23.012  1746  1746 I wm_on_top_resumed_gained_called: [177282407,com.google.android.apps.adm.activities.MainActivity,topStateChangedWhenResumed]
Input focus要从Settings的WifiSettingsActivity切到MainActivity的window
0B2C89  07-07 17:56:23.034  1145  1574 I WindowManager: Input focus has changed to Window{ea68aca u0 com.google.android.apps.adm/com.google.android.apps.adm.activities.MainActivity}, [type=1]-[Surface(name=*Title#238292)/@0xda57dda, shown=false, alpha=0.0, windowType=1] from c679d61 com.android.settings/com.android.settings.Settings$WifiSettingsActivity mDisplayId 0 updateInputWindows true
请求MainActivity window
E0B2C9D  07-07 17:56:23.037  1145  1186 I input_focus: [Focus request ea68aca com.google.android.apps.adm/com.google.android.apps.adm.activities.MainActivity,reason=UpdateInputWindows]
执行到View的绘制Q:\SPRO_14_SYS\SPRDROID14_SYS_MAIN_W2x.xx.x\idh.code\frameworks\base\core\java\android\view\ViewRootImpl.java的relayoutWindow方法
M0B2C9E  07-07 17:56:23.037  1746  1746 D VRI[MainActivity]: relayoutWindow: maybeSyncSeqId=-1, relayoutResult=3, mLastSyncSeqId=0, mRelayoutSeq=1

cancelDueToPreDrawListener 返回值为true,skip draw
M0B2CC5  07-07 17:56:23.054  1746  1746 D VRI[MainActivity]: reportNextDraw: reason=first_relayoutandroid.view.ViewRootImpl.performTraversals:3992 android.view.ViewRootImpl.doTraversal:2640 android.view.ViewRootImpl$TraversalRunnable.run:9766 android.view.Choreographer$CallbackRecord.run:1399 android.view.Choreographer$CallbackRecord.run:1408 
M0B2CC6  07-07 17:56:23.055  1746  1746 D VRI[MainActivity]: performtraversals: cancelAndRedraw not createSyncIfNeeded, cancelDueToPreDrawListener = true, cancelDraw = false, mDrewOnceForSync = false
M0B2CC7  07-07 17:56:23.055  1746  1746 D VRI[MainActivity]: performtraversals: skip draw, reason=predraw_ham
M0B2CC8  07-07 17:56:23.065  1746  1746 D VRI[MainActivity]: performtraversals: cancelAndRedraw not createSyncIfNeeded, cancelDueToPreDrawListener = true, cancelDraw = false, mDrewOnceForSync = false
M0B2CC9  07-07 17:56:23.065  1746  1746 D VRI[MainActivity]: performtraversals: skip draw, reason=predraw_diy
.......
M0B3963  07-07 17:56:27.886  1746  1746 D VRI[MainActivity]: performtraversals: cancelAndRedraw not createSyncIfNeeded, cancelDueToPreDrawListener = true, cancelDraw = false, mDrewOnceForSync = false
M0B3964  07-07 17:56:27.887  1746  1746 D VRI[MainActivity]: performtraversals: skip draw, reason=predraw_diy
从 07-07 17:56:23.054 到07-07 17:56:27.887  MainActivity的View一直都被skip draw

InputDispatcher等不到可以focus的window,通知WindowManager
WindowManager上报的ANR的事件
M0B3968  07-07 17:56:27.892  1145  1281 W InputDispatcher: ActivityRecord{a911d67 u0 com.google.android.apps.adm/.activities.MainActivity t7305 d0} does not have a focused window,start notifyNoFocusedWindowAnr

下面需要详细分析下MainActivity的View一直被skip draw的原因:

Q:\SPRO_14_SYS\SPRDROID14_SYS_MAIN_W2x.xx.x\idh.code\frameworks\base\core\java\android\view\ViewRootImpl.java
        boolean cancelDueToPreDrawListener = mAttachInfo.mTreeObserver.dispatchOnPreDraw();
        boolean cancelAndRedraw = cancelDueToPreDrawListener
                 || (cancelDraw && mDrewOnceForSync);
                 
        if (!cancelAndRedraw) {
        //这里没有走进去,没有开始draw
        
        } else if (true) {
            Log.d(mTag, "performtraversals: cancelAndRedraw not createSyncIfNeeded"
                    + ", cancelDueToPreDrawListener = " + cancelDueToPreDrawListener
                    + ", cancelDraw = " + cancelDraw + ", mDrewOnceForSync = " + mDrewOnceForSync);
        }
        这个log打印
cancelDueToPreDrawListener 为true,mAttachInfo.mTreeObserver.dispatchOnPreDraw()为true
具体需要看app的注册的Listener为什么返回为true
Q:\SPRO_14_SYS\SPRDROID14_SYS_MAIN_W2x.xx.x\idh.code\frameworks\base\core\java\android\view\ViewTreeObserver.java
    @SuppressWarnings("unchecked")
    public final boolean dispatchOnPreDraw() {
                         final OnPreDrawListener preDrawListener = access.get(i);
                    cancelDraw |= !(preDrawListener.onPreDraw());
                    if (cancelDraw) {
                        mLastDispatchOnPreDrawCanceledReason = preDrawListener.getClass().getName();
                    }
                    }
 cancelDraw 为true,preDrawListener.onPreDraw() 返回为false
 
M39CD8A  07-24 13:53:37.604 27693 27693 D ViewTreeObserver: addOnPreDrawListener, listener name: diy, listener = diy@858c78b, callers = com.google.android.apps.adm.activities.MainActivity.onCreate:26 android.app.Activity.performCreate:8646 android.app.Activity.performCreate:8624 android.app.Instrumentation.callActivityOnCreate:1459 android.app.ActivityThread.performLaunchActivity:3869 android.app.ActivityThread.handleLaunchActivity:4028 android.app.servertransaction.LaunchActivityItem.execute:103 android.app.servertransaction.TransactionExecutor.executeCallbacks:139 android.app.servertransaction.TransactionExecutor.execute:96 android.app.ActivityThread$H.handleMessage:2535 android.os.Handler.dispatchMessage:106 android.os.Looper.loopOnce:205 android.os.Looper.loop:294 android.app.ActivityThread.main:8376 java.lang.reflect.Method.invoke:-2 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run:640 
注册的是diy

ps:

Q:\SPRO_14_SYS\SPRDROID14_SYS_MAIN_W2x.xx.x\idh.code\frameworks\base\core\java\android\app\EventLogTags.logtags

# The activity's onTopResumedActivityChanged(true) has been called.
30064 wm_on_top_resumed_gained_called (Token|1|5),(Component Name|3),(Reason|3)
# The activity's onTopResumedActivityChanged(false) has been called.
30065 wm_on_top_resumed_lost_called (Token|1|5),(Component Name|3),(Reason|3)

Q:\SPRO_14_SYS\SPRDROID14_SYS_MAIN_W2x.xx.x\idh.code\frameworks\base\core\java\android\app\Activity.java
    public void onTopResumedActivityChanged(boolean isTopResumedActivity) {
    }
  在Android Q之后会出现多窗口的情况,多个Activity可能同时处于Resume状态,
  Called when activity gets or loses the top resumed position in the system.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值