1.adb shell dumpsys SurfaceFlinger
dump時(shí)會(huì)打印出是HWC合成還是GPU合成,androidO開始HWC換成了Device,GPU換成了Client。
2.問題場景
打開 Settings -> Accessibility -> Color inversion 后冷啟動(dòng)應(yīng)用會(huì)出現(xiàn)閃白屏。
在androidO上該問題是原生問題,但是在androidP上不再是原生問題。
通過dump SurfaceFlinger發(fā)現(xiàn)問題場景下為Client合成方式,而正常時(shí)為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的時(shí)候會(huì)去設(shè)置frame data到hwc hal中,會(huì)傳入compositionType,根據(jù)下面的代碼可以看出默認(rèn)是有四種方式的:Sideband、Cursor、Device、SolidColor。
frameworks/native/services/surfaceflinger/BufferLayer.cpp
618void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& 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<int32_t>(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<const DisplayDevice>& displayDevice) {
...
78 setCompositionType(hwcId, HWC2::Composition::SolidColor);
還有一個(gè)地方會(huì)強(qiáng)制設(shè)置compositionType為Client。
hwc Hal層的layer創(chuàng)建失??;禁用HWC;打開debugRegion;layer的一些特殊屬性等會(huì)設(shè)置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,會(huì)根據(jù)callIntoHwc去決定是否將compositionType設(shè)置到hwc hal中,surfaceflinger第一次會(huì)向hwc hal中設(shè)置compositionType(callIntoHwc為true),hwc hal會(huì)返回給surfaceflinger側(cè)compositionType改變的值(androidO上新增mChangeType),如果有改變的話只需要改變surfaceflinger側(cè)即可,無需往hwc hal再設(shè)置compositionType(callIntoHwc為false),這個(gè)后面會(huì)分析。
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<int>(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<int32_t>(error));
749 }
750 }
751}
最后,分析下hwc hal返回的結(jié)果。
在hwc hal層結(jié)束了prepare操作后,surfaceflinger側(cè)會(huì)調(diào)用getChangedCompositionTypes得到底層更改后的compositionType,hwc hal層會(huì)實(shí)現(xiàn)getChangedCompositionTypes方法,當(dāng)有改變的話changedTypes.count(hwcLayer)不為0,這樣的話會(huì)向layer中重新設(shè)置compositionType,但是此時(shí)的callIntoHwc為false,即不向hwc hal層中設(shè)置。
同時(shí),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<HWC2::Layer*, HWC2::Composition> 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.結(jié)論
有些平臺(tái)hwc可以很好的支持這種場景的合成,而有些平臺(tái)不支持的話就出現(xiàn)了問題。
至于底層如何實(shí)現(xiàn)的,這里就不方便貼出來了,自行研究~