Android9.0 CompositionType分析

1.adb shell dumpsys SurfaceFlinger

dump時會打印出是HWC合成還是GPU合成,androidO開始HWC換成了Device伟骨,GPU換成了Client饮潦。

2.問題場景

打開 Settings -> Accessibility -> Color inversion 后冷啟動應(yīng)用會出現(xiàn)閃白屏。
在androidO上該問題是原生問題继蜡,但是在androidP上不再是原生問題逛腿。
通過dump SurfaceFlinger發(fā)現(xiàn)問題場景下為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的時候會去設(shè)置frame data到hwc hal中,會傳入compositionType殴俱,根據(jù)下面的代碼可以看出默認是有四種方式的: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);

還有一個地方會強制設(shè)置compositionType為Client趴泌。
hwc Hal層的layer創(chuàng)建失斃嗜憔;禁用HWC氏仗;打開debugRegion;layer的一些特殊屬性等會設(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珊拼,會根據(jù)callIntoHwc去決定是否將compositionType設(shè)置到hwc hal中食呻,surfaceflinger第一次會向hwc hal中設(shè)置compositionType(callIntoHwc為true)澎现,hwc hal會返回給surfaceflinger側(cè)compositionType改變的值(androidO上新增mChangeType),如果有改變的話只需要改變surfaceflinger側(cè)即可饼问,無需往hwc hal再設(shè)置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<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è)會調(diào)用getChangedCompositionTypes得到底層更改后的compositionType成艘,hwc hal層會實現(xiàn)getChangedCompositionTypes方法,當(dāng)有改變的話changedTypes.count(hwcLayer)不為0断箫,這樣的話會向layer中重新設(shè)置compositionType秋冰,但是此時的callIntoHwc為false仲义,即不向hwc hal層中設(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é)論

有些平臺hwc可以很好的支持這種場景的合成芝发,而有些平臺不支持的話就出現(xiàn)了問題苛谷。
至于底層如何實現(xiàn)的,這里就不方便貼出來了腹殿,自行研究~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市刻炒,隨后出現(xiàn)的幾起案子自沧,更是在濱河造成了極大的恐慌,老刑警劉巖拇厢,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異访敌,居然都是意外死亡,警方通過查閱死者的電腦和手機寺旺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門势决,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人徽龟,你說我怎么就攤上這事〈福” “怎么了极颓?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長菠隆。 經(jīng)常有香客問我狂秘,道長躯肌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任清女,我火速辦了婚禮,結(jié)果婚禮上拴袭,老公的妹妹穿的比我還像新娘曙博。我一直安慰自己拥刻,他們只是感情好父泳,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逝她,像睡著了一般睬捶。 火紅的嫁衣襯著肌膚如雪黔宛。 梳的紋絲不亂的頭發(fā)上擒贸,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音徽惋,去河邊找鬼座韵。 笑死险绘,一個胖子當(dāng)著我的面吹牛誉碴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播黔帕,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼成黄,長吁一口氣:“原來是場噩夢啊……” “哼呐芥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起荸百,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤潮太,失蹤者是張志新(化名)和其女友劉穎虾攻,沒想到半個月后铡买,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霎箍,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年景埃,在試婚紗的時候發(fā)現(xiàn)自己被綠了顶别。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡完慧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出屈尼,到底是詐尸還是另有隱情拴孤,我是刑警寧澤脾歧,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布鞭执,位于F島的核電站,受9級特大地震影響蚕冬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜囤热,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一获三、第九天 我趴在偏房一處隱蔽的房頂上張望锨苏。 院中可真熱鬧,春花似錦伞租、人聲如沸限佩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晕城,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間砖顷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工豌熄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留物咳,地道東北人锣险。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓囱持,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纷妆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容