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
This commit is contained in:
Dan Stoza 2015-01-16 14:13:46 -08:00
parent 457731f69e
commit 03eccb6616
2 changed files with 98 additions and 1 deletions

View File

@ -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)
###############################################################

View File

@ -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;