SF: Move config of HWComposer to setupHwComposer

Eliminate the setupFramebuffer function from Layer and
use setupHwComposer to actually setup the HWComposer.
Additionally, move preComposition and RebuildLayerStacks
into handleMessageInvalidate, as they are more frontend
processing.

Test: Compile/Run manually

Merged-In: Iffffbd8d044513ef3586ae2d25bdd76e077ed1af
Change-Id: Iffffbd8d044513ef3586ae2d25bdd76e077ed1af
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 579f7ec..616d22e 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -620,6 +620,7 @@
     getBE().compositionInfo.mBufferSlot = mActiveBufferSlot;
     getBE().compositionInfo.mBuffer = mActiveBuffer;
     getBE().compositionInfo.hwc.fence = acquireFence;
+    getBE().compositionInfo.updateBuffer = true;
 }
 
 bool BufferLayer::isOpaque(const Layer::State& s) const {
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b072213..5083099 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -483,6 +483,9 @@
     const auto hwcId = displayDevice->getHwcDisplayId();
     auto& hwcInfo = getBE().mHwcLayers[hwcId];
 
+    // Need to program geometry parts
+    getBE().compositionInfo.hwc.skipGeometry = false;
+
     // enable this layer
     hwcInfo.forceClientComposition = false;
 
@@ -603,7 +606,7 @@
     const uint32_t orientation = transform.getOrientation();
     if (orientation & Transform::ROT_INVALID || extremeScaling) {
         // we can only handle simple transformation
-        hwcInfo.forceClientComposition = true;
+        getBE().mHwcLayers[hwcId].compositionType = HWC2::Composition::Client;
     } else {
         auto transform = static_cast<HWC2::Transform>(orientation);
         hwcInfo.transform = transform;
@@ -611,108 +614,6 @@
     }
 }
 
