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

Commit deb75f8d authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12573674 from d0217956 to 25Q1-release

Change-Id: Ia77106871f9509a124585aaefe4c8d334bd591ce
parents 0e040944 d0217956
Loading
Loading
Loading
Loading
+35 −119
Original line number Original line Diff line number Diff line
@@ -52,19 +52,18 @@ using namespace std::chrono_literals;
namespace {
namespace {


#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
// RAII wrapper to defer arbitrary work until the Deferred instance is deleted.
template <class Mutex>
template <class F>
class UnlockGuard {
class Deferred {
public:
public:
    explicit Deferred(F f) : mF{std::move(f)} {}
    explicit UnlockGuard(Mutex& lock) : mLock{lock} { mLock.unlock(); }


    ~Deferred() { mF(); }
    ~UnlockGuard() { mLock.lock(); }


    Deferred(const Deferred&) = delete;
    UnlockGuard(const UnlockGuard&) = delete;
    Deferred& operator=(const Deferred&) = delete;
    UnlockGuard& operator=(const UnlockGuard&) = delete;


private:
private:
    F mF;
    Mutex& mLock;
};
};
#endif
#endif


@@ -271,9 +270,6 @@ BLASTBufferQueue::~BLASTBufferQueue() {
void BLASTBufferQueue::onFirstRef() {
void BLASTBufferQueue::onFirstRef() {
    // safe default, most producers are expected to override this
    // safe default, most producers are expected to override this
    mProducer->setMaxDequeuedBufferCount(2);
    mProducer->setMaxDequeuedBufferCount(2);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    mBufferReleaseThread.emplace(sp<BLASTBufferQueue>::fromExisting(this));
#endif
}
}


void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
@@ -297,11 +293,16 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    mSurfaceControl = surface;
    mSurfaceControl = surface;
    SurfaceComposerClient::Transaction t;
    SurfaceComposerClient::Transaction t;
    if (surfaceControlChanged) {
    if (surfaceControlChanged) {
        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
                   layer_state_t::eEnableBackpressure);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
        t.setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer);
        // SELinux policy may prevent this process from sending the BufferReleaseChannel's file
        // descriptor to SurfaceFlinger, causing the entire transaction to be dropped. This
        // transaction is applied separately to ensure we don't lose the other updates.
        t.setApplyToken(mApplyToken)
                .setBufferReleaseChannel(mSurfaceControl, mBufferReleaseProducer)
                .apply(false /* synchronous */, true /* oneWay */);
#endif
#endif
        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
                   layer_state_t::eEnableBackpressure);
        applyTransaction = true;
        applyTransaction = true;
    }
    }
    mTransformHint = mSurfaceControl->getTransformHint();
    mTransformHint = mSurfaceControl->getTransformHint();
@@ -325,7 +326,7 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    }
    }
    if (applyTransaction) {
    if (applyTransaction) {
        // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
        // All transactions on our apply token are one-way. See comment on mAppliedLastTransaction
        t.setApplyToken(mApplyToken).apply(false, true);
        t.setApplyToken(mApplyToken).apply(false /* synchronous */, true /* oneWay */);
    }
    }
}
}


@@ -419,7 +420,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                    stat.latchTime,
                                                    stat.latchTime,
                                                    stat.frameEventStats.dequeueReadyTime);
                                                    stat.frameEventStats.dequeueReadyTime);
                }
                }
#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
                auto currFrameNumber = stat.frameEventStats.frameNumber;
                auto currFrameNumber = stat.frameEventStats.frameNumber;
                std::vector<ReleaseCallbackId> staleReleases;
                std::vector<ReleaseCallbackId> staleReleases;
                for (const auto& [key, value]: mSubmitted) {
                for (const auto& [key, value]: mSubmitted) {
@@ -435,7 +435,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                stat.currentMaxAcquiredBufferCount,
                                                stat.currentMaxAcquiredBufferCount,
                                                true /* fakeRelease */);
                                                true /* fakeRelease */);
                }
                }
#endif
            } else {
            } else {
                BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
                BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
            }
            }
