Merge "SF: Introduce struct surfaceflinger::Config"
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 89c80bc..bf07f72 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -195,6 +195,7 @@
         "ScreenCaptureOutput.cpp",
         "StartPropertySetThread.cpp",
         "SurfaceFlinger.cpp",
+        "SurfaceFlingerConfig.cpp",
         "SurfaceFlingerDefaultFactory.cpp",
         "Tracing/LayerTracing.cpp",
         "Tracing/TransactionTracing.cpp",
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f6ca9e2..2789fa6 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -78,18 +78,19 @@
                     .setDisplayHeight(ANativeWindow_getHeight(args.nativeWindow.get()))
                     .setNativeWindow(std::move(args.nativeWindow))
                     .setDisplaySurface(std::move(args.displaySurface))
-                    .setMaxTextureCacheSize(
-                            static_cast<size_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers))
+                    .setMaxTextureCacheSize(static_cast<size_t>(
+                            mFlinger->getConfig().maxFrameBufferAcquiredBuffers))
                     .build());
 
-    if (!mFlinger->mDisableClientCompositionCache &&
-        SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) {
+    if (!mFlinger->getConfig().disableClientCompositionCache &&
+        mFlinger->getConfig().maxFrameBufferAcquiredBuffers > 0) {
         mCompositionDisplay->createClientCompositionCache(
-                static_cast<uint32_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers));
+                static_cast<uint32_t>(mFlinger->getConfig().maxFrameBufferAcquiredBuffers));
     }
 
-    mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy);
-    mCompositionDisplay->setTreat170mAsSrgb(mFlinger->mTreat170mAsSrgb);
+    mCompositionDisplay->setPredictCompositionStrategy(
+            mFlinger->getConfig().predictCompositionStrategy);
+    mCompositionDisplay->setTreat170mAsSrgb(mFlinger->getConfig().treat170mAsSrgb);
     mCompositionDisplay->createDisplayColorProfile(
             compositionengine::DisplayColorProfileCreationArgsBuilder()
                     .setHasWideColorGamut(args.hasWideColorGamut)
@@ -411,23 +412,22 @@
                            capabilities.getDesiredMinLuminance());
 }
 
-void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner,
-                                             bool showRenderRate, bool showInMiddle) {
+void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc) {
     if (!enable) {
         mRefreshRateOverlay.reset();
         return;
     }
 
     ftl::Flags<RefreshRateOverlay::Features> features;
-    if (showSpinner) {
+    if (mFlinger->getConfig().refreshRateOverlay.showSpinner) {
         features |= RefreshRateOverlay::Features::Spinner;
     }
 
-    if (showRenderRate) {
+    if (mFlinger->getConfig().refreshRateOverlay.showRenderRate) {
         features |= RefreshRateOverlay::Features::RenderRate;
     }
 
-    if (showInMiddle) {
+    if (mFlinger->getConfig().refreshRateOverlay.showInMiddle) {
         features |= RefreshRateOverlay::Features::ShowInMiddle;
     }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index dc5f8a8..d2a9fb6 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -236,8 +236,7 @@
     }
 
     // Enables an overlay to be displayed with the current refresh rate
-    void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate,
-                                  bool showInMiddle) REQUIRES(kMainThreadContext);
+    void enableRefreshRateOverlay(bool enable, bool setByHwc) REQUIRES(kMainThreadContext);
     void updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc = false);
     bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; }
     bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index ce602a8..14fff77 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -50,7 +50,8 @@
 
 FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
                                        const sp<IGraphicBufferConsumer>& consumer,
-                                       const ui::Size& size, const ui::Size& maxSize)
+                                       const ui::Size& size, const ui::Size& maxSize,
+                                       int maxAcquiredBufferCount)
       : ConsumerBase(consumer),
         mDisplayId(displayId),
         mMaxSize(maxSize),
@@ -70,8 +71,7 @@
                                        GRALLOC_USAGE_HW_COMPOSER);
     const auto limitedSize = limitSize(size);
     mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
-    mConsumer->setMaxAcquiredBufferCount(
-            SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
+    mConsumer->setMaxAcquiredBufferCount(maxAcquiredBufferCount);
 
     for (size_t i = 0; i < sizeof(mHwcBufferIds) / sizeof(mHwcBufferIds[0]); ++i) {
         mHwcBufferIds[i] = UINT64_MAX;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 0b863da..5a1d14f 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -42,7 +42,7 @@
 public:
     FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
                        const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
-                       const ui::Size& maxSize);
+                       const ui::Size& maxSize, int maxAcquiredBufferCount);
 
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index d62075e..d759c12 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -50,7 +50,7 @@
                                              const sp<IGraphicBufferProducer>& sink,
                                              const sp<IGraphicBufferProducer>& bqProducer,
                                              const sp<IGraphicBufferConsumer>& bqConsumer,
-                                             const std::string& name)
+                                             const std::string& name, bool useHwcForRgbToYuv)
       : ConsumerBase(bqConsumer),
         mHwc(hwc),
         mDisplayId(displayId),
@@ -69,7 +69,7 @@
         mOutputFence(Fence::NO_FENCE),
         mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
         mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
