TransactionTraceWriter - always overwrite old files

Update TransactionTraceWriter to overwrite files older than ten minutes, even when overwrite is set to false.

Bug: 302249537
Bug: 306466281
Test: TransactionTraceWriterTest
Change-Id: Ic49662251debe3ccd2f0bba37535680733793c2d
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 9d0f285..17fa7be 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -245,6 +245,7 @@
     ],
     static_libs: [
         "android.frameworks.displayservice@1.0",
+        "libc++fs",
         "libdisplayservicehidl",
         "libserviceutils",
     ],
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9b9a67a..dc19cbd 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -103,6 +103,7 @@
 #include <cinttypes>
 #include <cmath>
 #include <cstdint>
+#include <filesystem>
 #include <functional>
 #include <memory>
 #include <mutex>
@@ -309,6 +310,19 @@
     return LayerHandle::getLayerId(surfaceControl->getHandle());
 }
 
+/**
+ * Returns true if the file at path exists and is newer than duration.
+ */
+bool fileNewerThan(const std::string& path, std::chrono::minutes duration) {
+    using Clock = std::filesystem::file_time_type::clock;
+    std::error_code error;
+    std::filesystem::file_time_type updateTime = std::filesystem::last_write_time(path, error);
+    if (error) {
+        return false;
+    }
+    return duration > (Clock::now() - updateTime);
+}
+
 }  // namespace anonymous
 
 // ---------------------------------------------------------------------------
@@ -899,7 +913,7 @@
     TransactionTraceWriter::getInstance().setWriterFunction(
             [&](const std::string& filename, bool overwrite) {
                 auto writeFn = [&]() {
-                    if (!overwrite && access(filename.c_str(), F_OK) == 0) {
+                    if (!overwrite && fileNewerThan(filename, std::chrono::minutes{10})) {
                         ALOGD("TransactionTraceWriter: file=%s already exists", filename.c_str());
                         return;
                     }
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
index 0f9060d..910e685 100644
--- a/services/surfaceflinger/fuzzer/Android.bp
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -31,6 +31,7 @@
     ],
     static_libs: [
         "android.hardware.graphics.composer@2.1-resources",
+        "libc++fs",
         "libgmock",
         "libgui_mocks",
         "libgmock_ndk",
diff --git a/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp
index 379135e..4a83d44 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp
@@ -45,12 +45,21 @@
     TestableSurfaceFlinger mFlinger;
 };
 
-TEST_F(TransactionTraceWriterTest, canWriteToFile) {
+// Check that a new file is written if overwrite=true and no file exists.
+TEST_F(TransactionTraceWriterTest, canWriteToFile_overwriteTrue) {
     TransactionTraceWriter::getInstance().invokeForTest(mFilename, /* overwrite */ true);
     EXPECT_EQ(access(mFilename.c_str(), F_OK), 0);
     verifyTraceFile();
 }
 
+// Check that a new file is written if overwrite=false and no file exists.
+TEST_F(TransactionTraceWriterTest, canWriteToFile_overwriteFalse) {
+    TransactionTraceWriter::getInstance().invokeForTest(mFilename, /* overwrite */ false);
+    EXPECT_EQ(access(mFilename.c_str(), F_OK), 0);
+    verifyTraceFile();
+}
+
+// Check that an existing file is overwritten when overwrite=true.
 TEST_F(TransactionTraceWriterTest, canOverwriteFile) {
     std::string testLine = "test";
     {
@@ -61,6 +70,7 @@
     verifyTraceFile();
 }
 
+// Check that an existing file isn't overwritten when it is new and overwrite=false.
 TEST_F(TransactionTraceWriterTest, doNotOverwriteFile) {
     std::string testLine = "test";
     {
@@ -76,4 +86,23 @@
         EXPECT_EQ(line, testLine);
     }
 }
+
+// Check that an existing file is overwritten when it is old and overwrite=false.
+TEST_F(TransactionTraceWriterTest, overwriteOldFile) {
+    std::string testLine = "test";
+    {
+        std::ofstream file(mFilename, std::ios::out);
+        file << testLine;
+    }
+
+    // Update file modification time to 15 minutes ago.
+    using Clock = std::filesystem::file_time_type::clock;
+    std::error_code error;
+    std::filesystem::last_write_time(mFilename, Clock::now() - std::chrono::minutes{15}, error);
+    ASSERT_EQ(error.value(), 0);
+
+    TransactionTraceWriter::getInstance().invokeForTest(mFilename, /* overwrite */ false);
+    verifyTraceFile();
+}
+
 } // namespace android
\ No newline at end of file