Merge "Fix caching runtime toggle" into sc-dev
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index bf36355..088a400 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -136,6 +136,14 @@
     } else {
         mPlanner.reset();
     }
+
+    for (auto* outputLayer : getOutputLayersOrderedByZ()) {
+        if (!outputLayer) {
+            continue;
+        }
+
+        outputLayer->editState().overrideInfo = {};
+    }
 }
 
 void Output::setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 11736d1..6677f40 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -259,6 +259,27 @@
     EXPECT_FALSE(mOutput->plannerEnabled());
 }
 
+TEST_F(OutputTest, setLayerCachingEnabled_disablesCachingAndResetsOverrideInfo) {
+    renderengine::mock::RenderEngine renderEngine;
+    const auto kSize = ui::Size(1, 1);
+    EXPECT_CALL(*mRenderSurface, getSize()).WillRepeatedly(ReturnRef(kSize));
+    mOutput->setLayerCachingEnabled(true);
+
+    // Inject some layers
+    InjectedLayer layer;
+    layer.outputLayerState.overrideInfo.buffer = std::make_shared<
+            renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine,
+                                           renderengine::ExternalTexture::Usage::READABLE |
+                                                   renderengine::ExternalTexture::Usage::WRITEABLE);
+    injectOutputLayer(layer);
+    // inject a null layer to check for null exceptions
+    injectNullOutputLayer();
+
+    EXPECT_NE(nullptr, layer.outputLayerState.overrideInfo.buffer);
+    mOutput->setLayerCachingEnabled(false);
+    EXPECT_EQ(nullptr, layer.outputLayerState.overrideInfo.buffer);
+}
+
 /*
  * Output::setProjection()
  */
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a5b7107..7085eaf 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5595,26 +5595,35 @@
             // Second argument is an optional uint64 - if present, then limits enabling/disabling
             // caching to a particular physical display
             case 1040: {
-                n = data.readInt32();
-                std::optional<PhysicalDisplayId> inputId = std::nullopt;
-                if (uint64_t inputDisplayId; data.readUint64(&inputDisplayId) == NO_ERROR) {
-                    const auto token =
-                            getPhysicalDisplayToken(static_cast<PhysicalDisplayId>(inputDisplayId));
-                    if (!token) {
-                        ALOGE("No display with id: %" PRIu64, inputDisplayId);
-                        return NAME_NOT_FOUND;
-                    }
+                status_t error =
+                        schedule([&] {
+                            n = data.readInt32();
+                            std::optional<PhysicalDisplayId> inputId = std::nullopt;
+                            if (uint64_t inputDisplayId;
+                                data.readUint64(&inputDisplayId) == NO_ERROR) {
+                                const auto token = getPhysicalDisplayToken(
+                                        static_cast<PhysicalDisplayId>(inputDisplayId));
+                                if (!token) {
+                                    ALOGE("No display with id: %" PRIu64, inputDisplayId);
+                                    return NAME_NOT_FOUND;
+                                }
 
-                    inputId = std::make_optional<PhysicalDisplayId>(inputDisplayId);
-                }
-                {
-                    Mutex::Autolock lock(mStateLock);
-                    mLayerCachingEnabled = n != 0;
-                    for (const auto& [_, display] : mDisplays) {
-                        if (!inputId || *inputId == display->getPhysicalId()) {
-                            display->enableLayerCaching(mLayerCachingEnabled);
-                        }
-                    }
+                                inputId = std::make_optional<PhysicalDisplayId>(inputDisplayId);
+                            }
+                            {
+                                Mutex::Autolock lock(mStateLock);
+                                mLayerCachingEnabled = n != 0;
+                                for (const auto& [_, display] : mDisplays) {
+                                    if (!inputId || *inputId == display->getPhysicalId()) {
+                                        display->enableLayerCaching(mLayerCachingEnabled);
+                                    }
+                                }
+                            }
+                            return OK;
+                        }).get();
+
+                if (error != OK) {
+                    return error;
                 }
                 invalidateHwcGeometry();
                 repaintEverything();