-        mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
+        mForceHwcCopy(useHwcForRgbToYuv) {
     mSource[SOURCE_SINK] = sink;
     mSource[SOURCE_SCRATCH] = bqProducer;
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index be06e2b..8a56d5f 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -77,7 +77,8 @@
 public:
     VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp<IGraphicBufferProducer>& sink,
                           const sp<IGraphicBufferProducer>& bqProducer,
-                          const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name);
+                          const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name,
+                          bool useHwcForRgbToYuv);
 
     //
     // DisplaySurface interface
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5a010e8..8e1b8f2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2562,7 +2562,7 @@
 compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
         const DisplayDevice* display) const {
     if (!display) return nullptr;
-    if (!mFlinger->mLayerLifecycleManagerEnabled) {
+    if (!mFlinger->getConfig().layerLifecycleManagerEnabled) {
         return display->getCompositionDisplay()->getOutputLayerForLayer(
                 getCompositionEngineLayerFE());
     }
@@ -2907,7 +2907,7 @@
 
 void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
     for (const auto& handle : mDrawingState.callbackHandles) {
-        if (mFlinger->mLayerLifecycleManagerEnabled) {
+        if (mFlinger->getConfig().layerLifecycleManagerEnabled) {
             handle->transformHint = mTransformHint;
         } else {
             handle->transformHint = mSkipReportingTransformHint
@@ -3162,7 +3162,7 @@
     mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(),
                                       mOwnerUid, postTime, getGameMode());
 
-    if (mFlinger->mLegacyFrontEndEnabled) {
+    if (mFlinger->getConfig().legacyFrontEndEnabled) {
         recordLayerHistoryBufferUpdate(getLayerProps());
     }
 
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index 51d4ff8..9c1944b 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -78,7 +78,7 @@
         mTransform = mLayerTransform.inverse();
     }
 
-    if (mFlinger.mLayerLifecycleManagerEnabled) {
+    if (mFlinger.getConfig().layerLifecycleManagerEnabled) {
         drawLayers();
         return;
     }
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 8f658d5..03f3b40 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -322,7 +322,7 @@
     };
 
     std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshots;
-    if (mFlinger.mLayerLifecycleManagerEnabled) {
+    if (mFlinger.getConfig().layerLifecycleManagerEnabled) {
         auto filterFn = [&](const frontend::LayerSnapshot& snapshot,
                             bool& outStopTraversal) -> bool {
             const Rect bounds =
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f3f6b6c..3165b9e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -214,16 +214,6 @@
 // TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
 constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
 
-float getDensityFromProperty(const char* property, bool required) {
-    char value[PROPERTY_VALUE_MAX];
-    const float density = property_get(property, value, nullptr) > 0 ? std::atof(value) : 0.f;
-    if (!density && required) {
-        ALOGE("%s must be defined as a build property", property);
-        return FALLBACK_DENSITY;
-    }
-    return density;
-}
-
 // Currently we only support V0_SRGB and DISPLAY_P3 as composition preference.
 bool validateCompositionDataspace(Dataspace dataspace) {
     return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3;
@@ -322,18 +312,6 @@
 static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB
 
 // ---------------------------------------------------------------------------
-int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
-bool SurfaceFlinger::useHwcForRgbToYuv;
-bool SurfaceFlinger::hasSyncFramework;
-int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
-int64_t SurfaceFlinger::minAcquiredBuffers = 1;
-uint32_t SurfaceFlinger::maxGraphicsWidth;
-uint32_t SurfaceFlinger::maxGraphicsHeight;
-bool SurfaceFlinger::useContextPriority;
-Dataspace SurfaceFlinger::defaultCompositionDataspace = Dataspace::V0_SRGB;
-ui::PixelFormat SurfaceFlinger::defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
-Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB;
-ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
 LatchUnsignaledConfig SurfaceFlinger::enableLatchUnsignaledConfig;
 
 std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) {
@@ -360,136 +338,35 @@
 
 ui::Transform::RotationFlags SurfaceFlinger::sActiveDisplayRotationFlags = ui::Transform::ROT_0;
 
-SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
-      : mFactory(factory),
-        mPid(getpid()),
+SurfaceFlinger::SurfaceFlinger(surfaceflinger::Config& config)
+      : mConfig(&config),
+        mDebugFlashDelay(base::GetUintProperty("debug.sf.showupdates"s, 0u)),
         mTimeStats(std::make_shared<impl::TimeStats>()),
-        mFrameTracer(mFactory.createFrameTracer()),
-        mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)),
-        mCompositionEngine(mFactory.createCompositionEngine()),
-        mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
+        mFrameTracer(mConfig->factory->createFrameTracer()),
+        mFrameTimeline(mConfig->factory->createFrameTimeline(mTimeStats, mConfig->pid)),
+        mCompositionEngine(mConfig->factory->createCompositionEngine()),
         mTunnelModeEnabledReporter(sp<TunnelModeEnabledReporter>::make()),
-        mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
-        mInternalDisplayDensity(
-                getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)),
         mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
         mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) {
-    ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
-}
-
-SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) {
     ATRACE_CALL();
-    ALOGI("SurfaceFlinger is starting");
+    ALOGI("SurfaceFlinger is starting.");
+    ALOGI("Using HWComposer service: %s", mConfig->hwcServiceName.c_str());
+    ALOGI_IF(mConfig->backpressureGpuComposition, "Enabling backpressure for GPU composition");
+    ALOGI_IF(!mConfig->supportsBlur, "Disabling blur effects, they are not supported.");
+    ALOGI_IF(mConfig->trebleTestingOverride, "Enabling Treble testing override");
 
-    hasSyncFramework = running_without_sync_framework(true);
-
-    dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0);
-
-    useHwcForRgbToYuv = force_hwc_copy_for_virtual_displays(false);
-
-    maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2);
-    minAcquiredBuffers =
-            SurfaceFlingerProperties::min_acquired_buffers().value_or(minAcquiredBuffers);
-
-    maxGraphicsWidth = std::max(max_graphics_width(0), 0);
-    maxGraphicsHeight = std::max(max_graphics_height(0), 0);
-
-    mSupportsWideColor = has_wide_color_display(false);
-    mDefaultCompositionDataspace =
-            static_cast<ui::Dataspace>(default_composition_dataspace(Dataspace::V0_SRGB));
-    mWideColorGamutCompositionDataspace = static_cast<ui::Dataspace>(wcg_composition_dataspace(
-            mSupportsWideColor ? Dataspace::DISPLAY_P3 : Dataspace::V0_SRGB));
-    defaultCompositionDataspace = mDefaultCompositionDataspace;
-    wideColorGamutCompositionDataspace = mWideColorGamutCompositionDataspace;
-    defaultCompositionPixelFormat = static_cast<ui::PixelFormat>(
-            default_composition_pixel_format(ui::PixelFormat::RGBA_8888));
-    wideColorGamutCompositionPixelFormat =
-            static_cast<ui::PixelFormat>(wcg_composition_pixel_format(ui::PixelFormat::RGBA_8888));
-
-    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);
-
-    mInternalDisplayPrimaries = sysprop::getDisplayNativePrimaries();
-
-    // debugging stuff...
-    char value[PROPERTY_VALUE_MAX];
-
-    property_get("ro.build.type", value, "user");
-    mIsUserBuild = strcmp(value, "user") == 0;
-
-    mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u);
-
-    mBackpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, true);
-    ALOGI_IF(mBackpressureGpuComposition, "Enabling backpressure for GPU composition");
-
-    property_get("ro.surface_flinger.supports_background_blur", value, "0");
-    bool supportsBlurs = atoi(value);
-    mSupportsBlur = supportsBlurs;
-    ALOGI_IF(!mSupportsBlur, "Disabling blur effects, they are not supported.");
-
-    const size_t defaultListSize = MAX_LAYERS;
-    auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
-    mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
-    mGraphicBufferProducerListSizeLogThreshold =
-            std::max(static_cast<int>(0.95 *
-                                      static_cast<double>(mMaxGraphicBufferProducerListSize)),
-                     1);
-
-    property_get("debug.sf.luma_sampling", value, "1");
-    mLumaSampling = atoi(value);
-
-    property_get("debug.sf.disable_client_composition_cache", value, "0");
-    mDisableClientCompositionCache = atoi(value);
-
-    property_get("debug.sf.predict_hwc_composition_strategy", value, "1");
-    mPredictCompositionStrategy = atoi(value);
-
-    property_get("debug.sf.treat_170m_as_sRGB", value, "0");
-    mTreat170mAsSrgb = atoi(value);
-
-    mIgnoreHwcPhysicalDisplayOrientation =
-            base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, false);
-
-    // We should be reading 'persist.sys.sf.color_saturation' here
-    // but since /data may be encrypted, we need to wait until after vold
-    // comes online to attempt to read the property. The property is
-    // instead read after the boot animation
-
-    if (base::GetBoolProperty("debug.sf.treble_testing_override"s, false)) {
+    if (mConfig->trebleTestingOverride) {
         // Without the override SurfaceFlinger cannot connect to HIDL
         // services that are not listed in the manifests.  Considered
         // deriving the setting from the set service name, but it
         // would be brittle if the name that's not 'default' is used
         // for production purposes later on.
-        ALOGI("Enabling Treble testing override");
         android::hardware::details::setTrebleTestingOverride(true);
     }
 
-    // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner
-    mRefreshRateOverlaySpinner = property_get_bool("debug.sf.show_refresh_rate_overlay_spinner", 0);
-    mRefreshRateOverlayRenderRate =
-            property_get_bool("debug.sf.show_refresh_rate_overlay_render_rate", 0);
-    mRefreshRateOverlayShowInMiddle =
-            property_get_bool("debug.sf.show_refresh_rate_overlay_in_middle", 0);
-
-    if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
+    if (!mConfig->isUserBuild && mConfig->enableTransactionTracing) {
         mTransactionTracing.emplace();
     }
-
-    mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false);
-
-    mLayerLifecycleManagerEnabled =
-            base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, false);
-    mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled ||
-            base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false);
 }
 
 LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
@@ -816,17 +693,18 @@
     // Get a RenderEngine for the given display / config (can't fail)
     // TODO(b/77156734): We need to stop casting and use HAL types when possible.
     // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
-    auto builder = renderengine::RenderEngineCreationArgs::Builder()
-                           .setPixelFormat(static_cast<int32_t>(defaultCompositionPixelFormat))
-                           .setImageCacheSize(maxFrameBufferAcquiredBuffers)
-                           .setUseColorManagerment(useColorManagement)
-                           .setEnableProtectedContext(enable_protected_contents(false))
-                           .setPrecacheToneMapperShaderOnly(false)
-                           .setSupportsBackgroundBlur(mSupportsBlur)
-                           .setContextPriority(
-                                   useContextPriority
-                                           ? renderengine::RenderEngine::ContextPriority::REALTIME
-                                           : renderengine::RenderEngine::ContextPriority::MEDIUM);
+    auto builder =
+            renderengine::RenderEngineCreationArgs::Builder()
+                    .setPixelFormat(static_cast<int32_t>(mConfig->defaultCompositionPixelFormat))
+                    .setImageCacheSize(mConfig->maxFrameBufferAcquiredBuffers)
+                    .setUseColorManagerment(useColorManagement)
+                    .setEnableProtectedContext(enable_protected_contents(false))
+                    .setPrecacheToneMapperShaderOnly(false)
+                    .setSupportsBackgroundBlur(mConfig->supportsBlur)
+                    .setContextPriority(
+                            mConfig->useContextPriority
+                                    ? renderengine::RenderEngine::ContextPriority::REALTIME
+                                    : renderengine::RenderEngine::ContextPriority::MEDIUM);
     if (auto type = chooseRenderEngineTypeViaSysProp()) {
         builder.setRenderEngineType(type.value());
     }
@@ -841,7 +719,7 @@
     }
 
     mCompositionEngine->setTimeStats(mTimeStats);
-    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
+    mCompositionEngine->setHwComposer(getFactory().createHWComposer(mConfig->hwcServiceName));
     mCompositionEngine->getHwComposer().setCallback(*this);
     ClientCache::getInstance().setRenderEngine(&getRenderEngine());
 
@@ -1031,11 +909,11 @@
     info->connectionType = snapshot.connectionType();
     info->deviceProductInfo = snapshot.deviceProductInfo();
 
-    if (mEmulatedDisplayDensity) {
-        info->density = mEmulatedDisplayDensity;
+    if (mConfig->emulatedDisplayDensity) {
+        info->density = mConfig->emulatedDisplayDensity;
     } else {
         info->density = info->connectionType == ui::DisplayConnectionType::Internal
-                ? mInternalDisplayDensity
+                ? mConfig->internalDisplayDensity
                 : FALLBACK_DENSITY;
     }
     info->density /= ACONFIGURATION_DENSITY_MEDIUM;
@@ -1098,7 +976,7 @@
         info->supportedDisplayModes.push_back(outMode);
     }
 
-    info->supportedColorModes = snapshot.filterColorModes(mSupportsWideColor);
+    info->supportedColorModes = snapshot.filterColorModes(mConfig->supportsWideColor);
 
     const PhysicalDisplayId displayId = snapshot.displayId();
 
@@ -1496,7 +1374,7 @@
     }
 
     // TODO(b/229846990): For now, assume that all internal displays have the same primaries.
-    primaries = mInternalDisplayPrimaries;
+    primaries = mConfig->internalDisplayPrimaries;
     return NO_ERROR;
 }
 
@@ -1520,7 +1398,7 @@
         const auto& [display, snapshotRef] = *displayOpt;
         const auto& snapshot = snapshotRef.get();
 
-        const auto modes = snapshot.filterColorModes(mSupportsWideColor);
+        const auto modes = snapshot.filterColorModes(mConfig->supportsWideColor);
         const bool exists = std::find(modes.begin(), modes.end(), mode) != modes.end();
 
         if (mode < ui::ColorMode::NATIVE || !exists) {
@@ -1826,7 +1704,7 @@
     }
 
     *outIsWideColorDisplay =
