Merge "[SurfaceFlinger] Enable SurfaceInterceptorTest in presubmit."
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index df6404a..aae3931 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -326,7 +326,7 @@
     if (presentFence->isValid()) {
         mTimeStats.setPresentFence(layerName, mCurrentFrameNumber, presentFence);
         mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
-    } else {
+    } else if (mFlinger->getHwComposer().isConnected(HWC_DISPLAY_PRIMARY)) {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
         const nsecs_t actualPresentTime =
@@ -710,8 +710,9 @@
         mProducer->setMaxDequeuedBufferCount(2);
     }
 
-    const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
-    updateTransformHint(hw);
+    if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+        updateTransformHint(display);
+    }
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index a4a6554..f440d29 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -315,7 +315,6 @@
 };
 
 struct DisplayDeviceState {
-    bool isValid() const { return type >= 0; }
     bool isVirtual() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
 
     int32_t sequenceId = sNextSequenceId++;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index f626a59..9546c86 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -124,6 +124,12 @@
     return mComposer->getMaxVirtualDisplayCount();
 }
 
+Error Device::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+                                           std::vector<uint8_t>* outData) const {
+    auto intError = mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
+    return static_cast<Error>(intError);
+}
+
 Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
         PixelFormat* format, Display** outDisplay)
 {
@@ -460,11 +466,6 @@
     return configs;
 }
 
-Error Display::getIdentificationData(uint8_t* outPort, std::vector<uint8_t>* outData) const {
-    auto intError = mComposer.getDisplayIdentificationData(mId, outPort, outData);
-    return static_cast<Error>(intError);
-}
-
 Error Display::getName(std::string* outName) const
 {
     auto intError = mComposer.getDisplayName(mId, outName);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 2cb6aea..eefab98 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -93,6 +93,9 @@
     };
 
     uint32_t getMaxVirtualDisplayCount() const;
+    Error getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+                                       std::vector<uint8_t>* outData) const;
+
     Error createVirtualDisplay(uint32_t width, uint32_t height,
             android::ui::PixelFormat* format, Display** outDisplay);
     void destroyDisplay(hwc2_display_t displayId);
@@ -224,8 +227,6 @@
     // Doesn't call into the HWC2 device, so no errors are possible
     std::vector<std::shared_ptr<const Config>> getConfigs() const;
 
-    [[clang::warn_unused_result]] Error getIdentificationData(uint8_t* outPort,
-                                                              std::vector<uint8_t>* outData) const;
     [[clang::warn_unused_result]] Error getName(std::string* outName) const;
     [[clang::warn_unused_result]] Error getRequests(
             DisplayRequest* outDisplayRequests,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index cd0635a..4e98b88 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -54,6 +54,9 @@
 #include "../Layer.h"           // needed only for debugging
 #include "../SurfaceFlinger.h"
 
+#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
+    ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
+
 #define LOG_DISPLAY_ERROR(displayId, msg) \
     ALOGE("%s failed for display %d: %s", __FUNCTION__, displayId, msg)
 
@@ -96,17 +99,11 @@
     mHwcDevice->registerCallback(callback, sequenceId);
 }
 
-bool HWComposer::getDisplayIdentificationData(hwc2_display_t displayId, uint8_t* outPort,
+bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                               DisplayIdentificationData* outData) const {
-    HWC2::Display* display = mHwcDevice->getDisplayById(displayId);
-    if (!display) {
-        ALOGE("getDisplayIdentificationData: Attempted to access invalid display %" PRIu64,
-              displayId);
-        return false;
-    }
-    const auto error = display->getIdentificationData(outPort, outData);
+    const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
     if (error != HWC2::Error::None) {
-        ALOGE("getDisplayIdentificationData failed for display %" PRIu64, displayId);
+        LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
         return false;
     }
     return true;
@@ -147,65 +144,53 @@
     }
 }
 
-std::optional<DisplayId> HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType,
+std::optional<DisplayId> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType,
                                                HWC2::Connection connection) {
     if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
         ALOGE("Invalid display type of %d", displayType);
         return {};
     }
 
-    ALOGV("hotplug: %" PRIu64 ", %s %s", displayId,
-            displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
-            to_string(connection).c_str());
-    mHwcDevice->onHotplug(displayId, connection);
+    ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId,
+          displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
+          to_string(connection).c_str());
+    mHwcDevice->onHotplug(hwcDisplayId, connection);
 
-    std::optional<DisplayId> stableId;
+    std::optional<DisplayId> displayId;
 
     uint8_t port;
     DisplayIdentificationData data;
-    if (getDisplayIdentificationData(displayId, &port, &data)) {
-        stableId = generateDisplayId(port, data);
-        ALOGE_IF(!stableId, "Failed to generate stable ID for display %" PRIu64, displayId);
+    if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
+        displayId = generateDisplayId(port, data);
+        ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
     }
 
     // Disconnect is handled through HWComposer::disconnectDisplay via
     // SurfaceFlinger's onHotplugReceived callback handling
     if (connection == HWC2::Connection::Connected) {
-        mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId);
-        mHwcDisplaySlots[displayId] = displayType;
+        mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
+        mHwcDisplaySlots[hwcDisplayId] = displayType;
     }
 
-    return stableId;
+    return displayId;
 }
 
-bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp,
-                         int32_t* outDisplay) {
-    auto display = mHwcDevice->getDisplayById(displayId);
-    if (!display) {
-        ALOGE("onVsync Failed to find display %" PRIu64, displayId);
-        return false;
-    }
-    auto displayType = HWC2::DisplayType::Invalid;
-    auto error = display->getType(&displayType);
-    if (error != HWC2::Error::None) {
-        ALOGE("onVsync: Failed to determine type of display %" PRIu64,
-                display->getId());
+bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplayId) {
+    const auto it = mHwcDisplaySlots.find(hwcDisplayId);
+    if (it == mHwcDisplaySlots.end()) {
+        LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid display");
         return false;
     }
 
-    if (displayType == HWC2::DisplayType::Virtual) {
-        ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
-                display->getId());
+    const int32_t displayId = it->second;
+    RETURN_IF_INVALID_DISPLAY(displayId, false);
+
+    const auto& displayData = mDisplayData[displayId];
+    if (displayData.isVirtual) {
+        LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
         return false;
     }
 
-    if (mHwcDisplaySlots.count(display->getId()) == 0) {
-        ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
-                display->getId());
-        return false;
-    }
-
-    int32_t disp = mHwcDisplaySlots[display->getId()];
     {
         Mutex::Autolock _l(mLock);
 
@@ -213,22 +198,22 @@
         // with the same timestamp when turning the display off and on. This
         // is a bug in the HWC implementation, but filter the extra events
         // out here so they don't cause havoc downstream.
-        if (timestamp == mLastHwVSync[disp]) {
+        if (timestamp == mLastHwVSync[displayId]) {
             ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
                     timestamp);
             return false;
         }
 
-        mLastHwVSync[disp] = timestamp;
+        mLastHwVSync[displayId] = timestamp;
     }
 
-    if (outDisplay) {
-        *outDisplay = disp;
+    if (outDisplayId) {
+        *outDisplayId = displayId;
     }
 
     char tag[16];
-    snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
-    ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
+    snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", displayId);
+    ATRACE_INT(tag, ++mVSyncCounts[displayId] & 1);
 
     return true;
 }
@@ -236,16 +221,15 @@
 status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
         ui::PixelFormat* format, int32_t *outId) {
     if (mRemainingHwcVirtualDisplays == 0) {
-        ALOGE("allocateVirtualDisplay: No remaining virtual displays");
+        ALOGE("%s: No remaining virtual displays", __FUNCTION__);
         return NO_MEMORY;
     }
 
     if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
         (width > SurfaceFlinger::maxVirtualDisplaySize ||
          height > SurfaceFlinger::maxVirtualDisplaySize)) {
-        ALOGE("createVirtualDisplay: Can't create a virtual display with"
-                      " a dimension > %" PRIu64 " (tried %u x %u)",
-              SurfaceFlinger::maxVirtualDisplaySize, width, height);
+        ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
+              height, SurfaceFlinger::maxVirtualDisplaySize);
         return INVALID_OPERATION;
     }
 
