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

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

Merge cherrypicks of ['android-review.googlesource.com/3134373'] into 24Q3-release.

Change-Id: Ifb68903ecc17213389613e36583b92cab9e30d32
parents 7eca2110 a9d953ed
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -45,6 +45,11 @@ cc_test {
        "C2SampleComponent_test.cpp",
        "C2UtilTest.cpp",
        "vndk/C2BufferTest.cpp",
        "vndk/C2FenceTest.cpp",
    ],

    static_libs: [
        "libgmock",
    ],

    shared_libs: [
@@ -52,6 +57,7 @@ cc_test {
        "libcodec2_vndk",
        "libcutils",
        "liblog",
        "libui",
        "libutils",
    ],

+455 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <C2Buffer.h>
#include <C2FenceFactory.h>

#include <unistd.h>

#include <android-base/unique_fd.h>
#include <linux/kcmp.h>       /* Definition of KCMP_* constants */
#include <sys/mman.h>
#include <sys/syscall.h>      /* Definition of SYS_* constants */
#include <ui/Fence.h>

namespace android {

static int fd_kcmp(int fd1, int fd2) {
    static pid_t pid = getpid();

    return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2);
}

// matcher to check if value (arg) and fd refers to the same file
MATCHER_P(RefersToTheSameFile, fd, "") {
    return fd_kcmp(fd, arg) == 0;
}

// matcher to check if value (arg) is a dup of an fd
MATCHER_P(IsDupOf, fd, "") {
    return (ExplainMatchResult(::testing::Ne(-1), arg, result_listener) &&
            ExplainMatchResult(::testing::Ne(fd), arg, result_listener) &&
            ExplainMatchResult(RefersToTheSameFile(fd), arg, result_listener));
}

class C2FenceTest : public ::testing::Test {
public:
    C2FenceTest() = default;

    ~C2FenceTest() = default;


protected:
    enum : int32_t {
        SYNC_FENCE_DEPRECATED_MAGIC     = 3,
        SYNC_FENCE_UNORDERED_MAGIC      = '\302fsu',
        SYNC_FENCE_MAGIC                = '\302fso',
    };

    // Validate a null fence
    void validateNullFence(const C2Fence &fence);

    // Validate a single fd sync fence
    void validateSingleFdFence(const C2Fence &fence, int fd);

    // Validate a two fd unordered sync fence
    void validateTwoFdUnorderedFence(const C2Fence &fence, int fd1, int fd2, int mergeFd);

    // Validate a three fd sync fence
    void validateThreeFdFence(const C2Fence &fence, int fd1, int fd2, int fd3);
};

TEST_F(C2FenceTest, IsDupOf_sanity) {
    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int fd3 = memfd_create("test3", 0 /* flags */);

    EXPECT_THAT(fd1, ::testing::Not(IsDupOf(fd2)));
    EXPECT_THAT(-1, ::testing::Not(IsDupOf(fd2)));
    EXPECT_THAT(-1, ::testing::Not(IsDupOf(-1)));
    EXPECT_THAT(fd3, ::testing::Not(IsDupOf(fd3)));

    int fd4 = dup(fd3);
    EXPECT_THAT(fd4, IsDupOf(fd3));
    EXPECT_THAT(fd3, IsDupOf(fd4));

    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
}

TEST_F(C2FenceTest, NullFence) {
    validateNullFence(C2Fence());
}

void C2FenceTest::validateNullFence(const C2Fence &fence) {
    // Verify that the fence is valid.
    EXPECT_TRUE(fence.valid());
    EXPECT_TRUE(fence.ready());
    base::unique_fd fenceFd{fence.fd()};
    EXPECT_EQ(fenceFd.get(), -1);
    EXPECT_FALSE(fence.isHW()); // perhaps this should be false for a null fence

    // A null fence has no fds
    std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
    EXPECT_THAT(fds, ::testing::IsEmpty());
    for (int fd : fds) {
        close(fd);
    }

    // A null fence has no native handle
    native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
    EXPECT_THAT(handle, ::testing::IsNull());
    if (handle) {
        native_handle_close(handle);
        native_handle_delete(handle);
    }
}

TEST_F(C2FenceTest, SyncFence_with_negative_fd) {
    // Create a SyncFence with a negative fd.
    C2Fence fence = _C2FenceFactory::CreateSyncFence(-1, false /* validate */);

    validateNullFence(fence);
}

TEST_F(C2FenceTest, SyncFence_with_valid_fd) {
    // Create a SyncFence with a valid fd. We cannot create an actual sync fd,
    // so we cannot test wait(), but we can verify the ABI APIs

    int fd = memfd_create("test", 0 /* flags */);

    C2Fence fence = _C2FenceFactory::CreateSyncFence(fd, false /* validate */);
    validateSingleFdFence(fence, fd);
}

void C2FenceTest::validateSingleFdFence(const C2Fence &fence, int fd) {
    // EXPECT_TRUE(fence.valid()); // need a valid sync fd to test this
    // EXPECT_TRUE(fence.ready());
    // Verify that the fence says it is a HW sync fence.
    EXPECT_TRUE(fence.isHW()); // FIXME this may be an implementation detail

    // Verify that the fd returned is a duped version of the initial fd
    base::unique_fd fenceFd{fence.fd()};
    EXPECT_THAT(fenceFd.get(), IsDupOf(fd));

    // Verify that fds returns a duped version of the initial fd
    std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
    EXPECT_THAT(fds, ::testing::SizeIs(1));
    EXPECT_THAT(fds, ::testing::ElementsAre(IsDupOf(fd)));
    for (int fd_i : fds) {
        close(fd_i);
    }

    native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
    EXPECT_THAT(handle, ::testing::NotNull());
    if (handle) {
        EXPECT_EQ(handle->numFds, 1);
        EXPECT_EQ(handle->numInts, 1);
        EXPECT_THAT(handle->data[0], IsDupOf(fd));
        EXPECT_EQ(handle->data[1], SYNC_FENCE_MAGIC);

        native_handle_close(handle);
        native_handle_delete(handle);
    }
}

TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_one_valid_test_fd) {
    // Create a multi SyncFence with a single valid fd. This should create
    // a single fd sync fence. We can only validate this through its public
    // methods: fd/fds and verify the native handle ABI.

    int fd = memfd_create("test", 0 /* flags */);

    c2_status_t status = C2_BAD_VALUE;
    C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
        { -1, fd, -1 }, &status);
    // if we only have one valid fd, we are not merging fences, so the test fd is not validated
    EXPECT_EQ(status, C2_OK);

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_one_valid_test_fd_null_status) {
    // Create a multi SyncFence with a single valid fd. This should create
    // a single fd sync fence. We can only validate this through its public
    // methods: fd/fds and verify the native handle ABI.

    int fd = memfd_create("test", 0 /* flags */);

    C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
        { -1, fd, -1 });

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_merge_failure) {
    // Create a multi SyncFence with a multiple non-sync fence fds. This should
    // result in a fence created, but also an error.

    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int fd3 = memfd_create("test3", 0 /* flags */);

    c2_status_t status = C2_BAD_VALUE;
    C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
        { fd1, fd2, fd3 }, &status);
    EXPECT_EQ(status, C2_CORRUPTED);

    validateThreeFdFence(fence, fd1, fd2, fd3);
}

TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_merge_failure_null_status) {
    // Create a multi SyncFence with a multiple non-sync fence fds. This should
    // result in a fence created, but also an error.

    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int fd3 = memfd_create("test3", 0 /* flags */);

    C2Fence fence = _C2FenceFactory::CreateUnorderedMultiSyncFence(
        { fd1, fd2, fd3 });

    validateThreeFdFence(fence, fd1, fd2, fd3);
}

TEST_F(C2FenceTest, UnorderedMultiSyncFence_with_multiple_fds) {
    // We cannot create a true unordered multi sync fence as we can only
    // create test fds and those cannot be merged. As such, we cannot
    // test the factory method CreateUnorderedMultiSyncFence. We can however
    // create a test fence from a constructed native handle.

    // Technically, we need 3 fds as if we end up with only 2, we wouldn't
    // actually need a 2nd (final fence fd) since it is equivalent to the
    // first. In fact we will generate (and always generated) a single fd
    // fence in that case.
    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int mergeFd = memfd_create("test3", 0 /* flags */);

    native_handle_t *handle = native_handle_create(3 /* numfds */, 1 /* numints */);
    handle->data[0] = fd1;
    handle->data[1] = fd2;
    handle->data[2] = mergeFd;
    handle->data[3] = SYNC_FENCE_UNORDERED_MAGIC;
    C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
    native_handle_delete(handle);

    validateTwoFdUnorderedFence(fence, fd1, fd2, mergeFd);
}

