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

Commit 3216919a authored by Vishnu Nair's avatar Vishnu Nair Committed by Android (Google) Code Review
Browse files

Merge "Fix deadlock when calling dumpsys surfaceflinger" into main

parents d28755ab d7ff85f5
Loading
Loading
Loading
Loading
+134 −161
Original line number Original line Diff line number Diff line
@@ -5952,20 +5952,22 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
            !PermissionCache::checkPermission(sDump, pid, uid)) {
            !PermissionCache::checkPermission(sDump, pid, uid)) {
        StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",
        StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                      pid, uid);
                      pid, uid);
    } else {
        write(fd, result.c_str(), result.size());
        Dumper hwclayersDump = [this](const DumpArgs&, bool, std::string& result)
        return NO_ERROR;
                                       FTL_FAKE_GUARD(mStateLock) -> void const {
    }
            if (mLayerLifecycleManagerEnabled) {

                mScheduler
    if (asProto && args.empty()) {
                        ->schedule([this, &result]() FTL_FAKE_GUARD(kMainThreadContext)
        perfetto::protos::LayersTraceFileProto traceFileProto =
                                           FTL_FAKE_GUARD(mStateLock) {
                mLayerTracing.createTraceFileProto();
                                               dumpHwcLayersMinidump(result);
        perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry();
                                           })
        perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread();
                        .get();
        layersTrace->mutable_layers()->Swap(&layersProto);
            } else {
        auto displayProtos = dumpDisplayProto();
                dumpHwcLayersMinidumpLockedLegacy(result);
        layersTrace->mutable_displays()->Swap(&displayProtos);
        result.append(traceFileProto.SerializeAsString());
        write(fd, result.c_str(), result.size());
        return NO_ERROR;
    }
    }
        };


    static const std::unordered_map<std::string, Dumper> dumpers = {
    static const std::unordered_map<std::string, Dumper> dumpers = {
            {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)},
            {"--comp-displays"s, dumper(&SurfaceFlinger::dumpCompositionDisplays)},
@@ -5974,8 +5976,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
            {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)},
            {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)},
            {"--events"s, dumper(&SurfaceFlinger::dumpEvents)},
            {"--events"s, dumper(&SurfaceFlinger::dumpEvents)},
            {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)},
            {"--frametimeline"s, argsDumper(&SurfaceFlinger::dumpFrameTimeline)},
            {"--frontend"s, mainThreadDumper(&SurfaceFlinger::dumpFrontEnd)},
            {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)},
            {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)},
                {"--hwclayers"s, std::move(hwclayersDump)},
            {"--hwclayers"s, mainThreadDumper(&SurfaceFlinger::dumpHwcLayersMinidump)},
            {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)},
            {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)},
            {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)},
            {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)},
            {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)},
            {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)},
@@ -5984,10 +5987,14 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
            {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)},
            {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)},
            {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)},
            {"--vsync"s, dumper(&SurfaceFlinger::dumpVsync)},
            {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)},
            {"--wide-color"s, dumper(&SurfaceFlinger::dumpWideColorInfo)},
                {"--frontend"s, dumper(&SurfaceFlinger::dumpFrontEnd)},
    };
    };


    const auto flag = args.empty() ? ""s : std::string(String8(args[0]));
    const auto flag = args.empty() ? ""s : std::string(String8(args[0]));
    if (const auto it = dumpers.find(flag); it != dumpers.end()) {
        (it->second)(args, asProto, result);
        write(fd, result.c_str(), result.size());
        return NO_ERROR;
    }


    // Traversal of drawing state must happen on the main thread.
    // Traversal of drawing state must happen on the main thread.
    // Otherwise, SortedVector may have shared ownership during concurrent
    // Otherwise, SortedVector may have shared ownership during concurrent
