Retrofit vsoc_input_service to use vsock

This allows using vsoc_input_service under qemu without the vsoc/ivshmem
support that is missing in 4.19 gki.

The alternative is to use virtio-input, but in qemu this requires
forwarding a hardware device (by using root permissions) while in crosvm
the same functionality is available through a file descriptor.

Test: launch_cvd -vm_manager=qemu_cli, check adb and vnc
Bug: 143713267
Change-Id: I5b7bdc063ff57aa3a455f77b8a7c23db29e1646e
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index 60a5dcd..af7d336 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -204,6 +204,10 @@
               "Binary for the tombstone server");
 DEFINE_int32(tombstone_receiver_port, vsoc::GetPerInstanceDefault(5630),
              "The vsock port for tombstones");
+DEFINE_int32(keyboard_server_port, GetPerInstanceDefault(5540),
+             "The port on which the vsock keyboard server should listen");
+DEFINE_int32(touch_server_port, GetPerInstanceDefault(5640),
+             "The port on which the vsock touch server should listen");
 DEFINE_bool(use_bootloader, false, "Boots the device using a bootloader");
 DEFINE_string(bootloader, "", "Bootloader binary path");
 DEFINE_string(boot_slot, "", "Force booting into the given slot. If empty, "
@@ -522,6 +526,15 @@
     tmp_config_obj.add_kernel_cmdline("androidboot.tombstone_transmit=0");
   }
 
+  tmp_config_obj.set_touch_socket_port(FLAGS_touch_server_port);
+  tmp_config_obj.set_keyboard_socket_port(FLAGS_keyboard_server_port);
+  if (FLAGS_vm_manager == vm_manager::QemuManager::name()) {
+    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_touch_port=",
+                                             FLAGS_touch_server_port));
+    tmp_config_obj.add_kernel_cmdline(concat("androidboot.vsock_keyboard_port=",
+                                             FLAGS_keyboard_server_port));
+  }
+
   tmp_config_obj.set_use_bootloader(FLAGS_use_bootloader);
   tmp_config_obj.set_bootloader(FLAGS_bootloader);
 
@@ -567,7 +580,8 @@
   // TODO(b/144111429): Consolidate to one hardware name
   SetCommandLineOptionWithMode("hardware_name", "cutf_cvm",
                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
-  SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatSerialMode,
+  // TODO(b/144119457) Use the serial port.
+  SetCommandLineOptionWithMode("logcat_mode", cvd::kLogcatVsockMode,
                                google::FlagSettingMode::SET_FLAGS_DEFAULT);
 }
 
diff --git a/host/commands/run_cvd/launch.cc b/host/commands/run_cvd/launch.cc
index 47cf2e2..5c42e59 100644
--- a/host/commands/run_cvd/launch.cc
+++ b/host/commands/run_cvd/launch.cc
@@ -12,6 +12,8 @@
 #include "host/commands/run_cvd/runner_defs.h"
 #include "host/commands/run_cvd/pre_launch_initializers.h"
 #include "host/commands/run_cvd/vsoc_shared_memory.h"
+#include "host/libs/vm_manager/crosvm_manager.h"
+#include "host/libs/vm_manager/qemu_manager.h"
 
 using cvd::RunnerExitCodes;
 using cvd::MonitorEntry;
@@ -246,10 +248,20 @@
                                    GetOnSubprocessExitCallback(config));
 }
 
-cvd::SharedFD CreateVncInputServer(const std::string& path) {
+cvd::SharedFD CreateUnixVncInputServer(const std::string& path) {
   auto server = cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 0666);
   if (!server->IsOpen()) {
-    LOG(ERROR) << "Unable to create mouse server: "
+    LOG(ERROR) << "Unable to create unix input server: "
+               << server->StrError();
+    return cvd::SharedFD();
+  }
+  return server;
+}
+
+cvd::SharedFD CreateVsockVncInputServer(int port) {
+  auto server = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
+  if (!server->IsOpen()) {
+    LOG(ERROR) << "Unable to create vsock input server: "
                << server->StrError();
     return cvd::SharedFD();
   }
@@ -264,33 +276,38 @@
     auto port_options = "-port=" + std::to_string(config.vnc_server_port());
     cvd::Command vnc_server(config.vnc_server_binary());
     vnc_server.AddParameter(port_options);
-    if (!config.enable_ivserver()) {
-      // When the ivserver is not enabled, the vnc touch_server needs to serve
-      // on unix sockets and send input events to whoever connects to it (namely
-      // crosvm)
-      auto touch_server = CreateVncInputServer(config.touch_socket_path());
-      if (!touch_server->IsOpen()) {
-        return false;
-      }
-      vnc_server.AddParameter("-touch_fd=", touch_server);
-
-      auto keyboard_server =
-          CreateVncInputServer(config.keyboard_socket_path());
-      if (!keyboard_server->IsOpen()) {
-        return false;
-      }
-      vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
-      // TODO(b/128852363): This should be handled through the wayland mock
-      //  instead.
-      // Additionally it receives the frame updates from a virtual socket
-      // instead
-      auto frames_server =
-          cvd::SharedFD::VsockServer(config.frames_vsock_port(), SOCK_STREAM);
-      if (!frames_server->IsOpen()) {
-        return false;
-      }
-      vnc_server.AddParameter("-frame_server_fd=", frames_server);
+    if (config.vm_manager() == vm_manager::QemuManager::name()) {
+      vnc_server.AddParameter("-write_virtio_input");
     }
+    // When the ivserver is not enabled, the vnc touch_server needs to serve
+    // on sockets and send input events to whoever connects to it (the VMM).
+    auto touch_server =
+        config.vm_manager() == vm_manager::CrosvmManager::name()
+            ? CreateUnixVncInputServer(config.touch_socket_path())
+            : CreateVsockVncInputServer(config.touch_socket_port());
+    if (!touch_server->IsOpen()) {
+      return false;
+    }
+    vnc_server.AddParameter("-touch_fd=", touch_server);
+
+    auto keyboard_server =
+        config.vm_manager() == vm_manager::CrosvmManager::name()
+            ? CreateUnixVncInputServer(config.keyboard_socket_path())
+            : CreateVsockVncInputServer(config.keyboard_socket_port());
+    if (!keyboard_server->IsOpen()) {
+      return false;
+    }
+    vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
+    // TODO(b/128852363): This should be handled through the wayland mock
+    //  instead.
+    // Additionally it receives the frame updates from a virtual socket
+    // instead
+    auto frames_server =
+        cvd::SharedFD::VsockServer(config.frames_vsock_port(), SOCK_STREAM);
+    if (!frames_server->IsOpen()) {
+      return false;
+    }
+    vnc_server.AddParameter("-frame_server_fd=", frames_server);
     process_monitor->StartSubprocess(std::move(vnc_server), callback);
     return true;
   }