Android14 TaskOrganizer导致黑屏
简介:
我们在对fw 原生的Task定制的时候,难免会出现各种黑屏的问题,如上图所示中间区域显示区域没有任何可见的view,然而我们来看看他的WindowManagerTrace 和 SurfaceFlingerTrace
WindowManagerTrace
SurfaceFlingerTrace
这里能看出来是因为父亲不可见导致的,我们再来看看父亲(Task)
根据我们抓取的相关窗口信息,可以得出以下结论:上层窗口明明可以看到,但在 SurfaceFlinger 层却不可见。这是为什么呢?
有经验的同学们应该知道,无论是 AMS 还是 WMS,都只是框架(fw)为应用封装的一套规则,真正的核心在于 SurfaceControl。它与底层的 SurfaceComposerClient 直接交互,控制着图层 Layer 的各种显示和隐藏状态。换句话说,WindowManagerTrace 抓取的只是客户端的上层表象,而真正的显示与否则由 SurfaceFlingerTrace 决定。我们大胆猜测,可能是这个 Task 的某个地方直接设置了 SurfaceControl 的状态,但没有通知 WindowManagerTrace,导致了显示上的差异。
通过对SurfaceFlingerTrace的我们能知道,桌面黑屏是因为Launcher的MainActivity不可见了,不可见的原因是 Hidden by parent Task=1,然而Task1不可见的原因是 Flag is hidden是隐藏状态,所以Task1处于隐藏中,所以我们要知道这个 Flag is hidden是怎么被设置的,fw所有的对窗口的操作,最终都会执行到SurfaceControl做最后的提交,我们看看SurfaceControl 中有那些方法控制着一个图层的隐藏
我们能发现在这三个地方控制这图层的隐藏,然后我们在这几个地方加上日志,复现问题或者加上堆栈的打印,我们就能知道是谁调用的隐藏,在进行反推看看,为什么被执行了隐藏,然而我可以很遗憾的告诉大家,在进行调试验证,问题复现时,这三个最直接的地方并没有被调用,对没错并没有调用,就那么水灵灵的在我眼前一下黑屏了!分析到这里一下就断了线索,一整懵逼不知道下一步又该怎么分析,(当然大家在对底层熟悉的可以继续往底层的Layer加日志调试堆栈CallStack callStack(mLogTag);)经过很久的...................................................................
再次分析SurfaceFlingerTrace
我们在回去SurfaceFlingerTrace的进行分析,我右发现了其他的怀疑点,我们先看看还没有黑屏的时候的Task1的状态
Task=1#68 ,在看异常的时候的
Task=1#188 ,task从68变成了188,恍然大悟,68变成了188 意味着Task被重新挂载了。继续打断点追踪
通过堆栈我们能看出来,Task =1进行了reparent,首先我们就会有一个疑问,执行了reparent就会导致Task的不可见吗? ,显然这并不能直接证明这是导致问题的直接原因,所以我们就需要对当前的这整个执行流程做详细的梳理
根据堆栈,我们来看到TaskOrganizerController--->registerTaskOrganizer
我们来看看这块都在做什么。这个方法时TaskOrganizerController中的registerTaskOrganizer注册任务组织者的实现,那什么是TaskOrganizer,这是fw中为了管理各个task的一个功能,比如在ShellTaskOrganizer extends TaskOrganizer 就是继承了TaskOrganizer,并且注册了registerOrganizer()
通过registerOrganizer最终会一步步的执行到TaskOrganizerController中的registerTaskOrganizer注册,后续就能监听到所有Task的变化,如registerTaskOrganizer(ITaskOrganizer organizer)中的接口定义
没错,就是接口中每个方法的英文的意思,这样就能监听到所有task的状态变化,来实现自己的相关业务,我们接着分段看TaskOrganizerController中的registerTaskOrganizer()
代码解读:
- 取出远端的Binder uid origId这样就知道是那个进程在注册
- 创建出一个集合taskInfos保存着当前被组织的TaskAppearedInfo信息,后面我们会讲解到这个集合
- withGlobalLock 在一个线程中去执行我们的任务
- 首先,检查当前注册的组织者是否已存在于
mTaskOrganizerStates
集合中。如果不存在,则将其添加到mTaskOrganizers
和mTaskOrganizerStates
两个集合中。这一步骤保证了仅有唯一的组织者参与任务管理,同时向其他模块提供当前任务组织者的信息。 -
-
mTaskOrganizerStates集合用organizer的Binder作为key,同时创建一个TaskOrganizerState对象记录者当前的组织者管理的所有的任务
- 通过前面创建的organizer.asBinder获取一个TaskOrganizerState
- 通过ActivityTaskManagerService拿到mRootWindowContainer循环遍历所有的Task
- 获取当前task的mCreatedByOrganizer,表示当前的task的创建是否是组织者创建的
- 循环遍历所有的task ,并且跟新他们的Organizer,task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */);
- 经过if判断后会创建一个TaskAppearedInfo保存在taskInfos,return并且返回
经过上面的堆栈,我们知道是通过updateTaskOrganizerState触发的重新reparent,
boolean updateTaskOrganizerState(boolean skipTaskAppeared) {
if (getSurfaceControl() == null) {
// Can't call onTaskAppeared without a surfacecontrol, so defer this until next one
// is created.
return false;
}
if (!canBeOrganized()) {
return setTaskOrganizer(null);
}
final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController;
final ITaskOrganizer organizer = controller.getTaskOrganizer();
// Do not change to different organizer if the task is created by organizer because only
// the creator knows how to manage it.
if (mCreatedByOrganizer && mTaskOrganizer != null && organizer != null
&& mTaskOrganizer != organizer) {
return false;
}
return setTaskOrganizer(organizer, skipTaskAppeared);
}
经过一些状态的判断继续执行setTaskOrganizer
@VisibleForTesting
boolean setTaskOrganizer(ITaskOrganizer organizer, boolean skipTaskAppeared) {
if (mTaskOrganizer == organizer) {
return false;
}
ITaskOrganizer prevOrganizer = mTaskOrganizer;
// Update the new task organizer before calling sendTaskVanished since it could result in
// a new SurfaceControl getting created that would notify the old organizer about it.
mTaskOrganizer = organizer;
// Let the old organizer know it has lost control.
sendTaskVanished(prevOrganizer);
if (mTaskOrganizer != null) {
if (!skipTaskAppeared) {
sendTaskAppeared();
}
} else {
// No longer managed by any organizer.
final TaskDisplayArea taskDisplayArea = getDisplayArea();
if (taskDisplayArea != null) {
taskDisplayArea.removeLaunchRootTask(this);
}
setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
if (mCreatedByOrganizer) {
removeImmediately("setTaskOrganizer");
}
}
return true;
}
这个地方需要注意,方法中我们传入了一个组织者organizer,并且把之前的mTaskOrganizer赋值给prevOrganizer,需要把之前的组织者全部数据清除sendTaskVanished(prevOrganizer);
private void sendTaskVanished(ITaskOrganizer organizer) {
if (organizer != null) {
mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this);
}
}
void onTaskVanished(ITaskOrganizer organizer, Task task) {
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
if (state != null && state.removeTask(task, task.mRemoveWithTaskOrganizer)) {
onTaskVanishedInternal(state, task);
}
}
如果state不为null ,就需要移除执行state.removeTask(task, task.mRemoveWithTaskOrganizer))
private boolean removeTask(Task t, boolean removeFromSystem) {
mOrganizedTasks.remove(t);
mInterceptBackPressedOnRootTasks.remove(t.mTaskId);
boolean taskAppearedSent = t.mTaskAppearedSent;
if (taskAppearedSent) {
if (t.getSurfaceControl() != null) {
t.migrateToNewSurfaceControl(t.getPendingTransaction());
}
t.mTaskAppearedSent = false;
}
if (removeFromSystem) {
mService.removeTask(t.mTaskId);
}
return taskAppearedSent;
}
根据堆栈的调用会调用各自task的migrateToNewSurfaceControl()挂载到新的SurfaceControl
@Override
void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
super.migrateToNewSurfaceControl(t);
mLastSurfaceSize.x = 0;
mLastSurfaceSize.y = 0;
updateSurfaceSize(t);
}
void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
t.remove(mSurfaceControl);
// Clear the last position so the new SurfaceControl will get correct position
mLastSurfacePosition.set(0, 0);
mLastDeltaRotation = Surface.ROTATION_0;
final Builder b = mWmService.makeSurfaceBuilder(null)
.setContainerLayer()
.setName(getName());
setInitialSurfaceControlProperties(b);
// If parent is null, the layer should be placed offscreen so reparent to null. Otherwise,
// set to the available parent.
t.reparent(mSurfaceControl, mParent == null ? null : mParent.getSurfaceControl());
if (mLastRelativeToLayer != null) {
t.setRelativeLayer(mSurfaceControl, mLastRelativeToLayer, mLastLayer);
} else {
t.setLayer(mSurfaceControl, mLastLayer);
}
for (int i = 0; i < mChildren.size(); i++) {
SurfaceControl sc = mChildren.get(i).getSurfaceControl();
if (sc != null) {
t.reparent(sc, mSurfaceControl);
}
}
if (mOverlayHost != null) {
mOverlayHost.setParent(t, mSurfaceControl);
}
scheduleAnimation();
}
代码解析
- 首先会通过t.remove(mSurfaceControl);移除当前Task的mSurfaceControl
- 在重新mWmService.makeSurfaceBuilder一个新的Builder b,设置他的层级和名字
- setInitialSurfaceControlProperties(b);重新创建一个新的SurfaceControl
- 创建完成后在把当前的Task重新挂载
看着也没有什么问题,我们在看看这个Builder b的Builder是什么
他是SurfaceControl中的一个内部类,而且他的mFlags = HIDDEN的状态默认就是隐藏
我们接着看setInitialSurfaceControlProperties(b);这个SurfaceControl是怎么创建的
void setInitialSurfaceControlProperties(Builder b) {
setSurfaceControl(b.setCallsite("WindowContainer.setInitialSurfaceControlProperties").build());
if (showSurfaceOnCreation()) {
Slog.d(TAG,"setInitialSurfaceControlProperties "+mSurfaceControl);
getSyncTransaction().show(mSurfaceControl);
}
updateSurfacePositionNonOrganized();
if (mLastMagnificationSpec != null) {
applyMagnificationSpec(getSyncTransaction(), mLastMagnificationSpec);
}
}
是通过Builder b,直接Build()一个SurfaceControl一个出来
if (showSurfaceOnCreation()) {
Slog.d(TAG,"setInitialSurfaceControlProperties "+mSurfaceControl);
getSyncTransaction().show(mSurfaceControl);
}
通过showSurfaceOnCreation()来判断当前的mSurfaceControl是否因该显示,这个showSurfaceOnCreation是
他是WMS中容器的基类中的一个基本方法,默认是true,默认是需要显示的,Task是他的子类是可以复写的
Task返回的就是fals,表示不需要显示,就不会执getSyncTransaction().show(mSurfaceControl);来显示这个Task,然后前面创建的Builder的时候默认也是mFlags = HIDDEN 隐藏,导致Task挂载在了一个是隐藏的mSurfaceControl的上了导致的下面的子窗口黑屏了
怎么解决呢?
我的解决方案是在Task中新增判断当前返回的showSurfaceOnCreation()的状态 亲测可行