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

Commit 0b06a8da authored by chaviw's avatar chaviw
Browse files

Send releaseCallbackId and releaseFence to correct listener

The scenario is the following:
1. Process1 creates a T1 with a new buffer, release callback, and
transaction callback. The release callback is stored locally in
mReleaseBufferCallbacks so it only lives in Process1.

2. Process2 creates a T2 with a transaction callback

3. When T1 and T2 are merged, the SC from T1 end up getting the
transaction callbacks from T2. SC will end up with multiple transaction
callbacks

4. In BufferStateLayer, we only added mPreviousReleaseCallbackId to one
transaction callback. There's a chance the release callback would only
end up on the transaction callback for Process2.

Process2 doesn't have the data about the callback since it was only
stored in Process1. When Process2 gets the transaction callback, it
will not handle the releaseCallbackId since it doesn't know what release
callback it represents. Process1 will get a transaction callback, but will
not contain a releaseCallbackId.

To fix, add releaseBufferEndpoint that is set when the client calls
setBuffer. This is used in SurfaceFlinger to recognize which listener
was the one that set the buffer so it can send the release information
to the correct listener.

Test: ReleaseBufferCallback_test
Bug: 193565751
Change-Id: I534fbde2a54608c2e30852e48dc0c75c86b22525
parent ad802be8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ status_t layer_state_t::write(Parcel& output) const
    SAFE_PARCEL(output.write, destinationFrame);
    SAFE_PARCEL(output.writeBool, isTrustedOverlay);

    SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
    return NO_ERROR;
}

@@ -303,6 +304,7 @@ status_t layer_state_t::read(const Parcel& input)
    SAFE_PARCEL(input.read, destinationFrame);
    SAFE_PARCEL(input.readBool, &isTrustedOverlay);

    SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
    return NO_ERROR;
}

+10 −1
Original line number Diff line number Diff line
@@ -147,8 +147,16 @@ int64_t TransactionCompletedListener::getNextIdLocked() {
    return mCallbackIdCounter++;
}

sp<TransactionCompletedListener> TransactionCompletedListener::sInstance = nullptr;

void TransactionCompletedListener::setInstance(const sp<TransactionCompletedListener>& listener) {
    sInstance = listener;
}

sp<TransactionCompletedListener> TransactionCompletedListener::getInstance() {
    static sp<TransactionCompletedListener> sInstance = new TransactionCompletedListener;
    if (sInstance == nullptr) {
        sInstance = new TransactionCompletedListener;
    }
    return sInstance;
}

@@ -1274,6 +1282,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe
    removeReleaseBufferCallback(s);
    s->what |= layer_state_t::eBufferChanged;
    s->buffer = buffer;
    s->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance());
    if (mIsAutoTimestamp) {
        mDesiredPresentTime = systemTime();
    }
+5 −0
Original line number Diff line number Diff line
@@ -242,6 +242,11 @@ struct layer_state_t {
    // is used to remove the old callback from the client process map if it is
    // overwritten by another setBuffer call.
    ReleaseCallbackId releaseCallbackId;

    // Stores which endpoint the release information should be sent to. We don't want to send the
    // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
    // was called with.
    sp<IBinder> releaseBufferEndpoint;
};

struct ComposerState {
+6 −0
Original line number Diff line number Diff line
@@ -655,8 +655,10 @@ public:
};

class TransactionCompletedListener : public BnTransactionCompletedListener {
public:
    TransactionCompletedListener();

protected:
    int64_t getNextIdLocked() REQUIRES(mMutex);

    std::mutex mMutex;
@@ -734,8 +736,12 @@ public:
    void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence, uint32_t transformHint,
                         uint32_t currentMaxAcquiredBufferCount) override;

    // For Testing Only
    static void setInstance(const sp<TransactionCompletedListener>&);

private:
    ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&);
    static sp<TransactionCompletedListener> sInstance;
};

} // namespace android
+7 −9
Original line number Diff line number Diff line
@@ -158,7 +158,8 @@ void BufferStateLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
    // transaction doesn't need a previous release fence.
    sp<CallbackHandle> ch;
    for (auto& handle : mDrawingState.callbackHandles) {
        if (handle->releasePreviousBuffer) {
        if (handle->releasePreviousBuffer &&
            mDrawingState.releaseBufferEndpoint == handle->listener) {
            ch = handle;
            break;
        }
@@ -199,14 +200,9 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
                mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
    }

    // If there are multiple transactions in this frame, set the previous id on the earliest
    // transacton. We don't need to pass in the released buffer id to multiple transactions.
    // The buffer id does not have to correspond to any particular transaction as long as the
    // listening end point is the same but the client expects the first transaction callback that
    // replaces the presented buffer to contain the release fence. This follows the same logic.
    // see BufferStateLayer::onLayerDisplayed.
    for (auto& handle : mDrawingState.callbackHandles) {
        if (handle->releasePreviousBuffer) {
        if (handle->releasePreviousBuffer &&
            mDrawingState.releaseBufferEndpoint == handle->listener) {
            handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
            break;
        }
@@ -420,7 +416,8 @@ bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTex
                                 nsecs_t desiredPresentTime, bool isAutoTimestamp,
                                 const client_cache_t& clientCacheId, uint64_t frameNumber,
                                 std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
                                 const sp<ITransactionCompletedListener>& releaseBufferListener) {
                                 const sp<ITransactionCompletedListener>& releaseBufferListener,
                                 const sp<IBinder>& releaseBufferEndpoint) {
    ATRACE_CALL();

    if (mDrawingState.buffer) {
@@ -484,6 +481,7 @@ bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTex

    mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
    mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
    mDrawingState.releaseBufferEndpoint = releaseBufferEndpoint;

    return true;
}
Loading