-            display->isPrimary() ? mSupportsWideColor : display->hasWideColorGamut();
+            display->isPrimary() ? mConfig->supportsWideColor : display->hasWideColorGamut();
     return NO_ERROR;
 }
 
@@ -1847,10 +1725,12 @@
         Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
         Dataspace* outWideColorGamutDataspace,
         ui::PixelFormat* outWideColorGamutPixelFormat) const {
-    *outDataspace = mDefaultCompositionDataspace;
-    *outPixelFormat = defaultCompositionPixelFormat;
-    *outWideColorGamutDataspace = mWideColorGamutCompositionDataspace;
-    *outWideColorGamutPixelFormat = wideColorGamutCompositionPixelFormat;
+    *outDataspace =
+            mOverrideDefaultCompositionDataspace.value_or(mConfig->defaultCompositionDataspace);
+    *outPixelFormat = mConfig->defaultCompositionPixelFormat;
+    *outWideColorGamutDataspace = mOverrideWideColorGamutCompositionDataspace.value_or(
+            mConfig->wideColorGamutCompositionDataspace);
+    *outWideColorGamutPixelFormat = mConfig->wideColorGamutCompositionPixelFormat;
     return NO_ERROR;
 }
 
@@ -2258,7 +2138,7 @@
                      .displays = mFrontEndDisplayInfos,
                      .displayChanges = mFrontEndDisplayInfosChanged,
                      .globalShadowSettings = mDrawingState.globalShadowSettings,
-                     .supportsBlur = mSupportsBlur,
+                     .supportsBlur = mConfig->supportsBlur,
                      .forceFullDamage = mForceFullDamage,
                      .supportedLayerGenericMetadata =
                              getHwComposer().getSupportedLayerGenericMetadata(),
@@ -2278,7 +2158,7 @@
     mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
 
     bool newDataLatched = false;
-    if (!mLegacyFrontEndEnabled) {
+    if (!mConfig->legacyFrontEndEnabled) {
         ATRACE_NAME("DisplayCallbackAndStatsUpdates");
         applyTransactions(update.transactions, vsyncId);
         const nsecs_t latchTime = systemTime();
@@ -2372,7 +2252,7 @@
     }
 
     if (pacesetterFrameTarget.isFramePending()) {
-        if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
+        if (mConfig->backpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
             scheduleCommit(FrameHint::kNone);
             return false;
         }
@@ -2403,7 +2283,7 @@
         mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod);
     }
 