void C2FenceTest::validateTwoFdUnorderedFence(
        const C2Fence &fence, int fd1, int fd2, int mergeFd) {
    // EXPECT_TRUE(fence.valid()); // need a valid sync fd to test this
    // EXPECT_TRUE(fence.ready());
    // Verify that the fence says it is a HW sync fence.
    EXPECT_TRUE(fence.isHW()); // FIXME this may be an implementation detail

    // Verify that the fd returned is a duped version of the merge fd
    base::unique_fd fenceFd{fence.fd()};
    EXPECT_THAT(fenceFd.get(), IsDupOf(mergeFd));

    // Verify that fds returns a duped versions of the initial fds (but not the merge fd)
    std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
    EXPECT_THAT(fds, ::testing::SizeIs(2));
    EXPECT_THAT(fds, ::testing::ElementsAre(IsDupOf(fd1), IsDupOf(fd2)));
    for (int fd_i : fds) {
        close(fd_i);
    }

    native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
    EXPECT_THAT(handle, ::testing::NotNull());
    if (handle) {
        EXPECT_EQ(handle->numFds, 3);
        EXPECT_EQ(handle->numInts, 1);
        EXPECT_THAT(handle->data[0], IsDupOf(fd1));
        EXPECT_THAT(handle->data[1], IsDupOf(fd2));
        EXPECT_THAT(handle->data[2], IsDupOf(mergeFd));
        EXPECT_EQ(handle->data[3], SYNC_FENCE_UNORDERED_MAGIC);

        native_handle_close(handle);
        native_handle_delete(handle);
    }
}

TEST_F(C2FenceTest, MultiSyncFence_with_one_valid_test_fd) {
    // Create a multi SyncFence with a single valid fd. This should create
    // a single fd sync fence. We can only validate this through its public
    // methods: fd/fds and verify the native handle ABI.

    int fd = memfd_create("test", 0 /* flags */);

    c2_status_t status = C2_BAD_VALUE;
    C2Fence fence = _C2FenceFactory::CreateMultiSyncFence(
        { -1, fd, -1 }, &status);
    // if we only have one valid fd, we are not merging fences, so the test fds are not validated
    EXPECT_EQ(status, C2_OK);

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, MultiSyncFence_with_one_valid_test_fd_null_status) {
    // Create a multi SyncFence with a single valid fd. This should create
    // a single fd sync fence. We can only validate this through its public
    // methods: fd/fds and verify the native handle ABI.

    int fd = memfd_create("test", 0 /* flags */);

    C2Fence fence = _C2FenceFactory::CreateMultiSyncFence(
        { -1, fd, -1 });

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, MultiSyncFence_with_multiple_fds) {
    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int fd3 = memfd_create("test3", 0 /* flags */);

    c2_status_t status = C2_BAD_VALUE;
    C2Fence fence = _C2FenceFactory::CreateMultiSyncFence(
        { fd1, fd2, fd3 }, &status);
    // test fds are not validated
    EXPECT_EQ(status, C2_OK);

    validateThreeFdFence(fence, fd1, fd2, fd3);
}

void C2FenceTest::validateThreeFdFence(const C2Fence &fence, int fd1, int fd2, int fd3) {
    // EXPECT_TRUE(fence.valid()); // need a valid sync fd to test this
    // EXPECT_TRUE(fence.ready());
    // Verify that the fence says it is a HW sync fence.
    EXPECT_TRUE(fence.isHW()); // FIXME this may be an implementation detail

    // Verify that the fd returned is a duped version of the final fd
    base::unique_fd fenceFd{fence.fd()};
    EXPECT_THAT(fenceFd.get(), IsDupOf(fd3));

    // Verify that fds returns a duped versions of all 3 initial fds
    std::vector<int> fds = ExtractFdsFromCodec2SyncFence(fence);
    EXPECT_THAT(fds, ::testing::SizeIs(3));
    EXPECT_THAT(fds, ::testing::ElementsAre(IsDupOf(fd1), IsDupOf(fd2), IsDupOf(fd3)));
    for (int fd_i : fds) {
        close(fd_i);
    }

    native_handle_t *handle = _C2FenceFactory::CreateNativeHandle(fence);
    EXPECT_THAT(handle, ::testing::NotNull());
    if (handle) {
        EXPECT_EQ(handle->numFds, 3);
        EXPECT_EQ(handle->numInts, 1);
        EXPECT_THAT(handle->data[0], IsDupOf(fd1));
        EXPECT_THAT(handle->data[1], IsDupOf(fd2));
        EXPECT_THAT(handle->data[2], IsDupOf(fd3));
        EXPECT_EQ(handle->data[3], SYNC_FENCE_MAGIC);

        native_handle_close(handle);
        native_handle_delete(handle);
    }
}

