From 5450fe526801ff9f5b05487995745a146dc5150b Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Wed, 13 Jul 2016 15:48:58 -0700 Subject: [PATCH] HWC2: Fix virtual displays Close the output buffer release fence per the contract in hwcomposer2.h. Also changes the HWC2 device to hold a weak pointer to the display, which allows it to properly remove it when it gets torn down. Test: Cherry-pick from internal branch Bug: 29945684 Change-Id: Ib1b5d81e42a63d0e65b189f7c6c62e661e0ab6ae --- services/surfaceflinger/DisplayHardware/HWC2.cpp | 18 ++++++++++++++++-- services/surfaceflinger/DisplayHardware/HWC2.h | 5 +++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index ed8cc08ff7..ae6ba98bd5 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -149,7 +149,12 @@ Device::~Device() } for (auto element : mDisplays) { - auto display = element.second; + auto display = element.second.lock(); + if (!display) { + ALOGE("~Device: Found a display (%" PRId64 " that has already been" + " destroyed", element.first); + continue; + } DisplayType displayType = HWC2::DisplayType::Invalid; auto error = display->getType(&displayType); @@ -208,6 +213,10 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height, ALOGI("Created virtual display"); *format = static_cast(intFormat); *outDisplay = getDisplayById(displayId); + if (!*outDisplay) { + ALOGE("Failed to get display by id"); + return Error::BadDisplay; + } (*outDisplay)->setVirtual(); return Error::None; } @@ -289,7 +298,10 @@ void Device::callVsync(std::shared_ptr display, nsecs_t timestamp) std::shared_ptr Device::getDisplayById(hwc2_display_t id) { if (mDisplays.count(id) != 0) { - return mDisplays.at(id); + auto strongDisplay = mDisplays[id].lock(); + ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no" + " longer alive", id); + return strongDisplay; } auto display = std::make_shared(*this, id); @@ -430,6 +442,7 @@ void Device::destroyVirtualDisplay(hwc2_display_t display) auto error = static_cast(intError); ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:" " %s (%d)", display, to_string(error).c_str(), intError); + mDisplays.erase(display); } // Display methods @@ -810,6 +823,7 @@ Error Display::setOutputBuffer(const sp& buffer, auto handle = buffer->getNativeBuffer()->handle; int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle, fenceFd); + close(fenceFd); return static_cast(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 1aa4205838..25a7d89c8c 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -88,7 +88,8 @@ public: // Other Device methods // This will create a Display if one is not found, but it will not be marked - // as connected + // as connected. This Display may be null if the display has been torn down + // but has not been removed from the map yet. std::shared_ptr getDisplayById(hwc2_display_t id); bool hasCapability(HWC2::Capability capability) const; @@ -181,7 +182,7 @@ private: HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder; std::vector mCapabilities; - std::unordered_map> mDisplays; + std::unordered_map> mDisplays; HotplugCallback mHotplug; std::vector, Connection>> -- 2.11.0