From 03eccb6616744c3789b6018680de7bf5a18f71ce Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Fri, 16 Jan 2015 14:13:46 -0800 Subject: [PATCH] SurfaceFlinger: Attempt to attribute fds to layers This tracks fds when layers are created and destroyed in an effort to determine which specific app (if any) is active when fds are leaked Bug: 19017008 Change-Id: I1f1d5a9cbc1399e3df3a2d350324f80b3a4e3477 --- services/surfaceflinger/Android.mk | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 95 ++++++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index eade2e221..af271b22c 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -90,7 +90,7 @@ else endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format -LOCAL_CFLAGS += -std=c++11 +LOCAL_CFLAGS += -std=c++1y LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -108,6 +108,8 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_MODULE:= libsurfaceflinger +include external/libcxx/libcxx.mk + include $(BUILD_SHARED_LIBRARY) ############################################################### diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 80d3cc2c3..828ba9dfc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -78,6 +78,12 @@ #include "RenderEngine/RenderEngine.h" #include +#include +#include +#include +#include +#include + #define DISPLAY_COUNT 1 /* @@ -1806,6 +1812,17 @@ void SurfaceFlinger::doDisplayComposition(const sp& hw, hw->swapBuffers(getHwComposer()); } +static std::set getOpenFds() +{ + std::set fds; + for (int fd = 0; fd < 1024; ++fd) { + if (fcntl(fd, F_GETFD) != -1 || errno != EBADF) { + fds.insert(fd); + } + } + return fds; +} + bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const Region& dirty) { RenderEngine& engine(getRenderEngine()); @@ -1880,6 +1897,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const * and then, render the layers targeted at the framebuffer */ + static std::set previousLayers; + std::set currentLayers; const Vector< sp >& layers(hw->getVisibleLayersSortedByZ()); const size_t count = layers.size(); const Transform& tr = hw->getTransform(); @@ -1889,6 +1908,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const const sp& layer(layers[i]); const Region clip(dirty.intersect(tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { + currentLayers.insert(layer->getName().string()); switch (cur->getCompositionType()) { case HWC_CURSOR_OVERLAY: case HWC_OVERLAY: { @@ -1924,11 +1944,86 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& hw, const const Region clip(dirty.intersect( tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { + currentLayers.insert(layer->getName().string()); layer->draw(hw, clip); } } } + std::set newLayers; + for (auto layer : currentLayers) { + if (previousLayers.count(layer) == 0) { + newLayers.insert(layer); + } + } + std::set deletedLayers; + for (auto layer : previousLayers) { + if (currentLayers.count(layer) == 0) { + deletedLayers.insert(layer); + } + } + previousLayers = std::move(currentLayers); + + static std::set previousFds; + static std::unordered_map> initialFds; + + for (auto layer : newLayers) { + initialFds[layer] = previousFds; + } + + std::set currentFds = getOpenFds(); + + if (!deletedLayers.empty()) { + std::unordered_map> currentBlame; + static std::map> persistentBlame; + for (auto layer : deletedLayers) { + std::vector newFds; + auto& layerInitialFds = initialFds[layer]; + std::set_difference( + currentFds.cbegin(), currentFds.cend(), + layerInitialFds.cbegin(), layerInitialFds.cend(), + std::back_inserter(newFds)); + + for (auto fd : newFds) { + currentBlame[fd].insert(layer); + } + + initialFds.erase(layer); + } + + for (auto blame : currentBlame) { + persistentBlame[blame.first] = blame.second; + } + + auto iter = persistentBlame.cbegin(); + while (iter != persistentBlame.cend()) { + if (currentFds.count(iter->first) == 0) { + iter = persistentBlame.erase(iter); + } else { + ++iter; + } + } + + std::map, int> blameCounts; + for (auto blame : persistentBlame) { + ++blameCounts[blame.second]; + } + + ALOGI("FD Blame: %d open fds", currentFds.size()); + for (auto blame : blameCounts) { + std::string layers; + for (auto layer : blame.first) { + if (!layers.empty()) { + layers += ", "; + } + layers += layer; + } + ALOGI(" %s: %d", layers.c_str(), blame.second); + } + } + + previousFds = std::move(currentFds); + // disable scissor at the end of the frame engine.disableScissor(); return true;