-void Layer::configureHwcLayer(const sp<const DisplayDevice>& displayDevice) {
-    ATRACE_CALL();
-
-    auto hwcId = displayDevice->getHwcDisplayId();
-    auto& hwcInfo = getBE().mHwcLayers[hwcId];
-    auto& hwcLayer = hwcInfo.layer;
-
-    auto error = (*hwcLayer)->setBlendMode(getBE().compositionInfo.hwc.blendMode);
-    ALOGE_IF(error != HWC2::Error::None,
-             "[%s] Failed to set blend mode %s:"
-             " %s (%d)",
-             mName.string(),
-             to_string(getBE().compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(),
-             static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setDisplayFrame(getBE().compositionInfo.hwc.displayFrame);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set the display frame [%d, %d, %d, %d] %s (%d)",
-            mName.string(),
-            getBE().compositionInfo.hwc.displayFrame.left,
-            getBE().compositionInfo.hwc.displayFrame.right,
-            getBE().compositionInfo.hwc.displayFrame.top,
-            getBE().compositionInfo.hwc.displayFrame.bottom,
-            to_string(error).c_str(), static_cast<int32_t>(error));
-
-
-    error = (*hwcLayer)->setPlaneAlpha(getBE().compositionInfo.hwc.alpha);
-    ALOGE_IF(error != HWC2::Error::None,
-             "[%s] Failed to set plane alpha %.3f: "
-             "%s (%d)",
-             mName.string(), getBE().compositionInfo.hwc.alpha,
-             to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setSourceCrop(getBE().compositionInfo.hwc.sourceCrop);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)",
-            mName.string(),
-            getBE().compositionInfo.hwc.sourceCrop.left,
-            getBE().compositionInfo.hwc.sourceCrop.right,
-            getBE().compositionInfo.hwc.sourceCrop.top,
-            getBE().compositionInfo.hwc.sourceCrop.bottom,
-            to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setTransform(getBE().compositionInfo.hwc.transform);
-    ALOGE_IF(error != HWC2::Error::None,
-             "[%s] Failed to set transform %s: "
-             "%s (%d)",
-             mName.string(),
-             to_string(getBE().compositionInfo.hwc.transform).c_str(), to_string(error).c_str(),
-             static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setZOrder(getBE().compositionInfo.hwc.z);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set Z %u: %s (%d)",
-            mName.string(), getBE().compositionInfo.hwc.z,
-            to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setInfo(getBE().compositionInfo.hwc.type, getBE().compositionInfo.hwc.appId);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set info (%d)",
-            mName.string(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setVisibleRegion(getBE().compositionInfo.hwc.visibleRegion);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set visible region: %s (%d)",
-            mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setSurfaceDamage(getBE().compositionInfo.hwc.surfaceDamage);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set surface damage: %s (%d)",
-            mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setCompositionType(getBE().compositionInfo.compositionType);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set composition type: %s (%d)",
-            mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setDataspace(getBE().compositionInfo.hwc.dataspace);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set dataspace: %s (%d)",
-            mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
-    error = (*hwcLayer)->setHdrMetadata(getBE().compositionInfo.hwc.hdrMetadata);
-    if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
-        ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-
-    error = (*hwcLayer)->setColor(getBE().compositionInfo.hwc.color);
-    ALOGE_IF(error != HWC2::Error::None,
-            "[%s] Failed to set color: %s (%d)",
-            mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-
-    if (getBE().compositionInfo.hwc.fence) {
-        error = (*hwcLayer)->setBuffer(getBE().compositionInfo.mBufferSlot,
-                getBE().compositionInfo.mBuffer, getBE().compositionInfo.hwc.fence);
-        ALOGE_IF(error != HWC2::Error::None,
-                "[%s] Failed to set buffer: %s (%d)",
-                mName.string(), to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-}
-
 void Layer::forceClientComposition(int32_t hwcId) {
     if (getBE().mHwcLayers.count(hwcId) == 0) {
         ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
@@ -794,26 +695,12 @@
     clearWithOpenGL(renderArea, 0, 0, 0, 0);
 }
 
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
-    if (getBE().mHwcLayers.count(hwcId) == 0) {
-        ALOGE("setCompositionType called without a valid HWC layer");
-        return;
-    }
-    auto& hwcInfo = getBE().mHwcLayers[hwcId];
-    auto& hwcLayer = hwcInfo.layer;
-    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (*hwcLayer)->getId(), to_string(type).c_str(),
-          static_cast<int>(callIntoHwc));
-    if (hwcInfo.compositionType != type) {
-        ALOGV("    actually setting");
-        hwcInfo.compositionType = type;
-        if (callIntoHwc) {
-            auto error = (*hwcLayer)->setCompositionType(type);
-            ALOGE_IF(error != HWC2::Error::None,
-                     "[%s] Failed to set "
-                     "composition type %s: %s (%d)",
-                     mName.string(), to_string(type).c_str(), to_string(error).c_str(),
-                     static_cast<int32_t>(error));
-        }
+void Layer::setCompositionType(int32_t /*hwcId*/, HWC2::Composition type, bool /*callIntoHwc*/) {
+    if (getBE().compositionInfo.compositionType != type) {
+        ALOGV("setCompositionType: Changing compositionType from %s to %s",
+                to_string(getBE().compositionInfo.compositionType).c_str(),
+                to_string(type).c_str());
+        getBE().compositionInfo.compositionType = type;
     }
 }
 
@@ -823,11 +710,7 @@
         // have a HWC counterpart, then it will always be Client
         return HWC2::Composition::Client;
     }
-    if (getBE().mHwcLayers.count(hwcId) == 0) {
-        ALOGE("getCompositionType called with an invalid HWC layer");
-        return HWC2::Composition::Invalid;
-    }
-    return getBE().mHwcLayers.at(hwcId).compositionType;
+    return getBE().compositionInfo.compositionType;
 }
 
 void Layer::setClearClientTarget(int32_t hwcId, bool clear) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 87f9489..cac1c20 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -309,7 +309,6 @@
     virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
 
     void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
-    void configureHwcLayer(const sp<const DisplayDevice>& displayDevice);
     void forceClientComposition(int32_t hwcId);
     bool getForceClientComposition(int32_t hwcId);
     virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0;
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 06c88a4..767a3b3 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -64,8 +64,10 @@
     sp<GraphicBuffer> mBuffer = nullptr;
     int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
     LayerBE* layer = nullptr;
+    bool updateBuffer = false;
     struct {
         std::shared_ptr<LayerContainer> hwcLayer;
+        bool skipGeometry = true;
         int32_t hwid = -1;
         sp<Fence> fence;
         HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8d5c496..6552781 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1416,7 +1416,16 @@
             bool refreshNeeded = handleMessageTransaction();
             refreshNeeded |= handleMessageInvalidate();
             refreshNeeded |= mRepaintEverything;
+
+            const nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+            preComposition(refreshStartTime);
+            rebuildLayerStacks();
+
+            calculateWorkingSet();
+
             if (refreshNeeded) {
+
                 // Signal a refresh if a transaction modified the window state,
                 // a new buffer was latched, or if HWC has requested a full
                 // repaint
@@ -1445,6 +1454,101 @@
     return handlePageFlip();
 }
 
+void SurfaceFlinger::calculateWorkingSet() {
+    ATRACE_CALL();
+    ALOGV(__FUNCTION__);
+
+    // build the h/w work list
+    if (CC_UNLIKELY(mGeometryInvalid)) {
+        mGeometryInvalid = false;
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
+            const auto hwcId = displayDevice->getHwcDisplayId();
+            if (hwcId >= 0) {
+                const Vector<sp<Layer>>& currentLayers(
+                        displayDevice->getVisibleLayersSortedByZ());
+                for (size_t i = 0; i < currentLayers.size(); i++) {
+                    const auto& layer = currentLayers[i];
+
+                    if (!layer->hasHwcLayer(hwcId)) {
+                        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
+                            layer->forceClientComposition(hwcId);
+                            continue;
+                        }
+                    }
+
+                    layer->setGeometry(displayDevice, i);
+                    if (mDebugDisableHWC || mDebugRegion) {
+                        layer->forceClientComposition(hwcId);
+                    }
+                }
+            }
+        }
+    }
+    mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
+
+    // Set the per-frame data
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        auto& displayDevice = mDisplays[displayId];
+        const auto hwcId = displayDevice->getHwcDisplayId();
+
+        if (hwcId < 0) {
+            continue;
+        }
+        if (colorMatrix != mPreviousColorMatrix) {
+            status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
+            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
+                    "display %zd: %d", displayId, result);
+        }
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ ||
+                 layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) &&
+                    !displayDevice->getHdrSupport()) {
+                layer->forceClientComposition(hwcId);
+            }
+
+            if (layer->getForceClientComposition(hwcId)) {
+                ALOGV("[%s] Requesting Client composition", layer->getName().string());
+                layer->setCompositionType(hwcId, HWC2::Composition::Client);
+                continue;
+            }
+
+            layer->setPerFrameData(displayDevice);
+        }
+
+        if (hasWideColorDisplay) {
+            ColorMode  newColorMode;
+            android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
+
+            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace,
+                        displayDevice->getHdrSupport());
+                ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
+                      layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
+                      layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
+            }
+            newColorMode = pickColorMode(newDataSpace);
+
+            setActiveColorModeInternal(displayDevice, newColorMode);
+        }
+    }
+
+    mPreviousColorMatrix = colorMatrix;
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        auto& displayDevice = mDisplays[displayId];
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            auto hwcId = displayDevice->getHwcDisplayId();
+            layer->getBE().compositionInfo.compositionType = layer->getCompositionType(hwcId);
+            if (!layer->setHwcLayer(hwcId)) {
+                ALOGV("Need to create HWCLayer for %s", layer->getName().string());
+            }
+            layer->getBE().compositionInfo.hwc.hwid = hwcId;
+            getBE().mCompositionInfo.push_back(layer->getBE().compositionInfo);
+            layer->getBE().compositionInfo.hwc.hwcLayer = nullptr;
+        }
+    }
+}
+
 void SurfaceFlinger::handleMessageRefresh() {
     ATRACE_CALL();
 
@@ -1452,8 +1556,6 @@
 
     nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
 
-    preComposition(refreshStartTime);
-    rebuildLayerStacks();
     setUpHWComposer();
     doDebugFlashRegions();
     doTracing("handleRefresh");
@@ -1756,17 +1858,21 @@
                         if (!drawRegion.isEmpty()) {
                             layersSortedByZ.add(layer);
                         } else {
-                            // Clear out the HWC layer if this layer was
-                            // previously visible, but no longer is
+                            if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) {
+                                // Clear out the HWC layer if this layer was
+                                // previously visible, but no longer is
+                                hwcLayerDestroyed = layer->destroyHwcLayer(
+                                        displayDevice->getHwcDisplayId());
+                            }
+                        }
+                    } else {
+                        if (layer->hasHwcLayer(displayDevice->getHwcDisplayId())) {
+                            // WM changes displayDevice->layerStack upon sleep/awake.
+                            // Here we make sure we delete the HWC layers even if
+                            // WM changed their layer stack.
                             hwcLayerDestroyed = layer->destroyHwcLayer(
                                     displayDevice->getHwcDisplayId());
                         }
-                    } else {
-                        // WM changes displayDevice->layerStack upon sleep/awake.
-                        // Here we make sure we delete the HWC layers even if
-                        // WM changed their layer stack.
-                        hwcLayerDestroyed = layer->destroyHwcLayer(
-                                displayDevice->getHwcDisplayId());
                     }
 
                     // If a layer is not going to get a release fence because
