当前位置: 首页 > news >正文

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()

代码解读:

  1. 取出远端的Binder uid origId这样就知道是那个进程在注册
  2. 创建出一个集合taskInfos保存着当前被组织的TaskAppearedInfo信息,后面我们会讲解到这个集合
  3. withGlobalLock 在一个线程中去执行我们的任务
  4. 首先,检查当前注册的组织者是否已存在于 mTaskOrganizerStates 集合中。如果不存在,则将其添加到 mTaskOrganizers 和 mTaskOrganizerStates 两个集合中。这一步骤保证了仅有唯一的组织者参与任务管理,同时向其他模块提供当前任务组织者的信息。
  5. mTaskOrganizerStates集合用organizer的Binder作为key,同时创建一个TaskOrganizerState对象记录者当前的组织者管理的所有的任务

  1. 通过前面创建的organizer.asBinder获取一个TaskOrganizerState
  2. 通过ActivityTaskManagerService拿到mRootWindowContainer循环遍历所有的Task
  3. 获取当前task的mCreatedByOrganizer,表示当前的task的创建是否是组织者创建的
  4. 循环遍历所有的task ,并且跟新他们的Organizer,task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */);
  5. 经过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();
    }

代码解析

  1. 首先会通过t.remove(mSurfaceControl);移除当前Task的mSurfaceControl
  2. 在重新mWmService.makeSurfaceBuilder一个新的Builder b,设置他的层级和名字
  3. setInitialSurfaceControlProperties(b);重新创建一个新的SurfaceControl
  4. 创建完成后在把当前的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()的状态 亲测可行

相关文章:

  • Vue的scoped原理是什么?
  • Spring boot3-WebClient远程调用非阻塞、响应式HTTP客户端
  • 数字电子技术基础(二十七)——输入端电阻的负载特性
  • electron 安装报错:RequestError: certificate has expired
  • 第14章 kali linux(网络安全防御实战--蓝军武器库)
  • 「JavaScript深入」理解 Object.defineProperty 与 Proxy
  • 每日一题之能量晶石
  • cursor中git提交记录出现 签出(已分离)
  • 反射、 Class类、JVM的类加载机制、Class的常用方法
  • 每日OJ_牛客_过桥_贪心+BFS_C++_Java
  • 51单片机汇编工程建立、仿真、调试全过程
  • 江科大51单片机笔记【15】直流电机驱动(PWM)
  • 图解AUTOSAR_CP_TcpIp
  • BFS比DFS更好理解「翻转二叉树」
  • 元宇宙与数字孪生
  • 基于Python懂车帝汽车数据分析平台(源码+lw+部署文档+讲解),源码可白嫖!
  • 《HTML + CSS + JS 打造炫酷轮播图详解》
  • 01 | Go 项目开发极速入门课介绍
  • C语言实现冒泡排序,超详解
  • 贝叶斯分层回归(Bayesian Hierarchical Regression)是一种基于贝叶斯统计理论的数据分析方法
  • 要更加冷静地看待“东升西降”的判断
  • 七大交响乐团在沪“神仙斗法”,时代交响奏出何等时代新声
  • 读图|展现城市品格,上海城市影像走进南美
  • 复旦设立新文科发展基金,校友曹国伟、王长田联合捐赠1亿助力人文学科与社会科学创新
  • 体坛联播|双杀阿森纳,巴黎晋级欧冠决赛对阵国际米兰
  • 全国铁路五一假期累计发送1.51亿人次,多项运输指标创历史新高