summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Stoza <stoza@google.com>2015-01-16 14:13:46 -0800
committerDan Stoza <stoza@google.com>2015-01-16 15:02:22 -0800
commit03eccb6616744c3789b6018680de7bf5a18f71ce (patch)
tree268c60e6d3ede0734546fd8d4fc84b8a1ea030f0
parent457731f69e3106b5aae8fc04f9565af1d875876c (diff)
downloadframeworks_native-03eccb6616744c3789b6018680de7bf5a18f71ce.zip
frameworks_native-03eccb6616744c3789b6018680de7bf5a18f71ce.tar.gz
frameworks_native-03eccb6616744c3789b6018680de7bf5a18f71ce.tar.bz2
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.mk4
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp95
2 files changed, 98 insertions, 1 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index eade2e2..af271b2 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 80d3cc2..828ba9d 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;