Update Linux template for headless mode (#56618)

diff --git a/packages/flutter_tools/templates/app/linux.tmpl/Makefile b/packages/flutter_tools/templates/app/linux.tmpl/Makefile
index c27a1ad..2a3e5ba 100644
--- a/packages/flutter_tools/templates/app/linux.tmpl/Makefile
+++ b/packages/flutter_tools/templates/app/linux.tmpl/Makefile
@@ -49,6 +49,7 @@
 # issues if they start with one or more '../'s.
 WRAPPER_ROOT=$(abspath $(FLUTTER_EPHEMERAL_DIR)/cpp_client_wrapper_glfw)
 WRAPPER_SOURCES= \
+	$(WRAPPER_ROOT)/flutter_engine.cc \
 	$(WRAPPER_ROOT)/flutter_window_controller.cc \
 	$(WRAPPER_ROOT)/plugin_registrar.cc \
 	$(WRAPPER_ROOT)/engine_method_result.cc
diff --git a/packages/flutter_tools/templates/app/linux.tmpl/main.cc b/packages/flutter_tools/templates/app/linux.tmpl/main.cc
index 47b0343..e92332d 100644
--- a/packages/flutter_tools/templates/app/linux.tmpl/main.cc
+++ b/packages/flutter_tools/templates/app/linux.tmpl/main.cc
@@ -1,3 +1,4 @@
+#include <flutter/flutter_engine.h>
 #include <flutter/flutter_window_controller.h>
 #include <linux/limits.h>
 #include <unistd.h>
@@ -12,34 +13,22 @@
 
 namespace {
 
-// Returns the path of the directory containing this executable, or an empty
-// string if the directory cannot be found.
-std::string GetExecutableDirectory() {
-  char buffer[PATH_MAX + 1];
-  ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer));
-  if (length > PATH_MAX) {
-    std::cerr << "Couldn't locate executable" << std::endl;
-    return "";
+// Runs the application in headless mode, without a window.
+void RunHeadless(const std::string& icu_data_path,
+                 const std::string& assets_path,
+                 const std::vector<std::string>& arguments) {
+  flutter::FlutterEngine engine;
+  engine.Start(icu_data_path, assets_path, arguments);
+  RegisterPlugins(&engine);
+  while (true) {
+    engine.RunEventLoopWithTimeout();
   }
-  std::string executable_path(buffer, length);
-  size_t last_separator_position = executable_path.find_last_of('/');
-  if (last_separator_position == std::string::npos) {
-    std::cerr << "Unabled to find parent directory of " << executable_path
-              << std::endl;
-    return "";
-  }
-  return executable_path.substr(0, last_separator_position);
 }
 
 }  // namespace
 
 int main(int argc, char **argv) {
-  // Resources are located relative to the executable.
-  std::string base_directory = GetExecutableDirectory();
-  if (base_directory.empty()) {
-    base_directory = ".";
-  }
-  std::string data_directory = base_directory + "/data";
+  std::string data_directory = "data";
   std::string assets_path = data_directory + "/flutter_assets";
   std::string icu_data_path = data_directory + "/icudtl.dat";
 
@@ -55,13 +44,17 @@
   // Start the engine.
   if (!flutter_controller.CreateWindow(window_properties, assets_path,
                                        arguments)) {
+    if (getenv("DISPLAY") == nullptr) {
+      std::cout << "No DISPLAY; falling back to headless mode." << std::endl;
+      RunHeadless(icu_data_path, assets_path, arguments);
+      return EXIT_SUCCESS;
+    }
     return EXIT_FAILURE;
   }
   RegisterPlugins(&flutter_controller);
 
   // Run until the window is closed.
-  while (flutter_controller.RunEventLoopWithTimeout(
-      std::chrono::milliseconds::max())) {
+  while (flutter_controller.RunEventLoopWithTimeout()) {
   }
   return EXIT_SUCCESS;
 }