SF: Plumb physical display IDs to libgui

This CL replaces ISurfaceComposer::{eDisplayIdMain,eDisplayIdHdmi} with
the stable 64-bit display IDs generated by SF. Note that the 64-bit IDs
fall back to the old values if the HWC API for display identification is
not supported.

Bug: 74619554
Test: LocalDisplayAdapter and Choreographer receive 64-bit IDs
Test: 64-bit IDs fall back to 0 and 1 on HWC 2.2 and below
Change-Id: I3c08eff6eb8bb179ecce596ab2820a2aa44c8649
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index 1599995..d63cd79 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -23,10 +23,12 @@
 #include <string_view>
 #include <vector>
 
+#include <ui/GraphicTypes.h>
+
 namespace android {
 
 struct DisplayId {
-    using Type = uint64_t;
+    using Type = PhysicalDisplayId;
     Type value;
 
     uint16_t manufacturerId() const;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 52abe9c..91ae087 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -69,24 +69,28 @@
 std::string toString(const DisplayEventReceiver::Event& event) {
     switch (event.header.type) {
         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
-            return StringPrintf("Hotplug{displayId=%u, %s}", event.header.id,
+            return StringPrintf("Hotplug{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", %s}",
+                                event.header.displayId,
                                 event.hotplug.connected ? "connected" : "disconnected");
         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
-            return StringPrintf("VSync{displayId=%u, count=%u}", event.header.id,
-                                event.vsync.count);
+            return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
+                                ", count=%u}",
+                                event.header.displayId, event.vsync.count);
         default:
             return "Event{}";
     }
 }
 
-DisplayEventReceiver::Event makeHotplug(uint32_t displayId, nsecs_t timestamp, bool connected) {
+DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
+                                        bool connected) {
     DisplayEventReceiver::Event event;
     event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
     event.hotplug.connected = connected;
     return event;
 }
 
-DisplayEventReceiver::Event makeVSync(uint32_t displayId, nsecs_t timestamp, uint32_t count) {
+DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
+                                      uint32_t count) {
     DisplayEventReceiver::Event event;
     event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
     event.vsync.count = count;
@@ -290,10 +294,9 @@
     mCondition.notify_all();
 }
 
-void EventThread::onHotplugReceived(DisplayType displayType, bool connected) {
+void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) {
     std::lock_guard<std::mutex> lock(mMutex);
 
-    const uint32_t displayId = displayType == DisplayType::Primary ? 0 : 1;
     mPendingEvents.push_back(makeHotplug(displayId, systemTime(), connected));
     mCondition.notify_all();
 }
@@ -312,9 +315,9 @@
             switch (event->header.type) {
                 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                     if (event->hotplug.connected && !mVSyncState) {
-                        mVSyncState.emplace(event->header.id);
+                        mVSyncState.emplace(event->header.displayId);
                     } else if (!event->hotplug.connected && mVSyncState &&
-                               mVSyncState->displayId == event->header.id) {
+                               mVSyncState->displayId == event->header.displayId) {
                         mVSyncState.reset();
                     }
                     break;
@@ -440,8 +443,9 @@
 
     StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState));
     if (mVSyncState) {
-        StringAppendF(&result, "{displayId=%u, count=%u%s}\n", mVSyncState->displayId,
-                      mVSyncState->count, mVSyncState->synthetic ? ", synthetic" : "");
+        StringAppendF(&result, "{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%u%s}\n",
+                      mVSyncState->displayId, mVSyncState->count,
+                      mVSyncState->synthetic ? ", synthetic" : "");
     } else {
         StringAppendF(&result, "none\n");
     }
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 89b799e..62b6a8b 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -94,9 +94,6 @@
 
 class EventThread {
 public:
-    // TODO: Remove once stable display IDs are plumbed through SF/WM interface.
-    enum class DisplayType { Primary, External };
-
     virtual ~EventThread();
 
     virtual sp<EventThreadConnection> createEventConnection(
@@ -108,8 +105,7 @@
     // called after the screen is turned on from main thread
     virtual void onScreenAcquired() = 0;
 
-    // called when receiving a hotplug event
-    virtual void onHotplugReceived(DisplayType displayType, bool connected) = 0;
+    virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
 
     virtual void dump(std::string& result) const = 0;
 
@@ -151,8 +147,7 @@
     // called after the screen is turned on from main thread
     void onScreenAcquired() override;
 
-    // called when receiving a hotplug event
-    void onHotplugReceived(DisplayType displayType, bool connected) override;
+    void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
 
     void dump(std::string& result) const override;
 
@@ -199,9 +194,9 @@
 
     // VSYNC state of connected display.
     struct VSyncState {
-        explicit VSyncState(uint32_t displayId) : displayId(displayId) {}
+        explicit VSyncState(PhysicalDisplayId displayId) : displayId(displayId) {}
 
-        const uint32_t displayId;
+        const PhysicalDisplayId displayId;
 
         // Number of VSYNC events since display was connected.
         uint32_t count = 0;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 00820f1..a29877e 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -29,7 +29,6 @@
 #include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 #include <cutils/properties.h>
-#include <gui/ISurfaceComposer.h>
 #include <ui/DisplayStatInfo.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
@@ -128,9 +127,9 @@
 }
 
 void Scheduler::hotplugReceived(const sp<Scheduler::ConnectionHandle>& handle,
-                                EventThread::DisplayType displayType, bool connected) {
+                                PhysicalDisplayId displayId, bool connected) {
     RETURN_IF_INVALID();
-    mConnections[handle->id]->thread->onHotplugReceived(displayType, connected);
+    mConnections[handle->id]->thread->onHotplugReceived(displayId, connected);
 }
 
 void Scheduler::onScreenAcquired(const sp<Scheduler::ConnectionHandle>& handle) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index b717605..e77dc06 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -19,8 +19,8 @@
 #include <cstdint>
 #include <memory>
 
-#include <gui/ISurfaceComposer.h>
 #include <ui/DisplayStatInfo.h>
+#include <ui/GraphicTypes.h>
 
 #include "DispSync.h"
 #include "EventControlThread.h"
@@ -85,7 +85,7 @@
     sp<EventThreadConnection> getEventConnection(const sp<ConnectionHandle>& handle);
 
     // Should be called when receiving a hotplug event.
-    void hotplugReceived(const sp<ConnectionHandle>& handle, EventThread::DisplayType displayType,
+    void hotplugReceived(const sp<ConnectionHandle>& handle, PhysicalDisplayId displayId,
                          bool connected);
 
     // Should be called after the screen is turned on.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2cf2cd8..4c1b267 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -496,21 +496,30 @@
     setTransactionFlags(eDisplayTransactionNeeded);
 }
 
-sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
-    std::optional<DisplayId> displayId;
+std::vector<PhysicalDisplayId> SurfaceFlinger::getPhysicalDisplayIds() const {
+    Mutex::Autolock lock(mStateLock);
 
-    if (id == HWC_DISPLAY_PRIMARY) {
-        displayId = getInternalDisplayId();
-    } else if (id == HWC_DISPLAY_EXTERNAL) {
-        displayId = getExternalDisplayId();
+    const auto internalDisplayId = getInternalDisplayIdLocked();
+    if (!internalDisplayId) {
+        return {};
     }
 
-    if (!displayId) {
-        ALOGE("%s: Invalid display %d", __FUNCTION__, id);
-        return nullptr;
+    std::vector<PhysicalDisplayId> displayIds;
+    displayIds.reserve(mPhysicalDisplayTokens.size());
+    displayIds.push_back(internalDisplayId->value);
+
+    for (const auto& [id, token] : mPhysicalDisplayTokens) {
+        if (id != *internalDisplayId) {
+            displayIds.push_back(id.value);
+        }
     }
 
-    return getPhysicalDisplayToken(*displayId);
+    return displayIds;
+}
+
+sp<IBinder> SurfaceFlinger::getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
+    Mutex::Autolock lock(mStateLock);
+    return getPhysicalDisplayTokenLocked(DisplayId{displayId});
 }
 
 status_t SurfaceFlinger::getColorManagement(bool* outGetColorManagement) const {
@@ -614,9 +623,9 @@
 
     // start the EventThread
     if (mUseScheduler) {
-        mScheduler = getFactory().createScheduler([this](bool enabled) {
-            setVsyncEnabled(EventThread::DisplayType::Primary, enabled);
-        });
+        mScheduler = getFactory().createScheduler(
+                [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
+
         // TODO(b/113612090): Currently we assume that if scheduler is turned on, then the refresh
         // rate is 90. Once b/122905403 is completed, this should be updated accordingly.
         mPhaseOffsets->setRefreshRateType(
@@ -705,7 +714,7 @@
     }
 
     mEventControlThread = getFactory().createEventControlThread(
-            [this](bool enabled) { setVsyncEnabled(EventThread::DisplayType::Primary, enabled); });
+            [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
 
     // initialize our drawing state
     mDrawingState = mCurrentState;
@@ -820,7 +829,9 @@
         return BAD_VALUE;
     }
 
-    const auto displayId = getPhysicalDisplayId(displayToken);
+    ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
+
+    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
     if (!displayId) {
         return NAME_NOT_FOUND;
     }
@@ -844,8 +855,6 @@
 
     configs->clear();
 
-    ConditionalLock _l(mStateLock,
-            std::this_thread::get_id() != mMainThreadId);
     for (const auto& hwConfig : getHwComposer().getConfigs(*displayId)) {
         DisplayInfo info = DisplayInfo();
 
@@ -858,7 +867,7 @@
         info.viewportW = info.w;
         info.viewportH = info.h;
 
-        if (displayId == getInternalDisplayId()) {
+        if (displayId == getInternalDisplayIdLocked()) {
             // The density of the device is provided by a build property
             float density = Density::getBuildDensity() / 160.0f;
             if (density == 0) {
@@ -914,7 +923,7 @@
         // All non-virtual displays are currently considered secure.
         info.secure = true;
 
-        if (displayId == getInternalDisplayId() &&
+        if (displayId == getInternalDisplayIdLocked() &&
             primaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
             std::swap(info.w, info.h);
         }
@@ -1012,15 +1021,15 @@
         return BAD_VALUE;
     }
 
-    const auto displayId = getPhysicalDisplayId(displayToken);
-    if (!displayId) {
-        return NAME_NOT_FOUND;
-    }
-
     std::vector<ColorMode> modes;
     {
-        ConditionalLock _l(mStateLock,
-                std::this_thread::get_id() != mMainThreadId);
+        ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
+
+        const auto displayId = getPhysicalDisplayIdLocked(displayToken);
+        if (!displayId) {
+            return NAME_NOT_FOUND;
+        }
+
         modes = getHwComposer().getColorModes(*displayId);
     }
     outColorModes->clear();
@@ -1330,7 +1339,7 @@
 }
 
 nsecs_t SurfaceFlinger::getVsyncPeriod() const {
-    const auto displayId = getInternalDisplayId();
+    const auto displayId = getInternalDisplayIdLocked();
     if (!displayId || !getHwComposer().isConnected(*displayId)) {
         return 0;
     }
@@ -1447,9 +1456,10 @@
     *compositorTiming = getBE().mCompositorTiming;
 }
 
-void SurfaceFlinger::setRefreshRateTo(float newFps) {
-    const auto displayId = getInternalDisplayId();
-    if (!displayId || mBootStage != BootStage::FINISHED) {
+// TODO(b/123715322): Fix thread safety.
+void SurfaceFlinger::setRefreshRateTo(float newFps) NO_THREAD_SAFETY_ANALYSIS {
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (!display || mBootStage != BootStage::FINISHED) {
         return;
     }
     // TODO(b/113612090): There should be a message queue flush here. Because this esentially
@@ -1458,8 +1468,7 @@
     // refresh cycle.
 
     // Don't do any updating if the current fps is the same as the new one.
-    const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
-    const nsecs_t currentVsyncPeriod = activeConfig->getVsyncPeriod();
+    const nsecs_t currentVsyncPeriod = getVsyncPeriod();
     if (currentVsyncPeriod == 0) {
         return;
     }
@@ -1470,7 +1479,7 @@
         return;
     }
 
-    auto configs = getHwComposer().getConfigs(*displayId);
+    auto configs = getHwComposer().getConfigs(*display->getId());
     for (int i = 0; i < configs.size(); i++) {
         const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
         if (vsyncPeriod == 0) {
@@ -1480,11 +1489,12 @@
         // TODO(b/113612090): There should be a better way at determining which config
         // has the right refresh rate.
         if (std::abs(fps - newFps) <= 1) {
-            const auto display = getBuiltInDisplay(HWC_DISPLAY_PRIMARY);
-            if (!display) return;
+            const sp<IBinder> token = display->getDisplayToken().promote();
+            LOG_ALWAYS_FATAL_IF(token == nullptr);
+
             // This is posted in async function to avoid deadlock when getDisplayDevice
             // requires mStateLock.
-            setActiveConfigAsync(display, i);
+            setActiveConfigAsync(token, i);
             ATRACE_INT("FPS", newFps);
         }
     }
@@ -1524,10 +1534,10 @@
     repaintEverythingForHWC();
 }
 
-void SurfaceFlinger::setVsyncEnabled(EventThread::DisplayType /*displayType*/, bool enabled) {
+void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
     ATRACE_CALL();
     Mutex::Autolock lock(mStateLock);
-    if (const auto displayId = getInternalDisplayId()) {
+    if (const auto displayId = getInternalDisplayIdLocked()) {
         getHwComposer().setVsyncEnabled(*displayId,
                                         enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
     }
@@ -2593,14 +2603,13 @@
     mPendingHotplugEvents.clear();
 }
 
-void SurfaceFlinger::dispatchDisplayHotplugEvent(EventThread::DisplayType displayType,
-                                                 bool connected) {
+void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected) {
     if (mUseScheduler) {
-        mScheduler->hotplugReceived(mAppConnectionHandle, displayType, connected);
-        mScheduler->hotplugReceived(mSfConnectionHandle, displayType, connected);
+        mScheduler->hotplugReceived(mAppConnectionHandle, displayId, connected);
+        mScheduler->hotplugReceived(mSfConnectionHandle, displayId, connected);
     } else {
-        mEventThread->onHotplugReceived(displayType, connected);
-        mSFEventThread->onHotplugReceived(displayType, connected);
+        mEventThread->onHotplugReceived(displayId, connected);
+        mSFEventThread->onHotplugReceived(displayId, connected);
     }
 }
 
@@ -2616,7 +2625,7 @@
     creationArgs.hasWideColorGamut = false;
     creationArgs.supportedPerFrameMetadata = 0;
 
-    const bool isInternalDisplay = displayId && displayId == getInternalDisplayId();
+    const bool isInternalDisplay = displayId && displayId == getInternalDisplayIdLocked();
     creationArgs.isPrimary = isInternalDisplay;
 
     if (useColorManagement && displayId) {
@@ -2699,19 +2708,18 @@
         for (size_t i = 0; i < dc;) {
             const ssize_t j = curr.indexOfKey(draw.keyAt(i));
             if (j < 0) {
-                // Save display IDs before disconnecting.
-                const auto internalDisplayId = getInternalDisplayId();
-                const auto externalDisplayId = getExternalDisplayId();
-
                 // in drawing state but not in current state
                 if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
+                    // Save display ID before disconnecting.
+                    const auto displayId = display->getId();
                     display->disconnect();
+
+                    if (!display->isVirtual()) {
+                        LOG_ALWAYS_FATAL_IF(!displayId);
+                        dispatchDisplayHotplugEvent(displayId->value, false);
+                    }
                 }
-                if (internalDisplayId && internalDisplayId == draw[i].displayId) {
-                    dispatchDisplayHotplugEvent(EventThread::DisplayType::Primary, false);
-                } else if (externalDisplayId && externalDisplayId == draw[i].displayId) {
-                    dispatchDisplayHotplugEvent(EventThread::DisplayType::External, false);
-                }
+
                 mDisplays.erase(draw.keyAt(i));
             } else {
                 // this display is in both lists. see if something changed.
@@ -2814,12 +2822,7 @@
                                                                     dispSurface, producer));
                     if (!state.isVirtual()) {
                         LOG_ALWAYS_FATAL_IF(!displayId);
-
-                        if (displayId == getInternalDisplayId()) {
-                            dispatchDisplayHotplugEvent(EventThread::DisplayType::Primary, true);
-                        } else if (displayId == getExternalDisplayId()) {
-                            dispatchDisplayHotplugEvent(EventThread::DisplayType::External, true);
-                        }
+                        dispatchDisplayHotplugEvent(displayId->value, true);
                     }
                 }
             }
@@ -4829,7 +4832,7 @@
                   "  gpu_to_cpu_unsupported    : %d\n",
                   mTransactionFlags.load(), !mGpuToCpuSupported);
 
-    if (const auto displayId = getInternalDisplayId();
+    if (const auto displayId = getInternalDisplayIdLocked();
         displayId && getHwComposer().isConnected(*displayId)) {
         const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
         StringAppendF(&result,
@@ -4999,7 +5002,8 @@
         // information, so it is OK to pass them.
         case AUTHENTICATE_SURFACE:
         case GET_ACTIVE_CONFIG:
-        case GET_BUILT_IN_DISPLAY:
+        case GET_PHYSICAL_DISPLAY_IDS:
+        case GET_PHYSICAL_DISPLAY_TOKEN:
         case GET_DISPLAY_COLOR_MODES:
         case GET_DISPLAY_NATIVE_PRIMARIES:
         case GET_DISPLAY_CONFIGS:
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a48e811..73b0cde 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -313,7 +313,7 @@
     compositionengine::CompositionEngine& getCompositionEngine() const;
 
     // returns the default Display
-    sp<const DisplayDevice> getDefaultDisplayDevice() const {
+    sp<const DisplayDevice> getDefaultDisplayDevice() {
         Mutex::Autolock _l(mStateLock);
         return getDefaultDisplayDeviceLocked();
     }
@@ -327,7 +327,7 @@
 
     // enable/disable h/w composer event
     // TODO: this should be made accessible only to EventThread
-    void setVsyncEnabled(EventThread::DisplayType displayType, bool enabled);
+    void setPrimaryVsyncEnabled(bool enabled);
 
     // called on the main thread by MessageQueue when an internal message
     // is received
@@ -414,7 +414,8 @@
     sp<ISurfaceComposerClient> createConnection() override;
     sp<IBinder> createDisplay(const String8& displayName, bool secure) override;
     void destroyDisplay(const sp<IBinder>& displayToken) override;
-    sp<IBinder> getBuiltInDisplay(int32_t id) override;
+    std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override;
+    sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override;
     void setTransactionState(const Vector<ComposerState>& state,
                              const Vector<DisplayState>& displays, uint32_t flags,
                              const sp<IBinder>& applyToken,
@@ -657,7 +658,7 @@
     }
 
     sp<DisplayDevice> getDefaultDisplayDeviceLocked() {
-        if (const auto token = getInternalDisplayToken()) {
+        if (const auto token = getInternalDisplayTokenLocked()) {
             return getDisplayDeviceLocked(token);
         }
         return nullptr;
@@ -761,7 +762,7 @@
     void processDisplayChangesLocked();
     void processDisplayHotplugEventsLocked();
 
-    void dispatchDisplayHotplugEvent(EventThread::DisplayType displayType, bool connected);
+    void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected);
 
     /* ------------------------------------------------------------------------
      * VSync
@@ -801,12 +802,12 @@
     /*
      * Display identification
      */
-    sp<IBinder> getPhysicalDisplayToken(DisplayId displayId) const {
+    sp<IBinder> getPhysicalDisplayTokenLocked(DisplayId displayId) const {
         const auto it = mPhysicalDisplayTokens.find(displayId);
         return it != mPhysicalDisplayTokens.end() ? it->second : nullptr;
     }
 
-    std::optional<DisplayId> getPhysicalDisplayId(const sp<IBinder>& displayToken) const {
+    std::optional<DisplayId> getPhysicalDisplayIdLocked(const sp<IBinder>& displayToken) const {
         for (const auto& [id, token] : mPhysicalDisplayTokens) {
             if (token == displayToken) {
                 return id;
@@ -816,22 +817,16 @@
     }
 
     // TODO(b/74619554): Remove special cases for primary display.
-    sp<IBinder> getInternalDisplayToken() const {
-        const auto displayId = getInternalDisplayId();
-        return displayId ? getPhysicalDisplayToken(*displayId) : nullptr;
+    sp<IBinder> getInternalDisplayTokenLocked() const {
+        const auto displayId = getInternalDisplayIdLocked();
+        return displayId ? getPhysicalDisplayTokenLocked(*displayId) : nullptr;
     }
 
-    std::optional<DisplayId> getInternalDisplayId() const {
+    std::optional<DisplayId> getInternalDisplayIdLocked() const {
         const auto hwcDisplayId = getHwComposer().getInternalHwcDisplayId();
         return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
     }
 
-    // TODO(b/74619554): Remove special cases for external display.
-    std::optional<DisplayId> getExternalDisplayId() const {
-        const auto hwcDisplayId = getHwComposer().getExternalHwcDisplayId();
-        return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
-    }
-
     /*
      * Debugging & dumpsys
      */
@@ -951,7 +946,6 @@
     std::unique_ptr<VSyncSource> mSfEventThreadSource;
     std::unique_ptr<InjectVSyncSource> mVSyncInjector;
     std::unique_ptr<EventControlThread> mEventControlThread;
-    std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
 
     // Calculates correct offsets.
     VSyncModulator mVsyncModulator;
@@ -985,6 +979,7 @@
     // this may only be written from the main thread with mStateLock held
     // it may be read from other threads with mStateLock held
     std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
+    std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
 
     // don't use a lock for these, we don't care
     int mDebugRegion;
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index f021d3d..61d09da 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -62,9 +62,11 @@
     }
 
     void setupBackgroundSurface() {
-        mDisplay = SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+        mDisplay = SurfaceComposerClient::getInternalDisplayToken();
+        ASSERT_FALSE(mDisplay == nullptr);
+
         DisplayInfo info;
-        SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
         const ssize_t displayWidth = info.w;
         const ssize_t displayHeight = info.h;
 
@@ -170,10 +172,8 @@
 }
 
 TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
-    std::function<bool()> condition = [=]() {
-        sp<IBinder> display(
-                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
-        return (display != nullptr);
+    std::function<bool()> condition = [] {
+        return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
     };
     // Anyone can access display information.
     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
@@ -183,7 +183,7 @@
     // The following methods are tested with a UID that is not root, graphics,
     // or system, to show that anyone can access them.
     setBinUID();
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
     ASSERT_TRUE(display != nullptr);
 
     DisplayInfo info;
@@ -199,7 +199,7 @@
 }
 
 TEST_F(CredentialsTest, GetDisplayColorModesTest) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
     std::function<status_t()> condition = [=]() {
         Vector<ui::ColorMode> outColorModes;
         return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
@@ -208,7 +208,7 @@
 }
 
 TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
     std::function<status_t()> condition = [=]() {
         ui::DisplayPrimaries primaries;
         return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
@@ -217,7 +217,7 @@
 }
 
 TEST_F(CredentialsTest, SetActiveConfigTest) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
     std::function<status_t()> condition = [=]() {
         return SurfaceComposerClient::setActiveConfig(display, 0);
     };
@@ -225,7 +225,7 @@
 }
 
 TEST_F(CredentialsTest, SetActiveColorModeTest) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
     std::function<status_t()> condition = [=]() {
         return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
     };
@@ -258,7 +258,7 @@
 }
 
 TEST_F(CredentialsTest, CaptureTest) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
     std::function<status_t()> condition = [=]() {
         sp<GraphicBuffer> outBuffer;
         return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
@@ -324,7 +324,8 @@
 }
 
 TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
+    ASSERT_FALSE(display == nullptr);
     bool result = false;
     status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
     ASSERT_EQ(NO_ERROR, error);
@@ -346,7 +347,8 @@
 }
 
 TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
+    ASSERT_FALSE(display == nullptr);
     std::function<status_t()> condition = [=]() {
         bool result = false;
         return SurfaceComposerClient::isWideColorDisplay(display, &result);
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8ec3e15..5cc946a 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -240,10 +240,12 @@
 }
 
 void SurfaceInterceptorTest::setupBackgroundSurface() {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
-                ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
+    ASSERT_FALSE(display == nullptr);
+
     DisplayInfo info;
-    SurfaceComposerClient::getDisplayInfo(display, &info);
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
+
     ssize_t displayWidth = info.w;
     ssize_t displayHeight = info.h;
 
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 56d3bd4..05a73dc 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -195,13 +195,12 @@
 class ScreenCapture : public RefBase {
 public:
     static void captureScreen(std::unique_ptr<ScreenCapture>* sc) {
-        sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-        sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+        const auto sf = ComposerService::getComposerService();
+        const auto token = sf->getInternalDisplayToken();
         SurfaceComposerClient::Transaction().apply(true);
 
         sp<GraphicBuffer> outBuffer;
-        ASSERT_EQ(NO_ERROR,
-                  sf->captureScreen(display, &outBuffer, Rect(), 0, 0, false));
+        ASSERT_EQ(NO_ERROR, sf->captureScreen(token, &outBuffer, Rect(), 0, 0, false));
         *sc = std::make_unique<ScreenCapture>(outBuffer);
     }
 
@@ -324,7 +323,6 @@
         ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
 
         sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-        sp<IBinder> binder = sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
         ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed));
     }
 
@@ -502,12 +500,12 @@
 
 private:
     void SetUpDisplay() {
-        mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
-        ASSERT_NE(nullptr, mDisplay.get()) << "failed to get built-in display";
+        mDisplay = mClient->getInternalDisplayToken();
+        ASSERT_FALSE(mDisplay == nullptr) << "failed to get display";
 
         // get display width/height
         DisplayInfo info;
-        SurfaceComposerClient::getDisplayInfo(mDisplay, &info);
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
         mDisplayWidth = info.w;
         mDisplayHeight = info.h;
         mDisplayRect =
@@ -558,8 +556,7 @@
                 return mDelegate->screenshot();
             case RenderPath::VIRTUAL_DISPLAY:
 
-                sp<IBinder> mainDisplay =
-                        SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
+                const auto mainDisplay = SurfaceComposerClient::getInternalDisplayToken();
                 DisplayInfo mainDisplayInfo;
                 SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo);
 
@@ -3930,10 +3927,11 @@
         LayerTransactionTest::SetUp();
         ASSERT_EQ(NO_ERROR, mClient->initCheck());
 
-        sp<IBinder> display(
-                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+        const auto display = SurfaceComposerClient::getInternalDisplayToken();
+        ASSERT_FALSE(display == nullptr);
+
         DisplayInfo info;
-        SurfaceComposerClient::getDisplayInfo(display, &info);
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
 
         ssize_t displayWidth = info.w;
         ssize_t displayHeight = info.h;
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 16e0891..f9e0b64 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -145,7 +145,7 @@
     void TearDown() override;
 
     void waitForDisplayTransaction();
-    bool waitForHotplugEvent(uint32_t id, bool connected);
+    bool waitForHotplugEvent(PhysicalDisplayId displayId, bool connected);
 
     sp<IComposer> mFakeService;
     sp<SurfaceComposerClient> mComposerClient;
@@ -242,7 +242,7 @@
     mMockComposer->runVSyncAndWait();
 }
 
-bool DisplayTest::waitForHotplugEvent(uint32_t id, bool connected) {
+bool DisplayTest::waitForHotplugEvent(PhysicalDisplayId displayId, bool connected) {
     int waitCount = 20;
     while (waitCount--) {
         while (!mReceivedDisplayEvents.empty()) {
@@ -250,11 +250,12 @@
             mReceivedDisplayEvents.pop_front();
 
             ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
-                    "event hotplug: id %d, connected %d\t", event.header.id,
-                    event.hotplug.connected);
+                     "event hotplug: displayId %" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
+                     ", connected %d\t",
+                     event.header.displayId, event.hotplug.connected);
 
             if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
-                event.header.id == id && event.hotplug.connected == connected) {
+                event.header.displayId == displayId && event.hotplug.connected == connected) {
                 return true;
             }
         }
@@ -294,13 +295,14 @@
 
     waitForDisplayTransaction();
 
-    EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdHdmi, true));
+    EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
     {
-        sp<android::IBinder> display(
-                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdHdmi));
+        const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+        ASSERT_FALSE(display == nullptr);
+
         DisplayInfo info;
-        SurfaceComposerClient::getDisplayInfo(display, &info);
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
         ASSERT_EQ(400u, info.w);
         ASSERT_EQ(200u, info.h);
 
@@ -328,14 +330,15 @@
 
     waitForDisplayTransaction();
 
-    EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdHdmi, false));
-    EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdHdmi, true));
+    EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
+    EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
 
     {
-        sp<android::IBinder> display(
-                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdHdmi));
+        const auto display = SurfaceComposerClient::getPhysicalDisplayToken(EXTERNAL_DISPLAY);
+        ASSERT_FALSE(display == nullptr);
+
         DisplayInfo info;
-        SurfaceComposerClient::getDisplayInfo(display, &info);
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
         ASSERT_EQ(400u, info.w);
         ASSERT_EQ(200u, info.h);
 
@@ -364,11 +367,12 @@
 
     waitForDisplayTransaction();
 
-    EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdMain, false));
+    EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
 
     {
-        sp<android::IBinder> display(
-                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+        const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY);
+        EXPECT_FALSE(display == nullptr);
+
         DisplayInfo info;
         auto result = SurfaceComposerClient::getDisplayInfo(display, &info);
         EXPECT_NE(NO_ERROR, result);
@@ -402,11 +406,12 @@
 
     waitForDisplayTransaction();
 
-    EXPECT_TRUE(waitForHotplugEvent(ISurfaceComposer::eDisplayIdMain, true));
+    EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
 
     {
-        sp<android::IBinder> display(
-                SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+        const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY);
+        EXPECT_FALSE(display == nullptr);
+
         DisplayInfo info;
         auto result = SurfaceComposerClient::getDisplayInfo(display, &info);
         EXPECT_EQ(NO_ERROR, result);
@@ -473,10 +478,11 @@
     ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
 
     ALOGI("TransactionTest::SetUp - display");
-    sp<android::IBinder> display(
-            SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
+    const auto display = SurfaceComposerClient::getPhysicalDisplayToken(PRIMARY_DISPLAY);
+    ASSERT_FALSE(display == nullptr);
+
     DisplayInfo info;
-    SurfaceComposerClient::getDisplayInfo(display, &info);
+    ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
 
     mDisplayWidth = info.w;
     mDisplayHeight = info.h;
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 4cb79ab..da3472e 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -45,9 +45,9 @@
 namespace {
 
 using testing::_;
-using testing::ByMove;
 using testing::DoAll;
 using testing::Mock;
+using testing::ResultOf;
 using testing::Return;
 using testing::SetArgPointee;
 
@@ -321,11 +321,6 @@
     // Whether the display is primary
     static constexpr Primary PRIMARY = primary;
 
-    static constexpr auto displayType() {
-        return static_cast<bool>(PRIMARY) ? EventThread::DisplayType::Primary
-                                          : EventThread::DisplayType::External;
-    }
-
     static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
         auto injector =
                 FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(),
@@ -1470,6 +1465,9 @@
     template <typename Case>
     void setupCommonPreconditions();
 
+    template <typename Case, bool connected>
+    static void expectHotplugReceived(mock::EventThread*);
+
     template <typename Case>
     void setupCommonCallExpectationsForConnectProcessing();
 
@@ -1507,6 +1505,17 @@
     injectFakeNativeWindowSurfaceFactory();
 }
 
+template <typename Case, bool connected>
+void HandleTransactionLockedTest::expectHotplugReceived(mock::EventThread* eventThread) {
+    const auto convert = [](auto physicalDisplayId) {
+        return std::make_optional(DisplayId{physicalDisplayId});
+    };
+
+    EXPECT_CALL(*eventThread,
+                onHotplugReceived(ResultOf(convert, Case::Display::DISPLAY_ID::get()), connected))
+            .Times(1);
+}
+
 template <typename Case>
 void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessing() {
     Case::Display::setupHwcHotplugCallExpectations(this);
@@ -1522,16 +1531,16 @@
 
     EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
 
-    EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::displayType(), true)).Times(1);
-    EXPECT_CALL(*mSFEventThread, onHotplugReceived(Case::Display::displayType(), true)).Times(1);
+    expectHotplugReceived<Case, true>(mEventThread);
+    expectHotplugReceived<Case, true>(mSFEventThread);
 }
 
 template <typename Case>
 void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() {
     EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
 
-    EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::displayType(), false)).Times(1);
-    EXPECT_CALL(*mSFEventThread, onHotplugReceived(Case::Display::displayType(), false)).Times(1);
+    expectHotplugReceived<Case, false>(mEventThread);
+    expectHotplugReceived<Case, false>(mSFEventThread);
 }
 
 template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index dd90063..ad7dcb4 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -36,6 +36,9 @@
 namespace android {
 namespace {
 
+constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = 111;
+constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID = 222;
+
 class MockVSyncSource : public VSyncSource {
 public:
     MOCK_METHOD1(setVSyncEnabled, void(bool));
@@ -72,7 +75,7 @@
                                               ConnectionEventRecorder& connectionEventRecorder,
                                               nsecs_t expectedTimestamp, unsigned expectedCount);
     void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
-    void expectHotplugEventReceivedByConnection(EventThread::DisplayType expectedDisplayType,
+    void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
                                                 bool expectedConnected);
 
     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
@@ -106,8 +109,8 @@
     mConnection = createConnection(mConnectionEventCallRecorder);
 
     // A display must be connected for VSYNC events to be delivered.
-    mThread->onHotplugReceived(EventThread::DisplayType::Primary, true);
-    expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, true);
+    mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
+    expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true);
 }
 
 EventThreadTest::~EventThreadTest() {
@@ -183,16 +186,13 @@
                                          expectedCount);
 }
 
-void EventThreadTest::expectHotplugEventReceivedByConnection(
-        EventThread::DisplayType expectedDisplayType, bool expectedConnected) {
-    const uint32_t expectedDisplayId =
-            expectedDisplayType == EventThread::DisplayType::Primary ? 0 : 1;
-
+void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId,
+                                                             bool expectedConnected) {
     auto args = mConnectionEventCallRecorder.waitForCall();
     ASSERT_TRUE(args.has_value());
     const auto& event = std::get<0>(args.value());
     EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type);
-    EXPECT_EQ(expectedDisplayId, event.header.id);
+    EXPECT_EQ(expectedDisplayId, event.header.displayId);
     EXPECT_EQ(expectedConnected, event.hotplug.connected);
 }
 
@@ -212,8 +212,8 @@
 }
 
 TEST_F(EventThreadTest, vsyncRequestIsIgnoredIfDisplayIsDisconnected) {
-    mThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
-    expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, false);
+    mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
+    expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
 
     // Signal that we want the next vsync event to be posted to the connection.
     mThread->requestNextVsync(mConnection, false);
@@ -400,24 +400,24 @@
     expectVSyncSetPhaseOffsetCallReceived(321);
 }
 
-TEST_F(EventThreadTest, postHotplugPrimaryDisconnect) {
-    mThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
-    expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, false);
+TEST_F(EventThreadTest, postHotplugInternalDisconnect) {
+    mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false);
+    expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false);
 }
 
-TEST_F(EventThreadTest, postHotplugPrimaryConnect) {
-    mThread->onHotplugReceived(EventThread::DisplayType::Primary, true);
-    expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, true);
+TEST_F(EventThreadTest, postHotplugInternalConnect) {
+    mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true);
+    expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true);
 }
 
 TEST_F(EventThreadTest, postHotplugExternalDisconnect) {
-    mThread->onHotplugReceived(EventThread::DisplayType::External, false);
-    expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, false);
+    mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, false);
+    expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, false);
 }
 
 TEST_F(EventThreadTest, postHotplugExternalConnect) {
-    mThread->onHotplugReceived(EventThread::DisplayType::External, true);
-    expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, true);
+    mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, true);
+    expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, true);
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 4d9aec6..0db96d9 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -18,6 +18,8 @@
 
 namespace android {
 
+constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID = 999;
+
 class SchedulerTest : public testing::Test {
 protected:
     class MockEventThreadConnection : public android::EventThreadConnection {
@@ -104,8 +106,7 @@
     EXPECT_TRUE(returnedValue == nullptr);
     EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
-    ASSERT_NO_FATAL_FAILURE(
-            mScheduler->hotplugReceived(nullptr, EventThread::DisplayType::Primary, false));
+    ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(nullptr, PHYSICAL_DISPLAY_ID, false));
     ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(nullptr));
     ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(nullptr));
     std::string testString;
