diff options
| author | 2024-05-23 15:59:08 +0800 | |
|---|---|---|
| committer | 2024-08-15 11:38:40 +0000 | |
| commit | 0e011d0729ca3ada4c2954c603f8ed6162591a6e (patch) | |
| tree | 5d60c6a5def5d2dabf4fd36f66180c7a702762a3 | |
| parent | 438a0acc763691fa6f4c2a9eba287b4aeeb2b426 (diff) | |
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
| -rw-r--r-- | services/surfaceflinger/FrontEnd/LayerHierarchy.cpp | 51 | ||||
| -rw-r--r-- | services/surfaceflinger/FrontEnd/LayerHierarchy.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 66 |
3 files changed, 68 insertions, 52 deletions
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index f4335f36bc..d709530990 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -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}; diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index d023f9e9f5..47d0041a8b 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -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*); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9eca01a453..09fe52def6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -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) { + 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; + } + 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" : "")); - } - }); - } - }); - - 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)); - } - } + 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; } |