@@ -469,6 +468,9 @@ ReleaseBufferCallback BLASTBufferQueue::makeReleaseBufferCallbackThunk() {
            return;
            return;
        }
        }
        bbq->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
        bbq->releaseBufferCallback(id, releaseFence, currentMaxAcquiredBufferCount);
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
        bbq->drainBufferReleaseConsumer();
#endif
    };
    };
}
}


@@ -535,8 +537,6 @@ void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
                                     const sp<Fence>& releaseFence) {
                                     const sp<Fence>& releaseFence) {
    auto it = mSubmitted.find(callbackId);
    auto it = mSubmitted.find(callbackId);
    if (it == mSubmitted.end()) {
    if (it == mSubmitted.end()) {
        BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
                 callbackId.to_string().c_str());
        return;
        return;
    }
    }
    mNumAcquired--;
    mNumAcquired--;
@@ -646,12 +646,7 @@ status_t BLASTBufferQueue::acquireNextBufferLocked(
                           bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
                           bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
                           bufferItem.mScalingMode, crop);
                           bufferItem.mScalingMode, crop);


#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
    ReleaseBufferCallback releaseBufferCallback =
            applyTransaction ? nullptr : makeReleaseBufferCallbackThunk();
#else
    auto releaseBufferCallback = makeReleaseBufferCallbackThunk();
    auto releaseBufferCallback = makeReleaseBufferCallbackThunk();
#endif
    sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
    sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;


    nsecs_t dequeueTime = -1;
    nsecs_t dequeueTime = -1;
@@ -1230,12 +1225,7 @@ public:
        // we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
        // we want to ignore it. This must be done before unlocking the BufferQueue lock to ensure
        // we don't miss an interrupt.
        // we don't miss an interrupt.
        bbq->mBufferReleaseReader->clearInterrupts();
        bbq->mBufferReleaseReader->clearInterrupts();
        bbq->mThreadsBlockingOnDequeue++;
        UnlockGuard unlockGuard{bufferQueueLock};
        bufferQueueLock.unlock();
        Deferred cleanup{[&]() {
            bufferQueueLock.lock();
            bbq->mThreadsBlockingOnDequeue--;
        }};


        ATRACE_FORMAT("waiting for free buffer");
        ATRACE_FORMAT("waiting for free buffer");
        ReleaseCallbackId id;
        ReleaseCallbackId id;