TEST_F(C2FenceTest, BackwardCompat_UDC_sync_fence) {
    // Create a single SyncFence from a UDC native handle

    int fd = memfd_create("test", 0 /* flags */);

    native_handle_t *handle = native_handle_create(1 /* numfds */, 1 /* numints */);
    handle->data[0] = fd;
    handle->data[1] = SYNC_FENCE_DEPRECATED_MAGIC;
    C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
    native_handle_delete(handle);

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, BackwardCompat_24Q1_single_fd_fence) {
    // Create a single SyncFence from a 24Q1 native handle
    // This had the same (albeit separately duped) fd twice, and used the legacy
    // magic number.

    int fd = memfd_create("test", 0 /* flags */);

    native_handle_t *handle = native_handle_create(2 /* numfds */, 1 /* numints */);
    handle->data[0] = fd;
    handle->data[1] = dup(fd);
    handle->data[2] = SYNC_FENCE_DEPRECATED_MAGIC;
    C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
    native_handle_delete(handle);

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, BackwardCompat_24Q3_single_fd_fence) {
    // Create a single SyncFence from the defined native handle

    int fd = memfd_create("test", 0 /* flags */);

    native_handle_t *handle = native_handle_create(1 /* numfds */, 1 /* numints */);
    handle->data[0] = fd;
    handle->data[1] = SYNC_FENCE_MAGIC;
    C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
    native_handle_delete(handle);

    validateSingleFdFence(fence, fd);
}

TEST_F(C2FenceTest, BackwardCompat_24Q1_multi_fd_fence) {
    // Create a single SyncFence from a 24Q1 era native handle with
    // the legacy magic number.

    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int mergeFd = memfd_create("test3", 0 /* flags */);

    native_handle_t *handle = native_handle_create(3 /* numfds */, 1 /* numints */);
    handle->data[0] = fd1;
    handle->data[1] = fd2;
    handle->data[2] = mergeFd;
    handle->data[3] = SYNC_FENCE_DEPRECATED_MAGIC;
    C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
    native_handle_delete(handle);

    validateTwoFdUnorderedFence(fence, fd1, fd2, mergeFd);
}

// No need to create BackwardCompat_24Q3_unordered_multi_fd_fence because
// we are creating that fence already from the 24Q3 native handle layout
// in the UnorderedMultiSyncFence_with_multiple_fds test.

TEST_F(C2FenceTest, BackwardCompat_24Q3_multi_fd_fence) {
    // Create a single SyncFence from a 24Q1 era native handle with
    // the legacy magic number.

    int fd1 = memfd_create("test1", 0 /* flags */);
    int fd2 = memfd_create("test2", 0 /* flags */);
    int fd3 = memfd_create("test3", 0 /* flags */);

    native_handle_t *handle = native_handle_create(3 /* numfds */, 1 /* numints */);
    handle->data[0] = fd1;
    handle->data[1] = fd2;
    handle->data[2] = fd3;
    handle->data[3] = SYNC_FENCE_MAGIC;
    C2Fence fence = _C2FenceFactory::CreateFromNativeHandle(handle, true /* takeOwnership */);
    native_handle_delete(handle);

    validateThreeFdFence(fence, fd1, fd2, fd3);
}

} // namespace android
+340 −73

File changed.

Preview size limit exceeded, changes collapsed.

+82 −15
Original line number Diff line number Diff line
@@ -23,13 +23,19 @@
#include <android-base/unique_fd.h>

/*
 * Create a list of fds from fence
 * Extract a list of sync fence fds from a potentially multi-sync C2Fence.
 * This will return dupped file descriptors of the fences used to creating the
 * sync fence. Specifically, for an unordered mult-sync fence, the merged
 * singular fence will not be returned even though it is created aspart of
 * constructing the C2Fence object. On the other hand, for a single fd sync
 * fence, the returned list will contain the sole file descriptor.
 *
 * \param fence   C2Fence object from which associated
 *                file descriptors need to be extracted
 * \return a vector of fds otherwise return vector of size 0
 * \return a vector of sync fence fds. This will be a vector of size 0 if C2Fence
 *         is not a sync fence. The caller is responsible for closing the
 *         fds in the returned vector.
 */

std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence);