@@ -253,7 +237,7 @@
     auto error = mHwcDevice->createVirtualDisplay(width, height, format,
             &display);
     if (error != HWC2::Error::None) {
-        ALOGE("allocateVirtualDisplay: Failed to create HWC virtual display");
+        ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
         return NO_MEMORY;
     }
 
@@ -266,11 +250,13 @@
         displaySlot = mDisplayData.size();
         mDisplayData.resize(displaySlot + 1);
     } else {
-        ALOGE("allocateVirtualDisplay: Unable to allocate a display slot");
+        ALOGE("%s: Unable to allocate a display slot", __FUNCTION__);
         return NO_MEMORY;
     }
 
-    mDisplayData[displaySlot].hwcDisplay = display;
+    auto& displayData = mDisplayData[displaySlot];
+    displayData.hwcDisplay = display;
+    displayData.isVirtual = true;
 
     --mRemainingHwcVirtualDisplays;
     *outId = static_cast<int32_t>(displaySlot);
@@ -347,21 +333,19 @@
 }
 
 int HWComposer::getActiveConfigIndex(int32_t displayId) const {
-    if (!isValidDisplay(displayId)) {
-        ALOGV("getActiveConfigIndex: Attempted to access invalid display %d", displayId);
-        return -1;
-    }
+    RETURN_IF_INVALID_DISPLAY(displayId, -1);
+
     int index;
     auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index);
     if (error == HWC2::Error::BadConfig) {
-        ALOGE("getActiveConfigIndex: No config active, returning -1");
+        LOG_DISPLAY_ERROR(displayId, "No active config");
         return -1;
-    } else if (error != HWC2::Error::None) {
-        ALOGE("getActiveConfigIndex failed for display %d: %s (%d)", displayId,
-              to_string(error).c_str(), static_cast<int32_t>(error));
-        return -1;
-    } else if (index < 0) {
-        ALOGE("getActiveConfigIndex returned an unknown config for display %d", displayId);
+    }
+
+    RETURN_IF_HWC_ERROR(error, displayId, -1);
+
+    if (index < 0) {
+        LOG_DISPLAY_ERROR(displayId, "Unknown config");
         return -1;
     }
 
