diff options
author | Dan Stoza <stoza@google.com> | 2015-01-16 14:13:46 -0800 |
---|---|---|
committer | The Android Automerger <android-build@google.com> | 2015-01-16 17:32:53 -0800 |
commit | 5fc19fde74c564c84dd10708b4cc33de145fd15d (patch) | |
tree | 268c60e6d3ede0734546fd8d4fc84b8a1ea030f0 | |
parent | c01fcaaeebc362b8aa2f7ecc652038c1b1df120f (diff) | |
download | native-5fc19fde74c564c84dd10708b4cc33de145fd15d.tar.gz |
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
-rw-r--r-- | services/surfaceflinger/Android.mk | 4 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 95 |
2 files changed, 98 insertions, 1 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index eade2e2210..af271b22c5 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 80d3cc2c32..828ba9dfc8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -78,6 +78,12 @@ #include "RenderEngine/RenderEngine.h" #include <cutils/compiler.h> +#include <map> +#include <set> +#include <string> +#include <unordered_map> +#include <vector> + #define DISPLAY_COUNT 1 /* @@ -1806,6 +1812,17 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, hw->swapBuffers(getHwComposer()); } +static std::set<int> getOpenFds() +{ + std::set<int> 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<const DisplayDevice>& hw, const Region& dirty) { RenderEngine& engine(getRenderEngine()); @@ -1880,6 +1897,8 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const * and then, render the layers targeted at the framebuffer */ + static std::set<std::string> previousLayers; + std::set<std::string> currentLayers; const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ()); const size_t count = layers.size(); const Transform& tr = hw->getTransform(); @@ -1889,6 +1908,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const const sp<Layer>& 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<const DisplayDevice>& 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<std::string> newLayers; + for (auto layer : currentLayers) { + if (previousLayers.count(layer) == 0) { + newLayers.insert(layer); + } + } + std::set<std::string> deletedLayers; + for (auto layer : previousLayers) { + if (currentLayers.count(layer) == 0) { + deletedLayers.insert(layer); + } + } + previousLayers = std::move(currentLayers); + + static std::set<int> previousFds; + static std::unordered_map<std::string, std::set<int>> initialFds; + + for (auto layer : newLayers) { + initialFds[layer] = previousFds; + } + + std::set<int> currentFds = getOpenFds(); + + if (!deletedLayers.empty()) { + std::unordered_map<int, std::set<std::string>> currentBlame; + static std::map<int, std::set<std::string>> persistentBlame; + for (auto layer : deletedLayers) { + std::vector<int> 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<std::set<std::string>, 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; |