SF: Remove *DisplayId::tryCast usage from Output

Work towards DisplayId opaqueness by eliminating call-sites to APIs that
parse the display ID values directly. One such site is
compositionengine::Output and its implementers, such as
compositionengine::Display.

Replace all calls to *DisplayId::tryCast with local calls to cached
display state at the time of Output creation.

Flag: com.android.graphics.surfaceflinger.flags.stable_edid_ids
Bug: 390690584
Test: libcompositionengine_test && libsurfaceflinger_unittest
Change-Id: I5524928e839e683184a878d08c2515e3d9d0593d
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 252adaa..2c0a66f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -34,7 +34,7 @@
  * A parameter object for creating Display instances
  */
 struct DisplayCreationArgs {
-    DisplayId id;
+    DisplayIdVariant idVariant;
 
     // Size of the display in pixels
     ui::Size pixels = ui::kInvalidSize;
@@ -68,8 +68,8 @@
 public:
     DisplayCreationArgs build() { return std::move(mArgs); }
 
-    DisplayCreationArgsBuilder& setId(DisplayId id) {
-        mArgs.id = id;
+    DisplayCreationArgsBuilder& setId(DisplayIdVariant idVariant) {
+        mArgs.idVariant = idVariant;
         return *this;
     }
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index bda7856..4266da4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -170,6 +170,7 @@
 
     // Returns the DisplayId the output represents, if it has one
     virtual ftl::Optional<DisplayId> getDisplayId() const = 0;
+    virtual ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const = 0;
 
     // Enables (or disables) composition on this output
     virtual void setCompositionEnabled(bool) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 5519aaf..ec87acc 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -46,6 +46,7 @@
 
     // compositionengine::Output overrides
     ftl::Optional<DisplayId> getDisplayId() const override;
+    ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override;
     bool isValid() const override;
     void dump(std::string&) const override;
     using compositionengine::impl::Output::setReleasedLayers;
@@ -104,8 +105,11 @@
             override;
     bool hasPictureProcessing() const override;
     int32_t getMaxLayerPictureProfiles() const override;
+    bool isGpuVirtualDisplay() const {
+        return std::holds_alternative<GpuVirtualDisplayId>(mIdVariant);
+    }
 
-    DisplayId mId;
+    DisplayIdVariant mIdVariant;
     bool mIsDisconnected = false;
     adpf::PowerAdvisor* mPowerAdvisor = nullptr;
     bool mHasPictureProcessing = false;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 0ccdd22..873764b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -45,6 +45,7 @@
     // compositionengine::Output overrides
     bool isValid() const override;
     ftl::Optional<DisplayId> getDisplayId() const override;
+    ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override;
     void setCompositionEnabled(bool) override;
     void setLayerCachingEnabled(bool) override;
     void setLayerCachingTexturePoolEnabled(bool) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index f2c265a..eaa3dd3 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -35,6 +35,7 @@
 
     MOCK_CONST_METHOD0(isValid, bool());
     MOCK_CONST_METHOD0(getDisplayId, ftl::Optional<DisplayId>());
+    MOCK_CONST_METHOD0(getDisplayIdVariant, ftl::Optional<DisplayIdVariant>());
 
     MOCK_METHOD1(setCompositionEnabled, void(bool));
     MOCK_METHOD1(setLayerCachingEnabled, void(bool));
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 989f8e3..d7d8b7c 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -97,7 +97,7 @@
 
     ui::PhysicalDisplayVector<compositionengine::Output*> outputsToOffload;
     for (const auto& output : outputs) {
-        if (!ftl::Optional(output->getDisplayId()).and_then(HalDisplayId::tryCast)) {
+        if (!output->getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
             // Not HWC-enabled, so it is always client-composited. No need to offload.
             continue;
         }
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 8364f4e..5a54677 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -52,7 +52,7 @@
 Display::~Display() = default;
 
 void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
-    mId = args.id;
+    mIdVariant = args.idVariant;
     mPowerAdvisor = args.powerAdvisor;
     mHasPictureProcessing = args.hasPictureProcessing;
     mMaxLayerPictureProfiles = args.maxLayerPictureProfiles;
@@ -67,7 +67,7 @@
 }
 
 DisplayId Display::getId() const {
-    return mId;
+    return asDisplayId(mIdVariant);
 }
 
 bool Display::isSecure() const {
@@ -79,11 +79,15 @@
 }
 
 bool Display::isVirtual() const {
-    return mId.isVirtual();
+    return !std::holds_alternative<PhysicalDisplayId>(mIdVariant);
 }
 
 ftl::Optional<DisplayId> Display::getDisplayId() const {
-    return mId;
+    return getId();
+}
+
+ftl::Optional<DisplayIdVariant> Display::getDisplayIdVariant() const {
+    return mIdVariant;
 }
 
 void Display::disconnect() {
@@ -93,14 +97,14 @@
 
     mIsDisconnected = true;
 
-    if (const auto id = HalDisplayId::tryCast(mId)) {
+    if (const auto id = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
         getCompositionEngine().getHwComposer().disconnectDisplay(*id);
     }
 }
 
 void Display::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
     Output::setColorTransform(args);
-    const auto halDisplayId = HalDisplayId::tryCast(mId);
+    const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
     if (mIsDisconnected || !halDisplayId || CC_LIKELY(!args.colorTransformMatrix)) {
         return;
     }
@@ -108,7 +112,7 @@
     auto& hwc = getCompositionEngine().getHwComposer();
     status_t result = hwc.setColorTransform(*halDisplayId, *args.colorTransformMatrix);
     ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display \"%s\": %d",
-             to_string(mId).c_str(), result);
+             to_string(*halDisplayId).c_str(), result);
 }
 
 void Display::setColorProfile(const ColorProfile& colorProfile) {
@@ -125,7 +129,7 @@
 
     Output::setColorProfile(colorProfile);
 
-    const auto physicalId = PhysicalDisplayId::tryCast(mId);
+    const auto physicalId = getDisplayIdVariant().and_then(asPhysicalDisplayId);
     LOG_FATAL_IF(!physicalId);
     getCompositionEngine().getHwComposer().setActiveColorMode(*physicalId, colorProfile.mode,
                                                               colorProfile.renderIntent);
@@ -133,7 +137,7 @@
 
 void Display::dump(std::string& out) const {
     const char* const type = isVirtual() ? "virtual" : "physical";
-    base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(mId).c_str(), type,
+    base::StringAppendF(&out, "Display %s (%s, \"%s\")", to_string(getId()).c_str(), type,
                         getName().c_str());
 
     out.append("\n   Composition Display State:\n");
@@ -157,7 +161,7 @@
         const sp<compositionengine::LayerFE>& layerFE) const {
     auto outputLayer = impl::createOutputLayer(*this, layerFE);
 
-    if (const auto halDisplayId = HalDisplayId::tryCast(mId);
+    if (const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
         outputLayer && !mIsDisconnected && halDisplayId) {
         auto& hwc = getCompositionEngine().getHwComposer();
         auto hwcLayer = hwc.createLayer(*halDisplayId);
@@ -171,8 +175,7 @@
 void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& refreshArgs) {
     Output::setReleasedLayers(refreshArgs);
 
-    if (mIsDisconnected || GpuVirtualDisplayId::tryCast(mId) ||
-        refreshArgs.layersWithQueuedFrames.empty()) {
+    if (mIsDisconnected || isGpuVirtualDisplay() || refreshArgs.layersWithQueuedFrames.empty()) {
         return;
     }
 
@@ -208,7 +211,7 @@
     if (!getState().displayBrightness) {
         return;
     }
-    if (auto displayId = PhysicalDisplayId::tryCast(mId)) {
+    if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) {
         auto& hwc = getCompositionEngine().getHwComposer();
         status_t result = hwc.setDisplayBrightness(*displayId, *getState().displayBrightness,
                                                    getState().displayBrightnessNits,
@@ -226,7 +229,7 @@
     Output::beginFrame();
 
     // If we don't have a HWC display, then we are done.
-    const auto halDisplayId = HalDisplayId::tryCast(mId);
+    const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
     if (!halDisplayId) {
         return;
     }
@@ -244,7 +247,7 @@
     }
 
     // If we don't have a HWC display, then we are done.
-    const auto halDisplayId = HalDisplayId::tryCast(mId);
+    const auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
     if (!halDisplayId) {
         return false;
     }
@@ -266,9 +269,9 @@
     }
 
     if (isPowerHintSessionEnabled()) {
-        mPowerAdvisor->setHwcValidateTiming(mId, hwcValidateStartTime, TimePoint::now());
-        if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
-            mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId));
+        mPowerAdvisor->setHwcValidateTiming(getId(), hwcValidateStartTime, TimePoint::now());
+        if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
+            mPowerAdvisor->setSkippedValidate(*halDisplayId, hwc.getValidateSkipped(*halDisplayId));
         }
     }
 
@@ -292,7 +295,7 @@
 
 bool Display::getSkipColorTransform() const {
     auto& hwc = getCompositionEngine().getHwComposer();
-    if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
+    if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
         return hwc.hasDisplayCapability(*halDisplayId,
                                         DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
     }
@@ -383,7 +386,7 @@
 }
 
 void Display::executeCommands() {
-    const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
+    const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
     if (mIsDisconnected || !halDisplayIdOpt) {
         return;
     }
@@ -394,7 +397,7 @@
 compositionengine::Output::FrameFences Display::presentFrame() {
     auto fences = impl::Output::presentFrame();
 
-    const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
+    const auto halDisplayIdOpt = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>);
     if (mIsDisconnected || !halDisplayIdOpt) {
         return fences;
     }
@@ -404,13 +407,13 @@
     const TimePoint startTime = TimePoint::now();
 
     if (isPowerHintSessionEnabled() && getState().earliestPresentTime) {
-        mPowerAdvisor->setHwcPresentDelayedTime(mId, *getState().earliestPresentTime);
+        mPowerAdvisor->setHwcPresentDelayedTime(*halDisplayIdOpt, *getState().earliestPresentTime);
     }
 
     hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime);
 
     if (isPowerHintSessionEnabled()) {
-        mPowerAdvisor->setHwcPresentTiming(mId, startTime, TimePoint::now());
+        mPowerAdvisor->setHwcPresentTiming(*halDisplayIdOpt, startTime, TimePoint::now());
     }
 
     fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
@@ -433,8 +436,8 @@
 void Display::setExpensiveRenderingExpected(bool enabled) {
     Output::setExpensiveRenderingExpected(enabled);
 
-    if (mPowerAdvisor && !GpuVirtualDisplayId::tryCast(mId)) {
-        mPowerAdvisor->setExpensiveRenderingExpected(mId, enabled);
+    if (mPowerAdvisor && !isGpuVirtualDisplay()) {
+        mPowerAdvisor->setExpensiveRenderingExpected(getId(), enabled);
     }
 }
 
@@ -449,15 +452,15 @@
 // For ADPF GPU v0 this is expected to set start time to when the GPU commands are submitted with
 // fence returned, i.e. when RenderEngine flushes the commands and returns the draw fence.
 void Display::setHintSessionGpuStart(TimePoint startTime) {
-    mPowerAdvisor->setGpuStartTime(mId, startTime);
+    mPowerAdvisor->setGpuStartTime(getId(), startTime);
 }
 
 void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) {
-    mPowerAdvisor->setGpuFenceTime(mId, std::move(gpuFence));
+    mPowerAdvisor->setGpuFenceTime(getId(), std::move(gpuFence));
 }
 
 void Display::setHintSessionRequiresRenderEngine(bool requiresRenderEngine) {
-    mPowerAdvisor->setRequiresRenderEngine(mId, requiresRenderEngine);
+    mPowerAdvisor->setRequiresRenderEngine(getId(), requiresRenderEngine);
 }
 
 const aidl::android::hardware::graphics::composer3::OverlayProperties*
@@ -478,7 +481,7 @@
     // 1) It is being handled by hardware composer, which may need this to
     //    keep its virtual display state machine in sync, or
     // 2) There is work to be done (the dirty region isn't empty)
-    if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) {
+    if (isGpuVirtualDisplay() && !mustRecompose()) {
         ALOGV("Skipping display composition");
         return;
     }
@@ -487,7 +490,7 @@
 }
 
 bool Display::supportsOffloadPresent() const {
-    if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
+    if (auto halDisplayId = getDisplayIdVariant().and_then(asHalDisplayId<DisplayIdVariant>)) {
         auto& hwc = getCompositionEngine().getHwComposer();
         return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::MULTI_THREADED_PRESENT);
     }
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index b30cf20..25f6436 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -118,6 +118,10 @@
     return {};
 }
 
+ftl::Optional<DisplayIdVariant> Output::getDisplayIdVariant() const {
+    return {};
+}
+
 const std::string& Output::getName() const {
     return mName;
 }
@@ -436,8 +440,8 @@
 ftl::Future<std::monostate> Output::present(
         const compositionengine::CompositionRefreshArgs& refreshArgs) {
     const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string {
-        return getDisplayId()
-                .and_then(PhysicalDisplayId::tryCast)
+        return getDisplayIdVariant()
+                .and_then(asPhysicalDisplayId)
                 .and_then([&refreshArgs](PhysicalDisplayId id) {
                     return refreshArgs.frameTargets.get(id);
                 })
@@ -890,8 +894,8 @@
         return;
     }
 
-    if (auto frameTargetPtrOpt = getDisplayId()
-                                         .and_then(PhysicalDisplayId::tryCast)
+    if (auto frameTargetPtrOpt = getDisplayIdVariant()
+                                         .and_then(asPhysicalDisplayId)
                                          .and_then([&refreshArgs](PhysicalDisplayId id) {
                                              return refreshArgs.frameTargets.get(id);
                                          })) {
@@ -1841,7 +1845,7 @@
     if (!getDisplayId()) {
         return;
     }
-    if (auto displayId = PhysicalDisplayId::tryCast(*getDisplayId())) {
+    if (auto displayId = getDisplayIdVariant().and_then(asPhysicalDisplayId)) {
         auto& hwc = getCompositionEngine().getHwComposer();
         const status_t error =
                 hwc.setDisplayPictureProfileHandle(*displayId, getState().pictureProfileHandle);
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index ad65c44..882da18 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -294,12 +294,23 @@
     void SetUp() override {
         EXPECT_CALL(*mDisplay1, getDisplayId)
                 .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId1)));
+        EXPECT_CALL(*mDisplay1, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId1));
+
         EXPECT_CALL(*mDisplay2, getDisplayId)
                 .WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId2)));