@@ -1345,6 +1335,21 @@ void BLASTBufferQueue::setApplyToken(sp<IBinder> applyToken) {


#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)


void BLASTBufferQueue::drainBufferReleaseConsumer() {
    ATRACE_CALL();
    while (true) {
        ReleaseCallbackId id;
        sp<Fence> fence;
        uint32_t maxAcquiredBufferCount;
        status_t status =
                mBufferReleaseConsumer->readReleaseFence(id, fence, maxAcquiredBufferCount);
        if (status != OK) {
            return;
        }
        releaseBufferCallback(id, fence, maxAcquiredBufferCount);
    }
}

BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(BLASTBufferQueue& bbq) : mBbq{bbq} {
BLASTBufferQueue::BufferReleaseReader::BufferReleaseReader(BLASTBufferQueue& bbq) : mBbq{bbq} {
    mEpollFd = android::base::unique_fd{epoll_create1(EPOLL_CLOEXEC)};
    mEpollFd = android::base::unique_fd{epoll_create1(EPOLL_CLOEXEC)};
    LOG_ALWAYS_FATAL_IF(!mEpollFd.ok(),
    LOG_ALWAYS_FATAL_IF(!mEpollFd.ok(),
@@ -1438,95 +1443,6 @@ void BLASTBufferQueue::BufferReleaseReader::clearInterrupts() {
    }
    }
}
}


BLASTBufferQueue::BufferReleaseThread::BufferReleaseThread(const sp<BLASTBufferQueue>& bbq) {
    android::base::unique_fd epollFd{epoll_create1(EPOLL_CLOEXEC)};
    LOG_ALWAYS_FATAL_IF(!epollFd.ok(),
                        "Failed to create buffer release background thread epoll file descriptor. "
                        "errno=%d message='%s'",
                        errno, strerror(errno));

    epoll_event registerEndpointFd{};
    registerEndpointFd.events = EPOLLIN;
    registerEndpointFd.data.fd = bbq->mBufferReleaseConsumer->getFd();
    status_t status = epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, bbq->mBufferReleaseConsumer->getFd(),
                                &registerEndpointFd);
    LOG_ALWAYS_FATAL_IF(status == -1,
                        "Failed to register background thread buffer release consumer file "
                        "descriptor with epoll. errno=%d message='%s'",
                        errno, strerror(errno));

    // EventFd is used to break the background thread's loop.
    android::base::unique_fd eventFd{eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)};
    LOG_ALWAYS_FATAL_IF(!eventFd.ok(),
                        "Failed to create background thread buffer release event file descriptor. "
                        "errno=%d message='%s'",
                        errno, strerror(errno));

    epoll_event registerEventFd{};
    registerEventFd.events = EPOLLIN;
    registerEventFd.data.fd = eventFd.get();
    status = epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &registerEventFd);
    LOG_ALWAYS_FATAL_IF(status == -1,
                        "Failed to register background thread event file descriptor with epoll. "
                        "errno=%d message='%s'",
                        errno, strerror(errno));

    mEventFd = eventFd.get();

    std::thread([epollFd = std::move(epollFd), eventFd = std::move(eventFd),
                 weakBbq = wp<BLASTBufferQueue>(bbq)]() {
        pthread_setname_np(pthread_self(), "BufferReleaseThread");
        while (true) {
            epoll_event event{};
            int eventCount;
            do {
                eventCount = epoll_wait(epollFd.get(), &event, 1 /*maxevents*/, -1 /*timeout*/);
            } while (eventCount == -1 && errno != EINTR);

            if (eventCount == -1) {
                ALOGE("epoll_wait error while waiting for buffer release in background thread. "
                      "errno=%d message='%s'",
                      errno, strerror(errno));
                continue;
            }

            // EventFd is used to join this thread.
            if (event.data.fd == eventFd.get()) {
                return;
            }

            sp<BLASTBufferQueue> bbq = weakBbq.promote();
            if (!bbq) {
                return;
            }

            // If there are threads blocking on dequeue, give those threads priority for handling
            // the release.
            if (bbq->mThreadsBlockingOnDequeue > 0) {
                std::this_thread::sleep_for(0ms);
                continue;
            }

            ReleaseCallbackId id;
            sp<Fence> fence;
            uint32_t maxAcquiredBufferCount;
            status_t status = bbq->mBufferReleaseConsumer->readReleaseFence(id, fence,
                                                                            maxAcquiredBufferCount);
            if (status != OK) {
                ALOGE("failed to read from buffer release consumer in background thread. errno=%d "
                      "message='%s'",
                      errno, strerror(errno));
                continue;
            }
            bbq->releaseBufferCallback(id, fence, maxAcquiredBufferCount);
        }
    }).detach();
}

BLASTBufferQueue::BufferReleaseThread::~BufferReleaseThread() {
    eventfd_write(mEventFd, 1);
}

