summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp95
1 files changed, 95 insertions, 0 deletions
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;