+        EXPECT_CALL(*mDisplay2, getDisplayIdVariant).WillRepeatedly(Return(kDisplayId2));
+
         EXPECT_CALL(*mVirtualDisplay, getDisplayId)
                 .WillRepeatedly(Return(std::make_optional<DisplayId>(kGpuVirtualDisplayId)));
+        const DisplayIdVariant gpuVariant =
+                GpuVirtualDisplayId::fromValue(kGpuVirtualDisplayId.value);
+        EXPECT_CALL(*mVirtualDisplay, getDisplayIdVariant).WillRepeatedly(Return(gpuVariant));
+
         EXPECT_CALL(*mHalVirtualDisplay, getDisplayId)
                 .WillRepeatedly(Return(std::make_optional<DisplayId>(kHalVirtualDisplayId)));
+        const DisplayIdVariant halVariant =
+                HalVirtualDisplayId::fromValue(kHalVirtualDisplayId.value);
+        EXPECT_CALL(*mHalVirtualDisplay, getDisplayIdVariant).WillRepeatedly(Return(halVariant));
 
         // Most tests will depend on the outputs being enabled.
         for (auto& state : mOutputStates) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index c1e59d0..77fd446 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -278,7 +278,7 @@
             impl::createDisplay(mCompositionEngine, getDisplayCreationArgsForGpuVirtualDisplay());
     EXPECT_FALSE(display->isSecure());
     EXPECT_TRUE(display->isVirtual());
