tui: Output test render to a file for inspection. am: bb248049d1

Original change: https://android-review.googlesource.com/c/platform/system/teeui/+/2332344

Change-Id: I5b5cd4a1f4c5ae47b377e9e4a61d300bf599c6de
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/test/example_config/README b/test/example_config/README
index 5e4f63c..f841fcf 100644
--- a/test/example_config/README
+++ b/test/example_config/README
@@ -72,6 +72,9 @@
           },
           {
             "native-test-flag": "--volUpButtonBottom=<distance from the bottom of the UP power button to the top of the screen in mm>"
+          },
+          {
+             "native-test-flag": "--saveScreen"
           }
         ]
     }
diff --git a/test/teeui_device_config.cpp b/test/teeui_device_config.cpp
index ff8bf71..bdb4c82 100644
--- a/test/teeui_device_config.cpp
+++ b/test/teeui_device_config.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
+#include <fstream>
 #include <getopt.h>
 #include <gtest/gtest.h>
+#include <inttypes.h>
 #include <iostream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,6 +39,39 @@
     ::teeui::test::TeeuiRenderTest::Instance()->initFromOptions(argc, argv);
 }
 
+void saveToPpm(const uint32_t* data, uint32_t w, uint32_t h, uint32_t linestride) {
+    const testing::TestInfo* const test_info =
+        testing::UnitTest::GetInstance()->current_test_info();
+    std::string testname = test_info->name();
+    std::ofstream out;
+
+    out.open(testname + ".ppm", std::ios::binary);
+    if (out.is_open()) {
+        uint32_t linestart = 0;
+
+        /* Write the header */
+        out << "P6\n" << w << " " << h << "\n255\n";
+
+        /* Write binary Pixel data */
+        for (uint32_t line = 0; line < h; line++) {
+            for (uint32_t col = 0; col < w; col++) {
+                const uint32_t color = data[linestart + col];
+                char rgb[3];
+
+                rgb[0] = color >> 16;
+                rgb[1] = color >> 8;
+                rgb[2] = color;
+
+                out.write(rgb, sizeof(rgb));
+            }
+
+            linestart += linestride;
+        }
+
+        out.close();
+    }
+}
+
 int runRenderTest(const char* language, bool magnified, bool inverted,
                   const char* confirmationMessage, const char* layout) {
     std::unique_ptr<ITeeuiExample> sCurrentExample = createExample(
@@ -54,6 +89,11 @@
 
     int error =
         sCurrentExample->renderUIIntoBuffer(0, 0, w, h, linestride, buffer.data(), buffer_size);
+
+    if (TeeuiRenderTest::Instance()->saveScreen()) {
+        saveToPpm(buffer.data(), w, h, linestride);
+    }
+
     return error;
 }
 
@@ -97,6 +137,7 @@
                                       {"powerButtonBottom", required_argument, 0, 'b'},
                                       {"volUpButtonTop", required_argument, 0, 'u'},
                                       {"volUpButtonBottom", required_argument, 0, 'v'},
+                                      {"saveScreen", 0, 0, 's'},
                                       {"help", 0, 0, 'h'},
                                       {"?", 0, 0, '?'},
                                       {0, 0, 0, 0}};
@@ -135,6 +176,9 @@
             numeric_value = strtod(optarg, NULL);
             volUpButtonBottomMm = numeric_value;
             break;
+        case 's':
+            saveScreen_ = true;
+            break;
         case '?':
         case 'h':
             std::cout << "Options:" << std::endl;
@@ -156,6 +200,8 @@
             std::cout << "--volUpButtonBottom=<distance from the bottom of the UP power button to "
                          "the top of the screen in mm>"
                       << std::endl;
+            std::cout << "--saveScreen - save rendered screen to ppm files in working directory"
+                      << std::endl;
             exit(0);
         }
     }
diff --git a/test/teeui_device_config.h b/test/teeui_device_config.h
index 7bcfa5a..5e3e33c 100644
--- a/test/teeui_device_config.h
+++ b/test/teeui_device_config.h
@@ -57,6 +57,11 @@
     void createDevice(int widthPx, int heightPx, double dp2px, double mm2px,
                       double powerButtonTopMm, double powerButtonBottomMm, double volUpButtonTopMm,
                       double volUpButtonBottomMm);
+
+    bool saveScreen() { return saveScreen_; }
+
+  private:
+    bool saveScreen_ = false;
 };
 
 }  // namespace test