@@ -129,8 +130,8 @@
 
     // The EXPECT_CALLS make sure we don't call the functions on the subsequent event threads.
     EXPECT_CALL(*mEventThread, onHotplugReceived(_, _)).Times(0);
-    ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(connectionHandle,
-                                                        EventThread::DisplayType::Primary, false));
+    ASSERT_NO_FATAL_FAILURE(
+            mScheduler->hotplugReceived(connectionHandle, PHYSICAL_DISPLAY_ID, false));
 
     EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(0);
     ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(connectionHandle));
@@ -158,10 +159,9 @@
     EXPECT_TRUE(mScheduler->getEventThread(mConnectionHandle) != nullptr);
     EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle) != nullptr);
 
-    EXPECT_CALL(*mEventThread, onHotplugReceived(EventThread::DisplayType::Primary, false))
-            .Times(1);
-    ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(mConnectionHandle,
-                                                        EventThread::DisplayType::Primary, false));
+    EXPECT_CALL(*mEventThread, onHotplugReceived(PHYSICAL_DISPLAY_ID, false)).Times(1);
+    ASSERT_NO_FATAL_FAILURE(
+            mScheduler->hotplugReceived(mConnectionHandle, PHYSICAL_DISPLAY_ID, false));
 
     EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(1);
     ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(mConnectionHandle));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 3242ef1..aaf67e9 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -31,7 +31,7 @@
     MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
-    MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool));
+    MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
     MOCK_CONST_METHOD1(dump, void(std::string&));
     MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset));
     MOCK_METHOD1(registerDisplayEventConnection,