@@ -1861,6 +1967,109 @@
     return HAL_DATASPACE_V0_SRGB;
 }
 
+void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const
+{
+    HWC2::Error error;
+
+    if (!compositionInfo.hwc.skipGeometry) {
+        if (compositionInfo.hwc.blendMode != HWC2::BlendMode::Invalid) {
+            error = (*compositionInfo.hwc.hwcLayer)->setBlendMode(compositionInfo.hwc.blendMode);
+            ALOGE_IF(error != HWC2::Error::None,
+                     "[SF] Failed to set blend mode %s:"
+                     " %s (%d)",
+                     to_string(compositionInfo.hwc.blendMode).c_str(), to_string(error).c_str(),
+                     static_cast<int32_t>(error));
+        }
+
+        if (compositionInfo.hwc.displayFrame.isValid()) {
+            error = (*compositionInfo.hwc.hwcLayer)->setDisplayFrame(compositionInfo.hwc.displayFrame);
+            ALOGE_IF(error != HWC2::Error::None,
+                    "[SF] Failed to set the display frame [%d, %d, %d, %d] %s (%d)",
+                    compositionInfo.hwc.displayFrame.left,
+                    compositionInfo.hwc.displayFrame.right,
+                    compositionInfo.hwc.displayFrame.top,
+                    compositionInfo.hwc.displayFrame.bottom,
+                    to_string(error).c_str(), static_cast<int32_t>(error));
+        }
+
+        if ((compositionInfo.hwc.sourceCrop.getWidth() > 0) && (compositionInfo.hwc.sourceCrop.getHeight() > 0)) {
+            error = (*compositionInfo.hwc.hwcLayer)->setSourceCrop(compositionInfo.hwc.sourceCrop);
+            ALOGE_IF(error != HWC2::Error::None,
+                    "[SF] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: %s (%d)",
+                    compositionInfo.hwc.sourceCrop.left,
+                    compositionInfo.hwc.sourceCrop.right,
+                    compositionInfo.hwc.sourceCrop.top,
+                    compositionInfo.hwc.sourceCrop.bottom,
+                    to_string(error).c_str(), static_cast<int32_t>(error));
+        }
+
+        error = (*compositionInfo.hwc.hwcLayer)->setPlaneAlpha(compositionInfo.hwc.alpha);
+        ALOGE_IF(error != HWC2::Error::None,
+                 "[SF] Failed to set plane alpha %.3f: "
+                 "%s (%d)",
+                 compositionInfo.hwc.alpha,
+                 to_string(error).c_str(), static_cast<int32_t>(error));
+
+
+        error = (*compositionInfo.hwc.hwcLayer)->setZOrder(compositionInfo.hwc.z);
+        ALOGE_IF(error != HWC2::Error::None,
+                "[SF] Failed to set Z %u: %s (%d)",
+                compositionInfo.hwc.z,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+
+        error = (*compositionInfo.hwc.hwcLayer)->setInfo(compositionInfo.hwc.type, compositionInfo.hwc.appId);
+        ALOGE_IF(error != HWC2::Error::None,
+                "[SF] Failed to set info (%d)",
+                static_cast<int32_t>(error));
+
+        if (compositionInfo.hwc.transform != HWC2::Transform::None) {
+            error = (*compositionInfo.hwc.hwcLayer)->setTransform(compositionInfo.hwc.transform);
+            ALOGE_IF(error != HWC2::Error::None,
+                     "[SF] Failed to set transform %s: "
+                     "%s (%d)",
+                     to_string(compositionInfo.hwc.transform).c_str(), to_string(error).c_str(),
+                     static_cast<int32_t>(error));
+        }
+    }
+
+    if (!compositionInfo.hwc.visibleRegion.isEmpty()) {
+        error = (*compositionInfo.hwc.hwcLayer)->setVisibleRegion(compositionInfo.hwc.visibleRegion);
+        ALOGE_IF(error != HWC2::Error::None,
+                "[SF] Failed to set visible region: %s (%d)",
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+
+    if (!compositionInfo.hwc.surfaceDamage.isEmpty()) {
+        error = (*compositionInfo.hwc.hwcLayer)->setSurfaceDamage(compositionInfo.hwc.surfaceDamage);
+        ALOGE_IF(error != HWC2::Error::None,
+                "[SF] Failed to set surface damage: %s (%d)",
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+
+    error = (*compositionInfo.hwc.hwcLayer)->setCompositionType(compositionInfo.compositionType);
+    ALOGE_IF(error != HWC2::Error::None,
+            "[SF] Failed to set composition type: %s (%d)",
+            to_string(error).c_str(), static_cast<int32_t>(error));
+
+    error = (*compositionInfo.hwc.hwcLayer)->setDataspace(compositionInfo.hwc.dataspace);
+    ALOGE_IF(error != HWC2::Error::None,
+            "[SF] Failed to set dataspace: %s (%d)",
+            to_string(error).c_str(), static_cast<int32_t>(error));
+
+    error = (*compositionInfo.hwc.hwcLayer)->setHdrMetadata(compositionInfo.hwc.hdrMetadata);
+    ALOGE_IF(error != HWC2::Error::None && error != HWC2::Error::Unsupported,
+            "[SF] Failed to set hdrMetadata: %s (%d)",
+            to_string(error).c_str(), static_cast<int32_t>(error));
+
+    if (compositionInfo.updateBuffer) {
+        error = (*compositionInfo.hwc.hwcLayer)->setBuffer(compositionInfo.mBufferSlot,
+                compositionInfo.mBuffer, compositionInfo.hwc.fence);
+        ALOGE_IF(error != HWC2::Error::None,
+                "[SF] Failed to set buffer: %s (%d)",
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+}
+
 void SurfaceFlinger::setUpHWComposer() {
     ATRACE_CALL();
     ALOGV("setUpHWComposer");
@@ -1894,94 +2103,36 @@
         }
     }
 
-    // build the h/w work list
-    if (CC_UNLIKELY(mGeometryInvalid)) {
-        mGeometryInvalid = false;
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
-            const auto hwcId = displayDevice->getHwcDisplayId();
-            if (hwcId >= 0) {
-                const Vector<sp<Layer>>& currentLayers(
-                        displayDevice->getVisibleLayersSortedByZ());
-                for (size_t i = 0; i < currentLayers.size(); i++) {
-                    const auto& layer = currentLayers[i];
-                    if (!layer->hasHwcLayer(hwcId)) {
-                        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
-                            layer->forceClientComposition(hwcId);
-                            continue;
-                        }
-                    }
+    {
+        ATRACE_NAME("Programming_HWCOMPOSER");
+        for (auto compositionInfo : getBE().mCompositionInfo) {
+            ALOGV("[SF] hwcLayer=%p(%lu), compositionType=%d",
+                  static_cast<HWC2::Layer*>(*compositionInfo.hwc.hwcLayer),
+                  compositionInfo.hwc.hwcLayer.use_count(), compositionInfo.compositionType);
 
-                    layer->setGeometry(displayDevice, i);
-                    if (mDebugDisableHWC || mDebugRegion) {
-                        layer->forceClientComposition(hwcId);
-                    }
-                }
+            switch (compositionInfo.compositionType)
+            {
+                case HWC2::Composition::Invalid:
+                    break;
+
+                case HWC2::Composition::Client:
+                    break;
+
+                case HWC2::Composition::SolidColor:
+                    break;
+
+                case HWC2::Composition::Cursor:
+                    break;
+
+                case HWC2::Composition::Sideband:
+                    break;
+
+                case HWC2::Composition::Device:
+                    configureDeviceComposition(compositionInfo);
+                break;
             }
         }
-    }
-
-
-    mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
-
-    // Set the per-frame data
-    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
-        auto& displayDevice = mDisplays[displayId];
-        const auto hwcId = displayDevice->getHwcDisplayId();
-
-        if (hwcId < 0) {
-            continue;
-        }
-        if (colorMatrix != mPreviousColorMatrix) {
-            status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
-            ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
-                    "display %zd: %d", displayId, result);
-        }
-        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-            if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ ||
-                 layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) &&
-                    !displayDevice->getHdrSupport()) {
-                layer->forceClientComposition(hwcId);
-            }
-
-            if (layer->getForceClientComposition(hwcId)) {
-                ALOGV("[%s] Requesting Client composition", layer->getName().string());
-                layer->setCompositionType(hwcId, HWC2::Composition::Client);
-                continue;
-            }
-
-            layer->setPerFrameData(displayDevice);
-        }
-
-        if (hasWideColorDisplay) {
-            ColorMode newColorMode;
-            android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
-
-            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
-                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace,
-                        displayDevice->getHdrSupport());
-                ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
-                      layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
-                      layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
-            }
-            newColorMode = pickColorMode(newDataSpace);
-
-            setActiveColorModeInternal(displayDevice, newColorMode);
-        }
-    }
-
-    mPreviousColorMatrix = colorMatrix;
-
-    for (size_t dpy = 0; dpy < mDisplays.size(); dpy++) {
-        sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
-        const auto hwcId = displayDevice->getHwcDisplayId();
-        if (hwcId >= 0) {
-            const Vector<sp<Layer>>& currentLayers(
-                    displayDevice->getVisibleLayersSortedByZ());
-            for (auto& layer : currentLayers) {
-                layer->configureHwcLayer(displayDevice);
-            }
-        }
+        getBE().mCompositionInfo.clear();
     }
 
     for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c7ffea7..f1ab81b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -201,6 +201,8 @@
     // use to differentiate callbacks from different hardware composer
     // instances. Each hardware composer instance gets a different sequence id.
     int32_t mComposerSequenceId;
+
+    std::vector<CompositionInfo> mCompositionInfo;
 };
 
 
@@ -631,6 +633,7 @@
 
     mat4 computeSaturationMatrix() const;
 
+    void calculateWorkingSet();
     void setUpHWComposer();
     void doComposition();
     void doDebugFlashRegions();
@@ -737,6 +740,9 @@
     // access must be protected by mInvalidateLock
     volatile int32_t mRepaintEverything;
 
+    // helper methods
+    void configureDeviceComposition(const CompositionInfo& compositionInfo) const;
+
     // constant members (no synchronization needed for access)
     nsecs_t mBootTime;
     bool mGpuToCpuSupported;