admin管理员组文章数量:1566619
Monkey跑出的 Launcher ANR,场景为在Launcher的Recents界面下一个Activity启动又快速销毁导致的无焦点窗口问题。
1. log分析
2. 模拟ANR
根据之前的log分析,我们已经可以写一个Demo App来模拟该ANR的发生情况了,总结如下:
1、启动任意一个Activity,我这里写的Demo App为MainActivity。
2、接着输入事件KEYCODE_RECENT_APPS,回到Recents。
3、切回到Launcher后100ms,马上让MainActivity以NEW_TASK的方式调起一个另外一个Activity,我这里用一个名为SingleTaskActivity的Activity去模拟。
4、SingleTaskActivity启动后,马上调用finish,我这里是在onCreate方法中调用的 —— KO,可以复现无焦点窗口的情况,如果此时再输入一个KeyEvent事件,即可发生ANR。
另外把Demo App安装在Pixel上发现没问题:
有可能是Pixel多了一些patch,所以修复了此问题?
3. recents_animation_input_consumer分析
多打些log:
看到及时是发生问题后,其实也是有继续调用InputMonitor.updateInputFocusRequest方法的,但是"recents_animation_input_consumer"却没有获取焦点,继续看看代码是为什么:
这里的RecentsAnimationController是之前的逻辑了,现在点击切换到Recents,RecentsAnimationController也是为空的,那么我们主要看这个逻辑:
// Shell transitions doesn't use RecentsAnimationController but we still
// have carryover legacy logic that relies on the consumer.
|| (getWeak(mActiveRecentsActivity) != null && focus.inTransition()
// only take focus from the recents activity to avoid intercepting
// events before the gesture officially starts.
&& focus.isActivityTypeHomeOrRecents()
看下"recents_animation_input_consumer"能够获取焦点的log:
逐条看下这三个条件。
3.1 InputMonitor.mActivityRecentsActivity
首先看下这里的成员变量mActivityRecentsActivity的设置逻辑。
当在某一个非Launcher界面点击Recents时会进行设置:
当回到Launcher时则清除:
3.2 focus.inTransition()
点击Recents后只走到onTransitionReady,不会走到finishTransition,所以这个也可以满足。
3.3 focus.isActivityTypeHomeOrRecents()
如果focus时Launcher,这个条件肯定满足,更不用多说。
那么这里说明了,如果“recents_animation_input_consumer”想要取得焦点,只能从Launcher那边拿。如果之前获取焦点的是别的非Home或者Recents类型的窗口,那么“recents_animation_input_consumer”是不能拿到焦点的。
再次回看发生问题时的log,发现阻碍“recents_animation_input_consumer”成为焦点的原因是走到这里时的focus为空:
再看下正常的pixel的情况:
发现是在finishActivity的流程下,将窗口焦点从null切换到了Launcher,接着“recents_animation_input_consumer”就请求了焦点。
再看有问题的情况,发现finishActivity流程下也是去更新了窗口焦点:
但是Launcher的isVisibleRequestedOrAdding返回了false,所以不能取得焦点。
所以问题还是回到了DisplayContent.mCurrent为null,即焦点窗口丢失。
4. 对焦点窗口丢失的原因分析
再看下问题Activity,如之前所说,我这里模拟用的是“SingleTaskActivity”,快速启动又销毁的流程的log信息:
看到这个Activity走finish流程的时候,该流程是有重新去更新焦点窗口的,但是此时由于此时“Window{TclQuickstepLauncher}”的isVisibleRequestedOrAdding仍然为false,所以不满足作为焦点窗口的条件,因此无法将焦点窗口切换为“Window{TclQuickstepLauncher}”。
而当后续“SingleTaskActivity”走pause流程的时候,“TclQuickstepLauncher”的可见性才被设置为true,但是后续没有再调用DisplayContent.updateFocusedWindowLocked去更新焦点窗口了,所以这之后即使“TclQuickstepLauncher”满足了canReceiveKeys的条件,也无法变为焦点窗口了。
那为什么pixel没问题呢,看下pixel的情况,发现从发送keyEvent=312之后,“NexusLauncherActivity”的可见性始终都没有改变过,所以“NexusLauncherActivity”一直都可以满足canReceiveKeys的条件。
而我们的情况则不同,“TclQuickstepLauncher”在它的completePause的流程中设置了可见性为false:
再看“TclQuickstepLauncher”为什么会被pause:
从log看,是“SingleTaskActivity”被启动后,在TaskDisplayArea,pauseBackTasks中被pause:
被pause的原因则是Launcher对应的Task,调用canBeResuemd方法返回了false,所以这里认为该Task中的Activity应该被pause。
TaskFragment.canBeResumed的方法为:
主要的逻辑就是调用TaskFragment.getVisibility去获取当前TaskFragment的可见性。
另外看pixel的情况,反而是“MainActivity”被pause,Launcher没有被pause:
说明pixel的代码和我们的代码在TaskFragment.getVisibility上有差异?拿从集成那边的最新基线比较我们的代码,很快发现了差异点:
打入该patch后问题不再复现。
5. 一点题外话
在问题log中还看到有以下log:
01-26 13:58:02.241 1543 3349 I InputDispatcher: Dropping event because all windows would just receive ACTION_OUTSIDE: MotionEvent
虽然该ANR并不是有MotionEvent触发,但是还是看下这个log打印的场景。
写一个绘制需要15000ms的Activity2,让Activity1启动Activity2的时候finish,此时点击屏幕,即输入MotionEvent,有三个阶段:
1、首先是Activity1还没有被stop的时候,此时屏幕上仍然可以看见Activity1,但是Activity2正在启动,导致了Activity1无法接收事件,因此这里的log是:
02-27 17:52:36.560 1473 1654 I InputDispatcher: Dropping event because all windows would just receive ACTION_OUTSIDE: MotionEvent
2、接着Activity1被stop,Activity2也还没有起来,此时屏幕上是黑屏显示:
此时的log为:
02-27 17:52:39.214 1473 1654 I InputDispatcher: Dropping event because there is no touchable window at (423.4, 734.5) on display 0.
可以看到,虽然任何窗口都无法接收该MotionEvent,但是此时并不会触发ANR的计时,也就是MotionEvent在此场景下不会导致ANR?
3、最后我们再手动输入一个KeyEvent,此时log为:
看到此时才真正触发了ANR的倒计时:
02-27 17:52:48.246 1473 1654 W InputDispatcher: Waiting because no window has focus but ActivityRecord{e0a1ba7 u0 com.example.demoapp/.LongDrawActivity t479} may eventually add a window when it finishes starting up. Will wait for 5000ms
版权声明:本文标题:【问题分析】WMS无焦点窗口的ANR问题【Android 14】 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1726872619a1087997.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论