Support toggling layer caching at runtime

The use-case for this is dynamically enabling and disabling layer
caching when a bad layer state is encountered that is difficult to
reproduce.

Bug: 187448777
Test: adb shell service call SurfaceFlinger 1040 i32 1
Test: libcompositionengine_test
Change-Id: Id441a0894ff5a4c654db9fd706ceb1c0d1c343f0
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5bd43e1..1e39d05 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -381,6 +381,12 @@
     mColorSpaceAgnosticDataspace =
             static_cast<ui::Dataspace>(color_space_agnostic_dataspace(Dataspace::UNKNOWN));
 
+    mLayerCachingEnabled = [] {
+        const bool enable =
+                android::sysprop::SurfaceFlingerProperties::enable_layer_caching().value_or(false);
+        return base::GetBoolProperty(std::string("debug.sf.enable_layer_caching"), enable);
+    }();
+
     useContextPriority = use_context_priority(true);
 
     using Values = SurfaceFlingerProperties::primary_display_orientation_values;
@@ -2641,6 +2647,7 @@
     builder.setGpuVirtualDisplayIdGenerator(mGpuVirtualDisplayIdGenerator);
     builder.setName(state.displayName);
     const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
+    compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled);
 
     sp<compositionengine::DisplaySurface> displaySurface;
     sp<IGraphicBufferProducer> producer;
@@ -5186,9 +5193,9 @@
         code == IBinder::SYSPROPS_TRANSACTION) {
         return OK;
     }
-    // Numbers from 1000 to 1038 are currently used for backdoors. The code
+    // Numbers from 1000 to 1040 are currently used for backdoors. The code
     // in onTransact verifies that the user is root, and has access to use SF.
-    if (code >= 1000 && code <= 1039) {
+    if (code >= 1000 && code <= 1040) {
         ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
         return OK;
     }
@@ -5572,6 +5579,33 @@
                 mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
                 return NO_ERROR;
             }
+            // Toggle caching feature
+            // First argument is an int32 - nonzero enables caching and zero disables caching
+            // 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) {
+                    inputId = DisplayId::fromValue<PhysicalDisplayId>(inputDisplayId);
+                    if (!inputId || getPhysicalDisplayToken(*inputId)) {
+                        ALOGE("No display with id: %" PRIu64, inputDisplayId);
+                        return NAME_NOT_FOUND;
+                    }
+                }
+                {
+                    Mutex::Autolock lock(mStateLock);
+                    mLayerCachingEnabled = n != 0;
+                    for (const auto& [_, display] : mDisplays) {
+                        if (!inputId || *inputId == display->getPhysicalId()) {
+                            display->enableLayerCaching(mLayerCachingEnabled);
+                        }
+                    }
+                }
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
         }
     }
     return err;