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