背景:
针对冻屏类问题,昨天晚上进行直播分享如何手把手教你分析:
https://www.bilibili.com/video/BV1nsmgYWEPZ/
这里针对直播讲解的知识,也进行了笔记整理
ActiveGestureLog日志分析
抓取方式:
adb shell dumpsys activity service com.android.launcher3/com.android.quickstep.TouchInteractionService
查看方式:
ActiveGestureLog history:
异常冻屏情况
正常情况日志
明显可以看出来这里正常情况有相关的finishRecentsAnimation操作,但是异常情况下没有finishRecentsAnimation,这个其实也可以判断出来异常冻屏的本质原因是因为没有进行相关的finishRecentsAnimation操作,即相当于动画在执行,但是因为某些异常没有得到良好收尾操作,从而导致问题。
events日志看看区别:
正常taskbar情况,额外多了如下日志,主要就是对Task相关的操作
10-12 11:15:30.446 491 1464 I wm_task_moved: [100,100,0,1,2]
10-12 11:15:30.446 491 1464 I wm_task_to_front: [0,100,0]
10-12 11:15:30.447 1116 1373 I jank_cuj_events_end_request: [9,1728702930444979000,1727153610532,1727153610563]
10-12 11:15:30.448 1116 1373 I jank_cuj_events_end_request: [66,1728702930444980000,1727153611788,1727153611810]
10-12 11:15:30.451 491 1464 I wm_set_resumed_activity: [0,com.android.messaging/.ui.conversationlist.ConversationListActivity,positionChildTaskAt]
10-12 11:15:30.451 491 1464 I wm_task_moved: [1,1,0,0,1]
10-12 11:15:30.452 491 1464 I wm_add_to_stopping: [0,211827476,com.android.launcher3/.uioverrides.QuickstepLauncher,makeInvisible]
10-12 11:15:30.455 491 1464 I wm_pause_activity: [0,211827476,com.android.launcher3/.uioverrides.QuickstepLauncher,userLeaving=true,finishTransition]
10-12 11:15:30.457 491 514 I input_focus: [Focus request f5f5789 com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity,reason=UpdateInputWindows]
10-12 11:15:30.460 491 514 I wm_wallpaper_surface: [0,0,Window{
bc34d70 u0 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}]
10-12 11:15:30.466 1116 1116 I wm_on_top_resumed_lost_called: [211827476,com.android.launcher3.uioverrides.QuickstepLauncher,topStateChangedWhenResumed]
10-12 11:15:30.466 1767 1767 I wm_on_top_resumed_gained_called: [159589383,com.android.messaging.ui.conversationlist.ConversationListActivity,topStateChangedWhenResumed]
10-12 11:15:30.467 1116 1116 I wm_on_paused_called: [211827476,com.android.launcher3.uioverrides.QuickstepLauncher,performPause,0]
10-12 11:15:30.468 491 510 I sysui_multi_action: [757,803,799,window_time_0,802,24]
10-12 11:15:30.468 491 513 I wm_stop_activity: [0,211827476,com.android.launcher3/.uioverrides.QuickstepLauncher]
10-12 11:15:30.476 491 589 I input_focus: [Focus leaving recents_animation_input_consumer (server),reason=setFocusedWindow]
10-12 11:15:30.476 491 589 I input_focus: [Focus entering f5f5789 com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity (server),reason=setFocusedWindow]
10-12 11:15:30.478 1116 1116 I wm_on_stop_called: [211827476,com.android.launcher3.uioverrides.QuickstepLauncher,STOP_ACTIVITY_ITEM,7]
所以这里也大概可以看出明显缺少很多的task的操作,因为task这些操作才可以让activity的相关图层生命周期正常,让activity的图层窗口位置重新排列到前面,这样就不会出现那种异常情况。
events日志中task操作触发源头
Launcher会正常调用finish
10-12 11:00:07.246 1116 1149 I Test888 : finish
10-12 11:00:07.246 1116 1149 I Test888 : java.lang.Exception
10-12 11:00:07.246 1116 1149 I Test888 : at com.android.systemui.shared.system.RecentsAnimationControllerCompat.finish(RecentsAnimationControllerCompat.java:94)
10-12 11:00:07.246 1116 1149 I Test888 : at com.android.quickstep.RecentsAnimationController.lambda$finishController$2(RecentsAnimationController.java:177)
10-12 11:00:07.246 1116 1149 I Test888 : at com.android.quickstep.RecentsAnimationController.$r8$lambda$O-UPBLzcUdBJUpKkV1r9nfpt78c(Unknown Source:0)
10-12 11:00:07.246 1116 1149 I Test888 : at com.android.quickstep.RecentsAnimationController$$ExternalSyntheticLambda2.run(Unknown Source:6)
10-12 11:00:07.246 1116 1149 I Test888 : at android.os.Handler.handleCallback(Handler.java:958)
10-12 11:00:07.246 1116 1149 I Test888 : at android.os.Handler.dispatchMessage(Handler.java:99)
10-12 11:00:07.246 1116 1149 I Test888 : at android.os.Looper.loopOnce(Looper.java:205)
10-12 11:00:07.246 1116 1149 I Test888 : at android.os.Looper.loop(Looper.java:294)
10-12 11:00:07.246 1116 1149 I Test888 : at android.os.HandlerThread.run(HandlerThread.java:67)
SystemUI作为finish的服务端
10-12 11:00:07.248 699 746 I Test888 : finishTransition t WindowContainerTransaction {
changes = {
} hops = [{
reorder: android.os.BinderProxy@98aecf3 to top}, {
HOP(9): container=android.os.BinderProxy@b4b1db0 reparent=null mToTop=false mWindowingMode=null mActivityType=null}] errorCallbackToken=null taskFragmentOrganizer=null }
10-12 11:00:07.248 699 746 I Test888 : java.lang.Exception
10-12 11:00:07.248 699 746 I Test888 : at android.window.WindowOrganizer.finishTransition(WindowOrganizer.java:129)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.transition.Transitions.onFinish(Transitions.java:1022)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.transition.Transitions.lambda$playTransition$2(Transitions.java:886)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.transition.Transitions.$r8$lambda$rZGWGYWr2d1jBlWrN4VwN2bEtp8(Transitions.java:0)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.transition.Transitions$$ExternalSyntheticLambda6.onTransitionFinished(R8$$SyntheticClass:0)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.recents.RecentsTransitionHandler$RecentsController.finishInner(RecentsTransitionHandler.java:936)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.recents.RecentsTransitionHandler$RecentsController.lambda$finish$4(RecentsTransitionHandler.java:844)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.recents.RecentsTransitionHandler$RecentsController.$r8$lambda$bE4NZGOeGmWTYvy_B5v3UtTGYHs(RecentsTransitionHandler.java:0)
10-12 11:00:07.248 699 746 I Test888 : at com.android.wm.shell.recents.RecentsTransitionHandler$RecentsController$$ExternalSyntheticLambda4.run(R8$$SyntheticClass:0)
10-12 11:00:07.248 699 746 I Test888 : at android.os.Handler.handleCallback(Handler.java:958)
10-12 11:00:07.248 699 746 I Test888 : at android.os.Handler.dispatchMessage(Handler.java:99)
10-12 11:00:07.248 699 746 I Test888 : at android.os.Looper.loopOnce(Looper.java:205)
10-12 11:00:07.248 699 746 I Test888 : at android.os.Looper.loop(Looper.java:294)
10-12 11:00:07.248 699 746 I Test888 : at android.os.HandlerThread.run(HandlerThread.java:67)
system_server端会进行相关的task操作
10-12 11:00:07.248 491 1927 I Test888 : updateTaskMovement
10-12 11:00:07.248 491 1927 I Test888 : java.lang.Exception
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.Task.updateTaskMovement(Task.java:1267)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.TaskDisplayArea.positionChildTaskAt(TaskDisplayArea.java:407)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.TaskDisplayArea.positionChildAt(TaskDisplayArea.java:368)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.WindowOrganizerController.sanitizeAndApplyHierarchyOp(WindowOrganizerController.java:1487)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.WindowOrganizerController.applyHierarchyOp(WindowOrganizerController.java:992)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.WindowOrganizerController.applyTransaction(WindowOrganizerController.java:589)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.WindowOrganizerController.finishTransition(WindowOrganizerController.java:394)
10-12 11:00:07.248 491 1927 I Test888 : at android.window.IWindowOrganizerController$Stub.onTransact(IWindowOrganizerController.java:286)
10-12 11:00:07.248 491 1927 I Test888 : at com.android.server.wm.WindowOrganizerController.onTransact(WindowOrganizerController.java:181)
10-12 11:00:07.248 491 1927 I Test888 : at android.os.Binder.execTransactInternal(Binder.java:1339)
10-12 11:00:07.248 491 1927 I Test888 : at android.os.Binder.execTransact(Binder.java:1275)
为啥没有finishRecentsAnimation结束动画
查看ActiveGestureLog日志分析出来是因为没有执行finishRecentsAnimation,这里作为线索进行搜索:
查到了对应代码且加上堆栈:
正常打印如下:
定位到相关源码:
这里加入相关日志进行定位对比setState是哪里调用的,查找代码发现是如下地方:
因为这里
都有打印onSettledOnEndTarget:
onSettledOnEndTarget LAST_TASK
这里就说明肯定会进入圈中的地方。
ViewUtils.postFrameDrawn追踪分析:
/** See {@link #postFrameDrawn(View, Runnable, BooleanSupplier)}} */
public static boolean postFrameDrawn(View view, Runnable onFinishRunnable) {
return postFrameDrawn(view, onFinishRunnable, () -> false);
}
public static boolean postFrameDrawn(
View view, Runnable onFinishRunnable, BooleanSupplier canceled) {
return new FrameHandler(view, onFinishRunnable, canceled).schedule();
}
这里其实postFrameDrawn最后调用到了new FrameHandler(view, onFinishRunnable, canceled).schedule()方法,看看这里的schedule方法:
private boolean schedule() {
if (mViewRoot != null && mViewRoot.getView() != null) {
if (!mSurfaceCallbackRegistered) {
mSurfaceCallbackRegistered = true;
mViewRoot.addSurfaceChangedCallback(this);
}
mViewRoot.registerRtFrameCallback(this);
mViewRoot.getView().invalidate();
return true;
}
return false;
}
这里可以看出这里主要是注册了同步刷新相关的回调操作registerRtFrameCallback(但是这个地方大家注意,因为直接吧mDragLayer都隐藏了,导致TaskBar就相当于没有了一样,这里registerRtFrameCallback后是否会真的回调呢)最后完成会回调FrameHandler的onFrameDraw方法。
@Override
public void onFrameDraw(long frame) {
Utilities.postAsyncCallback(mHandler, this::onFrame);
}
private void onFrame() {
if (mCancelled.getAsBoolean()) {
return;
}
if (mDeferFrameCount > 0) {
mDeferFrameCount--;
schedule();
return;
}
finish();
}
private void finish() {
if (mFinished) {
return;
}
mFinished = true;
mDeferFrameCount = 0;
if (mFinishCallback != null) {
mFinishCallback.run();
}
if (mViewRoot != null) {
mViewRoot.removeSurfaceChangedCallback(this);
mSurfaceCallbackRegistered = false;
}
}
可以看出最后onFrameDraw会调用到finish方法,finish方法最重要就是执行了传递进来的onFinishRunnable即
mStateCallback.setState(STATE_RESUME_LAST_TASK)
ViewUtils.postFrameDrawn(postResumeLastTask,
() -> mStateCallback.setState(STATE_RESUME_LAST_TASK));
这里setState传递参数就是STATE_RESUME_LAST_TASK,这里最后就是会执行resumeLastTask方法,resumeLastTask方法是开始时候设置好的回调
调用到了resumeLastTask
@UiThread
private void resumeLastTask() {
if (mRecentsAnimationController != null) {
mRecentsAnimationController.finish(false /* toRecents */, null);
}
doLogGesture(LAST_TASK, null);
reset();
}
这个方法一路调到packages/apps/Launcher3/quickstep/src/com/android/quickstep/RecentsAnimationController.java的finishController方法。
通过打印分析,异常冻屏情况根本没有执行到finishController,但是日志看出确实有执行ViewUtils.postFrameDrawn,那么问题为啥异常情况没有调用到finishController呢?
其实本质还是出在同步等待的onFrameDraw方法没有被回调过,因为这个时候是依赖TaskBar窗口,但是TaskBar窗口本身又被隐藏了,所以就会导致onFrameDraw不会被回调,从而导致最后没正常调用finish。
修改验证:
修改方案1:
因为上面已经定位出来finishController没有被调用原因是onFrameDraw没被调用导致没办法mStateCallback.setState(STATE_RESUME_LAST_TASK)调用,那么是否可以不经过onFrameDraw回调,直接调用mStateCallback.setState(STATE_RESUME_LAST_TASK),其实这样修改是可以的
这里让不通过postFrameDraw这种同步绘制方式,直接调用,验证后是一切ok。
修改方案2:
其实TaskBar的隐藏本身系统中有更好的方法,不应该自己做的这种隐藏TaskBar的主View即mDragLayer方法,完全可以源头 上进行规避
更多framework干货请关注下面“千里马学框架”