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 Diff line number Diff line
@@ -52,19 +52,18 @@ using namespace std::chrono_literals;
namespace {

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
// RAII wrapper to defer arbitrary work until the Deferred instance is deleted.
template <class F>
class Deferred {
template <class Mutex>
class UnlockGuard {
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;
    Deferred& operator=(const Deferred&) = delete;
    UnlockGuard(const UnlockGuard&) = delete;
    UnlockGuard& operator=(const UnlockGuard&) = delete;

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

@@ -271,9 +270,6 @@ BLASTBufferQueue::~BLASTBufferQueue() {
void BLASTBufferQueue::onFirstRef() {
    // safe default, most producers are expected to override this
    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,
@@ -297,11 +293,16 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    mSurfaceControl = surface;
    SurfaceComposerClient::Transaction t;
    if (surfaceControlChanged) {
        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
                   layer_state_t::eEnableBackpressure);
#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
        t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
                   layer_state_t::eEnableBackpressure);
        applyTransaction = true;
    }
    mTransformHint = mSurfaceControl->getTransformHint();
@@ -325,7 +326,7 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    }
    if (applyTransaction) {
        // 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.frameEventStats.dequeueReadyTime);
                }
#if !COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
                auto currFrameNumber = stat.frameEventStats.frameNumber;
                std::vector<ReleaseCallbackId> staleReleases;
                for (const auto& [key, value]: mSubmitted) {
@@ -435,7 +435,6 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence
                                                stat.currentMaxAcquiredBufferCount,
                                                true /* fakeRelease */);
                }
#endif
            } else {
                BQA_LOGE("Failed to find matching SurfaceControl in transactionCallback");
            }
@@ -469,6 +468,9 @@ ReleaseBufferCallback BLASTBufferQueue::makeReleaseBufferCallbackThunk() {
            return;
        }
        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) {
    auto it = mSubmitted.find(callbackId);
    if (it == mSubmitted.end()) {
        BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %s",
                 callbackId.to_string().c_str());
        return;
    }
    mNumAcquired--;
@@ -646,12 +646,7 @@ status_t BLASTBufferQueue::acquireNextBufferLocked(
                           bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
                           bufferItem.mScalingMode, crop);

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

    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 don't miss an interrupt.
        bbq->mBufferReleaseReader->clearInterrupts();
        bbq->mThreadsBlockingOnDequeue++;
        bufferQueueLock.unlock();
        Deferred cleanup{[&]() {
            bufferQueueLock.lock();
            bbq->mThreadsBlockingOnDequeue--;
        }};
        UnlockGuard unlockGuard{bufferQueueLock};

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

#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} {
    mEpollFd = android::base::unique_fd{epoll_create1(EPOLL_CLOEXEC)};
    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

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

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);
    FlattenableUtils::read(buffer, size, value);
}

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);
    FlattenableUtils::write(buffer, size, value);
}

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 += sizeof(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));
}

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);
}

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);
}

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

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

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

    ssize_t result;
    do {
@@ -161,7 +160,7 @@ status_t BufferReleaseChannel::ConsumerEndpoint::readReleaseFence(
        if (errno == EWOULDBLOCK || errno == EAGAIN) {
            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;
    }

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

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

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

    msghdr msg{
            .msg_iov = &iov,
            .msg_iovlen = 1,
    };
    msghdr msg{};
    msg.msg_iov = &iov;
    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()) {
        msg.msg_control = controlMessageBuffer.data();
        msg.msg_controllen = controlMessageBuffer.size();
@@ -248,7 +244,6 @@ int BufferReleaseChannel::ProducerEndpoint::writeReleaseFence(const ReleaseCallb
        result = sendmsg(mFd, &msg, 0);
    } while (result == -1 && errno == EINTR);
    if (result == -1) {
        ALOGD("Error writing release fence to socket: error %#x (%s)", errno, strerror(errno));
        return -errno;
    }

@@ -344,13 +339,6 @@ status_t BufferReleaseChannel::open(std::string name,
        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));
    outProducer = std::make_shared<ProducerEndpoint>(std::move(name), std::move(producerFd));
    return STATUS_OK;
+2 −13
Original line number Diff line number Diff line
@@ -325,6 +325,8 @@ private:
    std::unique_ptr<gui::BufferReleaseChannel::ConsumerEndpoint> mBufferReleaseConsumer;
    std::shared_ptr<gui::BufferReleaseChannel::ProducerEndpoint> mBufferReleaseProducer;

    void drainBufferReleaseConsumer();

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

    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
};

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

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

} // 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};
    sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
    uint32_t maxAcquiredBufferCount = 5;
@@ -92,31 +103,23 @@ TEST(BufferReleaseChannelTest, MessageFlattenable) {

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

TEST_F(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
    ReleaseCallbackId releaseCallbackId;
    sp<Fence> releaseFence;
    uint32_t maxAcquiredBufferCount;
    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
// using the BufferReleaseChannel consumer.
TEST(BufferReleaseChannelTest, ProduceAndConsume) {
    std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
    std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
    ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));

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

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

        ASSERT_EQ(expectedId, consumerId);
        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
 No newline at end of file
+7 −7
Original line number Diff line number Diff line
@@ -294,7 +294,7 @@ public:
                    transactionBody) {
        SurfaceComposerClient::Transaction t;
        transactionBody(t, mSurfaceControl);
        t.apply(true);
        t.apply(/*synchronously=*/true);
    }

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

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

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

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

private:
@@ -417,7 +417,7 @@ public:
                BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE;
        sp<GraphicBuffer> buffer =
                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);
    }

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

        mVirtualDisplays.push_back(token);
    }
Loading