Android9.0 CompositionType分析

1.adb shell dumpsys SurfaceFlinger

dump时会打印出是HWC合成还是GPU合成,androidO开始HWC换成了Device,GPU换成了Client。

2.问题场景

打开 Settings -> Accessibility -> Color inversion 后冷启动应用会出现闪白屏。
在androidO上该问题是原生问题,但是在androidP上不再是原生问题。
通过dump SurfaceFlinger发现问题场景下为Client合成方式,而正常时为Device合成方式。
google原生解释理由:
The reason is that the surface of the app has been created, but the app does not send the data that needs to be displayed to the surfaceflinger in time, and waits for a few frames before starting to update. In this case, the surfaceflinger has no valid data, and it shows black surface. If it is a reverse color(using Invert colours option), we will see a white surface twinkling.

3.分析CompositionType

1) 在prepare的时候会去设置frame data到hwc hal中,会传入compositionType,根据下面的代码可以看出默认是有四种方式的:Sideband、Cursor、Device、SolidColor。

frameworks/native/services/surfaceflinger/BufferLayer.cpp
618void BufferLayer::setPerFrameData(const sp& displayDevice) {
...
641    // Sideband layers
642    if (getBE().compositionInfo.hwc.sidebandStream.get()) {
643        setCompositionType(hwcId, HWC2::Composition::Sideband);
644        ALOGV("[%s] Requesting Sideband composition", mName.string());
645        error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
646        if (error != HWC2::Error::None) {
647            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
648                  getBE().compositionInfo.hwc.sidebandStream->handle(), to_string(error).c_str(),
649                  static_cast(error));
650        }
651        return;
652    }
653
654    // Device or Cursor layers
655    if (mPotentialCursor) {
656        ALOGV("[%s] Requesting Cursor composition", mName.string());
657        setCompositionType(hwcId, HWC2::Composition::Cursor);
658    } else {
659        ALOGV("[%s] Requesting Device composition", mName.string());
660        setCompositionType(hwcId, HWC2::Composition::Device);
661    }

frameworks/native/services/surfaceflinger/ColorLayer.cpp
64void ColorLayer::setPerFrameData(const sp& displayDevice) {
...
78    setCompositionType(hwcId, HWC2::Composition::SolidColor);

还有一个地方会强制设置compositionType为Client。
hwc Hal层的layer创建失败;禁用HWC;打开debugRegion;layer的一些特殊属性等会设置compositionType为Client到hwc hal中。

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
1959void SurfaceFlinger::setUpHWComposer() {
...
2003                    if (!layer->hasHwcLayer(hwcId)) {
2004                        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
2005                            layer->forceClientComposition(hwcId);
2006                            continue;
2007                        }
2008                    }
2009
2010                    layer->setGeometry(displayDevice, i);
2011                    if (mDebugDisableHWC || mDebugRegion) {
2012                        layer->forceClientComposition(hwcId);
2013                    }
...
2033        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
2034            if (layer->isHdrY410()) {
2035                layer->forceClientComposition(hwcId);
2036            } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
2037                        layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
2038                    !displayDevice->hasHDR10Support()) {
2039                layer->forceClientComposition(hwcId);
2040            } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
2041                        layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
2042                    !displayDevice->hasHLGSupport()) {
2043                layer->forceClientComposition(hwcId);
2044            }
2045
2046            if (layer->getForceClientComposition(hwcId)) {
2047                ALOGV("[%s] Requesting Client composition", layer->getName().string());
2048                layer->setCompositionType(hwcId, HWC2::Composition::Client);
2049                continue;
2050            }

那么我们分析下Layer的setCompositionType,会根据callIntoHwc去决定是否将compositionType设置到hwc hal中,surfaceflinger第一次会向hwc hal中设置compositionType(callIntoHwc为true),hwc hal会返回给surfaceflinger侧compositionType改变的值(androidO上新增mChangeType),如果有改变的话只需要改变surfaceflinger侧即可,无需往hwc hal再设置compositionType(callIntoHwc为false),这个后面会分析。

frameworks/native/services/surfaceflinger/Layer.cpp
730void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
731    if (getBE().mHwcLayers.count(hwcId) == 0) {
732        ALOGE("setCompositionType called without a valid HWC layer");
733        return;
734    }
735    auto& hwcInfo = getBE().mHwcLayers[hwcId];
736    auto& hwcLayer = hwcInfo.layer;
737    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
738          static_cast(callIntoHwc));
739    if (hwcInfo.compositionType != type) {
740        ALOGV("    actually setting");
741        hwcInfo.compositionType = type;
742        if (callIntoHwc) {
743            auto error = hwcLayer->setCompositionType(type);
744            ALOGE_IF(error != HWC2::Error::None,
745                     "[%s] Failed to set "
746                     "composition type %s: %s (%d)",
747                     mName.string(), to_string(type).c_str(), to_string(error).c_str(),
748                     static_cast(error));
749        }
750    }
751}

最后,分析下hwc hal返回的结果。
在hwc hal层结束了prepare操作后,surfaceflinger侧会调用getChangedCompositionTypes得到底层更改后的compositionType,hwc hal层会实现getChangedCompositionTypes方法,当有改变的话changedTypes.count(hwcLayer)不为0,这样的话会向layer中重新设置compositionType,但是此时的callIntoHwc为false,即不向hwc hal层中设置。
同时,HWComposer中通过DisplayDate保存compositionType,注意只有两种:hasClientComposition、hasDeviceComposition。

frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
406status_t HWComposer::prepare(DisplayDevice& displayDevice) {
...
456        error = hwcDisplay->validate(&numTypes, &numRequests);
463    std::unordered_map changedTypes;
464    changedTypes.reserve(numTypes);
465    error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
477    for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
478        auto hwcLayer = layer->getHwcLayer(displayId);
479
480        if (changedTypes.count(hwcLayer) != 0) {
481            // We pass false so we only update our state and don't call back
482            // into the HWC device
483            validateChange(layer->getCompositionType(displayId),
484                    changedTypes[hwcLayer]);
485            layer->setCompositionType(displayId, changedTypes[hwcLayer], false);
486        }
488        switch (layer->getCompositionType(displayId)) {
489            case HWC2::Composition::Client:
490                displayData.hasClientComposition = true;
491                break;
492            case HWC2::Composition::Device:
493            case HWC2::Composition::SolidColor:
494            case HWC2::Composition::Cursor:
495            case HWC2::Composition::Sideband:
496                displayData.hasDeviceComposition = true;
497                break;
498            default:
499                break;
500        }

4.结论

有些平台hwc可以很好的支持这种场景的合成,而有些平台不支持的话就出现了问题。
至于底层如何实现的,这里就不方便贴出来了,自行研究~

你可能感兴趣的:(Android9.0 CompositionType分析)