-    if (mRefreshRateOverlaySpinner) {
+    if (mConfig->refreshRateOverlay.showSpinner) {
         Mutex::Autolock lock(mStateLock);
         if (const auto display = getDefaultDisplayDeviceLocked()) {
             display->animateRefreshRateOverlay();
@@ -2430,11 +2310,11 @@
             }
         }
         bool transactionsAreEmpty;
-        if (mLegacyFrontEndEnabled) {
+        if (mConfig->legacyFrontEndEnabled) {
             mustComposite |= updateLayerSnapshotsLegacy(vsyncId, updates, flushTransactions,
                                                         transactionsAreEmpty);
         }
-        if (mLayerLifecycleManagerEnabled) {
+        if (mConfig->layerLifecycleManagerEnabled) {
             mustComposite |=
                     updateLayerSnapshots(vsyncId, updates, flushTransactions, transactionsAreEmpty);
         }
@@ -2539,7 +2419,7 @@
     refreshArgs.outputColorSetting = useColorManagement
             ? mDisplayColorSetting
             : compositionengine::OutputColorSetting::kUnmanaged;
-    refreshArgs.colorSpaceAgnosticDataspace = mColorSpaceAgnosticDataspace;
+    refreshArgs.colorSpaceAgnosticDataspace = mConfig->colorSpaceAgnosticDataspace;
     refreshArgs.forceOutputColorMode = mForceColorMode;
 
     refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
@@ -2693,7 +2573,7 @@
     // Even though the camera layer may be using an HDR transfer function or otherwise be "HDR"
     // the device may need to avoid boosting the brightness as a result of these layers to
     // reduce power consumption during camera recording
-    if (mIgnoreHdrCameraLayers) {
+    if (mConfig->ignoreHdrCameraLayers) {
         if (snapshot.externalTexture &&
             (snapshot.externalTexture->getUsage() & GRALLOC_USAGE_HW_CAMERA_WRITE) != 0) {
             return false;
@@ -2724,7 +2604,7 @@
     if (!id) {
         return ui::ROTATION_0;
     }
-    if (!mIgnoreHwcPhysicalDisplayOrientation &&
+    if (!mConfig->ignoreHwcPhysicalDisplayOrientation &&
         getHwComposer().getComposer()->isSupported(
                 Hwc2::Composer::OptionalFeature::PhysicalDisplayOrientation)) {
         switch (getHwComposer().getPhysicalDisplayOrientation(*id)) {
@@ -2919,7 +2799,7 @@
     const bool isDisplayConnected =
             defaultDisplay && getHwComposer().isConnected(defaultDisplay->getPhysicalId());
 
-    if (!hasSyncFramework) {
+    if (!mConfig->hasSyncFramework) {
         if (isDisplayConnected && defaultDisplay->isPoweredOn()) {
             mScheduler->enableHardwareVsync(defaultDisplay->getPhysicalId());
         }
@@ -2960,7 +2840,7 @@
             if (!layer->hasTrustedPresentationListener()) {
                 return;
             }
-            const frontend::LayerSnapshot* snapshot = mLayerLifecycleManagerEnabled
+            const frontend::LayerSnapshot* snapshot = mConfig->layerLifecycleManagerEnabled
                     ? mLayerSnapshotBuilder.getSnapshot(layer->sequence)
                     : layer->getLayerSnapshot();
             std::optional<const DisplayDevice*> displayOpt = std::nullopt;
@@ -3355,7 +3235,7 @@
     builder.setPowerAdvisor(mPowerAdvisor.get());
     builder.setName(state.displayName);
     auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
-    compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled);
+    compositionDisplay->setLayerCachingEnabled(mConfig->layerCachingEnabled);
 
     sp<compositionengine::DisplaySurface> displaySurface;
     sp<IGraphicBufferProducer> producer;
@@ -3367,7 +3247,8 @@
         const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
         LOG_FATAL_IF(!displayId);
         auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,
-                                                       bqProducer, bqConsumer, state.displayName);
+                                                       bqProducer, bqConsumer, state.displayName,
+                                                       mConfig->useHwcForRgbToYuv);
         displaySurface = surface;
         producer = std::move(surface);
     } else {
@@ -3377,10 +3258,11 @@
                  state.surface.get());
         const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());
         LOG_FATAL_IF(!displayId);
-        displaySurface =
-                sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
-                                             state.physical->activeMode->getResolution(),
-                                             ui::Size(maxGraphicsWidth, maxGraphicsHeight));
+        displaySurface = sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
+                                                      state.physical->activeMode->getResolution(),
+                                                      ui::Size(mConfig->maxGraphicsWidth,
+                                                               mConfig->maxGraphicsHeight),
+                                                      mConfig->maxFrameBufferAcquiredBuffers);
         producer = bqProducer;
     }
 
@@ -3561,7 +3443,7 @@
     // Commit display transactions.
     const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded;
     mFrontEndDisplayInfosChanged = displayTransactionNeeded;
-    if (displayTransactionNeeded && !mLayerLifecycleManagerEnabled) {
+    if (displayTransactionNeeded && !mConfig->layerLifecycleManagerEnabled) {
         processDisplayChangesLocked();
         mFrontEndDisplayInfos.clear();
         for (const auto& [_, display] : mDisplays) {
@@ -3761,7 +3643,7 @@
     outWindowInfos.reserve(sNumWindowInfos);
     sNumWindowInfos = 0;
 
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         mLayerSnapshotBuilder.forEachInputSnapshot(
                 [&outWindowInfos](const frontend::LayerSnapshot& snapshot) {
                     outWindowInfos.push_back(snapshot.inputInfo);
@@ -3885,7 +3767,7 @@
     if (display->refreshRateSelector().kernelIdleTimerController()) {
         features |= Feature::kKernelIdleTimer;
     }
-    if (mBackpressureGpuComposition) {
+    if (mConfig->backpressureGpuComposition) {
         features |= Feature::kBackpressureGpuComposition;
     }
 
@@ -4558,7 +4440,7 @@
                                            const std::vector<ListenerCallbacks>& listenerCallbacks,
                                            int originPid, int originUid, uint64_t transactionId) {
     uint32_t transactionFlags = 0;
-    if (!mLayerLifecycleManagerEnabled) {
+    if (!mConfig->layerLifecycleManagerEnabled) {
         for (DisplayState& display : displays) {
             transactionFlags |= setDisplayStateLocked(display);
         }
@@ -4573,12 +4455,12 @@
 
     uint32_t clientStateFlags = 0;
     for (auto& resolvedState : states) {
-        if (mLegacyFrontEndEnabled) {
+        if (mConfig->legacyFrontEndEnabled) {
             clientStateFlags |=
                     setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime,
                                          isAutoTimestamp, postTime, transactionId);
 
-        } else /*mLayerLifecycleManagerEnabled*/ {
+        } else /* mConfig->layerLifecycleManagerEnabled */ {
             clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState,
                                                              desiredPresentTime, isAutoTimestamp,
                                                              postTime, transactionId);
@@ -4652,7 +4534,7 @@
     }
 
     mFrontEndDisplayInfosChanged = mTransactionFlags & eDisplayTransactionNeeded;
-    if (mFrontEndDisplayInfosChanged && !mLegacyFrontEndEnabled) {
+    if (mFrontEndDisplayInfosChanged && !mConfig->legacyFrontEndEnabled) {
         processDisplayChangesLocked();
         mFrontEndDisplayInfos.clear();
         for (const auto& [_, display] : mDisplays) {
@@ -4855,7 +4737,7 @@
         if (layer->setCornerRadius(s.cornerRadius))
             flags |= eTraversalNeeded;
     }
-    if (what & layer_state_t::eBackgroundBlurRadiusChanged && mSupportsBlur) {
+    if (what & layer_state_t::eBackgroundBlurRadiusChanged && mConfig->supportsBlur) {
         if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
     }
     if (what & layer_state_t::eBlurRegionsChanged) {
@@ -5259,7 +5141,7 @@
         return result;
     }
 
-    if (mLegacyFrontEndEnabled) {
+    if (mConfig->legacyFrontEndEnabled) {
         std::scoped_lock<std::mutex> lock(mMirrorDisplayLock);
         mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client);
     }
@@ -5366,9 +5248,10 @@
     const nsecs_t now = systemTime();
     state.desiredPresentTime = now;
     state.postTime = now;
-    state.originPid = mPid;
+    state.originPid = mConfig->pid;
     state.originUid = static_cast<int>(getuid());
-    const uint64_t transactionId = (static_cast<uint64_t>(mPid) << 32) | mUniqueTransactionId++;
+    const uint64_t transactionId =
+            (static_cast<uint64_t>(mConfig->pid) << 32) | mUniqueTransactionId++;
     state.id = transactionId;
 
     // reset screen orientation and use primary layer stack
@@ -5388,7 +5271,7 @@
     std::vector<TransactionState> transactions;
     transactions.emplace_back(state);
 
-    if (mLegacyFrontEndEnabled) {
+    if (mConfig->legacyFrontEndEnabled) {
         applyTransactions(transactions, VsyncId{0});
     } else {
         applyAndCommitDisplayTransactionStates(transactions);
@@ -5684,13 +5567,13 @@
 void SurfaceFlinger::appendSfConfigString(std::string& result) const {
     result.append(" [sf");
 
-    StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
-    StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
+    StringAppendF(&result, " PRESENT_TIME_OFFSET=%" PRId64, mConfig->dispSyncPresentTimeOffset);
+    StringAppendF(&result, " FORCE_HWC_FOR_RBG_TO_YUV=%d", mConfig->useHwcForRgbToYuv);
     StringAppendF(&result, " MAX_VIRT_DISPLAY_DIM=%zu",
                   getHwComposer().getMaxVirtualDisplayDimension());
-    StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
+    StringAppendF(&result, " RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !mConfig->hasSyncFramework);
     StringAppendF(&result, " NUM_FRAMEBUFFER_SURFACE_BUFFERS=%" PRId64,
-                  maxFrameBufferAcquiredBuffers);
+                  mConfig->maxFrameBufferAcquiredBuffers);
     result.append("]");
 }
 
@@ -5710,7 +5593,7 @@
     StringAppendF(&result,
                   "         present offset: %9" PRId64 " ns\t        VSYNC period: %9" PRId64
                   " ns\n\n",
-                  dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
+                  mConfig->dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
 }
 
 void SurfaceFlinger::dumpEvents(std::string& result) const {
@@ -5809,7 +5692,7 @@
 }
 
 void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {
-    StringAppendF(&result, "Device supports wide color: %d\n", mSupportsWideColor);
+    StringAppendF(&result, "Device supports wide color: %d\n", mConfig->supportsWideColor);
     StringAppendF(&result, "Device uses color management: %d\n", useColorManagement);
     StringAppendF(&result, "DisplayColorSetting: %s\n",
                   decodeDisplayColorSetting(mDisplayColorSetting).c_str());
@@ -5843,7 +5726,7 @@
         }
     }
 
-    if (mLegacyFrontEndEnabled) {
+    if (mConfig->legacyFrontEndEnabled) {
         LayersProto layersProto;
         for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
             if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) {
@@ -6500,7 +6383,7 @@
                         if (!validateCompositionDataspace(dataspace)) {
                             return BAD_VALUE;
                         }
-                        mDefaultCompositionDataspace = dataspace;
+                        mOverrideDefaultCompositionDataspace = dataspace;
                     }
                     n = data.readInt32();
                     if (n) {
@@ -6508,12 +6391,12 @@
                         if (!validateCompositionDataspace(dataspace)) {
                             return BAD_VALUE;
                         }
-                        mWideColorGamutCompositionDataspace = dataspace;
+                        mOverrideWideColorGamutCompositionDataspace = dataspace;
                     }
                 } else {
-                    // restore composition data space.
-                    mDefaultCompositionDataspace = defaultCompositionDataspace;
-                    mWideColorGamutCompositionDataspace = wideColorGamutCompositionDataspace;
+                    // Reset data space overrides.
+                    mOverrideDefaultCompositionDataspace.reset();
+                    mOverrideWideColorGamutCompositionDataspace.reset();
                 }
                 return NO_ERROR;
             }
@@ -6652,10 +6535,10 @@
                     }
                     {
                         Mutex::Autolock lock(mStateLock);
-                        mLayerCachingEnabled = n != 0;
+                        mConfig->layerCachingEnabled = n != 0;
                         for (const auto& [_, display] : mDisplays) {
                             if (!inputId || *inputId == display->getPhysicalId()) {
-                                display->enableLayerCaching(mLayerCachingEnabled);
+                                display->enableLayerCaching(mConfig->layerCachingEnabled);
                             }
                         }
                     }
@@ -6980,7 +6863,7 @@
     });
 
     GetLayerSnapshotsFunction getLayerSnapshots;
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         getLayerSnapshots =
                 getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds));
     } else {
@@ -7023,7 +6906,7 @@
     });
 
     GetLayerSnapshotsFunction getLayerSnapshots;
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
                                                             /*snapshotFilterFn=*/nullptr);
     } else {
@@ -7119,7 +7002,7 @@
     RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> {
         ui::Transform layerTransform;
         Rect layerBufferSize;
-        if (mLayerLifecycleManagerEnabled) {
+        if (mConfig->layerLifecycleManagerEnabled) {
             frontend::LayerSnapshot* snapshot =
                     mLayerSnapshotBuilder.getSnapshot(parent->getSequence());
             if (!snapshot) {
@@ -7139,7 +7022,7 @@
                                                  args.hintForSeamlessTransition);
     });
     GetLayerSnapshotsFunction getLayerSnapshots;
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         std::optional<FloatRect> parentCrop = std::nullopt;
         if (args.childrenOnly) {
             parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height)
@@ -7392,7 +7275,7 @@
                     layerStack, regionSampling, renderArea = std::move(renderArea),
                     renderIntent]() -> FenceResult {
         std::unique_ptr<compositionengine::CompositionEngine> compositionEngine =
-                mFactory.createCompositionEngine();
+                mConfig->factory->createCompositionEngine();
         compositionEngine->setRenderEngine(mRenderEngine.get());
 
         compositionengine::Output::ColorProfile colorProfile{.dataspace = dataspace,
@@ -7462,7 +7345,7 @@
 }
 
 void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const {
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         for (auto& layer : mLegacyLayers) {
             visitor(layer.second.get());
         }
@@ -7784,9 +7667,7 @@
             }
 
             if (const auto device = getDisplayDeviceLocked(id)) {
-                device->enableRefreshRateOverlay(enable, setByHwc, mRefreshRateOverlaySpinner,
-                                                 mRefreshRateOverlayRenderRate,
-                                                 mRefreshRateOverlayShowInMiddle);
+                device->enableRefreshRateOverlay(enable, setByHwc);
             }
         }
     }
@@ -7797,12 +7678,12 @@
 }
 
 int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate,
-                                                    std::chrono::nanoseconds presentLatency) {
+                                                    std::chrono::nanoseconds presentLatency) const {
     auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs();
     if (presentLatency.count() % refreshRate.getPeriodNsecs()) {
         pipelineDepth++;
     }
-    return std::max(minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1));
+    return std::max(mConfig->minAcquiredBuffers, static_cast<int64_t>(pipelineDepth - 1));
 }
 
 status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const {
@@ -7884,7 +7765,7 @@
 }
 
 void SurfaceFlinger::sample() {
-    if (!mLumaSampling || !mRegionSamplingThread) {
+    if (!mConfig->lumaSampling || !mRegionSamplingThread) {
         return;
     }
 
@@ -8076,7 +7957,7 @@
 void SurfaceFlinger::moveSnapshotsFromCompositionArgs(
         compositionengine::CompositionRefreshArgs& refreshArgs,
         const std::vector<std::pair<Layer*, LayerFE*>>& layers) {
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         std::vector<std::unique_ptr<frontend::LayerSnapshot>>& snapshots =
                 mLayerSnapshotBuilder.getSnapshots();
         for (auto [_, layerFE] : layers) {
@@ -8084,7 +7965,7 @@
             snapshots[i] = std::move(layerFE->mSnapshot);
         }
     }
-    if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
+    if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) {
         for (auto [layer, layerFE] : layers) {
             layer->updateLayerSnapshot(std::move(layerFE->mSnapshot));
         }
@@ -8094,7 +7975,7 @@
 std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToCompositionArgs(
         compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly) {
     std::vector<std::pair<Layer*, LayerFE*>> layers;
-    if (mLayerLifecycleManagerEnabled) {
+    if (mConfig->layerLifecycleManagerEnabled) {
         nsecs_t currentTime = systemTime();
         mLayerSnapshotBuilder.forEachVisibleSnapshot(
                 [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
@@ -8120,7 +8001,7 @@
                     layers.emplace_back(legacyLayer.get(), layerFE.get());
                 });
     }
-    if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) {
+    if (mConfig->legacyFrontEndEnabled && !mConfig->layerLifecycleManagerEnabled) {
         auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) {
             if (const auto& layerFE = layer->getCompositionEngineLayerFE()) {
                 if (cursorOnly &&
@@ -8212,7 +8093,7 @@
                      .displays = mFrontEndDisplayInfos,
                      .displayChanges = true,
                      .globalShadowSettings = mDrawingState.globalShadowSettings,
-                     .supportsBlur = mSupportsBlur,
+                     .supportsBlur = mConfig->supportsBlur,
                      .forceFullDamage = mForceFullDamage,
                      .excludeLayerIds = std::move(excludeLayerIds),
                      .supportedLayerGenericMetadata =
@@ -8246,7 +8127,7 @@
                      .displays = mFrontEndDisplayInfos,
                      .displayChanges = true,
                      .globalShadowSettings = mDrawingState.globalShadowSettings,
-                     .supportsBlur = mSupportsBlur,
+                     .supportsBlur = mConfig->supportsBlur,
                      .forceFullDamage = mForceFullDamage,
                      .parentCrop = parentCrop,
                      .excludeLayerIds = std::move(excludeLayerIds),
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 128da63..7910297 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -63,6 +63,7 @@
 #include <scheduler/interface/ICompositor.h>
 #include <ui/FenceResult.h>
 
+#include "Client.h"
 #include "Display/PhysicalDisplay.h"
 #include "DisplayDevice.h"
 #include "DisplayHardware/HWC2.h"
@@ -81,6 +82,7 @@
 #include "Scheduler/RefreshRateSelector.h"
 #include "Scheduler/RefreshRateStats.h"
 #include "Scheduler/Scheduler.h"
+#include "SurfaceFlingerConfig.h"
 #include "SurfaceFlingerFactory.h"
 #include "ThreadContext.h"
 #include "Tracing/LayerTracing.h"
@@ -107,7 +109,6 @@
 
 #include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
 #include <aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.h>
-#include "Client.h"
 
 using namespace android::surfaceflinger;
 
@@ -197,10 +198,7 @@
                        private scheduler::ISchedulerCallback,
                        private compositionengine::ICEPowerCallback {
 public:
-    struct SkipInitializationTag {};
-
-    SurfaceFlinger(surfaceflinger::Factory&, SkipInitializationTag) ANDROID_API;
-    explicit SurfaceFlinger(surfaceflinger::Factory&) ANDROID_API;
+    explicit SurfaceFlinger(surfaceflinger::Config&) ANDROID_API;
 
     // set main thread scheduling policy
     static status_t setSchedFifo(bool enabled) ANDROID_API;
@@ -210,51 +208,9 @@
 
     static char const* getServiceName() ANDROID_API { return "SurfaceFlinger"; }
 
-    // If fences from sync Framework are supported.
-    static bool hasSyncFramework;
-
-    // The offset in nanoseconds to use when VsyncController timestamps present fence
-    // signaling time.
-    static int64_t dispSyncPresentTimeOffset;
-
-    // Some hardware can do RGB->YUV conversion more efficiently in hardware
-    // controlled by HWC than in hardware controlled by the video encoder.
-    // This instruct VirtualDisplaySurface to use HWC for such conversion on
-    // GL composition.
-    static bool useHwcForRgbToYuv;
-
-    // Controls the number of buffers SurfaceFlinger will allocate for use in
-    // FramebufferSurface
-    static int64_t maxFrameBufferAcquiredBuffers;
-
-    // Controls the minimum acquired buffers SurfaceFlinger will suggest via
-    // ISurfaceComposer.getMaxAcquiredBufferCount().
-    static int64_t minAcquiredBuffers;
-
-    // Controls the maximum width and height in pixels that the graphics pipeline can support for
-    // GPU fallback composition. For example, 8k devices with 4k GPUs, or 4k devices with 2k GPUs.
-    static uint32_t maxGraphicsWidth;
-    static uint32_t maxGraphicsHeight;
-
     // Indicate if device wants color management on its display.
     static const constexpr bool useColorManagement = true;
 
-    static bool useContextPriority;
-
-    // The data space and pixel format that SurfaceFlinger expects hardware composer
-    // to composite efficiently. Meaning under most scenarios, hardware composer
-    // will accept layers with the data space and pixel format.
-    static ui::Dataspace defaultCompositionDataspace;
-    static ui::PixelFormat defaultCompositionPixelFormat;
-
-    // The data space and pixel format that SurfaceFlinger expects hardware composer
-    // to composite efficiently for wide color gamut surfaces. Meaning under most scenarios,
-    // hardware composer will accept layers with the data space and pixel format.
-    static ui::Dataspace wideColorGamutCompositionDataspace;
-    static ui::PixelFormat wideColorGamutCompositionPixelFormat;
-
-    static constexpr SkipInitializationTag SkipInitialization;
-
     static LatchUnsignaledConfig enableLatchUnsignaledConfig;
 
     // must be called before clients can connect
@@ -275,7 +231,8 @@
     // Schedule sampling independently from commit or composite.
     void scheduleSample();
 
-    surfaceflinger::Factory& getFactory() { return mFactory; }
+    const surfaceflinger::Config& getConfig() { return *mConfig; }
+    surfaceflinger::Factory& getFactory() { return *mConfig->factory; }
 
     // The CompositionEngine encapsulates all composition related interfaces and actions.
     compositionengine::CompositionEngine& getCompositionEngine() const;
@@ -307,10 +264,6 @@
         return mTransactionCallbackInvoker;
     }
 
-    // If set, disables reusing client composition buffers. This can be set by
-    // debug.sf.disable_client_composition_cache
-    bool mDisableClientCompositionCache = false;
-
     // Disables expensive rendering for all displays
     // This is scheduled on the main thread
     void disableExpensiveRendering();
@@ -321,17 +274,6 @@
     // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect.
     bool mPredictCompositionStrategy = false;
 
-    // If true, then any layer with a SMPTE 170M transfer function is decoded using the sRGB
-    // transfer instead. This is mainly to preserve legacy behavior, where implementations treated
-    // SMPTE 170M as sRGB prior to color management being implemented, and now implementations rely
-    // on this behavior to increase contrast for some media sources.
-    bool mTreat170mAsSrgb = false;
-
-    // Allows to ignore physical orientation provided through hwc API in favour of
-    // 'ro.surface_flinger.primary_display_orientation'.
-    // TODO(b/246793311): Clean up a temporary property
-    bool mIgnoreHwcPhysicalDisplayOrientation = false;
-
     void forceFutureUpdate(int delayInMs);
     const DisplayDevice* getDisplayFromLayerStack(ui::LayerStack)
             REQUIRES(mStateLock, kMainThreadContext);
@@ -666,12 +608,6 @@
     // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
     // make calls to sys prop each time.
     bool mKernelIdleTimerEnabled = false;
-    // Show spinner with refresh rate overlay
-    bool mRefreshRateOverlaySpinner = false;
-    // Show render rate with refresh rate overlay
-    bool mRefreshRateOverlayRenderRate = false;
-    // Show render rate overlay offseted to the middle of the screen (e.g. for circular displays)
-    bool mRefreshRateOverlayShowInMiddle = false;
 
     void setDesiredActiveMode(display::DisplayModeRequest&&, bool force = false)
             REQUIRES(mStateLock);
@@ -1105,8 +1041,8 @@
      */
     const std::unordered_map<std::string, uint32_t>& getGenericLayerMetadataKeyMap() const;
 
-    static int calculateMaxAcquiredBufferCount(Fps refreshRate,
-                                               std::chrono::nanoseconds presentLatency);
+    int calculateMaxAcquiredBufferCount(Fps refreshRate,
+                                        std::chrono::nanoseconds presentLatency) const;
     int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;
 
     bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const;
@@ -1116,8 +1052,7 @@
     void traverseLegacyLayers(const LayerVector::Visitor& visitor) const;
 
     sp<StartPropertySetThread> mStartPropertySetThread;
-    surfaceflinger::Factory& mFactory;
-    pid_t mPid;
+    surfaceflinger::Config* const mConfig = nullptr;
     std::future<void> mRenderEnginePrimeCacheFuture;
 
     // mStateLock has conventions related to the current thread, because only
@@ -1144,12 +1079,6 @@
     float mGlobalSaturationFactor = 1.0f;
     mat4 mClientColorMatrix;
 
-    size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
-    // If there are more GraphicBufferProducers tracked by SurfaceFlinger than
-    // this threshold, then begin logging.
-    size_t mGraphicBufferProducerListSizeLogThreshold =
-            static_cast<size_t>(0.95 * static_cast<double>(MAX_LAYERS));
-
     // protected by mStateLock (but we could use another lock)
     bool mLayersRemoved = false;
     bool mLayersAdded = false;
@@ -1159,7 +1088,6 @@
 
     // constant members (no synchronization needed for access)
     const nsecs_t mBootTime = systemTime();
-    bool mIsUserBuild = true;
 
     // Can only accessed from the main thread, these members
     // don't need synchronization
@@ -1171,7 +1099,6 @@
     // Used to ensure we omit a callback when HDR layer info listener is newly added but the
     // scene hasn't changed
     bool mAddingHDRLayerInfoListener = false;
-    bool mIgnoreHdrCameraLayers = false;
 
     // Set during transaction application stage to track if the input info or children
     // for a layer has changed.
@@ -1230,9 +1157,6 @@
     std::atomic<nsecs_t> mDebugInTransaction = 0;
     std::atomic_bool mForceFullDamage = false;
 
-    bool mLayerCachingEnabled = false;
-    bool mBackpressureGpuComposition = false;
-
     LayerTracing mLayerTracing;
     bool mLayerTracingEnabled = false;
 
@@ -1245,9 +1169,6 @@
 
     VsyncId mLastCommittedVsyncId;
 
-    // If blurs should be enabled on this device.
-    bool mSupportsBlur = false;
-
     TransactionCallbackInvoker mTransactionCallbackInvoker;
 
     // We maintain a pool of pre-generated texture names to hand out to avoid
@@ -1279,13 +1200,9 @@
     // This property can be used to force SurfaceFlinger to always pick a certain color mode.
     ui::ColorMode mForceColorMode = ui::ColorMode::NATIVE;
 
-    // Whether to enable wide color gamut (e.g. Display P3) for internal displays that support it.
-    // If false, wide color modes are filtered out for all internal displays.
-    bool mSupportsWideColor = false;
+    std::optional<ui::Dataspace> mOverrideDefaultCompositionDataspace;
+    std::optional<ui::Dataspace> mOverrideWideColorGamutCompositionDataspace;
 
-    ui::Dataspace mDefaultCompositionDataspace;
-    ui::Dataspace mWideColorGamutCompositionDataspace;
-    ui::Dataspace mColorSpaceAgnosticDataspace;
     float mDimmingRatio = -1.f;
 
     std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
@@ -1299,8 +1216,6 @@
     // any mutex.
     size_t mMaxRenderTargetSize{1};
 
-    const std::string mHwcServiceName;
-
     /*
      * Scheduler
      */
@@ -1317,14 +1232,9 @@
     // below flags are set by main thread only
     bool mSetActiveModePending = false;
 
-    bool mLumaSampling = true;
     sp<RegionSamplingThread> mRegionSamplingThread;
     sp<FpsReporter> mFpsReporter;
     sp<TunnelModeEnabledReporter> mTunnelModeEnabledReporter;
-    ui::DisplayPrimaries mInternalDisplayPrimaries;
-
-    const float mEmulatedDisplayDensity;
-    const float mInternalDisplayDensity;
 
     // Should only be accessed by the main thread.
     sp<os::IInputFlinger> mInputFlinger;
@@ -1401,9 +1311,6 @@
 
     bool mPowerHintSessionEnabled;
 
-    bool mLayerLifecycleManagerEnabled = false;
-    bool mLegacyFrontEndEnabled = true;
-
     frontend::LayerLifecycleManager mLayerLifecycleManager;
     frontend::LayerHierarchyBuilder mLayerHierarchyBuilder{{}};
     frontend::LayerSnapshotBuilder mLayerSnapshotBuilder;
diff --git a/services/surfaceflinger/SurfaceFlingerConfig.cpp b/services/surfaceflinger/SurfaceFlingerConfig.cpp
new file mode 100644
index 0000000..0b25a44
--- /dev/null
+++ b/services/surfaceflinger/SurfaceFlingerConfig.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdlib>
+
+#include <SurfaceFlingerProperties.h>
+#include <SurfaceFlingerProperties.sysprop.h>
+#include <android-base/properties.h>
+#include <android/configuration.h>
+
+#include "SurfaceFlingerConfig.h"
+
+namespace android::surfaceflinger {
+
+using namespace std::string_literals;
+
+namespace {
+
+// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
+constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
+
+float getDensityFromProperty(const std::string& key, bool required) {
+    std::string value = base::GetProperty(key, ""s);
+    const float density = static_cast<float>(std::atof(value.c_str()));
+    if (density == 0.f && required) {
+        ALOGE("%s must be defined as a build property", key.c_str());
+        return FALLBACK_DENSITY;
+    }
+    return density;
+}
+
+} // namespace
+
+Config::Config() = default;
+
+Config Config::makeDefault(Factory* factory) {
+    Config cfg{};
+
+    // Note: The values set here will affect tests.
+    // To keep tests hermetic, do not set values here based on runtime values.
+
+    cfg.factory = factory;
+    cfg.hwcServiceName = "default"s;
+    cfg.pid = getpid(); // Exception to the hermetic rules. Allow the pid to be cached.
+
+    return cfg;
+}
+
+Config Config::makeProduction(Factory* factory) {
+    Config cfg = makeDefault(factory);
+
+    cfg.hwcServiceName = base::GetProperty("debug.sf.hwc_service_name"s, "default"s);
+
+    cfg.emulatedDisplayDensity = getDensityFromProperty("qemu.sf.lcd_density"s, false),
+    cfg.internalDisplayDensity =
+            getDensityFromProperty("ro.sf.lcd_density"s, cfg.emulatedDisplayDensity == 0.f),
+
+    cfg.hasSyncFramework = sysprop::running_without_sync_framework(cfg.hasSyncFramework);
+    cfg.dispSyncPresentTimeOffset =
+            sysprop::present_time_offset_from_vsync_ns(cfg.dispSyncPresentTimeOffset);
+    cfg.useHwcForRgbToYuv = sysprop::force_hwc_copy_for_virtual_displays(cfg.useHwcForRgbToYuv);
+    cfg.maxFrameBufferAcquiredBuffers =
+            sysprop::max_frame_buffer_acquired_buffers(cfg.maxFrameBufferAcquiredBuffers);
+    cfg.minAcquiredBuffers = sysprop::SurfaceFlingerProperties::min_acquired_buffers().value_or(
+            cfg.minAcquiredBuffers);
+
+    cfg.maxGraphicsWidth = std::max(static_cast<uint32_t>(sysprop::max_graphics_width(
+                                            static_cast<int32_t>(cfg.maxGraphicsWidth))),
+                                    0u);
+    cfg.maxGraphicsHeight = std::max(static_cast<uint32_t>(sysprop::max_graphics_height(
+                                             static_cast<int32_t>(cfg.maxGraphicsHeight))),
+                                     0u);
+
+    cfg.supportsWideColor = sysprop::has_wide_color_display(cfg.supportsWideColor);
+
+    cfg.defaultCompositionDataspace = static_cast<ui::Dataspace>(
+            sysprop::default_composition_dataspace(cfg.defaultCompositionDataspace));
+    cfg.defaultCompositionPixelFormat = static_cast<ui::PixelFormat>(
+            sysprop::default_composition_pixel_format(cfg.defaultCompositionPixelFormat));
+
+    cfg.wideColorGamutCompositionDataspace =
+            static_cast<ui::Dataspace>(sysprop::wcg_composition_dataspace(
+                    cfg.supportsWideColor ? ui::Dataspace::DISPLAY_P3 : ui::Dataspace::V0_SRGB));
+    cfg.wideColorGamutCompositionPixelFormat = static_cast<ui::PixelFormat>(
+            sysprop::wcg_composition_pixel_format(cfg.wideColorGamutCompositionPixelFormat));
+
+    cfg.colorSpaceAgnosticDataspace = static_cast<ui::Dataspace>(
+            sysprop::color_space_agnostic_dataspace(cfg.colorSpaceAgnosticDataspace));
+
+    cfg.internalDisplayPrimaries = sysprop::getDisplayNativePrimaries();
+
+    cfg.layerCachingEnabled =
+            base::GetBoolProperty("debug.sf.enable_layer_caching"s,
+                                  android::sysprop::SurfaceFlingerProperties::enable_layer_caching()
+                                          .value_or(cfg.layerCachingEnabled));
+    cfg.useContextPriority = sysprop::use_context_priority(cfg.useContextPriority);
+
+    cfg.isUserBuild = "user"s == base::GetProperty("ro.build.type"s, "user"s);
+
+    cfg.backpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s,
+                                                           cfg.backpressureGpuComposition);
+    cfg.supportsBlur =
+            base::GetBoolProperty("ro.surface_flinger.supports_background_blur"s, cfg.supportsBlur);
+
+    cfg.lumaSampling = base::GetBoolProperty("debug.sf.luma_sampling"s, cfg.lumaSampling);
+
+    cfg.disableClientCompositionCache =
+            base::GetBoolProperty("debug.sf.disable_client_composition_cache"s,
+                                  cfg.disableClientCompositionCache);
+
+    cfg.predictCompositionStrategy =
+            base::GetBoolProperty("debug.sf.predict_hwc_composition_strategy"s,
+                                  cfg.predictCompositionStrategy);
+
+    cfg.treat170mAsSrgb =
+            base::GetBoolProperty("debug.sf.treat_170m_as_sRGB"s, cfg.treat170mAsSrgb);
+
+    cfg.ignoreHwcPhysicalDisplayOrientation =
+            base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s,
+                                  cfg.ignoreHwcPhysicalDisplayOrientation);
+
+    cfg.trebleTestingOverride =
+            base::GetBoolProperty("debug.sf.treble_testing_override"s, cfg.trebleTestingOverride);
+
+    // TODO (b/270966065) Update the HWC based refresh rate overlay to support spinner
+    cfg.refreshRateOverlay.showSpinner =
+            base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_spinner"s,
+                                  cfg.refreshRateOverlay.showSpinner);
+    cfg.refreshRateOverlay.showRenderRate =
+            base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_render_rate"s,
+                                  cfg.refreshRateOverlay.showRenderRate);
+    cfg.refreshRateOverlay.showInMiddle =
+            base::GetBoolProperty("debug.sf.show_refresh_rate_overlay_in_middle"s,
+                                  cfg.refreshRateOverlay.showInMiddle);
+
+    cfg.ignoreHdrCameraLayers = sysprop::ignore_hdr_camera_layers(cfg.ignoreHdrCameraLayers);
+
+    cfg.enableTransactionTracing = base::GetBoolProperty("debug.sf.enable_transaction_tracing"s,
+                                                         cfg.enableTransactionTracing);
+    cfg.layerLifecycleManagerEnabled =
+            base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s,
+                                  cfg.layerLifecycleManagerEnabled);
+    cfg.legacyFrontEndEnabled = !cfg.layerLifecycleManagerEnabled ||
+            base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false);
+
+    return cfg;
+}
+
+} // namespace android::surfaceflinger
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlingerConfig.h b/services/surfaceflinger/SurfaceFlingerConfig.h
new file mode 100644
index 0000000..7c3348e
--- /dev/null
+++ b/services/surfaceflinger/SurfaceFlingerConfig.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdlib>
+
+#include <ui/ConfigStoreTypes.h>
+#include <ui/GraphicTypes.h>
+
+namespace android::surfaceflinger {
+
+class Factory;
+
+struct Config final {
+    Factory* factory = nullptr;
+
+    std::string hwcServiceName;
+    pid_t pid;
+
+    float emulatedDisplayDensity = 0;
+    float internalDisplayDensity = 0;
+
+    // If fences from sync Framework are supported.
+    bool hasSyncFramework = true;
+
+    // The offset in nanoseconds to use when VsyncController timestamps present
+    // fence signaling time.
+    int64_t dispSyncPresentTimeOffset = 0;
+
+    // Some hardware can do RGB->YUV conversion more efficiently in hardware
+    // controlled by HWC than in hardware controlled by the video encoder. This
+    // instruct VirtualDisplaySurface to use HWC for such conversion on GL
+    // composition.
+    bool useHwcForRgbToYuv = false;
+
+    // Controls the number of buffers SurfaceFlinger will allocate for use in
+    // FramebufferSurface
+    int64_t maxFrameBufferAcquiredBuffers = 2;
+
+    // Controls the minimum acquired buffers SurfaceFlinger will suggest via
+    // ISurfaceComposer.getMaxAcquiredBufferCount().
+    int64_t minAcquiredBuffers = 1;
+
+    // Controls the maximum width and height in pixels that the graphics
+    // pipeline can support for GPU fallback composition. For example, 8k
+    // devices with 4k GPUs, or 4k devices with 2k GPUs.
+    uint32_t maxGraphicsWidth = 0;
+    uint32_t maxGraphicsHeight = 0;
+
+    // Whether to enable wide color gamut (e.g. Display P3) for internal
+    // displays that support it. If false, wide color modes are filtered out
+    // for all internal displays.
+    bool mSupportsWideColor = false;
+    bool supportsWideColor = false;
+
+    // The data space and pixel format that SurfaceFlinger expects hardware
+    // composer to composite efficiently. Meaning under most scenarios,
+    // hardware composer will accept layers with the data space and pixel
+    // format.
+    ui::Dataspace defaultCompositionDataspace = ui::Dataspace::V0_SRGB;
+    ui::PixelFormat defaultCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
+
+    // The data space and pixel format that SurfaceFlinger expects hardware
+    // composer to composite efficiently for wide color gamut surfaces. Meaning
+    // under most scenarios, hardware composer will accept layers with the data
+    // space and pixel format.
+    ui::Dataspace wideColorGamutCompositionDataspace = ui::Dataspace::V0_SRGB;
+    ui::PixelFormat wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
+
+    ui::Dataspace colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
+
+    ui::DisplayPrimaries internalDisplayPrimaries{};
+
+    bool layerCachingEnabled = false;
+    bool useContextPriority = true;
+    bool isUserBuild = true;
+    bool backpressureGpuComposition = true;
+
+    // If blurs should be enabled on this device.
+    bool supportsBlur = false;
+    bool lumaSampling = true;
+
+    // If set, disables reusing client composition buffers. This can be set by
+    // debug.sf.disable_client_composition_cache
+    bool disableClientCompositionCache = false;
+
+    // If set, composition engine tries to predict the composition strategy
+    // provided by HWC based on the previous frame. If the strategy can be
+    // predicted, gpu composition will run parallel to the hwc validateDisplay
+    // call and re-run if the predition is incorrect.
+    bool predictCompositionStrategy = true;
+
+    // If true, then any layer with a SMPTE 170M transfer function is decoded
+    // using the sRGB transfer instead. This is mainly to preserve legacy
+    // behavior, where implementations treated SMPTE 170M as sRGB prior to
+    // color management being implemented, and now implementations rely on this
+    // behavior to increase contrast for some media sources.
+    bool treat170mAsSrgb = false;
+
+    // Allows to ignore physical orientation provided through hwc API in favour
+    // of 'ro.surface_flinger.primary_display_orientation'.
+    // TODO(b/246793311): Clean up a temporary property
+    bool ignoreHwcPhysicalDisplayOrientation = false;
+
+    bool trebleTestingOverride = false;
+
+    struct {
+        // Show spinner with refresh rate overlay
+        bool showSpinner = false;
+
+        // Show render rate with refresh rate overlay
+        bool showRenderRate = false;
+
+        // Show render rate overlay offseted to the middle of the screen (e.g.
+        // for circular displays)
+        bool showInMiddle = false;
+    } refreshRateOverlay;
+
+    bool ignoreHdrCameraLayers = false;
+    bool enableTransactionTracing = true;
+    bool layerLifecycleManagerEnabled = false;
+    bool legacyFrontEndEnabled = true;
+
+    static Config makeDefault(Factory* factory);
+    static Config makeProduction(Factory* factory);
+
+private:
+    Config();
+};
+
+} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 7bd6cf6..ac351cb 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -14,22 +14,17 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
 #include "SurfaceFlinger.h"
+#include "SurfaceFlingerConfig.h"
 #include "SurfaceFlingerDefaultFactory.h"
 
 namespace android::surfaceflinger {
 
 sp<SurfaceFlinger> createSurfaceFlinger() {
     static DefaultFactory factory;
+    static Config config = Config::makeProduction(&factory);
 
-    return sp<SurfaceFlinger>::make(factory);
+    return sp<SurfaceFlinger>::make(config);
 }
 
 } // namespace android::surfaceflinger
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
index 9fac14e..d296c47 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_displayhardware_fuzzer.cpp
@@ -481,7 +481,8 @@
 
     sp<FramebufferSurface> surface =
             sp<FramebufferSurface>::make(mHwc, mPhysicalDisplayId, bqConsumer,
-                                         getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/);
+                                         getFuzzedSize() /*size*/, getFuzzedSize() /*maxSize*/,
+                                         mFdp.PickValueInArray(kMaxFrameBufferAcquiredBuffers));
     surface->beginFrame(mFdp.ConsumeBool());
 
     surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes));