#endif
#endif


} // namespace android
} // namespace android
+27 −39
Original line number Original line Diff line number Diff line
@@ -35,35 +35,35 @@ namespace android::gui {
namespace {
namespace {


template <typename T>
template <typename T>
static void readAligned(const void*& buffer, size_t& size, T& value) {
void readAligned(const void*& buffer, size_t& size, T& value) {
    size -= FlattenableUtils::align<alignof(T)>(buffer);
    size -= FlattenableUtils::align<alignof(T)>(buffer);
    FlattenableUtils::read(buffer, size, value);
    FlattenableUtils::read(buffer, size, value);
}
}


template <typename T>
template <typename T>
static void writeAligned(void*& buffer, size_t& size, T value) {
void writeAligned(void*& buffer, size_t& size, T value) {
    size -= FlattenableUtils::align<alignof(T)>(buffer);
    size -= FlattenableUtils::align<alignof(T)>(buffer);
    FlattenableUtils::write(buffer, size, value);
    FlattenableUtils::write(buffer, size, value);
}
}


template <typename T>
template <typename T>
static void addAligned(size_t& size, T /* value */) {
void addAligned(size_t& size, T /* value */) {
    size = FlattenableUtils::align<sizeof(T)>(size);
    size = FlattenableUtils::align<sizeof(T)>(size);
    size += sizeof(T);
    size += sizeof(T);
}
}


template <typename T>
template <typename T>
static inline constexpr uint32_t low32(const T n) {
inline constexpr uint32_t low32(const T n) {
    return static_cast<uint32_t>(static_cast<uint64_t>(n));
    return static_cast<uint32_t>(static_cast<uint64_t>(n));
}
}


template <typename T>
template <typename T>
static inline constexpr uint32_t high32(const T n) {
inline constexpr uint32_t high32(const T n) {
    return static_cast<uint32_t>(static_cast<uint64_t>(n) >> 32);
    return static_cast<uint32_t>(static_cast<uint64_t>(n) >> 32);
}
}


template <typename T>
template <typename T>
static inline constexpr T to64(const uint32_t lo, const uint32_t hi) {
inline constexpr T to64(const uint32_t lo, const uint32_t hi) {
    return static_cast<T>(static_cast<uint64_t>(hi) << 32 | lo);
    return static_cast<T>(static_cast<uint64_t>(hi) << 32 | lo);
}
}


@@ -139,19 +139,18 @@ status_t BufferReleaseChannel::ConsumerEndpoint::readReleaseFence(
    std::lock_guard lock{mMutex};
    std::lock_guard lock{mMutex};
    Message message;
    Message message;
    mFlattenedBuffer.resize(message.getFlattenedSize());
    mFlattenedBuffer.resize(message.getFlattenedSize());
    std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer;
    std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer{};


    iovec iov{
    iovec iov{
            .iov_base = mFlattenedBuffer.data(),
            .iov_base = mFlattenedBuffer.data(),
            .iov_len = mFlattenedBuffer.size(),
            .iov_len = mFlattenedBuffer.size(),
    };
    };


    msghdr msg{
    msghdr msg{};
            .msg_iov = &iov,
    msg.msg_iov = &iov;
            .msg_iovlen = 1,
    msg.msg_iovlen = 1;
            .msg_control = controlMessageBuffer.data(),
    msg.msg_control = controlMessageBuffer.data();
            .msg_controllen = controlMessageBuffer.size(),
    msg.msg_controllen = controlMessageBuffer.size();
    };


    ssize_t result;
    ssize_t result;
    do {
    do {
@@ -161,7 +160,7 @@ status_t BufferReleaseChannel::ConsumerEndpoint::readReleaseFence(
        if (errno == EWOULDBLOCK || errno == EAGAIN) {
        if (errno == EWOULDBLOCK || errno == EAGAIN) {
            return WOULD_BLOCK;
            return WOULD_BLOCK;
        }
        }
        ALOGE("Error reading release fence from socket: error %#x (%s)", errno, strerror(errno));
        ALOGE("Error reading release fence from socket: error %d (%s)", errno, strerror(errno));
        return UNKNOWN_ERROR;
        return UNKNOWN_ERROR;
    }
    }


@@ -200,8 +199,8 @@ status_t BufferReleaseChannel::ConsumerEndpoint::readReleaseFence(
    return OK;
    return OK;
}
}


int BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(const ReleaseCallbackId& callbackId,
status_t BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(
                                                              const sp<Fence>& fence,
        const ReleaseCallbackId& callbackId, const sp<Fence>& fence,
        uint32_t maxAcquiredBufferCount) {
        uint32_t maxAcquiredBufferCount) {
    Message message{callbackId, fence ? fence : Fence::NO_FENCE, maxAcquiredBufferCount};
    Message message{callbackId, fence ? fence : Fence::NO_FENCE, maxAcquiredBufferCount};
    mFlattenedBuffer.resize(message.getFlattenedSize());
    mFlattenedBuffer.resize(message.getFlattenedSize());
@@ -213,25 +212,22 @@ int BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(const ReleaseCallb
        size_t flattenedBufferSize = mFlattenedBuffer.size();
        size_t flattenedBufferSize = mFlattenedBuffer.size();
        int* flattenedFdPtr = &flattenedFd;
        int* flattenedFdPtr = &flattenedFd;
        size_t flattenedFdCount = 1;
        size_t flattenedFdCount = 1;
        if (status_t err = message.flatten(flattenedBufferPtr, flattenedBufferSize, flattenedFdPtr,
        if (status_t status = message.flatten(flattenedBufferPtr, flattenedBufferSize,
                                           flattenedFdCount);
                                              flattenedFdPtr, flattenedFdCount);
            err != OK) {
            status != OK) {
            ALOGE("Failed to flatten BufferReleaseChannel message.");
            return status;
            return err;
        }
        }
    }
    }


    iovec iov{
    iovec iov{};
            .iov_base = mFlattenedBuffer.data(),
    iov.iov_base = mFlattenedBuffer.data();
            .iov_len = mFlattenedBuffer.size(),
    iov.iov_len = mFlattenedBuffer.size();
    };


    msghdr msg{
    msghdr msg{};
            .msg_iov = &iov,
    msg.msg_iov = &iov;
            .msg_iovlen = 1,
    msg.msg_iovlen = 1;
    };


    std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer;
    std::array<uint8_t, CMSG_SPACE(sizeof(int))> controlMessageBuffer{};
    if (fence && fence->isValid()) {
    if (fence && fence->isValid()) {
        msg.msg_control = controlMessageBuffer.data();
        msg.msg_control = controlMessageBuffer.data();
        msg.msg_controllen = controlMessageBuffer.size();
        msg.msg_controllen = controlMessageBuffer.size();
@@ -248,7 +244,6 @@ int BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(const ReleaseCallb
        result = sendmsg(mFd, &msg, 0);
        result = sendmsg(mFd, &msg, 0);
    } while (result == -1 && errno == EINTR);
    } while (result == -1 && errno == EINTR);
    if (result == -1) {
    if (result == -1) {
        ALOGD("Error writing release fence to socket: error %#x (%s)", errno, strerror(errno));
        return -errno;
        return -errno;
    }
    }


@@ -344,13 +339,6 @@ status_t BufferReleaseChannel::open(std::string name,
        return -errno;
        return -errno;
    }
    }


    // Make the producer write-only
    if (shutdown(producerFd.get(), SHUT_RD) == -1) {
        ALOGE("[%s] Failed to shutdown reading on producer socket. errno=%d message='%s'",
              name.c_str(), errno, strerror(errno));
        return -errno;
    }

    outConsumer = std::make_unique<ConsumerEndpoint>(name, std::move(consumerFd));
    outConsumer = std::make_unique<ConsumerEndpoint>(name, std::move(consumerFd));
    outProducer = std::make_shared<ProducerEndpoint>(std::move(name), std::move(producerFd));
    outProducer = std::make_shared<ProducerEndpoint>(std::move(name), std::move(producerFd));
    return STATUS_OK;
    return STATUS_OK;
+2 −13
Original line number Original line Diff line number Diff line
@@ -325,6 +325,8 @@ private:
    std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mBufferReleaseConsumer;
    std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mBufferReleaseConsumer;
    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;
    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;


    void drainBufferReleaseConsumer();

    class BufferReleaseReader {
    class BufferReleaseReader {
    public:
    public:
        explicit BufferReleaseReader(BLASTBufferQueue&);
        explicit BufferReleaseReader(BLASTBufferQueue&);
@@ -353,19 +355,6 @@ private:
    };
    };


    std::optional<BufferReleaseReader> mBufferReleaseReader;
    std::optional<BufferReleaseReader> mBufferReleaseReader;

    std::atomic<int> mThreadsBlockingOnDequeue = 0;

    class BufferReleaseThread {
    public:
        BufferReleaseThread(const sp<BLASTBufferQueue>&);
        ~BufferReleaseThread();

    private:
        int mEventFd;
    };

    std::optional<BufferReleaseThread> mBufferReleaseThread;
#endif
#endif
};
};


+31 −16
Original line number Original line Diff line number Diff line
@@ -29,11 +29,11 @@ namespace {


// Helper function to check if two file descriptors point to the same file.
// Helper function to check if two file descriptors point to the same file.
bool is_same_file(int fd1, int fd2) {
bool is_same_file(int fd1, int fd2) {
    struct stat stat1;
    struct stat stat1 {};
    if (fstat(fd1, &stat1) != 0) {
    if (fstat(fd1, &stat1) != 0) {
        return false;
        return false;
    }
    }
    struct stat stat2;
    struct stat stat2 {};
    if (fstat(fd2, &stat2) != 0) {
    if (fstat(fd2, &stat2) != 0) {
        return false;
        return false;
    }
    }
@@ -42,7 +42,18 @@ bool is_same_file(int fd1, int fd2) {


} // namespace
} // namespace


TEST(BufferReleaseChannelTest, MessageFlattenable) {
class BufferReleaseChannelTest : public testing::Test {
protected:
    std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> mConsumer;
    std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> mProducer;

    void SetUp() override {
        ASSERT_EQ(OK,
                  BufferReleaseChannel::open("BufferReleaseChannelTest"s, mConsumer, mProducer));
    }
};

TEST_F(BufferReleaseChannelTest, MessageFlattenable) {
    ReleaseCallbackId releaseCallbackId{1, 2};
    ReleaseCallbackId releaseCallbackId{1, 2};
    sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
    sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
    uint32_t maxAcquiredBufferCount = 5;
    uint32_t maxAcquiredBufferCount = 5;
@@ -92,31 +103,23 @@ TEST(BufferReleaseChannelTest, MessageFlattenable) {


// Verify that the BufferReleaseChannel consume returns WOULD_BLOCK when there's no message
// Verify that the BufferReleaseChannel consume returns WOULD_BLOCK when there's no message
// available.
// available.
TEST(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
TEST_F(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
    std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
    std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
    ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));

    ReleaseCallbackId releaseCallbackId;
    ReleaseCallbackId releaseCallbackId;
    sp<Fence> releaseFence;
    sp<Fence> releaseFence;
    uint32_t maxAcquiredBufferCount;
    uint32_t maxAcquiredBufferCount;
    ASSERT_EQ(WOULD_BLOCK,
    ASSERT_EQ(WOULD_BLOCK,
              consumer->readReleaseFence(releaseCallbackId, releaseFence, maxAcquiredBufferCount));
              mConsumer->readReleaseFence(releaseCallbackId, releaseFence, maxAcquiredBufferCount));
}
}


// Verify that we can write a message to the BufferReleaseChannel producer and read that message
// Verify that we can write a message to the BufferReleaseChannel producer and read that message
// using the BufferReleaseChannel consumer.
// using the BufferReleaseChannel consumer.
TEST(BufferReleaseChannelTest, ProduceAndConsume) {
TEST_F(BufferReleaseChannelTest, ProduceAndConsume) {
    std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
    std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
    ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));

    sp<Fence> fence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
    sp<Fence> fence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));


    for (uint64_t i = 0; i < 64; i++) {
    for (uint64_t i = 0; i < 64; i++) {
        ReleaseCallbackId producerId{i, i + 1};
        ReleaseCallbackId producerId{i, i + 1};
        uint32_t maxAcquiredBufferCount = i + 2;
        uint32_t maxAcquiredBufferCount = i + 2;
        ASSERT_EQ(OK, producer->writeReleaseFence(producerId, fence, maxAcquiredBufferCount));
        ASSERT_EQ(OK, mProducer->writeReleaseFence(producerId, fence, maxAcquiredBufferCount));
    }
    }


    for (uint64_t i = 0; i < 64; i++) {
    for (uint64_t i = 0; i < 64; i++) {
@@ -127,7 +130,7 @@ TEST(BufferReleaseChannelTest, ProduceAndConsume) {
        sp<Fence> consumerFence;
        sp<Fence> consumerFence;
        uint32_t maxAcquiredBufferCount;
        uint32_t maxAcquiredBufferCount;
        ASSERT_EQ(OK,
        ASSERT_EQ(OK,
                  consumer->readReleaseFence(consumerId, consumerFence, maxAcquiredBufferCount));
                  mConsumer->readReleaseFence(consumerId, consumerFence, maxAcquiredBufferCount));


        ASSERT_EQ(expectedId, consumerId);
        ASSERT_EQ(expectedId, consumerId);
        ASSERT_TRUE(is_same_file(fence->get(), consumerFence->get()));
        ASSERT_TRUE(is_same_file(fence->get(), consumerFence->get()));
@@ -135,4 +138,16 @@ TEST(BufferReleaseChannelTest, ProduceAndConsume) {
    }
    }
}
}


// Verify that BufferReleaseChannel::ConsumerEndpoint's socket can't be written to.
TEST_F(BufferReleaseChannelTest, ConsumerSocketReadOnly) {
    uint64_t data = 0;
    ASSERT_EQ(-1, write(mConsumer->getFd().get(), &data, sizeof(uint64_t)));
    ASSERT_EQ(errno, EPIPE);
}

// Verify that BufferReleaseChannel::ProducerEndpoint's socket can't be read from.
TEST_F(BufferReleaseChannelTest, ProducerSocketWriteOnly) {
    ASSERT_EQ(0, read(mProducer->getFd().get(), nullptr, sizeof(uint64_t)));
}

} // namespace android
} // namespace android
 No newline at end of file
+7 −7
Original line number Original line Diff line number Diff line
@@ -294,7 +294,7 @@ public:
                    transactionBody) {
                    transactionBody) {
        SurfaceComposerClient::Transaction t;
        SurfaceComposerClient::Transaction t;
        transactionBody(t, mSurfaceControl);
        transactionBody(t, mSurfaceControl);
        t.apply(true);
        t.apply(/*synchronously=*/true);
    }
    }


    virtual void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
    virtual void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) {
@@ -307,7 +307,7 @@ public:
        t.setAlpha(mSurfaceControl, 1);
        t.setAlpha(mSurfaceControl, 1);
        auto reportedListener = sp<SynchronousWindowInfosReportedListener>::make();
        auto reportedListener = sp<SynchronousWindowInfosReportedListener>::make();
        t.addWindowInfosReportedListener(reportedListener);
        t.addWindowInfosReportedListener(reportedListener);
        t.apply();
        t.apply(/*synchronously=*/true);
        reportedListener->wait();
        reportedListener->wait();
    }
    }


