sync: implement sync_file_info

Also modifies sync-unit-test to use sync_file_info instead of the
deprecated sync_fence_info, but check that they match in several tests.

Bug: 35138793
Test: sync-unit-tests on bullhead
Change-Id: Ic672d1c89798435a8b71469500e82c770a66bf4d
diff --git a/libsync/sync.c b/libsync/sync.c
index 6680f11..f3e26e1 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -173,6 +173,46 @@
     return legacy_info;
 }
 
+static struct sync_file_info* legacy_fence_info_to_sync_file_info(
+                                    struct sync_fence_info_data *legacy_info)
+{
+    struct sync_file_info *info;
+    struct sync_pt_info *pt;
+    struct sync_fence_info *fence;
+    size_t num_fences;
+    int err;
+
+    pt = NULL;
+    num_fences = 0;
+    while ((pt = sync_pt_info(legacy_info, pt)) != NULL)
+        num_fences++;
+
+    info = calloc(1, sizeof(struct sync_file_info) +
+                     num_fences * sizeof(struct sync_fence_info));
+    if (!info) {
+        free(legacy_info);
+        return NULL;
+    }
+    info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
+
+    strlcpy(info->name, legacy_info->name, sizeof(info->name));
+    info->status = legacy_info->status;
+    info->num_fences = num_fences;
+
+    pt = NULL;
+    fence = sync_get_fence_info(info);
+    while ((pt = sync_pt_info(legacy_info, pt)) != NULL) {
+        strlcpy(fence->obj_name, pt->obj_name, sizeof(fence->obj_name));
+        strlcpy(fence->driver_name, pt->driver_name,
+                sizeof(fence->driver_name));
+        fence->status = pt->status;
+        fence->timestamp_ns = pt->timestamp_ns;
+        fence++;
+    }
+
+    return info;
+}
+
 struct sync_fence_info_data *sync_fence_info(int fd)
 {
     struct sync_fence_info_data *legacy_info;
@@ -190,6 +230,23 @@
     return legacy_info;
 }
 
+struct sync_file_info* sync_file_info(int32_t fd)
+{
+    struct sync_file_info *info;
+    struct sync_fence_info_data *legacy_info;
+
+    info = modern_sync_file_info(fd);
+    if (info || errno != ENOTTY)
+        return info;
+
+    legacy_info = legacy_sync_fence_info(fd);
+    if (!legacy_info)
+        return NULL;
+    info = legacy_fence_info_to_sync_file_info(legacy_info);
+    sync_fence_info_free(legacy_info);
+    return info;
+}
+
 struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
                                   struct sync_pt_info *itr)
 {
diff --git a/libsync/tests/sync_test.cpp b/libsync/tests/sync_test.cpp
index 401aaee..7770fcb 100644
--- a/libsync/tests/sync_test.cpp
+++ b/libsync/tests/sync_test.cpp
@@ -172,20 +172,20 @@
         return sync_wait(m_fd, timeout);
     }
     vector<SyncPointInfo> getInfo() const {
-        struct sync_pt_info *pointInfo = nullptr;
         vector<SyncPointInfo> fenceInfo;
-        sync_fence_info_data *info = sync_fence_info(getFd());
+        struct sync_file_info *info = sync_file_info(getFd());
         if (!info) {
             return fenceInfo;
         }
-        while ((pointInfo = sync_pt_info(info, pointInfo))) {
+        const auto fences = sync_get_fence_info(info);
+        for (uint32_t i = 0; i < info->num_fences; i++) {
             fenceInfo.push_back(SyncPointInfo{
-                pointInfo->driver_name,
-                pointInfo->obj_name,
-                pointInfo->timestamp_ns,
-                pointInfo->status});
+                fences[i].driver_name,
+                fences[i].obj_name,
+                fences[i].timestamp_ns,
+                fences[i].status});
         }
-        sync_fence_info_free(info);
+        sync_file_info_free(info);
         return fenceInfo;
     }
     int getSize() const {
@@ -212,6 +212,32 @@
     }
 };
 
