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

Commit 9f0835e7 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

SF: Make BufferData mockable

Expose GraphicBuffer properties through the BufferData
class so we can inject fake GraphicBuffers in transactions.
This is required to recreate layer state from transaction
traces without actually allocating buffers.

Test: compiles
Bug: 200284593
Change-Id: I74036cba1f544cbd045489fa5337d59ae4bdebcb
parent 1df8d38a
Loading
Loading
Loading
Loading
+30 −27
Original line number Diff line number Diff line
@@ -153,7 +153,8 @@ status_t layer_state_t::write(Parcel& output) const
    SAFE_PARCEL(output.writeBool, isTrustedOverlay);

    SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode));
    SAFE_PARCEL(bufferData.write, output);
    SAFE_PARCEL(output.writeNullableParcelable,
                bufferData ? std::make_optional<BufferData>(*bufferData) : std::nullopt);
    return NO_ERROR;
}

@@ -263,7 +264,9 @@ status_t layer_state_t::read(const Parcel& input)
    uint32_t mode;
    SAFE_PARCEL(input.readUint32, &mode);
    dropInputMode = static_cast<gui::DropInputMode>(mode);
    SAFE_PARCEL(bufferData.read, input);
    std::optional<BufferData> tmpBufferData;
    SAFE_PARCEL(input.readParcelable, &tmpBufferData);
    bufferData = tmpBufferData ? std::make_shared<BufferData>(*tmpBufferData) : nullptr;
    return NO_ERROR;
}

@@ -518,7 +521,7 @@ bool layer_state_t::hasBufferChanges() const {
}

bool layer_state_t::hasValidBuffer() const {
    return bufferData.buffer || bufferData.cachedBuffer.isValid();
    return bufferData && (bufferData->buffer || bufferData->cachedBuffer.isValid());
}

status_t layer_state_t::matrix22_t::write(Parcel& output) const {
@@ -681,64 +684,64 @@ ReleaseCallbackId BufferData::generateReleaseCallbackId() const {
    return {buffer->getId(), frameNumber};
}

status_t BufferData::write(Parcel& output) const {
    SAFE_PARCEL(output.writeInt32, flags.get());
status_t BufferData::writeToParcel(Parcel* output) const {
    SAFE_PARCEL(output->writeInt32, flags.get());

    if (buffer) {
        SAFE_PARCEL(output.writeBool, true);
        SAFE_PARCEL(output.write, *buffer);
        SAFE_PARCEL(output->writeBool, true);
        SAFE_PARCEL(output->write, *buffer);
    } else {
        SAFE_PARCEL(output.writeBool, false);
        SAFE_PARCEL(output->writeBool, false);
    }

    if (acquireFence) {
        SAFE_PARCEL(output.writeBool, true);
        SAFE_PARCEL(output.write, *acquireFence);
        SAFE_PARCEL(output->writeBool, true);
        SAFE_PARCEL(output->write, *acquireFence);
    } else {
        SAFE_PARCEL(output.writeBool, false);
        SAFE_PARCEL(output->writeBool, false);
    }

    SAFE_PARCEL(output.writeUint64, frameNumber);
    SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener));
    SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
    SAFE_PARCEL(output->writeUint64, frameNumber);
    SAFE_PARCEL(output->writeStrongBinder, IInterface::asBinder(releaseBufferListener));
    SAFE_PARCEL(output->writeStrongBinder, releaseBufferEndpoint);

    SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote());
    SAFE_PARCEL(output.writeUint64, cachedBuffer.id);
    SAFE_PARCEL(output->writeStrongBinder, cachedBuffer.token.promote());
    SAFE_PARCEL(output->writeUint64, cachedBuffer.id);

    return NO_ERROR;
}