@@ -5995,97 +6002,10 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
    std::string compositionLayers;
    std::string compositionLayers;
    mScheduler
    mScheduler
            ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
            ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
                    if (!mLayerLifecycleManagerEnabled) {
                dumpVisibleFrontEnd(compositionLayers);
                        StringAppendF(&compositionLayers, "Composition layers\n");
                        mDrawingState.traverseInZOrder([&](Layer* layer) {
                            auto* compositionState = layer->getCompositionState();
                            if (!compositionState || !compositionState->isVisible) return;
                            android::base::StringAppendF(&compositionLayers, "* Layer %p (%s)\n",
                                                         layer,
                                                         layer->getDebugName()
                                                                 ? layer->getDebugName()
                                                                 : "<unknown>");
                            compositionState->dump(compositionLayers);
                        });
                    } else {
                        std::ostringstream out;
                        out << "\nComposition list\n";
                        ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
                        mLayerSnapshotBuilder.forEachVisibleSnapshot(
                                [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
                                    if (snapshot->hasSomethingToDraw()) {
                                        if (lastPrintedLayerStackHeader !=
                                            snapshot->outputFilter.layerStack) {
                                            lastPrintedLayerStackHeader =
                                                    snapshot->outputFilter.layerStack;
                                            out << "LayerStack=" << lastPrintedLayerStackHeader.id
                                                << "\n";
                                        }
                                        out << "  " << *snapshot << "\n";
                                    }
                                });

                        out << "\nInput list\n";
                        lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
                        mLayerSnapshotBuilder.forEachInputSnapshot(
                                [&](const frontend::LayerSnapshot& snapshot) {
                                    if (lastPrintedLayerStackHeader !=
                                        snapshot.outputFilter.layerStack) {
                                        lastPrintedLayerStackHeader =
                                                snapshot.outputFilter.layerStack;
                                        out << "LayerStack=" << lastPrintedLayerStackHeader.id
                                            << "\n";
                                    }
                                    out << "  " << snapshot << "\n";
                                });

                        out << "\nLayer Hierarchy\n"
                            << mLayerHierarchyBuilder.getHierarchy()
                            << "\nOffscreen Hierarchy\n"
                            << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n";
                        compositionLayers = out.str();
                        dumpHwcLayersMinidump(compositionLayers);
                    }
            })
            })
            .get();
            .get();

    dumpAll(args, compositionLayers, result);
        bool dumpLayers = true;
        {
            TimedLock lock(mStateLock, s2ns(1), __func__);
            if (!lock.locked()) {
                StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",
                              strerror(-lock.status), lock.status);
            }

            if (const auto it = dumpers.find(flag); it != dumpers.end()) {
                (it->second)(args, asProto, result);
                dumpLayers = false;
            } else if (!asProto) {
                dumpAllLocked(args, compositionLayers, result);
            }
        }

        if (dumpLayers) {
            perfetto::protos::LayersTraceFileProto traceFileProto =
                    mLayerTracing.createTraceFileProto();
            perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry();
            perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread();
            layersTrace->mutable_layers()->Swap(&layersProto);
            auto displayProtos = dumpDisplayProto();
            layersTrace->mutable_displays()->Swap(&displayProtos);

            if (asProto) {
                result.append(traceFileProto.SerializeAsString());
            } else {
                // Dump info that we need to access from the main thread
                const auto layerTree = LayerProtoParser::generateLayerTree(layersTrace->layers());
                result.append(LayerProtoParser::layerTreeToString(layerTree));
                result.append("\n");
                dumpOffscreenLayers(result);
            }
        }
    }

    write(fd, result.c_str(), result.size());
    write(fd, result.c_str(), result.size());
    return NO_ERROR;
    return NO_ERROR;
}
}
@@ -6297,8 +6217,6 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const {
}
}


void SurfaceFlinger::dumpFrontEnd(std::string& result) {
void SurfaceFlinger::dumpFrontEnd(std::string& result) {
    mScheduler
            ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
    std::ostringstream out;
    std::ostringstream out;
    out << "\nComposition list\n";
    out << "\nComposition list\n";
    ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
    ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
@@ -6312,8 +6230,7 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) {


    out << "\nInput list\n";
    out << "\nInput list\n";
    lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
    lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
                mLayerSnapshotBuilder.forEachInputSnapshot(
    mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) {
                        [&](const frontend::LayerSnapshot& snapshot) {
        if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) {
        if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) {
            lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack;
            lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack;
            out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
            out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
@@ -6322,12 +6239,59 @@ void SurfaceFlinger::dumpFrontEnd(std::string& result) {
    });
    });


    out << "\nLayer Hierarchy\n"
    out << "\nLayer Hierarchy\n"
                    << mLayerHierarchyBuilder.getHierarchy().dump()
        << mLayerHierarchyBuilder.getHierarchy().dump() << "\nOffscreen Hierarchy\n"
                    << "\nOffscreen Hierarchy\n"
        << mLayerHierarchyBuilder.getOffscreenHierarchy().dump() << "\n\n";
        << mLayerHierarchyBuilder.getOffscreenHierarchy().dump() << "\n\n";
    result.append(out.str());
    result.append(out.str());
            })
}
            .get();