@@ -515,7 +516,8 @@
 
     auto surface =
             sp<VirtualDisplaySurface>::make(mHwc, VirtualDisplayId, sink, bqProducer, bqConsumer,
-                                            mFdp.ConsumeRandomLengthString().c_str() /*name*/);
+                                            mFdp.ConsumeRandomLengthString().c_str() /*name*/,
+                                            mFdp.ConsumeBool() /* useHwcForRgbToYuv */);
 
     surface->beginFrame(mFdp.ConsumeBool());
     surface->prepareFrame(mFdp.PickValueInArray(kCompositionTypes));
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index 80943b5..df342dc 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -124,19 +124,20 @@
     mFlinger->setSchedFifo(mFdp.ConsumeBool());
     mFlinger->setSchedAttr(mFdp.ConsumeBool());
     mFlinger->getServiceName();
-    mFlinger->hasSyncFramework = mFdp.ConsumeBool();
-    mFlinger->dispSyncPresentTimeOffset = mFdp.ConsumeIntegral<int64_t>();
-    mFlinger->useHwcForRgbToYuv = mFdp.ConsumeBool();
-    mFlinger->maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral<int64_t>();
-    mFlinger->maxGraphicsWidth = mFdp.ConsumeIntegral<uint32_t>();
-    mFlinger->maxGraphicsHeight = mFdp.ConsumeIntegral<uint32_t>();
-    mTestableFlinger.mutableSupportsWideColor() = mFdp.ConsumeBool();
-    mFlinger->useContextPriority = mFdp.ConsumeBool();
 
