退出分屏进入桌面闪现黑帧问题分析
分屏退出到桌面的过程应该是桌面启动到前台后,分屏就退出到后台消失,这里已经收到了main和side stage的task不可见,那么说明桌面已经启动了,就可以正常交接了,但是hide后,发现底下却没有任何图层,在trace中继续向后寻找几帧后,找到了桌面layer,说明桌面的启动速度要低于ATMS的预期。从trace上看,在两帧之间,发送了更新事务的有两个进程,分别是shortcut和system

第一帧

第二帧

第三帧
录屏后,逐帧分析,上面为问题发生时的前后三帧。
第一帧是正常的,第二帧变黑,发现黑帧也不是全黑,底部导航栏和顶部状态栏也可以看见,对比第一帧,分屏两边APP界面和中间divider消失了,第三帧恢复回来后,两边APP界面回来了,中间还是消失的divider。
目前仅从视频分析,无法得知黑色帧的原因,需要进一步抓trace来分析。

从trace上看,黑色的这一帧layer组成,divider和app的activity的layer都消失了,所以露出了黑色底图,而在下一帧的layer,app的activity layer回来了,但是divider消失了,所以黑色帧应该是某个绘制控制进程设置了分屏的surface hide。
从trace上看,在两帧之间,发送了更新事务的有两个进程,分别是shortcut和systemui,进一步分析能够控制divider的进程只有分屏自己,所以应该是systemUI进程。
查看systemUI分屏控制代码 StageCoordinator.java
private void onStageVisibilityChanged(StageListenerImpl stageListener) {
final boolean sideStageVisible = mSideStageListener.mVisible;
final boolean mainStageVisible = mMainStageListener.mVisible;
// Divider is only visible if both the main stage and side stages are visible
setDividerVisibility(isSplitScreenVisible());
if (mExitSplitScreenOnHide && !mainStageVisible && !sideStageVisible) {
// Exit split-screen if both stage are not visible.
// TODO: This is only a temporary request from UX and is likely to be removed soon...
exitSplitScreen();
}
if (mainStageVisible) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (sideStageVisible) {
// The main stage configuration should to follow split layout when side stage is
// visible.
mMainStage.updateConfiguration(
WINDOWING_MODE_MULTI_WINDOW, getMainStageBounds(), wct);
} else {
// We want the main stage configuration to be fullscreen when the side stage isn't
// visible.
mMainStage.updateConfiguration(WINDOWING_MODE_FULLSCREEN, null, wct);
}
// TODO: Change to `mSyncQueue.queue(wct)` once BLAST is stable.
mTaskOrganizer.applyTransaction(wct);
}
mSyncQueue.runInSync(t -> {
final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
final SurfaceControl sideStageLeash = mSideStage.mRootLeash;
final SurfaceControl mainStageLeash = mMainStage.mRootLeash;
if (dividerLeash != null) {
if (mDividerVisible) {
t.show(dividerLeash)
.setLayer(dividerLeash, Integer.MAX_VALUE)
.setPosition(dividerLeash,
mSplitLayout.getDividerBounds().left,
mSplitLayout.getDividerBounds().top);
} else {
t.hide(dividerLeash);
}
}
if (sideStageVisible) {
final Rect sideStageBounds = getSideStageBounds();
t.show(sideStageLeash)
.setPosition(sideStageLeash,
sideStageBounds.left, sideStageBounds.top)
.setWindowCrop(sideStageLeash,
sideStageBounds.width(), sideStageBounds.height());
} else {
t.hide(sideStageLeash);
}
if (mainStageVisible) {
final Rect mainStageBounds = getMainStageBounds();
t.show(mainStageLeash);
if (sideStageVisible) {
t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top)
.setWindowCrop(mainStageLeash,
mainStageBounds.width(), mainStageBounds.height());
} else {
// Clear window crop and position if side stage isn't visible.
t.setPosition(mainStageLeash, 0, 0)
.setWindowCrop(mainStageLeash, null);
}
} else {
t.hide(mainStageLeash);
}
});
}

通过代码分析,可以看到,当TaskOrganizer通知StageCoordinator main和side stage的visible为false时,StageCoordinator就会将divider和main以及side的surface设置成false。通过调试确认了黑色帧就是在这里产生的,注释掉hide后,从分屏退到桌面正常。
但是这里有两个问题:
1.收到TaskOrganizer通知stage visable为false时hide应该是正常的,为什么hide会导致黑色帧呢?
2.为什么StageCoordinator hide之后第二帧就恢复了stage,但是没有恢复divider,如果不是StageCoordinator,那么是谁恢复的?
第一个问题:
收到TaskOrganizer通知stage visable为false时hide应该是正常的,为什么hide会导致黑色帧呢?
分屏退出到桌面的过程应该是桌面启动到前台后,分屏就退出到后台消失,这里已经收到了main和side stage的task不可见,那么说明桌面已经启动了,就可以正常交接了,但是hide后,发现底下却没有任何图层,在trace中继续向后寻找几帧后,找到了桌面layer,说明桌面的启动速度要低于ATMS的预期。这点需要进一步到ATMS中查看相关代码。
第二个问题:
为什么StageCoordinator hide之后第二帧就恢复了stage,但是没有恢复divider,如果不是StageCoordinator,那么是谁恢复的?
在StageCoordinator中没有看到任何地方会恢复,但trace中可以看到第二帧到第三帧是由WMS提交的事务,再进一步追踪,WMS是由shortcut提交的请求触发的,结合退出分屏时,有过渡动画,猜测是因为shortcut控制过渡动画时,将stage的leash surface的可见属性再此设置成了true。由于shortcut拿到的动画target没有divider,所以divider是隐藏的。
所以这里应该存在一个冲突的问题,分屏模块本身不知道动画存在,所以在收到ATMS的TaskOrganizer可见为false就直接退出了,但是动画模块正在绘制,还控制着leash surface,又设置了可见,而这时launcher并没有启动完成,所以闪黑帧根本原因是WMS和ATMS在做动画过渡时,没有考虑分屏和launcher的状态同步导致。
更多推荐


所有评论(0)