Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e011d07 authored by qinyige1's avatar qinyige1 Committed by Vishnu Nair
Browse files

Adapt addClientLayer to LayerHierarchy.

Method addClientLayer still traverses mDrawingState, which is not
adapted after LayerLifecycleManager enabled. Dump info through
LayerHierarchyBuilder.

Flag: EXEMPT bugfix
Bug: 341641452
Test: Manual
Change-Id: I781696548138dfcb1ec3e463a32ae5b399f10eac
parent 438a0acc
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#undef LOG_TAG
#define LOG_TAG "SurfaceFlinger"

#include <android-base/logging.h>

#include "LayerHierarchy.h"
#include "LayerLog.h"
#include "SwapErase.h"
@@ -485,6 +487,55 @@ LayerHierarchy* LayerHierarchyBuilder::getHierarchyFromId(uint32_t layerId, bool
    return it->second;
}

void LayerHierarchyBuilder::logSampledChildren(const LayerHierarchy& hierarchy) const {
    LOG(ERROR) << "Dumping random sampling of child layers.";
    int sampleSize = static_cast<int>(hierarchy.mChildren.size() / 100 + 1);
    for (const auto& [child, variant] : hierarchy.mChildren) {
        if (rand() % sampleSize == 0) {
            LOG(ERROR) << "Child Layer: " << *(child->mLayer);
        }
    }
}

void LayerHierarchyBuilder::dumpLayerSample(const LayerHierarchy& root) const {
    LOG(ERROR) << "Dumping layer keeping > 20 children alive:";
    // If mLayer is nullptr, it will be skipped while traversing.
    if (!root.mLayer && root.mChildren.size() > 20) {
        LOG(ERROR) << "ROOT has " << root.mChildren.size() << " children";
        logSampledChildren(root);
    }
    root.traverse([&](const LayerHierarchy& hierarchy, const auto&) -> bool {
        if (hierarchy.mChildren.size() <= 20) {
            return true;
        }
        // mLayer is ensured to be non-null. See LayerHierarchy::traverse.
        const auto* layer = hierarchy.mLayer;
        const auto childrenCount = hierarchy.mChildren.size();
        LOG(ERROR) << "Layer " << *layer << " has " << childrenCount << " children";

        const auto* parent = hierarchy.mParent;
        while (parent != nullptr) {
            if (!parent->mLayer) break;
            LOG(ERROR) << "Parent Layer: " << *(parent->mLayer);
            parent = parent->mParent;
        }

        logSampledChildren(hierarchy);
        // Stop traversing.
        return false;
    });
    LOG(ERROR) << "Dumping random sampled layers.";
    size_t numLayers = 0;
    root.traverse([&](const LayerHierarchy& hierarchy, const auto&) -> bool {
        if (hierarchy.mLayer) numLayers++;
        if ((rand() % 20 == 13) && hierarchy.mLayer) {
            LOG(ERROR) << "Layer: " << *(hierarchy.mLayer);
        }
        return true;
    });
    LOG(ERROR) << "Total layer count: " << numLayers;
}

const LayerHierarchy::TraversalPath LayerHierarchy::TraversalPath::ROOT =
        {.id = UNASSIGNED_LAYER_ID, .variant = LayerHierarchy::Attached};

+3 −0
Original line number Diff line number Diff line
@@ -211,8 +211,11 @@ public:
    const LayerHierarchy& getHierarchy() const;
    const LayerHierarchy& getOffscreenHierarchy() const;
    std::string getDebugString(uint32_t layerId, uint32_t depth = 0) const;
    void dumpLayerSample(const LayerHierarchy& layerHierarchy) const;

private:
    void logSampledChildren(const LayerHierarchy& hierarchy) const;

    void onLayerAdded(RequestedLayerState* layer);
    void attachToParent(LayerHierarchy*);
    void detachFromParent(LayerHierarchy*);
+14 −52
Original line number Diff line number Diff line
@@ -4473,60 +4473,22 @@ status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinde
                                        const sp<Layer>& layer, const wp<Layer>& parent,
                                        uint32_t* outTransformHint) {
    if (mNumLayers >= MAX_LAYERS) {
        ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
              MAX_LAYERS);
        static_cast<void>(mScheduler->schedule([=, this] {
            ALOGE("Dumping layer keeping > 20 children alive:");
            bool leakingParentLayerFound = false;
            mDrawingState.traverse([&](Layer* layer) {
                if (leakingParentLayerFound) {
                    return;
                }
                if (layer->getChildrenCount() > 20) {
                    leakingParentLayerFound = true;
                    sp<Layer> parent = sp<Layer>::fromExisting(layer);
                    while (parent) {
                        ALOGE("Parent Layer: %s%s", parent->getName().c_str(),
                              (parent->isHandleAlive() ? "handleAlive" : ""));
                        parent = parent->getParent();
                    }
                    // Sample up to 100 layers
                    ALOGE("Dumping random sampling of child layers total(%zu): ",
                          layer->getChildrenCount());
                    int sampleSize = (layer->getChildrenCount() / 100) + 1;
                    layer->traverseChildren([&](Layer* layer) {
                        if (rand() % sampleSize == 0) {
                            ALOGE("Child Layer: %s%s", layer->getName().c_str(),
                                  (layer->isHandleAlive() ? "handleAlive" : ""));
                        }
                    });
        static std::atomic<nsecs_t> lasttime{0};
        nsecs_t now = systemTime();
        if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
            ALOGE("AddClientLayer already dumped 10s before");
            return NO_MEMORY;
        } else {
            lasttime = now;
        }
            });

            int numLayers = 0;
            mDrawingState.traverse([&](Layer* layer) { numLayers++; });

            ALOGE("Dumping random sampling of on-screen layers total(%u):", numLayers);
            mDrawingState.traverse([&](Layer* layer) {
                // Aim to dump about 200 layers to avoid totally trashing
                // logcat. On the other hand, if there really are 4096 layers
                // something has gone totally wrong its probably the most
                // useful information in logcat.
                if (rand() % 20 == 13) {
                    ALOGE("Layer: %s%s", layer->getName().c_str(),
                          (layer->isHandleAlive() ? "handleAlive" : ""));
                    std::this_thread::sleep_for(std::chrono::milliseconds(5));
                }
            });
            ALOGE("Dumping random sampling of off-screen layers total(%zu): ",
                  mOffscreenLayers.size());
            for (Layer* offscreenLayer : mOffscreenLayers) {
                if (rand() % 20 == 13) {
                    ALOGE("Offscreen-layer: %s%s", offscreenLayer->getName().c_str(),
                          (offscreenLayer->isHandleAlive() ? "handleAlive" : ""));
                    std::this_thread::sleep_for(std::chrono::milliseconds(5));
                }
            }
        ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
              MAX_LAYERS);
        static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
            ALOGE("Dumping on-screen layers.");
            mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
            ALOGE("Dumping off-screen layers.");
            mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
        }));
        return NO_MEMORY;
    }