-    EXPECT_TRUE(GpuVirtualDisplayId::tryCast(display->getId()));
+    EXPECT_TRUE(display->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>));
 }
 
 /*
@@ -318,6 +318,7 @@
     EXPECT_EQ(HAL_VIRTUAL_DISPLAY_ID, mDisplay->getId());
     EXPECT_FALSE(mDisplay->isSecure());
     EXPECT_TRUE(mDisplay->isVirtual());
+    EXPECT_TRUE(mDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<HalVirtualDisplayId>));
     EXPECT_FALSE(mDisplay->isValid());
 
     const auto& filter = mDisplay->getState().layerFilter;
@@ -337,6 +338,7 @@
     EXPECT_EQ(GPU_VIRTUAL_DISPLAY_ID, mDisplay->getId());
     EXPECT_FALSE(mDisplay->isSecure());
     EXPECT_TRUE(mDisplay->isVirtual());
+    EXPECT_TRUE(mDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>));
     EXPECT_FALSE(mDisplay->isValid());
 
     const auto& filter = mDisplay->getState().layerFilter;
@@ -572,7 +574,7 @@
     auto args = getDisplayCreationArgsForGpuVirtualDisplay();
     std::shared_ptr<Display> gpuDisplay =
             createPartialMockDisplay<Display>(mCompositionEngine, args);
-    EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId()));
+    EXPECT_TRUE(gpuDisplay->getDisplayIdVariant().and_then(asDisplayIdOfType<GpuVirtualDisplayId>));
 
     chooseCompositionStrategy(gpuDisplay.get());
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 09ad9fa..b56147a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -148,20 +148,23 @@
         virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
 
         virtual ftl::Optional<DisplayId> getDisplayId() const override { return mId; }
+        virtual ftl::Optional<DisplayIdVariant> getDisplayIdVariant() const override {
+            return DisplayIdVariant(mId);
+        }
 
         virtual bool hasPictureProcessing() const override { return mHasPictureProcessing; }
         virtual int32_t getMaxLayerPictureProfiles() const override {
             return mMaxLayerPictureProfiles;
         }
 
-        void setDisplayIdForTest(DisplayId value) { mId = value; }
+        void setDisplayIdForTest(PhysicalDisplayId value) { mId = value; }
 
         void setHasPictureProcessingForTest(bool value) { mHasPictureProcessing = value; }
 
         void setMaxLayerPictureProfilesForTest(int32_t value) { mMaxLayerPictureProfiles = value; }
 
     private:
-        ftl::Optional<DisplayId> mId;
+        PhysicalDisplayId mId;
         bool mHasPictureProcessing;
         int32_t mMaxLayerPictureProfiles;
     };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9cd2314..ab468c9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -659,13 +659,15 @@
     }
 }
 
-VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui::PixelFormat format,
-                                                       const std::string& uniqueId) {
+void SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution, ui::PixelFormat format,
+                                           const std::string& uniqueId,
+                                           compositionengine::DisplayCreationArgsBuilder& builder) {
     if (auto& generator = mVirtualDisplayIdGenerators.hal) {
         if (const auto id = generator->generateId()) {
             if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format)) {
                 acquireVirtualDisplaySnapshot(*id, uniqueId);
-                return *id;
+                builder.setId(*id);
+                return;
             }
 
             generator->releaseId(*id);
@@ -679,7 +681,7 @@
     const auto id = mVirtualDisplayIdGenerators.gpu.generateId();
     LOG_ALWAYS_FATAL_IF(!id, "Failed to generate ID for GPU virtual display");
     acquireVirtualDisplaySnapshot(*id, uniqueId);
-    return *id;
+    builder.setId(*id);
 }
 
 void SurfaceFlinger::releaseVirtualDisplay(VirtualDisplayId displayId) {
@@ -4008,7 +4010,7 @@
     if (const auto& physical = state.physical) {
         builder.setId(physical->id);
     } else {
-        builder.setId(acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId));
+        acquireVirtualDisplay(resolution, pixelFormat, state.uniqueId, builder);
     }
 
     builder.setPixels(resolution);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index fc596d7..2d81738 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -160,6 +160,7 @@
 class OutputLayer;
 
 struct CompositionRefreshArgs;
+class DisplayCreationArgsBuilder;
 } // namespace compositionengine
 
 namespace renderengine {
@@ -1125,8 +1126,8 @@
     void enableHalVirtualDisplays(bool);
 
     // Virtual display lifecycle for ID generation and HAL allocation.
-    VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat, const std::string& uniqueId)
-            REQUIRES(mStateLock);
+    void acquireVirtualDisplay(ui::Size, ui::PixelFormat, const std::string& uniqueId,
+                               compositionengine::DisplayCreationArgsBuilder&) REQUIRES(mStateLock);
     template <typename ID>
     void acquireVirtualDisplaySnapshot(ID displayId, const std::string& uniqueId) {
         std::lock_guard lock(mVirtualDisplaysMutex);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
index aa5b786..aa48c1b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp
@@ -50,9 +50,9 @@
         EXPECT_EQ(display.requestedRefreshRate, Fps::fromValue(requestedRefreshRate));
         EXPECT_EQ(name.c_str(), display.displayName);
 
-        const VirtualDisplayId vid = GpuVirtualDisplayId(baseId);
         sp<DisplayDevice> device =
-                mFlinger.createVirtualDisplayDevice(displayToken, vid, requestedRefreshRate);
+                mFlinger.createVirtualDisplayDevice(displayToken, GpuVirtualDisplayId(baseId),
+                                                    requestedRefreshRate);
 
         EXPECT_TRUE(device->isVirtual());
         device->adjustRefreshRate(Fps::fromValue(pacesetterDisplayRefreshRate));
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index a3ee08f..42e7ab9 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -583,7 +583,7 @@
     }
 
     sp<DisplayDevice> createVirtualDisplayDevice(const sp<IBinder> displayToken,
-                                                 VirtualDisplayId displayId,
+                                                 GpuVirtualDisplayId displayId,
                                                  float requestedRefreshRate) {
         constexpr ui::Size kResolution = {1080, 1920};
         auto compositionDisplay = compositionengine::impl::
@@ -983,8 +983,8 @@
         sp<IBinder> token() const { return mDisplayToken; }
 
         auto physicalDisplay() const {
-            return ftl::Optional(mCreationArgs.compositionDisplay->getDisplayId())
-                    .and_then(&PhysicalDisplayId::tryCast)
+            return mCreationArgs.compositionDisplay->getDisplayIdVariant()
+                    .and_then(asPhysicalDisplayId)
                     .and_then(display::getPhysicalDisplay(mFlinger.physicalDisplays()));
         }
 
@@ -1082,7 +1082,9 @@
             DisplayDeviceState state;
             state.isSecure = mCreationArgs.isSecure;
 
-            if (const auto physicalId = PhysicalDisplayId::tryCast(*displayId)) {
+            if (const auto physicalId =
+                        mCreationArgs.compositionDisplay->getDisplayIdVariant().and_then(
+                                asPhysicalDisplayId)) {
                 LOG_ALWAYS_FATAL_IF(!mConnectionType);
                 LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);