Android 深色模式适配原理分析( 四 )

接着查找调用userForceDark()方法的地方
frameworks/base/libs/hwui/TreeInfo.cpp
TreeInfo::TreeInfo(TraversalMode mode, renderthread::CanvasContext// ...};到了这里 , 可以看出 , 当设置了Force Dark之后 , 最终会设置到TreeInfo类中的disableForceDark变量 , 如果没有设置主题的Force Dark , 那么根据false的默认值 , disableForceDark变量会别设置成1 , 如果设置了使用强制深色模式 , 那么disableForceDark会变成0 。
这个变量最终会用在RenderNode的RenderNode.handleForceDark()过程中 , 到达的流程如下图:
Android 深色模式适配原理分析文章插图
frameworks/base/libs/hwui/RenderNode.cpp
void RenderNode::prepareTreeImpl(TreeObserver}// 如果当前View不允许被ForceDark , 那么info.disableForceDark值+1if (!mProperties.getAllowForceDark()) {info.disableForceDark++;}// ...// 同步正在处理的Render Node的Display List , 实现具体深色的逻辑if (info.mode == TreeInfo::MODE_FULL) {pushStagingDisplayListChanges(observer, info);}if (mDisplayList) {info.out.hasFunctors |= mDisplayList->hasFunctor();bool isDirty = mDisplayList->prepareListAndChildren(observer, info, childFunctorsNeedLayer,[](RenderNode* child, TreeObserver});if (isDirty) {damageSelf(info);}}pushLayerUpdate(info);// 递归结束后将之前设置过+1的值做回退-1恢复操作 , 避免影响其他兄弟结点的深色模式值判断if (!mProperties.getAllowForceDark()) {info.disableForceDark--;}info.damageAccumulator->popTransform();}void RenderNode::pushStagingDisplayListChanges(TreeObserver// ...}void RenderNode::syncDisplayList(TreeObservermDisplayList->syncContents(syncData);// 强制执行深色模式执行handleForceDark(info);}}void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) {if (CC_LIKELY(!info || info->disableForceDark)) {// 如果disableForceDark不为0 , 关闭强制深色模式 , 则直接返回return;}auto usage = usageHint();const auto// 如果有文字表示是前景策略if (mDisplayList->hasText()) {usage = UsageHint::Foreground;}if (usage == UsageHint::Unknown) {// 如果子节点大于1或者第一个子节点不是背景 , 那么设置为背景策略if (children.size() > 1) {usage = UsageHint::Background;} else if (children.size() == 1}}if (children.size() > 1) {// Crude overlap checkSkRect drawn = SkRect::MakeEmpty();for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {const auto// We use stagingProperties here because we haven't yet sync'd the childrenSkRect bounds = SkRect::MakeXYWH(child->stagingProperties().getX(), child->stagingProperties().getY(),child->stagingProperties().getWidth(), child->stagingProperties().getHeight());if (bounds.contains(drawn)) {// This contains everything drawn after it, so make it a backgroundchild->setUsageHint(UsageHint::Background);}drawn.join(bounds);}}// 根据前景还是背景策略对颜色进行提亮或者加深mDisplayList->mDisplayList.applyColorTransform(usage == UsageHint::Background ? ColorTransform::Dark : ColorTransform::Light);}【Android 深色模式适配原理分析】Tips:View的绘制会根据VSYNC信号 , 将UI线程的Display List树同步到Render线程的Display List树 , 并通过生产者消费者模式将layout信息放置到SurfaceFlinger中 , 并最后交给Haredware Composer进行合成绘制 。 具体View渲染逻辑见参考章节的15~19文章列表 。