SF: Move/Refactor updateCursorAsync to CompositionEngine

As part of this change, the existing LayerFE::latchCompositionState is
extended to allow for more state types to be fetched.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I71e0f547440a64c1025f36741beb68e72c18e475
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 9558266..8bc3a34 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -16,6 +16,7 @@
 
 #include <compositionengine/CompositionRefreshArgs.h>
 #include <compositionengine/LayerFE.h>
+#include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/CompositionEngine.h>
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/impl/Layer.h>
@@ -70,6 +71,22 @@
     return mRefreshStartTime;
 }
 
+void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) {
+    std::unordered_map<compositionengine::LayerFE*, compositionengine::LayerFECompositionState*>
+            uniqueVisibleLayers;
+
+    for (const auto& output : args.outputs) {
+        for (auto& layer : output->getOutputLayersOrderedByZ()) {
+            if (layer->isHardwareCursor()) {
+                // Latch the cursor composition state from each front-end layer.
+                layer->getLayerFE().latchCursorCompositionState(
+                        layer->getLayer().editState().frontEnd);
+                layer->writeCursorPositionToHWC();
+            }
+        }
+    }
+}
+
 void CompositionEngine::preComposition(CompositionRefreshArgs& args) {
     ATRACE_CALL();
     ALOGV(__FUNCTION__);
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index e721cf5..73bb03b 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -550,6 +550,27 @@
     }
 }
 
+void OutputLayer::writeCursorPositionToHWC() const {
+    // Skip doing this if there is no HWC interface
+    auto hwcLayer = getHwcLayer();
+    if (!hwcLayer) {
+        return;
+    }
+
+    const auto& layerFEState = mLayer->getState().frontEnd;
+    const auto& outputState = mOutput.getState();
+
+    Rect frame = layerFEState.cursorFrame;
+    frame.intersect(outputState.viewport, &frame);
+    Rect position = outputState.transform.transform(frame);
+
+    if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
+        error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)", mLayerFE->getDebugName(),
+              position.left, position.top, to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+}
+
 HWC2::Layer* OutputLayer::getHwcLayer() const {
     return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr;
 }
@@ -559,6 +580,11 @@
             mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT;
 }
 
+bool OutputLayer::isHardwareCursor() const {
+    return mState.hwc &&
+            mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR;
+}
+
 void OutputLayer::detectDisallowedCompositionTypeChange(
         Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const {
     bool result = false;