@@ -393,19 +377,19 @@
 
 
 void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) {
-    if (displayId < 0 || displayId >= HWC_DISPLAY_VIRTUAL) {
-        ALOGD("setVsyncEnabled: Ignoring for virtual display %d", displayId);
+    RETURN_IF_INVALID_DISPLAY(displayId);
+    auto& displayData = mDisplayData[displayId];
+
+    if (displayData.isVirtual) {
+        LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
         return;
     }
 
-    RETURN_IF_INVALID_DISPLAY(displayId);
-
     // NOTE: we use our own internal lock here because we have to call
     // into the HWC with the lock held, and we want to make sure
     // that even if HWC blocks (which it shouldn't), it won't
     // affect other threads.
     Mutex::Autolock _l(mVsyncLock);
-    auto& displayData = mDisplayData[displayId];
     if (enabled != displayData.vsyncEnabled) {
         ATRACE_CALL();
         auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
@@ -629,7 +613,8 @@
     ALOGV("setPowerMode(%d, %d)", displayId, intMode);
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
 
-    if (displayId >= VIRTUAL_DISPLAY_ID_BASE) {
+    const auto& displayData = mDisplayData[displayId];
+    if (displayData.isVirtual) {
         LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
         return INVALID_OPERATION;
     }
@@ -639,7 +624,7 @@
         setVsyncEnabled(displayId, HWC2::Vsync::Disable);
     }
 
-    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    auto& hwcDisplay = displayData.hwcDisplay;
     switch (mode) {
         case HWC2::PowerMode::Off:
         case HWC2::PowerMode::On:
@@ -708,24 +693,20 @@
     return NO_ERROR;
 }
 
-void HWComposer::disconnectDisplay(int displayId) {
-    LOG_ALWAYS_FATAL_IF(displayId < 0);
+void HWComposer::disconnectDisplay(int32_t displayId) {
+    RETURN_IF_INVALID_DISPLAY(displayId);
     auto& displayData = mDisplayData[displayId];
 
-    auto displayType = HWC2::DisplayType::Invalid;
-    auto error = displayData.hwcDisplay->getType(&displayType);
-    RETURN_IF_HWC_ERROR_FOR("getType", error, displayId);
-
     // If this was a virtual display, add its slot back for reuse by future
     // virtual displays
-    if (displayType == HWC2::DisplayType::Virtual) {
+    if (displayData.isVirtual) {
         mFreeDisplaySlots.insert(displayId);
         ++mRemainingHwcVirtualDisplays;
     }
 
     const auto hwcDisplayId = displayData.hwcDisplay->getId();
     mHwcDisplaySlots.erase(hwcDisplayId);
-    displayData.reset();
+    displayData = DisplayData();
 
     mHwcDevice->destroyDisplay(hwcDisplayId);
 }
@@ -733,18 +714,14 @@
 status_t HWComposer::setOutputBuffer(int32_t displayId,
         const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+    const auto& displayData = mDisplayData[displayId];
 
-    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
-    auto displayType = HWC2::DisplayType::Invalid;
-    auto error = hwcDisplay->getType(&displayType);
-    RETURN_IF_HWC_ERROR_FOR("getType", error, displayId, NAME_NOT_FOUND);
-
-    if (displayType != HWC2::DisplayType::Virtual) {
+    if (!displayData.isVirtual) {
         LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
         return INVALID_OPERATION;
     }
 
-    error = hwcDisplay->setOutputBuffer(buffer, acquireFence);
+    auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
     return NO_ERROR;
 }
@@ -833,26 +810,4 @@
     return mDisplayData[displayId].hwcDisplay->getId();
 }
 
-// ---------------------------------------------------------------------------
-
-HWComposer::DisplayData::DisplayData()
-  : hasClientComposition(false),
-    hasDeviceComposition(false),
-    hwcDisplay(nullptr),
-    lastPresentFence(Fence::NO_FENCE),
-    outbufHandle(nullptr),
-    outbufAcquireFence(Fence::NO_FENCE),
-    vsyncEnabled(HWC2::Vsync::Disable) {
-    ALOGV("Created new DisplayData");
-}
-
-HWComposer::DisplayData::~DisplayData() {
-}
-
-void HWComposer::DisplayData::reset() {
-    ALOGV("DisplayData reset");
-    *this = DisplayData();
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 9e4a683..3c5efea 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -76,7 +76,7 @@
     void registerCallback(HWC2::ComposerCallback* callback,
                           int32_t sequenceId);
 
-    bool getDisplayIdentificationData(hwc2_display_t displayId, uint8_t* outPort,
+    bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                       DisplayIdentificationData* outData) const;
 
     bool hasCapability(HWC2::Capability capability) const;
@@ -152,9 +152,8 @@
 
     // Returns true if successful, false otherwise. The
     // DisplayDevice::DisplayType of the display is returned as an output param.
-    bool onVsync(hwc2_display_t displayId, int64_t timestamp,
-                 int32_t* outDisplay);
-    std::optional<DisplayId> onHotplug(hwc2_display_t displayId, int32_t displayType,
+    bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay);
+    std::optional<DisplayId> onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType,
                                        HWC2::Connection connection);
 
     void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
@@ -189,31 +188,26 @@
     // For unit tests
     friend TestableSurfaceFlinger;
 
-    static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
-
     bool isValidDisplay(int32_t displayId) const;
     static void validateChange(HWC2::Composition from, HWC2::Composition to);
 
     struct cb_context;
 
     struct DisplayData {
-        DisplayData();
-        ~DisplayData();
-        void reset();
-
-        bool hasClientComposition;
-        bool hasDeviceComposition;
-        HWC2::Display* hwcDisplay;
+        bool isVirtual = false;
+        bool hasClientComposition = false;
+        bool hasDeviceComposition = false;
+        HWC2::Display* hwcDisplay = nullptr;
         HWC2::DisplayRequest displayRequests;
-        sp<Fence> lastPresentFence;  // signals when the last set op retires
+        sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
         std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
-        buffer_handle_t outbufHandle;
-        sp<Fence> outbufAcquireFence;
+        buffer_handle_t outbufHandle = nullptr;
+        sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
         mutable std::unordered_map<int32_t,
                 std::shared_ptr<const HWC2::Display::Config>> configMap;
 
         // protected by mVsyncLock
-        HWC2::Vsync vsyncEnabled;
+        HWC2::Vsync vsyncEnabled = HWC2::Vsync::Disable;
 
         bool validateWasSkipped;
         HWC2::Error presentError;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index bc271c8..5a8fd25 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -155,20 +155,17 @@
     mCondition.notify_all();
 }
 
-void EventThread::onHotplugReceived(int type, bool connected) {
-    ALOGE_IF(type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES,
-             "received hotplug event for an invalid display (id=%d)", type);
-
+void EventThread::onHotplugReceived(DisplayType displayType, bool connected) {
     std::lock_guard<std::mutex> lock(mMutex);
-    if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
-        DisplayEventReceiver::Event event;
-        event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
-        event.header.id = type;
-        event.header.timestamp = systemTime();
-        event.hotplug.connected = connected;
-        mPendingEvents.add(event);
-        mCondition.notify_all();
-    }
+
+    DisplayEventReceiver::Event event;
+    event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
+    event.header.id = displayType == DisplayType::Primary ? 0 : 1;
+    event.header.timestamp = systemTime();
+    event.hotplug.connected = connected;
+
+    mPendingEvents.add(event);
+    mCondition.notify_all();
 }
 
 void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
@@ -205,7 +202,7 @@
 // This will return when (1) a vsync event has been received, and (2) there was
 // at least one connection interested in receiving it when we started waiting.
 Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked(
-        std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* event) {
+        std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* outEvent) {
     Vector<sp<EventThread::Connection> > signalConnections;
 
     while (signalConnections.isEmpty() && mKeepRunning) {
@@ -214,16 +211,16 @@
 
         size_t vsyncCount = 0;
         nsecs_t timestamp = 0;
-        for (int32_t i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; i++) {
-            timestamp = mVSyncEvent[i].header.timestamp;
+        for (auto& event : mVSyncEvent) {
+            timestamp = event.header.timestamp;
             if (timestamp) {
                 // we have a vsync event to dispatch
                 if (mInterceptVSyncsCallback) {
                     mInterceptVSyncsCallback(timestamp);
                 }
-                *event = mVSyncEvent[i];
-                mVSyncEvent[i].header.timestamp = 0;
-                vsyncCount = mVSyncEvent[i].vsync.count;
+                *outEvent = event;
+                event.header.timestamp = 0;
+                vsyncCount = event.vsync.count;
                 break;
             }
         }
@@ -233,7 +230,7 @@
             eventPending = !mPendingEvents.isEmpty();
             if (eventPending) {
                 // we have some other event to dispatch
-                *event = mPendingEvents[0];
+                *outEvent = mPendingEvents[0];
                 mPendingEvents.removeAt(0);
             }
         }
@@ -319,7 +316,7 @@
                     // FIXME: how do we decide which display id the fake
                     // vsync came from ?
                     mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
-                    mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
+                    mVSyncEvent[0].header.id = 0;
                     mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                     mVSyncEvent[0].vsync.count++;
                 }
@@ -364,8 +361,7 @@
     result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled");
     result.appendFormat("  soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
     result.appendFormat("  numListeners=%zu,\n  events-delivered: %u\n",
-                        mDisplayEventConnections.size(),
-                        mVSyncEvent[DisplayDevice::DISPLAY_PRIMARY].vsync.count);
+                        mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count);
     for (size_t i = 0; i < mDisplayEventConnections.size(); i++) {
         sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote();
         result.appendFormat("    %p: count=%d\n", connection.get(),
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9c13ed2..a0262b2 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -16,9 +16,11 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <sys/types.h>
+
+#include <array>
 #include <condition_variable>
+#include <cstdint>
 #include <mutex>
 #include <thread>
 
@@ -31,8 +33,6 @@
 #include <utils/Errors.h>
 #include <utils/SortedVector.h>
 
-#include "DisplayDevice.h"
-
 // ---------------------------------------------------------------------------
 namespace android {
 // ---------------------------------------------------------------------------
@@ -59,6 +59,9 @@
 
 class EventThread {
 public:
+    // TODO: Remove once stable display IDs are plumbed through SF/WM interface.
+    enum class DisplayType { Primary, External };
+
     virtual ~EventThread();
 
     virtual sp<BnDisplayEventConnection> createEventConnection() const = 0;
@@ -70,7 +73,7 @@
     virtual void onScreenAcquired() = 0;
 
     // called when receiving a hotplug event
-    virtual void onHotplugReceived(int type, bool connected) = 0;
+    virtual void onHotplugReceived(DisplayType displayType, bool connected) = 0;
 
     virtual void dump(String8& result) const = 0;
 
@@ -122,7 +125,7 @@
     void onScreenAcquired() override;
 
     // called when receiving a hotplug event
-    void onHotplugReceived(int type, bool connected) override;
+    void onHotplugReceived(DisplayType displayType, bool connected) override;
 
     void dump(String8& result) const override;
 
@@ -155,8 +158,7 @@
     // protected by mLock
     SortedVector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex);
     Vector<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
-    DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES] GUARDED_BY(
-            mMutex);
+    std::array<DisplayEventReceiver::Event, 2> mVSyncEvent GUARDED_BY(mMutex);
     bool mUseSoftwareVSync GUARDED_BY(mMutex) = false;
     bool mVsyncEnabled GUARDED_BY(mMutex) = false;
     bool mKeepRunning GUARDED_BY(mMutex) = true;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5a0bf43..b4b3f4a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -363,7 +363,7 @@
     return reduce(floatWin, activeTransparentRegion);
 }
 
-Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const {
+Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
     // the crop is the area of the window that gets cropped, but not
     // scaled in any ways.
     const State& s(getDrawingState());
@@ -382,7 +382,7 @@
 
     Transform t = getTransform();
     activeCrop = t.transform(activeCrop);
-    if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+    if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
         activeCrop.clear();
     }
     if (!s.finalCrop.isEmpty()) {
@@ -393,14 +393,14 @@
 
     const auto& p = mDrawingParent.promote();
     if (p != nullptr) {
-        auto parentCrop = p->computeInitialCrop(hw);
+        auto parentCrop = p->computeInitialCrop(display);
         activeCrop.intersect(parentCrop, &activeCrop);
     }
 
     return activeCrop;
 }
 
-FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
+FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const {
     // the content crop is the area of the content that gets scaled to the
     // layer's size. This is in buffer space.
     FloatRect crop = getContentCrop().toFloatRect();
@@ -409,7 +409,7 @@
     const State& s(getDrawingState());
 
     // Screen space to make reduction to parent crop clearer.
-    Rect activeCrop = computeInitialCrop(hw);
+    Rect activeCrop = computeInitialCrop(display);
     Transform t = getTransform();
     // Back to layer space to work with the content crop.
     activeCrop = t.inverse().transform(activeCrop);
@@ -1376,13 +1376,13 @@
     return usage;
 }
 
-void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
+void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
     uint32_t orientation = 0;
     if (!mFlinger->mDebugDisableTransformHint) {
         // The transform hint is used to improve performance, but we can
         // only have a single transform hint, it cannot
         // apply to all displays.
-        const Transform& planeTransform(hw->getTransform());
+        const Transform& planeTransform = display->getTransform();
         orientation = planeTransform.getOrientation();
         if (orientation & Transform::ROT_INVALID) {
             orientation = 0;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index fe953cd..fb94058 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -328,7 +328,7 @@
     HWC2::Composition getCompositionType(int32_t displayId) const;
     void setClearClientTarget(int32_t displayId, bool clear);
     bool getClearClientTarget(int32_t displayId) const;
-    void updateCursorPosition(const sp<const DisplayDevice>& hw);
+    void updateCursorPosition(const sp<const DisplayDevice>& display);
 
     /*
      * called after page-flip
@@ -425,7 +425,7 @@
 
     // Updates the transform hint in our SurfaceFlingerConsumer to match
     // the current orientation of the display device.
-    void updateTransformHint(const sp<const DisplayDevice>& hw) const;
+    void updateTransformHint(const sp<const DisplayDevice>& display) const;
 
     /*
      * returns the rectangle that crops the content of the layer and scales it
@@ -556,12 +556,12 @@
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
 
-    FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
+    FloatRect computeCrop(const sp<const DisplayDevice>& display) const;
     // Compute the initial crop as specified by parent layers and the
     // SurfaceControl for this layer. Does not include buffer crop from the
     // IGraphicBufferProducer client, as that should not affect child clipping.
     // Returns in screen space.
-    Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const;
+    Rect computeInitialCrop(const sp<const DisplayDevice>& display) const;
 
     // drawing
     void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dec1178..2a2be83 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -668,12 +668,14 @@
     getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
     // Process any initial hotplug and resulting display changes.
     processDisplayHotplugEventsLocked();
-    LOG_ALWAYS_FATAL_IF(!getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY),
-            "Registered composer callback but didn't create the default primary display");
+    const auto display = getDefaultDisplayDeviceLocked();
+    LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback.");
+    LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getId()),
+                        "Internal display is disconnected.");
 
     // make the default display GLContext current so that we can create textures
     // when creating Layers (which may happens before we render something)
-    getDefaultDisplayDeviceLocked()->makeCurrent();
+    display->makeCurrent();
 
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
@@ -689,9 +691,11 @@
                 signalTransaction();
             }));
         };
-        mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(),
-                getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
-                vrFlingerRequestDisplayCallback);
+        mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
+                                            getHwComposer()
+                                                    .getHwcDisplayId(display->getId())
+                                                    .value_or(0),
+                                            vrFlingerRequestDisplayCallback);
         if (!mVrFlinger) {
             ALOGE("Failed to start vrflinger");
         }
@@ -720,8 +724,8 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
-    mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
-            Dataspace::SRGB_LINEAR);
+    mLegacySrgbSaturationMatrix =
+            getHwComposer().getDataspaceSaturationMatrix(display->getId(), Dataspace::SRGB_LINEAR);
 
     ALOGV("Done initializing");
 }
@@ -1207,7 +1211,6 @@
     Mutex::Autolock _l(mHWVsyncLock);
     if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
         mPrimaryDispSync.beginResync();
-        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
         mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
     }
@@ -1224,7 +1227,12 @@
         return;
     }
 
-    const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const auto displayId = DisplayDevice::DISPLAY_PRIMARY;
+    if (!getHwComposer().isConnected(displayId)) {
+        return;
+    }
+
+    const auto activeConfig = getHwComposer().getActiveConfig(displayId);
     const nsecs_t period = activeConfig->getVsyncPeriod();
 
     mPrimaryDispSync.reset();
@@ -1232,7 +1240,6 @@
 
     if (!mPrimaryHWVsyncEnabled) {
         mPrimaryDispSync.beginResync();
-        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
         mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
     }
@@ -1241,7 +1248,6 @@
 void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
     Mutex::Autolock _l(mHWVsyncLock);
     if (mPrimaryHWVsyncEnabled) {
-        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
         mEventControlThread->setVsyncEnabled(false);
         mPrimaryDispSync.endResync();
         mPrimaryHWVsyncEnabled = false;
@@ -1263,8 +1269,8 @@
     sLastResyncAttempted = now;
 }
 
-void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
-        hwc2_display_t displayId, int64_t timestamp) {
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
+                                     int64_t timestamp) {
     Mutex::Autolock lock(mStateLock);
     // Ignore any vsyncs from a previous hardware composer.
     if (sequenceId != getBE().mComposerSequenceId) {
@@ -1272,7 +1278,7 @@
     }
 
     int32_t type;
-    if (!getBE().mHwc->onVsync(displayId, timestamp, &type)) {
+    if (!getBE().mHwc->onVsync(hwcDisplayId, timestamp, &type)) {
         return;
     }
 
@@ -1297,9 +1303,9 @@
     *compositorTiming = getBE().mCompositorTiming;
 }
 
-void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
                                        HWC2::Connection connection) {
-    ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display,
+    ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
           connection == HWC2::Connection::Connected ? "connected" : "disconnected");
 
     // Ignore events that do not have the right sequenceId.
@@ -1313,7 +1319,7 @@
     // acquire it here.
     ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
 
-    mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection});
+    mPendingHotplugEvents.emplace_back(HotplugEvent{hwcDisplayId, connection});
 
     if (std::this_thread::get_id() == mMainThreadId) {
         // Process all pending hot plug events immediately if we are on the main thread.
@@ -1323,8 +1329,7 @@
     setTransactionFlags(eDisplayTransactionNeeded);
 }
 
-void SurfaceFlinger::onRefreshReceived(int sequenceId,
-                                       hwc2_display_t /*display*/) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
     Mutex::Autolock lock(mStateLock);
     if (sequenceId != getBE().mComposerSequenceId) {
         return;
@@ -1369,7 +1374,9 @@
 
     Mutex::Autolock _l(mStateLock);
 
-    int currentDisplayPowerMode = getDefaultDisplayDeviceLocked()->getPowerMode();
+    const auto display = getDefaultDisplayDeviceLocked();
+    LOG_ALWAYS_FATAL_IF(!display);
+    const int currentDisplayPowerMode = display->getPowerMode();
 
     if (!vrFlingerRequestsDisplay) {
         mVrFlinger->SeizeDisplayOwnership();
@@ -1394,11 +1401,10 @@
     invalidateHwcGeometry();
 
     // Re-enable default display.
-    setPowerModeInternal(getDefaultDisplayDeviceLocked(), currentDisplayPowerMode,
-                         /*stateLockHeld*/ true);
+    setPowerModeInternal(display, currentDisplayPowerMode, /*stateLockHeld*/ true);
 
     // Reset the timing values to account for the period of the swapped in HWC
-    const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const auto activeConfig = getHwComposer().getActiveConfig(display->getId());
     const nsecs_t period = activeConfig->getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(period);
 
@@ -1481,8 +1487,6 @@
     doComposition();
     postComposition(refreshStartTime);
 
-    mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
-
     mHadClientComposition = false;
     for (const auto& [token, display] : mDisplays) {
         mHadClientComposition = mHadClientComposition ||
@@ -1649,7 +1653,7 @@
 
     getBE().mGlCompositionDoneTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
-    if (display && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
+    if (display && getHwComposer().hasClientComposition(display->getId())) {
         glCompositionDoneFenceTime =
                 std::make_shared<FenceTime>(display->getClientTargetAcquireFence());
         getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
@@ -1658,8 +1662,9 @@
     }
 
     getBE().mDisplayTimeline.updateSignalTimes();
-    sp<Fence> presentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
-    auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
+    mPreviousPresentFence =
+            display ? getHwComposer().getPresentFence(display->getId()) : Fence::NO_FENCE;
+    auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
     nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
@@ -1694,7 +1699,7 @@
     }
 
     if (!hasSyncFramework) {
-        if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && display->isPoweredOn()) {
+        if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) {
             enableHardwareVsync();
         }
     }
@@ -1705,11 +1710,10 @@
         if (presentFenceTime->isValid()) {
             mAnimFrameTracker.setActualPresentFence(
                     std::move(presentFenceTime));
-        } else if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
+        } else if (display && getHwComposer().isConnected(display->getId())) {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
-            nsecs_t presentTime =
-                    getBE().mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
+            const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(display->getId());
             mAnimFrameTracker.setActualPresentTime(presentTime);
         }
         mAnimFrameTracker.advanceFrame();
@@ -1720,7 +1724,7 @@
         mTimeStats.incrementClientCompositionFrames();
     }
 
-    if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) &&
+    if (display && getHwComposer().isConnected(display->getId()) &&
         display->getPowerMode() == HWC_POWER_MODE_OFF) {
         return;
     }
@@ -2070,8 +2074,9 @@
     mDebugInSwapBuffers = 0;
 
     // |mStateLock| not needed as we are on the main thread
-    if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
-        uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
+    const auto display = getDefaultDisplayDeviceLocked();
+    if (display && getHwComposer().isConnected(display->getId())) {
+        const uint32_t flipCount = display->getPageFlipCount();
         if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
             logFrameStats();
         }
@@ -2135,9 +2140,9 @@
 
 void SurfaceFlinger::processDisplayHotplugEventsLocked() {
     for (const auto& event : mPendingHotplugEvents) {
-        auto displayType = determineDisplayType(event.display, event.connection);
+        auto displayType = determineDisplayType(event.hwcDisplayId, event.connection);
         if (displayType == DisplayDevice::DISPLAY_ID_INVALID) {
-            ALOGW("Unable to determine the display type for display %" PRIu64, event.display);
+            ALOGW("Unable to determine the display type for display %" PRIu64, event.hwcDisplayId);
             continue;
         }
 
@@ -2147,9 +2152,9 @@
         }
 
         const auto displayId =
-                getBE().mHwc->onHotplug(event.display, displayType, event.connection);
+                getBE().mHwc->onHotplug(event.hwcDisplayId, displayType, event.connection);
         if (displayId) {
-            ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.display, *displayId);
+            ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.hwcDisplayId, *displayId);
         }
 
         if (event.connection == HWC2::Connection::Connected) {
@@ -2294,8 +2299,11 @@
                 if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
                     display->disconnect(getHwComposer());
                 }
-                if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
-                    mEventThread->onHotplugReceived(draw[i].type, false);
+                if (draw[i].type == DisplayDevice::DISPLAY_PRIMARY) {
+                    mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
+                } else if (draw[i].type == DisplayDevice::DISPLAY_EXTERNAL) {
+                    mEventThread->onHotplugReceived(EventThread::DisplayType::External, false);
+                }
                 mDisplays.erase(draw.keyAt(i));
             } else {
                 // this display is in both lists. see if something changed.
@@ -2396,7 +2404,13 @@
                                       setupNewDisplayDeviceInternal(displayToken, displayId, state,
                                                                     dispSurface, producer));
                     if (!state.isVirtual()) {
-                        mEventThread->onHotplugReceived(state.type, true);
+                        if (state.type == DisplayDevice::DISPLAY_PRIMARY) {
+                            mEventThread->onHotplugReceived(EventThread::DisplayType::Primary,
+                                                            true);
+                        } else if (state.type == DisplayDevice::DISPLAY_EXTERNAL) {
+                            mEventThread->onHotplugReceived(EventThread::DisplayType::External,
+                                                            true);
+                        }
                     }
                 }
             }
@@ -2845,8 +2859,9 @@
             getRenderEngine().resetCurrentSurface();
 
             // |mStateLock| not needed as we are on the main thread
-            if(!getDefaultDisplayDeviceLocked()->makeCurrent()) {
-              ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
+            const auto defaultDisplay = getDefaultDisplayDeviceLocked();
+            if (!defaultDisplay || !defaultDisplay->makeCurrent()) {
+                ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
             }
             return false;
         }
@@ -3190,53 +3205,51 @@
     }
 }
 
-uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
-{
-    ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
-    if (dpyIdx < 0)
-        return 0;
+uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) {
+    const ssize_t index = mCurrentState.displays.indexOfKey(s.token);
+    if (index < 0) return 0;
 
     uint32_t flags = 0;
-    DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
-    if (disp.isValid()) {
-        const uint32_t what = s.what;
-        if (what & DisplayState::eSurfaceChanged) {
-            if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
-                disp.surface = s.surface;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-        if (what & DisplayState::eLayerStackChanged) {
-            if (disp.layerStack != s.layerStack) {
-                disp.layerStack = s.layerStack;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-        if (what & DisplayState::eDisplayProjectionChanged) {
-            if (disp.orientation != s.orientation) {
-                disp.orientation = s.orientation;
-                flags |= eDisplayTransactionNeeded;
-            }
-            if (disp.frame != s.frame) {
-                disp.frame = s.frame;
-                flags |= eDisplayTransactionNeeded;
-            }
-            if (disp.viewport != s.viewport) {
-                disp.viewport = s.viewport;
-                flags |= eDisplayTransactionNeeded;
-            }
-        }
-        if (what & DisplayState::eDisplaySizeChanged) {
-            if (disp.width != s.width) {
-                disp.width = s.width;
-                flags |= eDisplayTransactionNeeded;
-            }
-            if (disp.height != s.height) {
-                disp.height = s.height;
-                flags |= eDisplayTransactionNeeded;
-            }
+    DisplayDeviceState& state = mCurrentState.displays.editValueAt(index);
+
+    const uint32_t what = s.what;
+    if (what & DisplayState::eSurfaceChanged) {
+        if (IInterface::asBinder(state.surface) != IInterface::asBinder(s.surface)) {
+            state.surface = s.surface;
+            flags |= eDisplayTransactionNeeded;
         }
     }
+    if (what & DisplayState::eLayerStackChanged) {
+        if (state.layerStack != s.layerStack) {
+            state.layerStack = s.layerStack;
+            flags |= eDisplayTransactionNeeded;
+        }
+    }
+    if (what & DisplayState::eDisplayProjectionChanged) {
+        if (state.orientation != s.orientation) {
+            state.orientation = s.orientation;
+            flags |= eDisplayTransactionNeeded;
+        }
+        if (state.frame != s.frame) {
+            state.frame = s.frame;
+            flags |= eDisplayTransactionNeeded;
+        }
+        if (state.viewport != s.viewport) {
+            state.viewport = s.viewport;
+            flags |= eDisplayTransactionNeeded;
+        }
+    }
+    if (what & DisplayState::eDisplaySizeChanged) {
+        if (state.width != s.width) {
+            state.width = s.width;
+            flags |= eDisplayTransactionNeeded;
+        }
+        if (state.height != s.height) {
+            state.height = s.height;
+            flags |= eDisplayTransactionNeeded;
+        }
+    }
+
     return flags;
 }
 
@@ -3570,13 +3583,16 @@
 // ---------------------------------------------------------------------------
 
 void SurfaceFlinger::onInitializeDisplays() {
+    const auto displayToken = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY];
+    if (!displayToken) return;
+
     // reset screen orientation and use primary layer stack
     Vector<ComposerState> state;
     Vector<DisplayState> displays;
     DisplayState d;
     d.what = DisplayState::eDisplayProjectionChanged |
              DisplayState::eLayerStackChanged;
-    d.token = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY];
+    d.token = displayToken;
     d.layerStack = 0;
     d.orientation = DisplayState::eOrientationDefault;
     d.frame.makeInvalid();
@@ -3585,10 +3601,13 @@
     d.height = 0;
     displays.add(d);
     setTransactionState(state, displays, 0);
-    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL,
-                         /*stateLockHeld*/ false);
 
-    const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const auto display = getDisplayDevice(displayToken);
+    if (!display) return;
+
+    setPowerModeInternal(display, HWC_POWER_MODE_NORMAL, /*stateLockHeld*/ false);
+
+    const auto activeConfig = getHwComposer().getActiveConfig(display->getId());
     const nsecs_t period = activeConfig->getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(period);
 
@@ -3859,9 +3878,12 @@
         index++;
     }
 
-    const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
-    const nsecs_t period = activeConfig->getVsyncPeriod();
-    result.appendFormat("%" PRId64 "\n", period);
+    if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY;
+        getHwComposer().isConnected(displayId)) {
+        const auto activeConfig = getBE().mHwc->getActiveConfig(displayId);
+        const nsecs_t period = activeConfig->getVsyncPeriod();
+        result.appendFormat("%" PRId64 "\n", period);
+    }
 
     if (name.isEmpty()) {
         mAnimFrameTracker.dumpStats(result);
@@ -4142,15 +4164,20 @@
     result.append(SyncFeatures::getInstance().toString());
     result.append("\n");
 
-    const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
-
     colorizer.bold(result);
-    result.append("DispSync configuration: ");
+    result.append("DispSync configuration:\n");
     colorizer.reset(result);
-    result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64
-        " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
-        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(),
-        dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
+
+    if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY;
+        getHwComposer().isConnected(displayId)) {
+        const auto activeConfig = getHwComposer().getActiveConfig(displayId);
+        result.appendFormat("Display %d: app phase %" PRId64 " ns, sf phase %" PRId64
+                            " ns, early sf phase %" PRId64 " ns, present offset %" PRId64
+                            " ns (refresh %" PRId64 " ns)",
+                            displayId, vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
+                            mVsyncModulator.getEarlyPhaseOffset(), dispSyncPresentTimeOffset,
+                            activeConfig->getVsyncPeriod());
+    }
     result.append("\n");
 
     // Dump static screen stats
@@ -4206,22 +4233,21 @@
         result.appendFormat("  orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
                             display->isPoweredOn());
     }
-    result.appendFormat(
-            "  last eglSwapBuffers() time: %f us\n"
-            "  last transaction time     : %f us\n"
-            "  transaction-flags         : %08x\n"
-            "  refresh-rate              : %f fps\n"
-            "  x-dpi                     : %f\n"
-            "  y-dpi                     : %f\n"
-            "  gpu_to_cpu_unsupported    : %d\n"
-            ,
-            mLastSwapBufferTime/1000.0,
-            mLastTransactionTime/1000.0,
-            mTransactionFlags,
-            1e9 / activeConfig->getVsyncPeriod(),
-            activeConfig->getDpiX(),
-            activeConfig->getDpiY(),
-            !mGpuToCpuSupported);
+    result.appendFormat("  last eglSwapBuffers() time: %f us\n"
+                        "  last transaction time     : %f us\n"
+                        "  transaction-flags         : %08x\n"
+                        "  gpu_to_cpu_unsupported    : %d\n",
+                        mLastSwapBufferTime / 1000.0, mLastTransactionTime / 1000.0,
+                        mTransactionFlags, !mGpuToCpuSupported);
+
+    if (display) {
+        const auto activeConfig = getHwComposer().getActiveConfig(display->getId());
+        result.appendFormat("  refresh-rate              : %f fps\n"
+                            "  x-dpi                     : %f\n"
+                            "  y-dpi                     : %f\n",
+                            1e9 / activeConfig->getVsyncPeriod(), activeConfig->getDpiX(),
+                            activeConfig->getDpiY());
+    }
 
     result.appendFormat("  eglSwapBuffers time: %f us\n",
             inSwapBuffersDuration/1000.0);
@@ -4279,19 +4305,15 @@
 
 const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t displayId) {
     // Note: mStateLock is held here
-    wp<IBinder> displayToken;
     for (const auto& [token, display] : mDisplays) {
         if (display->getId() == displayId) {
-            displayToken = token;
-            break;
+            return getDisplayDeviceLocked(token)->getVisibleLayersSortedByZ();
         }
     }
-    if (displayToken == nullptr) {
-        ALOGE("getLayerSortedByZForHwcDisplay: Invalid display %d", displayId);
-        // Just use the primary display so we have something to return
-        displayToken = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
-    }
-    return getDisplayDeviceLocked(displayToken)->getVisibleLayersSortedByZ();
+
+    ALOGE("%s: Invalid display %d", __FUNCTION__, displayId);
+    static const Vector<sp<Layer>> empty;
+    return empty;
 }
 
 bool SurfaceFlinger::startDdmConnection()