void SurfaceFlinger::dumpVisibleFrontEnd(std::string& result) {
    if (!mLayerLifecycleManagerEnabled) {
        StringAppendF(&result, "Composition layers\n");
        mDrawingState.traverseInZOrder([&](Layer* layer) {
            auto* compositionState = layer->getCompositionState();
            if (!compositionState || !compositionState->isVisible) return;
            android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer,
                                         layer->getDebugName() ? layer->getDebugName()
                                                               : "<unknown>");
            compositionState->dump(result);
        });

        StringAppendF(&result, "Offscreen Layers\n");
        for (Layer* offscreenLayer : mOffscreenLayers) {
            offscreenLayer->traverse(LayerVector::StateSet::Drawing,
                                     [&](Layer* layer) { layer->dumpOffscreenDebugInfo(result); });
        }
    } else {
        std::ostringstream out;
        out << "\nComposition list\n";
        ui::LayerStack lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
        mLayerSnapshotBuilder.forEachVisibleSnapshot(
                [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
                    if (snapshot->hasSomethingToDraw()) {
                        if (lastPrintedLayerStackHeader != snapshot->outputFilter.layerStack) {
                            lastPrintedLayerStackHeader = snapshot->outputFilter.layerStack;
                            out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
                        }
                        out << "  " << *snapshot << "\n";
                    }
                });

        out << "\nInput list\n";
        lastPrintedLayerStackHeader = ui::INVALID_LAYER_STACK;
        mLayerSnapshotBuilder.forEachInputSnapshot([&](const frontend::LayerSnapshot& snapshot) {
            if (lastPrintedLayerStackHeader != snapshot.outputFilter.layerStack) {
                lastPrintedLayerStackHeader = snapshot.outputFilter.layerStack;
                out << "LayerStack=" << lastPrintedLayerStackHeader.id << "\n";
            }
            out << "  " << snapshot << "\n";
        });

        out << "\nLayer Hierarchy\n"
            << mLayerHierarchyBuilder.getHierarchy() << "\nOffscreen Hierarchy\n"
            << mLayerHierarchyBuilder.getOffscreenHierarchy() << "\n\n";
        result = out.str();
        dumpHwcLayersMinidump(result);
    }
}
}


perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
@@ -6428,7 +6392,7 @@ void SurfaceFlinger::dumpOffscreenLayers(std::string& result) {
}
}