-    mFlinger->defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
-    mFlinger->defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
-    mFlinger->wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
-    mFlinger->wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
+    auto& config = mTestableFlinger.mutableConfig();
+    config.hasSyncFramework = mFdp.ConsumeBool();
+    config.dispSyncPresentTimeOffset = mFdp.ConsumeIntegral<int64_t>();
+    config.useHwcForRgbToYuv = mFdp.ConsumeBool();
+    config.maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral<int64_t>();
+    config.maxGraphicsWidth = mFdp.ConsumeIntegral<uint32_t>();
+    config.maxGraphicsHeight = mFdp.ConsumeIntegral<uint32_t>();
+    config.supportsWideColor = mFdp.ConsumeBool();
+    config.useContextPriority = mFdp.ConsumeBool();
+    config.defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
+    config.defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
+    config.wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
+    config.wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
 
     mFlinger->enableLatchUnsignaledConfig = mFdp.PickValueInArray(kLatchUnsignaledConfig);
 
@@ -155,7 +156,7 @@
 }
 
 void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() {
-    ui::DisplayPrimaries primaries;
+    auto& primaries = mTestableFlinger.mutableConfig().internalDisplayPrimaries;
     primaries.red.X = mFdp.ConsumeFloatingPoint<float>();
     primaries.red.Y = mFdp.ConsumeFloatingPoint<float>();
     primaries.red.Z = mFdp.ConsumeFloatingPoint<float>();
@@ -168,7 +169,6 @@
     primaries.white.X = mFdp.ConsumeFloatingPoint<float>();
     primaries.white.Y = mFdp.ConsumeFloatingPoint<float>();
     primaries.white.Z = mFdp.ConsumeFloatingPoint<float>();
-    mTestableFlinger.setInternalDisplayPrimaries(primaries);
 }
 
 void SurfaceFlingerFuzzer::setTransactionState() {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 0c9a16b..97cb5d3 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -46,6 +46,7 @@
 #include "Scheduler/VsyncModulator.h"
 #include "StartPropertySetThread.h"
 #include "SurfaceFlinger.h"
+#include "SurfaceFlingerConfig.h"
 #include "SurfaceFlingerDefaultFactory.h"
 #include "ThreadContext.h"
 #include "TimeStats/TimeStats.h"
@@ -150,6 +151,8 @@
                                                     ui::PixelFormat::YCBCR_P010,
                                                     ui::PixelFormat::HSV_888};
 
