1 /*
2 * Copyright 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 <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 #include <C2Buffer.h>
21 #include <C2FenceFactory.h>
22
23 #include <unistd.h>
24
25 #include <android-base/unique_fd.h>
26 #include <linux/kcmp.h> /* Definition of KCMP_* constants */
27 #include <sys/mman.h>
28 #include <sys/syscall.h> /* Definition of SYS_* constants */
29 #include <ui/Fence.h>
30
31 namespace android {
32
fd_kcmp(int fd1,int fd2)33 static int fd_kcmp(int fd1, int fd2) {
34 static pid_t pid = getpid();
35
36 return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2);
37 }
38
39 // matcher to check if value (arg) and fd refers to the same file
40 MATCHER_P(RefersToTheSameFile, fd, "") {
41 return fd_kcmp(fd, arg) == 0;
42 }
43
44 // matcher to check if value (arg) is a dup of an fd
45 MATCHER_P(IsDupOf, fd, "") {
46 return (ExplainMatchResult(::testing::Ne(-1), arg, result_listener) &&
47 ExplainMatchResult(::testing::Ne(fd), arg, result_listener) &&
48 ExplainMatchResult(RefersToTheSameFile(fd), arg, result_listener));
49 }
50
51 class C2FenceTest : public ::testing::Test {
52 public:
53 C2FenceTest() = default;
54
55 ~C2FenceTest() = default;
56
57
58 protected:
59 enum : int32_t {
60 SYNC_FENCE_DEPRECATED_MAGIC = 3,
61 SYNC_FENCE_UNORDERED_MAGIC = '\302fsu',
62 SYNC_FENCE_MAGIC = '\302fso',
63 };
64
65 // Validate a null fence
66 void validateNullFence(const C2Fence &fence);
67
68 // Validate a single fd sync fence
69 void validateSingleFdFence(const C2Fence &fence, int fd);
70
71 // Validate a two fd unordered sync fence
72 void validateTwoFdUnorderedFence(const C2Fence &fence, int fd1, int fd2, int mergeFd);
73
74 // Validate a three fd sync fence
75 void validateThreeFdFence(const C2Fence &fence, int fd1, int fd2, int fd3);
76 };
77
TEST_F(C2FenceTest,IsDupOf_sanity)78 TEST_F(C2FenceTest, IsDupOf_sanity) {
79 int fd1 = memfd_create("test1", 0 /* flags */);
80 int fd2 = memfd_create("test2", 0 /* flags */);
81 int fd3 = memfd_create("test3", 0 /* flags */);
82
83 EXPECT_THAT(fd1, ::testing::Not(IsDupOf(fd2)));
84 EXPECT_THAT(-1, ::testing::Not(IsDupOf(fd2)));
85 EXPECT_THAT(-1, ::testing::Not(IsDupOf(-1)));
86 EXPECT_THAT(fd3, ::testing::Not(IsDupOf(fd3)));
87
88 int fd4 = dup(fd3);
89 EXPECT_THAT(fd4, IsDupOf(fd3));
90 EXPECT_THAT(fd3, IsDupOf(fd4));
91
92 close(fd1);
93 close(fd2);
94 close(fd3);
95 close(fd4);
96 }
97
TEST_F(C2FenceTest,NullFence)98 TEST_F(C2FenceTest, NullFence) {
99 validateNullFence(C2Fence());
100 }
101
validateNullFence(const C2Fence & fence)102 void C2FenceTest::validateNullFence(const C2Fence &fence) {
103 // Verify that the fence is valid.
104 EXPECT_TRUE(fence.valid());
105 EXPECT_TRUE(fence.ready());
106 base::unique_fd fenceFd{fence.fd()};
107 EXPECT_EQ(fenceFd.get(), -1);
108 EXPECT_FALSE(fence.isHW()); // perhaps this should be false for a null fence
109
110 // A null fence has no fds
111 std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
112 EXPECT_THAT(fds, ::testing::IsEmpty());
113 for (int fd : fds) {
114 close(fd);
115 }
116
117 // A null fence has no native handle
118 native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
119 EXPECT_THAT(handle, ::testing::IsNull());
120 if (handle) {
121 native_handle_close(handle);
122 native_handle_delete(handle);
123 }
124 }
125
TEST_F(C2FenceTest,SyncFence_with_negative_fd)126 TEST_F(C2FenceTest, SyncFence_with_negative_fd) {
127 // Create a SyncFence with a negative fd.
128 C2Fence fence = _C2FenceFactory::CreateSyncFence(-1, false /* validate */);
129
130 validateNullFence(fence);
131 }
132
TEST_F(C2FenceTest,SyncFence_with_valid_fd)133 TEST_F(C2FenceTest, SyncFence_with_valid_fd) {
134 // Create a SyncFence with a valid fd. We cannot create an actual sync fd,
135 // so we cannot test wait(), but we can verify the ABI APIs
136
137 int fd = memfd_create("test", 0 /* flags */);
138
139 C2Fence fence = _C2FenceFactory::CreateSyncFence(fd, false /* validate */);
140 validateSingleFdFence(fence, fd);
141 }
142
validateSingleFdFence(const C2Fence & fence,int fd)143 void C2FenceTest::validateSingleFdFence(const C2Fence &fence, int fd) {
144 // EXPECT_TRUE(fence.valid()); // need a valid sync fd to test this
145 // EXPECT_TRUE(fence.ready());
146 // Verify that the fence says it is a HW sync fence.
147 EXPECT_TRUE(fence.isHW()); // FIXME this may be an implementation detail
148
149 // Verify that the fd returned is a duped version of the initial fd
150 base::unique_fd fenceFd{fence.fd()};
151 EXPECT_THAT(fenceFd.get(), IsDupOf(fd));
152
153 // Verify that fds returns a duped version of the initial fd
154 std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
155 EXPECT_THAT(fds, ::testing::SizeIs(1));
156 EXPECT_THAT(fds, ::testing::ElementsAre(IsDupOf(fd)));
157 for (int fd_i : fds) {
158 close(fd_i);
159 }
160
161 native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
162 EXPECT_THAT(handle, ::testing::NotNull());
163 if (handle) {
164 EXPECT_EQ(handle->numFds, 1);
165 EXPECT_EQ(handle->numInts, 1);
166 EXPECT_THAT(handle->data[0], IsDupOf(fd));
167 EXPECT_EQ(handle->data[1], SYNC_FENCE_MAGIC);
168
169 native_handle_close(handle);
170 native_handle_delete(handle);
171 }
172 }
173
TEST_F(C2FenceTest,UnorderedMultiSyncFence_with_one_valid_test_fd)174 TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_one_valid_test_fd) {
175 // Create a multi SyncFence with a single valid fd. This should create
176 // a single fd sync fence. We can only validate this through its public
177 // methods: fd/fds and verify the native handle ABI.
178
179 int fd = memfd_create("test", 0 /* flags */);
180
181 c2_status_t status = C2_BAD_VALUE;
182 C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
183 { -1, fd, -1 }, &status);
184 // if we only have one valid fd, we are not merging fences, so the test fd is not validated
185 EXPECT_EQ(status, C2_OK);
186
187 validateSingleFdFence(fence, fd);
188 }
189
TEST_F(C2FenceTest,UnorderedMultiSyncFence_with_one_valid_test_fd_null_status)190 TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_one_valid_test_fd_null_status) {
191 // Create a multi SyncFence with a single valid fd. This should create
192 // a single fd sync fence. We can only validate this through its public
193 // methods: fd/fds and verify the native handle ABI.
194
195 int fd = memfd_create("test", 0 /* flags */);
196
197 C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
198 { -1, fd, -1 });
199
200 validateSingleFdFence(fence, fd);
201 }
202
TEST_F(C2FenceTest,UnorderedMultiSyncFence_with_merge_failure)203 TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_merge_failure) {
204 // Create a multi SyncFence with a multiple non-sync fence fds. This should
205 // result in a fence created, but also an error.
206
207 int fd1 = memfd_create("test1", 0 /* flags */);
208 int fd2 = memfd_create("test2", 0 /* flags */);
209 int fd3 = memfd_create("test3", 0 /* flags */);
210
211 c2_status_t status = C2_BAD_VALUE;
212 C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
213 { fd1, fd2, fd3 }, &status);
214 EXPECT_EQ(status, C2_CORRUPTED);
215
216 validateThreeFdFence(fence, fd1, fd2, fd3);
217 }
218
TEST_F(C2FenceTest,UnorderedMultiSyncFence_with_merge_failure_null_status)219 TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_merge_failure_null_status) {
220 // Create a multi SyncFence with a multiple non-sync fence fds. This should
221 // result in a fence created, but also an error.
222
223 int fd1 = memfd_create("test1", 0 /* flags */);
224 int fd2 = memfd_create("test2", 0 /* flags */);
225 int fd3 = memfd_create("test3", 0 /* flags */);
226
227 C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
228 { fd1, fd2, fd3 });
229
230 validateThreeFdFence(fence, fd1, fd2, fd3);
231 }
232
TEST_F(C2FenceTest,UnorderedMultiSyncFence_with_multiple_fds)233 TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_multiple_fds) {
234 // We cannot create a true unordered multi sync fence as we can only
235 // create test fds and those cannot be merged. As such, we cannot
236 // test the factory method CreateUnorderedMultiSyncFence. We can however
237 // create a test fence from a constructed native handle.
238
239 // Technically, we need 3 fds as if we end up with only 2, we wouldn't
240 // actually need a 2nd (final fence fd) since it is equivalent to the
241 // first. In fact we will generate (and always generated) a single fd
242 // fence in that case.
243 int fd1 = memfd_create("test1", 0 /* flags */);
244 int fd2 = memfd_create("test2", 0 /* flags */);
245 int mergeFd = memfd_create("test3", 0 /* flags */);
246
247 native_handle_t *handle = native_handle_create(3 /* numfds */, 1 /* numints */);
248 handle->data[0] = fd1;
249 handle->data[1] = fd2;
250 handle->data[2] = mergeFd;
251 handle->data[3] = SYNC_FENCE_UNORDERED_MAGIC;
252 C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
253 native_handle_delete(handle);
254
255 validateTwoFdUnorderedFence(fence, fd1, fd2, mergeFd);
256 }
257
validateTwoFdUnorderedFence(const C2Fence & fence,int fd1,int fd2,int mergeFd)258 void C2FenceTest::validateTwoFdUnorderedFence(
259 const C2Fence &fence, int fd1, int fd2, int mergeFd) {
260 // EXPECT_TRUE(fence.valid()); // need a valid sync fd to test this
261 // EXPECT_TRUE(fence.ready());
262 // Verify that the fence says it is a HW sync fence.
263 EXPECT_TRUE(fence.isHW()); // FIXME this may be an implementation detail
264
265 // Verify that the fd returned is a duped version of the merge fd
266 base::unique_fd fenceFd{fence.fd()};
267 EXPECT_THAT(fenceFd.get(), IsDupOf(mergeFd));
268
269 // Verify that fds returns a duped versions of the initial fds (but not the merge fd)
270 std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
271 EXPECT_THAT(fds, ::testing::SizeIs(2));
272 EXPECT_THAT(fds, ::testing::ElementsAre(IsDupOf(fd1), IsDupOf(fd2)));
273 for (int fd_i : fds) {
274 close(fd_i);
275 }
276
277 native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
278 EXPECT_THAT(handle, ::testing::NotNull());
279 if (handle) {
280 EXPECT_EQ(handle->numFds, 3);
281 EXPECT_EQ(handle->numInts, 1);
282 EXPECT_THAT(handle->data[0], IsDupOf(fd1));
283 EXPECT_THAT(handle->data[1], IsDupOf(fd2));
284 EXPECT_THAT(handle->data[2], IsDupOf(mergeFd));
285 EXPECT_EQ(handle->data[3], SYNC_FENCE_UNORDERED_MAGIC);
286
287 native_handle_close(handle);
288 native_handle_delete(handle);
289 }
290 }
291
TEST_F(C2FenceTest,MultiSyncFence_with_one_valid_test_fd)292 TEST_F(C2FenceTest, MultiSyncFence_with_one_valid_test_fd) {
293 // Create a multi SyncFence with a single valid fd. This should create
294 // a single fd sync fence. We can only validate this through its public
295 // methods: fd/fds and verify the native handle ABI.
296
297 int fd = memfd_create("test", 0 /* flags */);
298
299 c2_status_t status = C2_BAD_VALUE;
300 C2Fence fence = _C2FenceFactory::CreateMultiSyncFence(
301 { -1, fd, -1 }, &status);
302 // if we only have one valid fd, we are not merging fences, so the test fds are not validated
303 EXPECT_EQ(status, C2_OK);
304
305 validateSingleFdFence(fence, fd);
306 }
307
TEST_F(C2FenceTest,MultiSyncFence_with_one_valid_test_fd_null_status)308 TEST_F(C2FenceTest, MultiSyncFence_with_one_valid_test_fd_null_status) {
309 // Create a multi SyncFence with a single valid fd. This should create
310 // a single fd sync fence. We can only validate this through its public
311 // methods: fd/fds and verify the native handle ABI.
312
313 int fd = memfd_create("test", 0 /* flags */);
314
315 C2Fence fence = _C2FenceFactory::CreateMultiSyncFence(
316 { -1, fd, -1 });
317
318 validateSingleFdFence(fence, fd);
319 }
320
TEST_F(C2FenceTest,MultiSyncFence_with_multiple_fds)321 TEST_F(C2FenceTest, MultiSyncFence_with_multiple_fds) {
322 int fd1 = memfd_create("test1", 0 /* flags */);
323 int fd2 = memfd_create("test2", 0 /* flags */);
324 int fd3 = memfd_create("test3", 0 /* flags */);
325
326 c2_status_t status = C2_BAD_VALUE;
327 C2Fence fence = _C2FenceFactory::CreateMultiSyncFence(
328 { fd1, fd2, fd3 }, &status);
329 // test fds are not validated
330 EXPECT_EQ(status, C2_OK);
331
332 validateThreeFdFence(fence, fd1, fd2, fd3);
333 }
334
validateThreeFdFence(const C2Fence & fence,int fd1,int fd2,int fd3)335 void C2FenceTest::validateThreeFdFence(const C2Fence &fence, int fd1, int fd2, int fd3) {
336 // EXPECT_TRUE(fence.valid()); // need a valid sync fd to test this
337 // EXPECT_TRUE(fence.ready());
338 // Verify that the fence says it is a HW sync fence.
339 EXPECT_TRUE(fence.isHW()); // FIXME this may be an implementation detail
340
341 // Verify that the fd returned is a duped version of the final fd
342 base::unique_fd fenceFd{fence.fd()};
343 EXPECT_THAT(fenceFd.get(), IsDupOf(fd3));
344
345 // Verify that fds returns a duped versions of all 3 initial fds
346 std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
347 EXPECT_THAT(fds, ::testing::SizeIs(3));
348 EXPECT_THAT(fds, ::testing::ElementsAre(IsDupOf(fd1), IsDupOf(fd2), IsDupOf(fd3)));
349 for (int fd_i : fds) {
350 close(fd_i);
351 }
352
353 native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
354 EXPECT_THAT(handle, ::testing::NotNull());
355 if (handle) {
356 EXPECT_EQ(handle->numFds, 3);
357 EXPECT_EQ(handle->numInts, 1);
358 EXPECT_THAT(handle->data[0], IsDupOf(fd1));
359 EXPECT_THAT(handle->data[1], IsDupOf(fd2));
360 EXPECT_THAT(handle->data[2], IsDupOf(fd3));
361 EXPECT_EQ(handle->data[3], SYNC_FENCE_MAGIC);
362
363 native_handle_close(handle);
364 native_handle_delete(handle);
365 }
366 }
367
TEST_F(C2FenceTest,BackwardCompat_UDC_sync_fence)368 TEST_F(C2FenceTest, BackwardCompat_UDC_sync_fence) {
369 // Create a single SyncFence from a UDC native handle
370
371 int fd = memfd_create("test", 0 /* flags */);
372
373 native_handle_t *handle = native_handle_create(1 /* numfds */, 1 /* numints */);
374 handle->data[0] = fd;
375 handle->data[1] = SYNC_FENCE_DEPRECATED_MAGIC;
376 C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
377 native_handle_delete(handle);
378
379 validateSingleFdFence(fence, fd);
380 }
381
TEST_F(C2FenceTest,BackwardCompat_24Q1_single_fd_fence)382 TEST_F(C2FenceTest, BackwardCompat_24Q1_single_fd_fence) {
383 // Create a single SyncFence from a 24Q1 native handle
384 // This had the same (albeit separately duped) fd twice, and used the legacy
385 // magic number.
386
387 int fd = memfd_create("test", 0 /* flags */);
388
389 native_handle_t *handle = native_handle_create(2 /* numfds */, 1 /* numints */);
390 handle->data[0] = fd;
391 handle->data[1] = dup(fd);
392 handle->data[2] = SYNC_FENCE_DEPRECATED_MAGIC;
393 C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
394 native_handle_delete(handle);
395
396 validateSingleFdFence(fence, fd);
397 }
398
TEST_F(C2FenceTest,BackwardCompat_24Q3_single_fd_fence)399 TEST_F(C2FenceTest, BackwardCompat_24Q3_single_fd_fence) {
400 // Create a single SyncFence from the defined native handle
401
402 int fd = memfd_create("test", 0 /* flags */);
403
404 native_handle_t *handle = native_handle_create(1 /* numfds */, 1 /* numints */);
405 handle->data[0] = fd;
406 handle->data[1] = SYNC_FENCE_MAGIC;
407 C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
408 native_handle_delete(handle);
409
410 validateSingleFdFence(fence, fd);
411 }
412
TEST_F(C2FenceTest,BackwardCompat_24Q1_multi_fd_fence)413 TEST_F(C2FenceTest, BackwardCompat_24Q1_multi_fd_fence) {
414 // Create a single SyncFence from a 24Q1 era native handle with
415 // the legacy magic number.
416
417 int fd1 = memfd_create("test1", 0 /* flags */);
418 int fd2 = memfd_create("test2", 0 /* flags */);
419 int mergeFd = memfd_create("test3", 0 /* flags */);
420
421 native_handle_t *handle = native_handle_create(3 /* numfds */, 1 /* numints */);
422 handle->data[0] = fd1;
423 handle->data[1] = fd2;
424 handle->data[2] = mergeFd;
425 handle->data[3] = SYNC_FENCE_DEPRECATED_MAGIC;
426 C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
427 native_handle_delete(handle);
428
429 validateTwoFdUnorderedFence(fence, fd1, fd2, mergeFd);
430 }
431
432 // No need to create BackwardCompat_24Q3_unordered_multi_fd_fence because
433 // we are creating that fence already from the 24Q3 native handle layout
434 // in the UnorderedMultiSyncFence_with_multiple_fds test.
435
TEST_F(C2FenceTest,BackwardCompat_24Q3_multi_fd_fence)436 TEST_F(C2FenceTest, BackwardCompat_24Q3_multi_fd_fence) {
437 // Create a single SyncFence from a 24Q1 era native handle with
438 // the legacy magic number.
439
440 int fd1 = memfd_create("test1", 0 /* flags */);
441 int fd2 = memfd_create("test2", 0 /* flags */);
442 int fd3 = memfd_create("test3", 0 /* flags */);
443
444 native_handle_t *handle = native_handle_create(3 /* numfds */, 1 /* numints */);
445 handle->data[0] = fd1;
446 handle->data[1] = fd2;
447 handle->data[2] = fd3;
448 handle->data[3] = SYNC_FENCE_MAGIC;
449 C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
450 native_handle_delete(handle);
451
452 validateThreeFdFence(fence, fd1, fd2, fd3);
453 }
454
455 } // namespace android
456