@@ -319,7 +319,7 @@ public:
        request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
        request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
        request.displayId = displayId.val();
        request.displayId = displayId.val();
        t.setFocusedWindow(request);
        t.setFocusedWindow(request);
        t.apply(true);
        t.apply(/*synchronously=*/true);
    }
    }


public:
public:
@@ -363,7 +363,7 @@ public:
                    transactionBody) override {
                    transactionBody) override {
        SurfaceComposerClient::Transaction t;
        SurfaceComposerClient::Transaction t;
        transactionBody(t, mParentSurfaceControl);
        transactionBody(t, mParentSurfaceControl);
        t.apply(true);
        t.apply(/*synchronously=*/true);
    }
    }


    void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) override {
    void showAt(int x, int y, Rect crop = Rect(0, 0, 100, 100)) override {
@@ -377,7 +377,7 @@ public:
        t.setInputWindowInfo(mSurfaceControl, mInputInfo);
        t.setInputWindowInfo(mSurfaceControl, mInputInfo);
        t.setCrop(mSurfaceControl, crop);
        t.setCrop(mSurfaceControl, crop);
        t.setAlpha(mSurfaceControl, 1);
        t.setAlpha(mSurfaceControl, 1);
        t.apply(true);
        t.apply(/*synchronously=*/true);
    }
    }


private:
private:
@@ -417,7 +417,7 @@ public:
                BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
                BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
        sp<GraphicBuffer> buffer =
        sp<GraphicBuffer> buffer =
                new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888, 1, usageFlags, "test");
                new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888, 1, usageFlags, "test");
        Transaction().setBuffer(layer, buffer).apply(true);
        Transaction().setBuffer(layer, buffer).apply(/*synchronously=*/true);
        usleep(mBufferPostDelay);
        usleep(mBufferPostDelay);
    }
    }


@@ -1207,7 +1207,7 @@ public:
        t.setDisplayLayerStack(token, layerStack);
        t.setDisplayLayerStack(token, layerStack);
        t.setDisplayProjection(token, ui::ROTATION_0, {0, 0, width, height},
        t.setDisplayProjection(token, ui::ROTATION_0, {0, 0, width, height},
                               {offsetX, offsetY, offsetX + width, offsetY + height});
                               {offsetX, offsetY, offsetX + width, offsetY + height});
        t.apply(true);
        t.apply(/*synchronously=*/true);


        mVirtualDisplays.push_back(token);
        mVirtualDisplays.push_back(token);
    }
    }
Loading