status_t BufferData::read(const Parcel& input) {
status_t BufferData::readFromParcel(const Parcel* input) {
    int32_t tmpInt32;
    SAFE_PARCEL(input.readInt32, &tmpInt32);
    SAFE_PARCEL(input->readInt32, &tmpInt32);
    flags = Flags<BufferDataChange>(tmpInt32);

    bool tmpBool = false;
    SAFE_PARCEL(input.readBool, &tmpBool);
    SAFE_PARCEL(input->readBool, &tmpBool);
    if (tmpBool) {
        buffer = new GraphicBuffer();
        SAFE_PARCEL(input.read, *buffer);
        SAFE_PARCEL(input->read, *buffer);
    }

    SAFE_PARCEL(input.readBool, &tmpBool);
    SAFE_PARCEL(input->readBool, &tmpBool);
    if (tmpBool) {
        acquireFence = new Fence();
        SAFE_PARCEL(input.read, *acquireFence);
        SAFE_PARCEL(input->read, *acquireFence);
    }

    SAFE_PARCEL(input.readUint64, &frameNumber);
    SAFE_PARCEL(input->readUint64, &frameNumber);

    sp<IBinder> tmpBinder = nullptr;
    SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
    SAFE_PARCEL(input->readNullableStrongBinder, &tmpBinder);
    if (tmpBinder) {
        releaseBufferListener = checked_interface_cast<ITransactionCompletedListener>(tmpBinder);
    }
    SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
    SAFE_PARCEL(input->readNullableStrongBinder, &releaseBufferEndpoint);

    tmpBinder = nullptr;
    SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
    SAFE_PARCEL(input->readNullableStrongBinder, &tmpBinder);
    cachedBuffer.token = tmpBinder;
    SAFE_PARCEL(input.readUint64, &cachedBuffer.id);
    SAFE_PARCEL(input->readUint64, &cachedBuffer.id);

    return NO_ERROR;
}
+29 −29
Original line number Diff line number Diff line
@@ -728,18 +728,18 @@ void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_
        return;
    }

    auto listener = state.bufferData.releaseBufferListener;
    auto listener = state.bufferData->releaseBufferListener;
    sp<Fence> fence =
            state.bufferData.acquireFence ? state.bufferData.acquireFence : Fence::NO_FENCE;
    if (state.bufferData.releaseBufferEndpoint ==
            state.bufferData->acquireFence ? state.bufferData->acquireFence : Fence::NO_FENCE;
    if (state.bufferData->releaseBufferEndpoint ==
        IInterface::asBinder(TransactionCompletedListener::getIInstance())) {
        // if the callback is in process, run on a different thread to avoid any lock contigency
        // issues in the client.
        SurfaceComposerClient::getDefault()
                ->mReleaseCallbackThread
                .addReleaseCallback(state.bufferData.generateReleaseCallbackId(), fence);
                .addReleaseCallback(state.bufferData->generateReleaseCallbackId(), fence);
    } else {
        listener->onReleaseBuffer(state.bufferData.generateReleaseCallbackId(), fence, UINT_MAX);
        listener->onReleaseBuffer(state.bufferData->generateReleaseCallbackId(), fence, UINT_MAX);
    }
}