class C2SurfaceSyncMemory;
@@ -54,20 +60,76 @@ struct _C2FenceFactory {
            uint32_t waitId);

    /*
     * Create C2Fence from a fence file fd.
     * Create C2Fence from a sync fence fd.
     *
     * \param fenceFd           Fence file descriptor.
     * \param fenceFd           Sync fence file descriptor.
     *                          It will be owned and closed by the returned fence object.
     * \param validate          If true, the fence fd will be validated to ensure
     *                          it is a valid pending sync fence fd.
     */
    static C2Fence CreateSyncFence(int fenceFd);
    static C2Fence CreateSyncFence(int fenceFd, bool validate = true);

    /*
     * Create C2Fence from list of fence file fds.
     * Create C2Fence from list of sync fence fds, while also merging them to
     * create a singular fence, which can be used as a backward compatible sync
     * fence.
     *
     * \param fenceFds          Vector of file descriptor for fence.
     *                          It will be owned and closed by the returned fence object.
     * \param fenceFds   Vector of sync fence file descriptors.
     *                   All file descriptors will be owned (and closed) by
     *                   the returned fence object.
     */
    static C2Fence CreateMultipleFdSyncFence(const std::vector<int>& fenceFds);
    [[deprecated("Use CreateUnorderedMultiSyncFence instead.")]]
    static C2Fence CreateMultipleFdSyncFence(const std::vector<int>& fenceFds) {
        return CreateUnorderedMultiSyncFence(fenceFds);
    }

    /*
     * Create C2Fence from a list of unordered sync fence fds, while also merging
     * them to create a singular fence, which can be used as a backward compatible
     * sync fence.
     *
     * \param fenceFds   Vector of sync fence file descriptors.
     *                   All file descriptors will be owned (and closed) by
     *                   the returned fence object.
     * \param status     Optional pointer to a status field. If not null, it will be
     *                   updated with the status of the operation. Possible values
     *                   are:
     *                   - C2_OK: The operation succeeded.
     *                   - C2_NO_MEMORY: The operation failed because of lack of
     *                     memory.
     *                   - C2_CORRUPTED: The operation failed because the sync
     *                     fence fds could bot be merged.
     * \return           A C2Fence object representing the sync fence fds, or
     *                   an empty C2Fence if the no C2Fence could be created.
     *                   It is possible for the operation to fail but still return
     *                   a possibly viable C2Fence object, e.g. if the merge
     *                   operation failed only partially. Similarly, it is possible
     *                   for the operation to succeed but still return an empty
     *                   C2Fence object, e.g. if all fence fds were invalid.
     */
    static C2Fence CreateUnorderedMultiSyncFence(
            const std::vector<int>& fenceFds, c2_status_t *status = nullptr /* nullable */);

    /*
     * Create C2Fence from a list of sync fence fds. Waiting for the last fence
     * must guarantee that all other fences are also signaled.
     *
     * \param fenceFds   Vector of sync fence file descriptors.
     *                   All file descriptors will be owned (and closed) by
     *                   the returned fence object.
     * \param status     Optional pointer to a status field. If not null, it will be
     *                   updated with the status of the operation. Possible values
     *                   are:
     *                   - C2_OK: The operation succeeded.
     *                   - C2_NO_MEMORY: The operation failed because of lack of
     *                     memory.
     * \return           A C2Fence object representing the sync fence fds, or
     *                   an empty C2Fence if the operation failed.  It is possible
     *                   for the operation to succeed but still return an empty
     *                   C2Fence object, e.g. if all fence fds were invalid.
     */
    static C2Fence CreateMultiSyncFence(
            const std::vector<int>& fenceFds, c2_status_t *status = nullptr /* nullable */);

    /*
     * Create C2Fence from an fd created by pipe()/pipe2() syscall.
@@ -97,13 +159,18 @@ struct _C2FenceFactory {

    /*
     * Create C2Fence from a native handle.

     *
     * \param handle           A native handle representing a fence
     *                         The fd in the native handle will be duplicated, so the caller will
     *                         still own the handle and have to close it.
     * \param takeOwnership    If true, the native handle and the file descriptors
     *                         within will be owned by the returned fence object.
     *                         If false (default), the caller will still own the
     *                         handle and its file descriptors and will have to
     *                         close it.
     *                         In either case the caller is responsible for
     *                         deleting the native handle.
     */
    static C2Fence CreateFromNativeHandle(const native_handle_t* handle);
    static C2Fence CreateFromNativeHandle(
            const native_handle_t* handle, bool takeOwnership = false);
};


#endif // STAGEFRIGHT_CODEC2_FENCE_FACTORY_H_