+static constexpr int kMaxFrameBufferAcquiredBuffers[] = {2, 3, 4};
+
 inline VsyncId getFuzzedVsyncId(FuzzedDataProvider& fdp) {
     return VsyncId{fdp.ConsumeIntegral<int64_t>()};
 }
@@ -404,6 +407,8 @@
     SurfaceFlinger *flinger() { return mFlinger.get(); }
     scheduler::TestableScheduler *scheduler() { return mScheduler; }
 
+    auto& mutableConfig() { return mConfig; }
+
     void initializeDisplays() {
         FTL_FAKE_GUARD(kMainThreadContext, mFlinger->initializeDisplays());
     }
@@ -695,10 +700,6 @@
         mFactory.mCreateNativeWindowSurface = f;
     }
 
-    void setInternalDisplayPrimaries(const ui::DisplayPrimaries &primaries) {
-        memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
-    }
-
     static auto &mutableLayerDrawingState(const sp<Layer> &layer) { return layer->mDrawingState; }
 
     auto &mutableStateLock() { return mFlinger->mStateLock; }
@@ -764,13 +765,12 @@
 
     auto calculateMaxAcquiredBufferCount(Fps refreshRate,
                                          std::chrono::nanoseconds presentLatency) const {
-        return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
+        return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
     }
 
     /* Read-write access to private data to set up preconditions and assert
      * post-conditions.
      */
