Merge "SF: Move config of HWComposer to setupHwComposer"
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 ecd09c5..bbd7179 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;