+static void CheckModernLegacyInfoMatch(const SyncFence& f) {
+    struct sync_file_info* modern = sync_file_info(f.getFd());
+    struct sync_fence_info_data* legacy = sync_fence_info(f.getFd());
+
+    ASSERT_TRUE(modern != NULL);
+    ASSERT_TRUE(legacy != NULL);
+
+    EXPECT_STREQ(modern->name, legacy->name);
+    EXPECT_EQ(modern->status, legacy->status);
+
+    uint32_t fenceIdx = 0;
+    struct sync_pt_info* pt = sync_pt_info(legacy, NULL);
+    const struct sync_fence_info* fences = sync_get_fence_info(modern);
+    while (fenceIdx < modern->num_fences && pt != NULL) {
+        EXPECT_STREQ(fences[fenceIdx].obj_name, pt->obj_name);
+        EXPECT_STREQ(fences[fenceIdx].driver_name, pt->driver_name);
+        EXPECT_EQ(fences[fenceIdx].status, pt->status);
+        EXPECT_EQ(fences[fenceIdx].timestamp_ns, pt->timestamp_ns);
+
+        fenceIdx++;
+        pt = sync_pt_info(legacy, pt);
+    }
+    EXPECT_EQ(fenceIdx, modern->num_fences);
+    EXPECT_EQ(NULL, pt);
+}
+
 int SyncFence::s_fenceCount = 0;
 
 TEST(AllocTest, Timeline) {
@@ -225,6 +251,7 @@
 
     SyncFence fence(timeline, 1);
     ASSERT_TRUE(fence.isValid());
+    CheckModernLegacyInfoMatch(fence);
 }
 
 TEST(AllocTest, FenceNegative) {
@@ -321,15 +348,21 @@
     timeline.inc(1);
     ASSERT_EQ(a.getSignaledCount(), 1);
     ASSERT_EQ(d.getActiveCount(), 1);
+    CheckModernLegacyInfoMatch(a);
+    CheckModernLegacyInfoMatch(d);
 
     timeline.inc(1);
     ASSERT_EQ(b.getSignaledCount(), 1);
     ASSERT_EQ(d.getActiveCount(), 1);
+    CheckModernLegacyInfoMatch(b);
+    CheckModernLegacyInfoMatch(d);
 
     timeline.inc(1);
     ASSERT_EQ(c.getSignaledCount(), 1);
     ASSERT_EQ(d.getActiveCount(), 0);
     ASSERT_EQ(d.getSignaledCount(), 1);
+    CheckModernLegacyInfoMatch(c);
+    CheckModernLegacyInfoMatch(d);
 }
 
 TEST(FenceTest, MergeSameFence) {
@@ -343,9 +376,11 @@
     ASSERT_TRUE(selfMergeFence.isValid());
 
     ASSERT_EQ(selfMergeFence.getSignaledCount(), 0);
+    CheckModernLegacyInfoMatch(selfMergeFence);
 
     timeline.inc(5);
     ASSERT_EQ(selfMergeFence.getSignaledCount(), 1);
+    CheckModernLegacyInfoMatch(selfMergeFence);
 }
 
 TEST(FenceTest, PollOnDestroyedTimeline) {
@@ -397,14 +432,17 @@
     timelineA.inc(5);
     ASSERT_EQ(mergedFence.getActiveCount(), 2);
     ASSERT_EQ(mergedFence.getSignaledCount(), 1);
+    CheckModernLegacyInfoMatch(mergedFence);
 
     timelineB.inc(5);
     ASSERT_EQ(mergedFence.getActiveCount(), 1);
     ASSERT_EQ(mergedFence.getSignaledCount(), 2);
+    CheckModernLegacyInfoMatch(mergedFence);
 
     timelineC.inc(5);
     ASSERT_EQ(mergedFence.getActiveCount(), 0);
     ASSERT_EQ(mergedFence.getSignaledCount(), 3);
+    CheckModernLegacyInfoMatch(mergedFence);
 
     // confirm you can successfully wait.
     ASSERT_EQ(mergedFence.wait(100), 0);
@@ -560,6 +598,7 @@
         // Merge.
         fence = SyncFence(fence, SyncFence(timeline, syncPoint));
         ASSERT_TRUE(fence.isValid());
+        CheckModernLegacyInfoMatch(fence);
     }
 
     // Confirm our map matches the fence.