-    auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; }
     auto& mutableCurrentState() { return mFlinger->mCurrentState; }
     auto& mutableDisplays() { return mFlinger->mDisplays; }
     auto& mutableDrawingState() { return mFlinger->mDrawingState; }
@@ -794,8 +794,8 @@
     void triggerOnFrameRateOverridesChanged() override {}
 
     surfaceflinger::test::Factory mFactory;
-    sp<SurfaceFlinger> mFlinger =
-            sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization);
+    surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory);
+    sp<SurfaceFlinger> mFlinger = sp<SurfaceFlinger>::make(mConfig);
     scheduler::TestableScheduler *mScheduler = nullptr;
     std::shared_ptr<scheduler::RefreshRateSelector> mRefreshRateSelector;
 };
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp
index 849a896..c16a005 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_service_fuzzer.cpp
@@ -17,13 +17,15 @@
 #include <fuzzbinder/libbinder_driver.h>
 
 #include "SurfaceFlinger.h"
+#include "SurfaceFlingerConfig.h"
 #include "SurfaceFlingerDefaultFactory.h"
 
 using namespace android;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     DefaultFactory factory;
-    sp<SurfaceFlinger> flinger = sp<SurfaceFlinger>::make(factory);
+    surfaceflinger::Config config = surfaceflinger::Config::makeDefault(&factory);
+    sp<SurfaceFlinger> flinger = sp<SurfaceFlinger>::make(config);
     flinger->init();
 
     sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index e32cf88..7124f87 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -34,7 +34,7 @@
             ::testing::UnitTest::GetInstance()->current_test_info();
     ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
 
-    mFlinger.mutableSupportsWideColor() = false;
+    mFlinger.mutableConfig().supportsWideColor = false;
     mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
 
     mFlinger.setCreateBufferQueueFunction([](auto, auto, auto) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index ee12276..5599a7a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -684,7 +684,7 @@
     static constexpr bool WIDE_COLOR_SUPPORTED = false;
 
     static void injectConfigChange(DisplayTransactionTest* test) {
-        test->mFlinger.mutableSupportsWideColor() = true;
+        test->mFlinger.mutableConfig().supportsWideColor = true;
     }
 
     static void setupComposerCallExpectations(DisplayTransactionTest* test) {
@@ -699,7 +699,7 @@
     static constexpr bool WIDE_COLOR_SUPPORTED = false;
 
     static void injectConfigChange(DisplayTransactionTest* test) {
-        test->mFlinger.mutableSupportsWideColor() = false;
+        test->mFlinger.mutableConfig().supportsWideColor = false;
         test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
     }
 
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index fab3c0e..6c14f6e 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -250,10 +250,8 @@
 
     EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
 
-    const auto savedMinAcquiredBuffers = mFlinger.mutableMinAcquiredBuffers();
-    mFlinger.mutableMinAcquiredBuffers() = 2;
+    mFlinger.mutableConfig().minAcquiredBuffers = 2;
     EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(60_Hz, 10ms));
-    mFlinger.mutableMinAcquiredBuffers() = savedMinAcquiredBuffers;
 }
 
 MATCHER(Is120Hz, "") {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
index 5951c98..fe38384 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayNativePrimariesTest.cpp
@@ -84,9 +84,7 @@
     injector.inject();
     auto internalDisplayToken = injector.token();
 
-    ui::DisplayPrimaries expectedPrimaries;
-    populateDummyDisplayNativePrimaries(expectedPrimaries);
-    mFlinger.setInternalDisplayPrimaries(expectedPrimaries);
+    populateDummyDisplayNativePrimaries(mFlinger.mutableConfig().internalDisplayPrimaries);
 
     ui::DisplayPrimaries primaries;
     EXPECT_EQ(NO_ERROR, mFlinger.getDisplayNativePrimaries(internalDisplayToken, primaries));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index c0796df..61891c1 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -36,7 +36,7 @@
     static constexpr bool WIDE_COLOR_SUPPORTED = true;
 
     static void injectConfigChange(DisplayTransactionTest* test) {
-        test->mFlinger.mutableSupportsWideColor() = true;
+        test->mFlinger.mutableConfig().supportsWideColor = true;
         test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged;
     }
 
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 156c40a..099abf5 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -45,6 +45,8 @@
 #include "Scheduler/RefreshRateSelector.h"
 #include "StartPropertySetThread.h"
 #include "SurfaceFlinger.h"
+#include "SurfaceFlingerConfig.h"
+#include "SurfaceFlingerDefaultFactory.h"
 #include "TestableScheduler.h"
 #include "mock/DisplayHardware/MockComposer.h"
 #include "mock/DisplayHardware/MockDisplayMode.h"
@@ -168,13 +170,15 @@
 
     TestableSurfaceFlinger(sp<SurfaceFlinger> flinger = nullptr) : mFlinger(flinger) {
         if (!mFlinger) {
-            mFlinger = sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization);
+            mFlinger = sp<SurfaceFlinger>::make(mConfig);
         }
     }
 
     SurfaceFlinger* flinger() { return mFlinger.get(); }
     scheduler::TestableScheduler* scheduler() { return mScheduler; }
 
+    auto& mutableConfig() { return mConfig; }
+
     // Extend this as needed for accessing SurfaceFlinger private (and public)
     // functions.
 
@@ -312,10 +316,6 @@
         mFactory.mCreateNativeWindowSurface = f;
     }
 
-    void setInternalDisplayPrimaries(const ui::DisplayPrimaries& primaries) {
-        memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
-    }
-
     static auto& mutableLayerDrawingState(const sp<Layer>& layer) { return layer->mDrawingState; }
 
     auto& mutableStateLock() { return mFlinger->mStateLock; }
@@ -513,7 +513,7 @@
 
     auto calculateMaxAcquiredBufferCount(Fps refreshRate,
                                          std::chrono::nanoseconds presentLatency) const {
-        return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
+        return mFlinger->calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
     }
 
     auto setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
@@ -596,8 +596,6 @@
     const auto& hwcPhysicalDisplayIdMap() const { return getHwComposer().mPhysicalDisplayIdMap; }
     const auto& hwcDisplayData() const { return getHwComposer().mDisplayData; }
 
-    auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; }
-
     auto& mutableCurrentState() { return mFlinger->mCurrentState; }
     auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; }
     auto& mutableDisplays() { return mFlinger->mDisplays; }
@@ -622,8 +620,6 @@
         return SurfaceFlinger::sActiveDisplayRotationFlags;
     }
 
-    auto& mutableMinAcquiredBuffers() { return SurfaceFlinger::minAcquiredBuffers; }
-
     auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); }
 
     ~TestableSurfaceFlinger() {
@@ -1008,6 +1004,7 @@
     static constexpr VsyncId kVsyncId{123};
 
     surfaceflinger::test::Factory mFactory;
+    surfaceflinger::Config mConfig = surfaceflinger::Config::makeDefault(&mFactory);
     sp<SurfaceFlinger> mFlinger;
     scheduler::mock::SchedulerCallback mSchedulerCallback;
     scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;