@@ -839,7 +839,8 @@ void SurfaceComposerClient::Transaction::cacheBuffers() {
        layer_state_t* s = &(mComposerStates[handle].state);
        if (!(s->what & layer_state_t::eBufferChanged)) {
            continue;
        } else if (s->bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged)) {
        } else if (s->bufferData &&
                   s->bufferData->flags.test(BufferData::BufferDataChange::cachedBufferChanged)) {
            // If eBufferChanged and eCachedBufferChanged are both trued then that means
            // we already cached the buffer in a previous call to cacheBuffers, perhaps
            // from writeToParcel on a Transaction that was merged in to this one.
@@ -848,22 +849,22 @@ void SurfaceComposerClient::Transaction::cacheBuffers() {

        // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste
        // time trying to cache them.
        if (!s->bufferData.buffer) {
        if (!s->bufferData || !s->bufferData->buffer) {
            continue;
        }

        uint64_t cacheId = 0;
        status_t ret = BufferCache::getInstance().getCacheId(s->bufferData.buffer, &cacheId);
        status_t ret = BufferCache::getInstance().getCacheId(s->bufferData->buffer, &cacheId);
        if (ret == NO_ERROR) {
            // Cache-hit. Strip the buffer and send only the id.
            s->bufferData.buffer = nullptr;
            s->bufferData->buffer = nullptr;
        } else {
            // Cache-miss. Include the buffer and send the new cacheId.
            cacheId = BufferCache::getInstance().cache(s->bufferData.buffer);
            cacheId = BufferCache::getInstance().cache(s->bufferData->buffer);
        }
        s->bufferData.flags |= BufferData::BufferDataChange::cachedBufferChanged;
        s->bufferData.cachedBuffer.token = BufferCache::getInstance().getToken();
        s->bufferData.cachedBuffer.id = cacheId;
        s->bufferData->flags |= BufferData::BufferDataChange::cachedBufferChanged;
        s->bufferData->cachedBuffer.token = BufferCache::getInstance().getToken();
        s->bufferData->cachedBuffer.id = cacheId;

        // If we have more buffers than the size of the cache, we should stop caching so we don't
        // evict other buffers in this transaction
@@ -1322,23 +1323,22 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp<Surfac
    return *this;
}

std::optional<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer(
std::shared_ptr<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer(
        const sp<SurfaceControl>& sc) {
    layer_state_t* s = getLayerState(sc);
    if (!s) {
        return std::nullopt;
        return nullptr;
    }
    if (!(s->what & layer_state_t::eBufferChanged)) {
        return std::nullopt;
        return nullptr;
    }

    BufferData bufferData = s->bufferData;
    std::shared_ptr<BufferData> bufferData = std::move(s->bufferData);

    TransactionCompletedListener::getInstance()->removeReleaseBufferCallback(
            bufferData.generateReleaseCallbackId());
    BufferData emptyBufferData;
            bufferData->generateReleaseCallbackId());
    s->what &= ~layer_state_t::eBufferChanged;
    s->bufferData = emptyBufferData;
    s->bufferData = nullptr;

    mContainsBuffer = false;
    return bufferData;
@@ -1356,24 +1356,24 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe

    releaseBufferIfOverwriting(*s);

    BufferData bufferData;
    bufferData.buffer = buffer;
    std::shared_ptr<BufferData> bufferData = std::make_shared<BufferData>();
    bufferData->buffer = buffer;
    if (frameNumber) {
        bufferData.frameNumber = *frameNumber;
        bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
        bufferData->frameNumber = *frameNumber;
        bufferData->flags |= BufferData::BufferDataChange::frameNumberChanged;
    }
    if (fence) {
        bufferData.acquireFence = *fence;
        bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
        bufferData->acquireFence = *fence;
        bufferData->flags |= BufferData::BufferDataChange::fenceChanged;
    }
    bufferData.releaseBufferEndpoint =
    bufferData->releaseBufferEndpoint =
            IInterface::asBinder(TransactionCompletedListener::getIInstance());
    if (mIsAutoTimestamp) {
        mDesiredPresentTime = systemTime();
    }
    setReleaseBufferCallback(&bufferData, callback);
    setReleaseBufferCallback(bufferData.get(), callback);
    s->what |= layer_state_t::eBufferChanged;
    s->bufferData = bufferData;
    s->bufferData = std::move(bufferData);
    registerSurfaceControlForCallback(sc);

    mContainsBuffer = true;
+20 −4
Original line number Diff line number Diff line
@@ -58,7 +58,22 @@ struct client_cache_t {
    bool isValid() const { return token != nullptr; }
};

struct BufferData {
class BufferData : public Parcelable {
public:
    virtual ~BufferData() = default;
    virtual bool hasBuffer() const { return buffer != nullptr; }
    virtual bool hasSameBuffer(const BufferData& other) const {
        return buffer == other.buffer && frameNumber == other.frameNumber;
    }
    virtual uint32_t getWidth() const { return buffer->getWidth(); }
    virtual uint32_t getHeight() const { return buffer->getHeight(); }
    Rect getBounds() const {
        return {0, 0, static_cast<int32_t>(getWidth()), static_cast<int32_t>(getHeight())};
    }
    virtual uint64_t getId() const { return buffer->getId(); }
    virtual PixelFormat getPixelFormat() const { return buffer->getPixelFormat(); }
    virtual uint64_t getUsage() const { return buffer->getUsage(); }

    enum class BufferDataChange : uint32_t {
        fenceChanged = 0x01,
        frameNumberChanged = 0x02,
@@ -89,8 +104,9 @@ struct BufferData {
    // Generates the release callback id based on the buffer id and frame number.
    // This is used as an identifier when release callbacks are invoked.
    ReleaseCallbackId generateReleaseCallbackId() const;
    status_t write(Parcel& output) const;
    status_t read(const Parcel& input);

    status_t writeToParcel(Parcel* parcel) const override;
    status_t readFromParcel(const Parcel* parcel) override;
};

/*
@@ -204,7 +220,7 @@ struct layer_state_t {
    uint32_t transform;
    bool transformToDisplayInverse;
    Rect crop;
    BufferData bufferData;
    std::shared_ptr<BufferData> bufferData = nullptr;
    ui::Dataspace dataspace;
    HdrMetadata hdrMetadata;
    Region surfaceDamageRegion;
+1 −1
Original line number Diff line number Diff line
@@ -501,7 +501,7 @@ public:
                               const std::optional<sp<Fence>>& fence = std::nullopt,
                               const std::optional<uint64_t>& frameNumber = std::nullopt,
                               ReleaseBufferCallback callback = nullptr);
        std::optional<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc);
        std::shared_ptr<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc);
        Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
        Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata);
        Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc,
+8 −8
Original line number Diff line number Diff line
@@ -3719,9 +3719,9 @@ bool SurfaceFlinger::checkTransactionCanLatchUnsignaled(const TransactionState&
    if (transaction.states.size() == 1) {
        const auto& state = transaction.states.begin()->state;
        if ((state.flags & ~layer_state_t::eBufferChanged) == 0 &&
            state.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged) &&
            state.bufferData.acquireFence &&
            state.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) {
            state.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) &&
            state.bufferData->acquireFence &&
            state.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) {
            ATRACE_NAME("transactionCanLatchUnsignaled");
            return true;
        }
@@ -3786,10 +3786,10 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(

    for (const ComposerState& state : states) {
        const layer_state_t& s = state.state;
        const bool acquireFenceChanged =
                s.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged);
        if (acquireFenceChanged && s.bufferData.acquireFence && !allowLatchUnsignaled &&
            s.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) {
        const bool acquireFenceChanged = s.bufferData &&
                s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged);
        if (acquireFenceChanged && s.bufferData->acquireFence && !allowLatchUnsignaled &&
            s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) {
            ATRACE_NAME("fence unsignaled");
            return false;
        }
@@ -4420,7 +4420,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime
    }

    if (what & layer_state_t::eBufferChanged &&
        layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
        layer->setBuffer(*s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
                         dequeueBufferTimestamp, frameTimelineInfo)) {
        flags |= eTraversalNeeded;
    } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
Loading