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

Commit 0f085c6a authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Dump offscreen layers in dumpsys and winscope trace

Now that clients can keep layers alive by holding a reference to its handle and clients can also
create layers, we need to an easier way to keep track of layers that are offscreen but not
destroyed. This change keeps track of the calling pid and uid so it is easier to track the creating
process. Since the tracing thread will also read from mOffscreenLayers, we want to protect
access to it with the tracing lock.

Bug:127687760
Test: run dumpsys check for offscreen layers
Test: capture sf trace and check for offscreen layers
Change-Id: I400f33b11b0a4f78f4c35027c457eb56ff12c22e
parent f0aa9016
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "Layer.h"

#include <android-base/stringprintf.h>
#include <binder/IPCThreadState.h>
#include <compositionengine/Display.h>
#include <compositionengine/Layer.h>
#include <compositionengine/LayerFECompositionState.h>
@@ -121,7 +122,8 @@ Layer::Layer(const LayerCreationArgs& args)
    mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);

    mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType);

    mCallingPid = args.callingPid;
    mCallingUid = args.callingUid;
    mFlinger->onLayerCreated();
}

@@ -135,6 +137,21 @@ Layer::~Layer() {
    mFlinger->onLayerDestroyed(this);
}

LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client,
                                     const String8& name, uint32_t w, uint32_t h, uint32_t flags,
                                     LayerMetadata metadata)
      : flinger(flinger),
        client(client),
        name(name),
        w(w),
        h(h),
        flags(flags),
        metadata(std::move(metadata)) {
    IPCThreadState* ipc = IPCThreadState::self();
    callingPid = ipc->getCallingPid();
    callingUid = ipc->getCallingUid();
}

// ---------------------------------------------------------------------------
// callbacks
// ---------------------------------------------------------------------------
@@ -1340,6 +1357,11 @@ void Layer::dumpFrameEvents(std::string& result) {
    mFrameEventHistory.dump(result);
}

void Layer::dumpCallingUidPid(std::string& result) const {
    StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(),
                  mCallingPid, mCallingUid);
}

void Layer::onDisconnect() {
    Mutex::Autolock lock(mFrameEventHistoryMutex);
    mFrameEventHistory.onDisconnect();
+9 −3
Original line number Diff line number Diff line
@@ -80,9 +80,7 @@ class SurfaceInterceptor;

struct LayerCreationArgs {
    LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
                      uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata)
          : flinger(flinger), client(client), name(name), w(w), h(h), flags(flags),
            metadata(std::move(metadata)) {}
                      uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata);

    SurfaceFlinger* flinger;
    const sp<Client>& client;
@@ -91,6 +89,8 @@ struct LayerCreationArgs {
    uint32_t h;
    uint32_t flags;
    LayerMetadata metadata;
    pid_t callingPid;
    uid_t callingUid;
};

class Layer : public virtual compositionengine::LayerFE {
@@ -600,6 +600,7 @@ public:
    void miniDump(std::string& result, const sp<DisplayDevice>& display) const;
    void dumpFrameStats(std::string& result) const;
    void dumpFrameEvents(std::string& result);
    void dumpCallingUidPid(std::string& result) const;
    void clearFrameStats();
    void logFrameStats();
    void getFrameStats(FrameStats* outStats) const;
@@ -924,6 +925,11 @@ private:
    bool mGetHandleCalled = false;

    void removeRemoteSyncPoints();

    // Tracks the process and user id of the caller when creating this layer
    // to help debugging.
    pid_t mCallingPid;
    uid_t mCallingUid;
};

} // namespace android
+64 −21
Original line number Diff line number Diff line
@@ -2872,11 +2872,11 @@ void SurfaceFlinger::updateCursorAsync()

void SurfaceFlinger::commitTransaction()
{
    withTracingLock([&]() {
        if (!mLayersPendingRemoval.isEmpty()) {
            // Notify removed layers now that they can't be drawn from
            for (const auto& l : mLayersPendingRemoval) {
            recordBufferingStats(l->getName().string(),
                    l->getOccupancyHistory(true));
                recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true));

                // Ensure any buffers set to display on any children are released.
                if (l->isRemovedFromCurrentState()) {
@@ -2897,7 +2897,6 @@ void SurfaceFlinger::commitTransaction()
        // we composite should be considered an animation as well.
        mAnimCompositionPending = mAnimTransactionPending;

    withTracingLock([&]() {
        mDrawingState = mCurrentState;
        // clear the "changed" flags in current state
        mCurrentState.colorMatrixChanged = false;
@@ -4286,9 +4285,11 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,
            if (asProto) {
                result.append(layersProto.SerializeAsString());
            } else {
                // Dump info that we need to access from the main thread
                const auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
                result.append(LayerProtoParser::layerTreeToString(layerTree));
                result.append("\n");
                dumpOffscreenLayers(result);
            }
        }
    }
@@ -4546,12 +4547,54 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
    return layersProto;
}

void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const {
    // Add a fake invisible root layer to the proto output and parent all the offscreen layers to
    // it.
    LayerProto* rootProto = layersProto.add_layers();
    const int32_t offscreenRootLayerId = INT32_MAX - 2;
    rootProto->set_id(offscreenRootLayerId);
    rootProto->set_name("Offscreen Root");

    for (Layer* offscreenLayer : mOffscreenLayers) {
        // Add layer as child of the fake root
        rootProto->add_children(offscreenLayer->sequence);

        // Add layer
        LayerProto* layerProto = layersProto.add_layers();
        offscreenLayer->writeToProtoDrawingState(layerProto, traceFlags);
        offscreenLayer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing,
                                                traceFlags);
        layerProto->set_parent(offscreenRootLayerId);

        // Add children
        offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
            if (layer == offscreenLayer) {
                return;
            }
            LayerProto* childProto = layersProto.add_layers();
            layer->writeToProtoDrawingState(childProto, traceFlags);
            layer->writeToProtoCommonState(childProto, LayerVector::StateSet::Drawing, traceFlags);
        });
    }
}

LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
    LayersProto layersProto;
    postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); }));
    return layersProto;
}

void SurfaceFlinger::dumpOffscreenLayers(std::string& result) {
    result.append("Offscreen Layers:\n");
    postMessageSync(new LambdaMessage([&]() {
        for (Layer* offscreenLayer : mOffscreenLayers) {
            offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
                layer->dumpCallingUidPid(result);
            });
        }
    }));
}

void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const {
    const bool colorize = !args.empty() && args[0] == String16("--color");
    Colorizer colorizer(colorize);
+3 −0
Original line number Diff line number Diff line
@@ -876,8 +876,11 @@ private:
    void dumpDisplayIdentificationData(std::string& result) const;
    void dumpWideColorInfo(std::string& result) const;
    LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
    void dumpOffscreenLayersProto(LayersProto& layersProto,
                                  uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
    LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
            EXCLUDES(mStateLock);
    void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock);
    void withTracingLock(std::function<void()> operation) REQUIRES(mStateLock);

    bool isLayerTripleBufferingDisabled() const {
+1 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) {
    entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
    entry.set_where(where);
    LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags));
    mFlinger.dumpOffscreenLayersProto(layers);
    entry.mutable_layers()->Swap(&layers);

    return entry;