void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const {
void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) const {
    for (const auto& [token, display] : mDisplays) {
    for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
        const auto displayId = HalDisplayId::tryCast(display->getId());
        const auto displayId = HalDisplayId::tryCast(display->getId());
        if (!displayId) {
        if (!displayId) {
            continue;
            continue;
@@ -6445,7 +6409,10 @@ void SurfaceFlinger::dumpHwcLayersMinidumpLockedLegacy(std::string& result) cons
}
}


void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const {
void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const {
    for (const auto& [token, display] : mDisplays) {
    if (!mLayerLifecycleManagerEnabled) {
        return dumpHwcLayersMinidumpLockedLegacy(result);
    }
    for (const auto& [token, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
        const auto displayId = HalDisplayId::tryCast(display->getId());
        const auto displayId = HalDisplayId::tryCast(display->getId());
        if (!displayId) {
        if (!displayId) {
            continue;
            continue;
@@ -6470,8 +6437,14 @@ void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const {
    }
    }
}
}


void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers,
void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositionLayers,
                             std::string& result) const {
                             std::string& result) const {
    TimedLock lock(mStateLock, s2ns(1), __func__);
    if (!lock.locked()) {
        StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",
                      strerror(-lock.status), lock.status);
    }

    const bool colorize = !args.empty() && args[0] == String16("--color");
    const bool colorize = !args.empty() && args[0] == String16("--color");
    Colorizer colorizer(colorize);
    Colorizer colorizer(colorize);


+34 −6
Original line number Original line Diff line number Diff line
@@ -21,6 +21,8 @@
 * NOTE: Make sure this file doesn't include  anything from <gl/ > or <gl2/ >
 * NOTE: Make sure this file doesn't include  anything from <gl/ > or <gl2/ >
 */
 */


#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/thread_annotations.h>
#include <android-base/thread_annotations.h>
#include <android/gui/BnSurfaceComposer.h>
#include <android/gui/BnSurfaceComposer.h>
#include <android/gui/DisplayStatInfo.h>
#include <android/gui/DisplayStatInfo.h>
@@ -77,6 +79,7 @@
#include "FrontEnd/LayerSnapshotBuilder.h"
#include "FrontEnd/LayerSnapshotBuilder.h"
#include "FrontEnd/TransactionHandler.h"
#include "FrontEnd/TransactionHandler.h"
#include "LayerVector.h"
#include "LayerVector.h"
#include "MutexUtils.h"
#include "Scheduler/ISchedulerCallback.h"
#include "Scheduler/ISchedulerCallback.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/RefreshRateStats.h"
@@ -478,22 +481,46 @@ private:
        return std::bind(std::forward<F>(dump), _3);
        return std::bind(std::forward<F>(dump), _3);
    }
    }


    Dumper lockedDumper(Dumper dump) {
        return [this, dump](const DumpArgs& args, bool asProto, std::string& result) -> void {
            TimedLock lock(mStateLock, s2ns(1), __func__);
            if (!lock.locked()) {
                base::StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",
                                    strerror(-lock.status), lock.status);
            }
            dump(args, asProto, result);
        };
    }

    template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr>
    template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr>
    Dumper dumper(F dump) {
    Dumper dumper(F dump) {
        using namespace std::placeholders;
        using namespace std::placeholders;
        return std::bind(dump, this, _3);
        return lockedDumper(std::bind(dump, this, _3));
    }
    }


    template <typename F>
    template <typename F>
    Dumper argsDumper(F dump) {
    Dumper argsDumper(F dump) {
        using namespace std::placeholders;
        using namespace std::placeholders;
        return std::bind(dump, this, _1, _3);
        return lockedDumper(std::bind(dump, this, _1, _3));
    }
    }


    template <typename F>
    template <typename F>
    Dumper protoDumper(F dump) {
    Dumper protoDumper(F dump) {
        using namespace std::placeholders;
        using namespace std::placeholders;
        return std::bind(dump, this, _1, _2, _3);
        return lockedDumper(std::bind(dump, this, _1, _2, _3));
    }

    template <typename F, std::enable_if_t<std::is_member_function_pointer_v<F>>* = nullptr>
    Dumper mainThreadDumper(F dump) {
        using namespace std::placeholders;
        Dumper dumper = std::bind(dump, this, _3);
        return [this, dumper](const DumpArgs& args, bool asProto, std::string& result) -> void {
            mScheduler
                    ->schedule(
                            [&args, asProto, &result, dumper]() FTL_FAKE_GUARD(kMainThreadContext)
                                    FTL_FAKE_GUARD(mStateLock) { dumper(args, asProto, result); })
                    .get();
        };
    }
    }


    // Maximum allowed number of display frames that can be set through backdoor
    // Maximum allowed number of display frames that can be set through backdoor
@@ -1080,8 +1107,8 @@ private:
    /*
    /*
     * Debugging & dumpsys
     * Debugging & dumpsys
     */
     */
    void dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers,
    void dumpAll(const DumpArgs& args, const std::string& compositionLayers,
                       std::string& result) const REQUIRES(mStateLock);
                 std::string& result) const EXCLUDES(mStateLock);
    void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext);
    void dumpHwcLayersMinidump(std::string& result) const REQUIRES(mStateLock, kMainThreadContext);
    void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock);
    void dumpHwcLayersMinidumpLockedLegacy(std::string& result) const REQUIRES(mStateLock);


@@ -1103,7 +1130,8 @@ private:
    void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
    void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
    void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock);
    void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock);
    void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock);
    void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock);
    void dumpFrontEnd(std::string& result);
    void dumpFrontEnd(std::string& result) REQUIRES(kMainThreadContext);
    void dumpVisibleFrontEnd(std::string& result) REQUIRES(mStateLock, kMainThreadContext);


    perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
    perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
    void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto,
    void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto,