blob: 11d122b525898e339a66a153ff01920fe46d91dc [file] [log] [blame]
Patrick Williamsf693bcf2024-08-02 09:55:23 -05001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <string>
18#include <vector>
19
20#include <gtest/gtest.h>
21#include <gui/BufferReleaseChannel.h>
22
23using namespace std::string_literals;
24using android::gui::BufferReleaseChannel;
25
26namespace android {
27
28namespace {
29
30// Helper function to check if two file descriptors point to the same file.
31bool is_same_file(int fd1, int fd2) {
32 struct stat stat1;
33 if (fstat(fd1, &stat1) != 0) {
34 return false;
35 }
36 struct stat stat2;
37 if (fstat(fd2, &stat2) != 0) {
38 return false;
39 }
40 return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
41}
42
43} // namespace
44
45TEST(BufferReleaseChannelTest, MessageFlattenable) {
46 ReleaseCallbackId releaseCallbackId{1, 2};
47 sp<Fence> releaseFence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
48 uint32_t maxAcquiredBufferCount = 5;
49
50 std::vector<uint8_t> dataBuffer;
51 std::vector<int> fdBuffer;
52
53 // Verify that we can flatten a message
54 {
55 BufferReleaseChannel::Message message{releaseCallbackId, releaseFence,
56 maxAcquiredBufferCount};
57
58 dataBuffer.resize(message.getFlattenedSize());
59 void* dataPtr = dataBuffer.data();
60 size_t dataSize = dataBuffer.size();
61
62 fdBuffer.resize(message.getFdCount());
63 int* fdPtr = fdBuffer.data();
64 size_t fdSize = fdBuffer.size();
65
66 ASSERT_EQ(OK, message.flatten(dataPtr, dataSize, fdPtr, fdSize));
67
68 // Fence's unique_fd uses fdsan to check ownership of the file descriptor. Normally the file
69 // descriptor is passed through the Unix socket and duplicated (and sent to another process)
70 // so there's no problem with duplicate file descriptor ownership. For this unit test, we
71 // need to set up a duplicate file descriptor to avoid crashing due to duplicate ownership.
72 ASSERT_EQ(releaseFence->get(), fdBuffer[0]);
73 fdBuffer[0] = message.releaseFence->dup();
74 }
75
76 // Verify that we can unflatten a message
77 {
78 BufferReleaseChannel::Message message;
79
80 const void* dataPtr = dataBuffer.data();
81 size_t dataSize = dataBuffer.size();
82
83 const int* fdPtr = fdBuffer.data();
84 size_t fdSize = fdBuffer.size();
85
86 ASSERT_EQ(OK, message.unflatten(dataPtr, dataSize, fdPtr, fdSize));
87 ASSERT_EQ(releaseCallbackId, message.releaseCallbackId);
88 ASSERT_TRUE(is_same_file(releaseFence->get(), message.releaseFence->get()));
89 ASSERT_EQ(maxAcquiredBufferCount, message.maxAcquiredBufferCount);
90 }
91}
92
93// Verify that the BufferReleaseChannel consume returns WOULD_BLOCK when there's no message
94// available.
95TEST(BufferReleaseChannelTest, ConsumerEndpointIsNonBlocking) {
96 std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
97 std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
98 ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));
99
100 ReleaseCallbackId releaseCallbackId;
101 sp<Fence> releaseFence;
102 uint32_t maxAcquiredBufferCount;
103 ASSERT_EQ(WOULD_BLOCK,
104 consumer->readReleaseFence(releaseCallbackId, releaseFence, maxAcquiredBufferCount));
105}
106
107// Verify that we can write a message to the BufferReleaseChannel producer and read that message
108// using the BufferReleaseChannel consumer.
109TEST(BufferReleaseChannelTest, ProduceAndConsume) {
110 std::unique_ptr<BufferReleaseChannel::ConsumerEndpoint> consumer;
111 std::shared_ptr<BufferReleaseChannel::ProducerEndpoint> producer;
112 ASSERT_EQ(OK, BufferReleaseChannel::open("test-channel"s, consumer, producer));
113
114 sp<Fence> fence = sp<Fence>::make(memfd_create("fake-fence-fd", 0));
115
116 for (uint64_t i = 0; i < 64; i++) {
117 ReleaseCallbackId producerId{i, i + 1};
118 uint32_t maxAcquiredBufferCount = i + 2;
119 ASSERT_EQ(OK, producer->writeReleaseFence(producerId, fence, maxAcquiredBufferCount));
120 }
121
122 for (uint64_t i = 0; i < 64; i++) {
123 ReleaseCallbackId expectedId{i, i + 1};
124 uint32_t expectedMaxAcquiredBufferCount = i + 2;
125
126 ReleaseCallbackId consumerId;
127 sp<Fence> consumerFence;
128 uint32_t maxAcquiredBufferCount;
129 ASSERT_EQ(OK,
130 consumer->readReleaseFence(consumerId, consumerFence, maxAcquiredBufferCount));
131
132 ASSERT_EQ(expectedId, consumerId);
133 ASSERT_TRUE(is_same_file(fence->get(), consumerFence->get()));
134 ASSERT_EQ(expectedMaxAcquiredBufferCount, maxAcquiredBufferCount);
135 }
136}
137
138} // namespace android