@@ -4466,6 +4488,10 @@
                 return NO_ERROR;
             case 1013: {
                 const auto display = getDefaultDisplayDevice();
+                if (!display) {
+                    return NAME_NOT_FOUND;
+                }
+
                 reply->writeInt32(display->getPageFlipCount());
                 return NO_ERROR;
             }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 48c3f73..87e0699 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -457,11 +457,11 @@
     /* ------------------------------------------------------------------------
      * HWC2::ComposerCallback / HWComposer::EventHandler interface
      */
-    void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+    void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
                          int64_t timestamp) override;
-    void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+    void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
                            HWC2::Connection connection) override;
-    void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
+    void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override;
 
     /* ------------------------------------------------------------------------
      * Message handling
@@ -665,8 +665,7 @@
     void logLayerStats();
     void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
 
-    // compose surfaces for display hw. this fails if using GL and the surface
-    // has been destroyed and is no longer valid.
+    // This fails if using GL and the surface has been destroyed.
     bool doComposeSurfaces(const sp<const DisplayDevice>& display);
 
     void postFramebuffer();
@@ -675,8 +674,8 @@
     /* ------------------------------------------------------------------------
      * Display management
      */
-    DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display,
-            HWC2::Connection connection) const;
+    DisplayDevice::DisplayType determineDisplayType(hwc2_display_t hwcDisplayId,
+                                                    HWC2::Connection connection) const;
     sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken,
                                                     int32_t displayId,
                                                     const DisplayDeviceState& state,
@@ -802,7 +801,7 @@
     bool mHadClientComposition = false;
 
     struct HotplugEvent {
-        hwc2_display_t display;
+        hwc2_display_t hwcDisplayId;
         HWC2::Connection connection = HWC2::Connection::Invalid;
     };
     // protected by mStateLock
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 1a7805a..3be2ad0 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -245,6 +245,8 @@
 
     // The type for this display
     static constexpr DisplayDevice::DisplayType TYPE = type;
+    static_assert(TYPE != DisplayDevice::DISPLAY_ID_INVALID);
+
     static constexpr DisplayDevice::DisplayType DISPLAY_ID = displayId;
 
     // When creating native window surfaces for the framebuffer, whether those should be critical
@@ -385,11 +387,6 @@
                                  DisplayVariant<type, type, width, height, critical, Async::FALSE,
                                                 Secure::TRUE, GRALLOC_USAGE_PHYSICAL_DISPLAY>> {};
 
-// An invalid display
-using InvalidDisplayVariant =
-        DisplayVariant<DisplayDevice::DISPLAY_ID_INVALID, DisplayDevice::DISPLAY_ID_INVALID, 0, 0,
-                       Critical::FALSE, Async::FALSE, Secure::FALSE, 0>;
-
 // A primary display is a physical display that is critical
 using PrimaryDisplayVariant =
         PhysicalDisplayVariant<1001, DisplayDevice::DISPLAY_PRIMARY, 3840, 2160, Critical::TRUE>;
@@ -686,9 +683,7 @@
         Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
              HdrNotSupportedVariant<PrimaryDisplayVariant>,
              Cta861_3_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using InvalidDisplayCase = Case<InvalidDisplayVariant, WideColorSupportNotConfiguredVariant,
-                                NonHwcDisplayHdrSupportVariant,
-                                NoPerFrameMetadataSupportVariant<InvalidDisplayVariant>>;
+
 /* ------------------------------------------------------------------------
  *
  * SurfaceFlinger::onHotplugReceived
@@ -696,8 +691,8 @@
 
 TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) {
     constexpr int currentSequenceId = 123;
-    constexpr hwc2_display_t displayId1 = 456;
-    constexpr hwc2_display_t displayId2 = 654;
+    constexpr hwc2_display_t hwcDisplayId1 = 456;
+    constexpr hwc2_display_t hwcDisplayId2 = 654;
 
     // --------------------------------------------------------------------
     // Preconditions
@@ -720,8 +715,8 @@
     // Invocation
 
     // Simulate two hotplug events (a connect and a disconnect)
-    mFlinger.onHotplugReceived(currentSequenceId, displayId1, HWC2::Connection::Connected);
-    mFlinger.onHotplugReceived(currentSequenceId, displayId2, HWC2::Connection::Disconnected);
+    mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, HWC2::Connection::Connected);
+    mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, HWC2::Connection::Disconnected);
 
     // --------------------------------------------------------------------
     // Postconditions
@@ -732,9 +727,9 @@
     // All events should be in the pending event queue.
     const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
     ASSERT_EQ(2u, pendingEvents.size());
-    EXPECT_EQ(displayId1, pendingEvents[0].display);
+    EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
     EXPECT_EQ(HWC2::Connection::Connected, pendingEvents[0].connection);
-    EXPECT_EQ(displayId2, pendingEvents[1].display);
+    EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
     EXPECT_EQ(HWC2::Connection::Disconnected, pendingEvents[1].connection);
 }
 
@@ -1165,13 +1160,23 @@
     Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
 
     EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
-    EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::TYPE, true)).Times(1);
+    EXPECT_CALL(*mEventThread,
+                onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY
+                                          ? EventThread::DisplayType::Primary
+                                          : EventThread::DisplayType::External,
+                                  true))
+            .Times(1);
 }
 
 template <typename Case>
 void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() {
     EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
-    EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::TYPE, false)).Times(1);
+    EXPECT_CALL(*mEventThread,
+                onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY
+                                          ? EventThread::DisplayType::Primary
+                                          : EventThread::DisplayType::External,
+                                  false))
+            .Times(1);
 }
 
 template <typename Case>
@@ -1824,40 +1829,6 @@
     EXPECT_FALSE(hasCurrentDisplayState(displayToken));
 }
 
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWithInvalidDisplay) {
-    using Case = InvalidDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // An invalid display is set up
-    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
-    display.inject();
-
-    // The invalid display has some state
-    display.mutableCurrentDisplayState().layerStack = 654u;
-
-    // The requested display state tries to change the display state.
-    DisplayState state;
-    state.what = DisplayState::eLayerStackChanged;
-    state.token = display.token();
-    state.layerStack = 456;
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // The returned flags are empty
-    EXPECT_EQ(0u, flags);
-
-    // The current display layer stack value is unchanged.
-    EXPECT_EQ(654u, getCurrentDisplayState(display.token()).layerStack);
-}
-
 TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWhenNoChanges) {
     using Case = SimplePrimaryDisplayCase;
 
@@ -2684,7 +2655,7 @@
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.inject();
 
-    // The diplay is already set to HWC_POWER_MODE_NORMAL
+    // The display is already set to HWC_POWER_MODE_NORMAL
     display.mutableDisplayDevice()->setPowerMode(HWC_POWER_MODE_NORMAL);
 
     // --------------------------------------------------------------------
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 80fdb80..19747bd 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -71,7 +71,8 @@
                                               ConnectionEventRecorder& connectionEventRecorder,
                                               nsecs_t expectedTimestamp, unsigned expectedCount);
     void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
-    void expectHotplugEventReceivedByConnection(int expectedDisplayType, bool expectedConnected);
+    void expectHotplugEventReceivedByConnection(EventThread::DisplayType expectedDisplayType,
+                                                bool expectedConnected);
 
     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
@@ -169,13 +170,16 @@
                                          expectedCount);
 }
 
-void EventThreadTest::expectHotplugEventReceivedByConnection(int expectedDisplayType,
-                                                             bool expectedConnected) {
+void EventThreadTest::expectHotplugEventReceivedByConnection(
+        EventThread::DisplayType expectedDisplayType, bool expectedConnected) {
+    const uint32_t expectedDisplayId =
+            expectedDisplayType == EventThread::DisplayType::Primary ? 0 : 1;
+
     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(static_cast<unsigned>(expectedDisplayType), event.header.id);
+    EXPECT_EQ(expectedDisplayId, event.header.id);
     EXPECT_EQ(expectedConnected, event.hotplug.connected);
 }
 
@@ -394,28 +398,23 @@
 }
 
 TEST_F(EventThreadTest, postHotplugPrimaryDisconnect) {
-    mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, false);
-    expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, false);
+    mThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
+    expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, false);
 }
 
 TEST_F(EventThreadTest, postHotplugPrimaryConnect) {
-    mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true);
-    expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, true);
+    mThread->onHotplugReceived(EventThread::DisplayType::Primary, true);
+    expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, true);
 }
 
 TEST_F(EventThreadTest, postHotplugExternalDisconnect) {
-    mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, false);
-    expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, false);
+    mThread->onHotplugReceived(EventThread::DisplayType::External, false);
+    expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, false);
 }
 
 TEST_F(EventThreadTest, postHotplugExternalConnect) {
-    mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, true);
-    expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, true);
-}
-
-TEST_F(EventThreadTest, postHotplugVirtualDisconnectIsFilteredOut) {
-    mThread->onHotplugReceived(DisplayDevice::DISPLAY_VIRTUAL, false);
-    EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
+    mThread->onHotplugReceived(EventThread::DisplayType::External, true);
+    expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, true);
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 5dcac92..ae5a100 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -91,8 +91,9 @@
 
     auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); }
 
-    auto setPowerModeInternal(const sp<DisplayDevice>& hw, int mode, bool stateLockHeld = false) {
-        return mFlinger->setPowerModeInternal(hw, mode, stateLockHeld);
+    auto setPowerModeInternal(const sp<DisplayDevice>& display, int mode,
+                              bool stateLockHeld = false) {
+        return mFlinger->setPowerModeInternal(display, mode, stateLockHeld);
     }
 
     /* ------------------------------------------------------------------------
@@ -232,7 +233,7 @@
             display->mutableIsConnected() = true;
 
             ASSERT_TRUE(flinger->mutableHwcDisplayData().size() > static_cast<size_t>(mType));
-            flinger->mutableHwcDisplayData()[mType].reset();
+            flinger->mutableHwcDisplayData()[mType] = HWComposer::DisplayData();
             flinger->mutableHwcDisplayData()[mType].hwcDisplay = display.get();
             flinger->mutableHwcDisplaySlots().emplace(mHwcDisplayId, mType);
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index e6ea663..df9bfc6 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -31,7 +31,7 @@
     MOCK_CONST_METHOD0(createEventConnection, sp<BnDisplayEventConnection>());
     MOCK_METHOD0(onScreenReleased, void());
     MOCK_METHOD0(onScreenAcquired, void());
-    MOCK_METHOD2(onHotplugReceived, void(int, bool));
+    MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool));
     MOCK_CONST_METHOD1(dump, void(String8&));
     MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset));
 };
diff --git a/services/vr/performanced/directory_reader.h b/services/vr/performanced/directory_reader.h
index b9d27c3..f8359c4 100644
--- a/services/vr/performanced/directory_reader.h
+++ b/services/vr/performanced/directory_reader.h
@@ -16,10 +16,11 @@
 class DirectoryReader {
  public:
   explicit DirectoryReader(base::unique_fd directory_fd) {
-    directory_ = fdopendir(directory_fd.get());
+    int fd = directory_fd.release();
+    directory_ = fdopendir(fd);
     error_ = errno;
-    if (directory_ != nullptr)
-      (void) directory_fd.release(); // ignore return result?
+    if (directory_ == nullptr)
+      close(fd);
   }
 
   ~DirectoryReader() {