Support enabling vsock connections with a launcher flag.

vsock connections are a guest/host communication channel.

This is gated on a flag as it requires user access to /dev/vhost-vsock
on the host as well as guest kernel support, neither of which are
guaranteed by Cuttlefish at the moment. The flag is enabled when the
capability "vsock" is detected.

Bug: 121166534
Change-Id: I46cf79d12af9ec0cfb68b0fde810efe8b1abc386
Test: launch_cvd -kernel=...cf-4.14... -vsock_guest_cid=3
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index c5b8f62..8b731c2 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -179,6 +179,10 @@
               "Network interface to use for wifi");
 DEFINE_string(wifi_tap_name, "", // default handled on ParseCommandLine
               "The name of the tap interface to use for wifi");
+DEFINE_int32(vsock_guest_cid,
+             vsoc::GetDefaultPerInstanceVsockCid(),
+             "Guest identifier for vsock. Disabled if under 3.");
+
 // TODO(b/72969289) This should be generated
 DEFINE_string(dtb, "", "Path to the cuttlefish.dtb file");
 
@@ -820,6 +824,8 @@
   tmp_config_obj.set_wifi_guest_mac_addr(FLAGS_guest_mac_address);
   tmp_config_obj.set_wifi_host_mac_addr(FLAGS_host_mac_address);
 
+  tmp_config_obj.set_vsock_guest_cid(FLAGS_vsock_guest_cid);
+
   tmp_config_obj.set_entropy_source("/dev/urandom");
   tmp_config_obj.set_uuid(FLAGS_uuid);
 
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 533b593..771093c 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -108,6 +108,7 @@
 const char* kWifiGuestMacAddr = "wifi_guest_mac_addr";
 const char* kWifiHostMacAddr = "wifi_host_mac_addr";
 const char* kEntropySource = "entropy_source";
+const char* kVsockGuestCid = "vsock_guest_cid";
 
 const char* kUuid = "uuid";
 const char* kDisableDacSecurity = "disable_dac_security";
@@ -437,6 +438,14 @@
   (*dictionary_)[kEntropySource] = entropy_source;
 }
 
+int CuttlefishConfig::vsock_guest_cid() const {
+  return (*dictionary_)[kVsockGuestCid].asInt();
+}
+
+void CuttlefishConfig::set_vsock_guest_cid(int vsock_guest_cid) {
+  (*dictionary_)[kVsockGuestCid] = vsock_guest_cid;
+}
+
 std::string CuttlefishConfig::uuid() const {
   return (*dictionary_)[kUuid].asString();
 }
@@ -627,6 +636,11 @@
   return GetPerInstanceDefault("/var/run/shm/cvd-");
 }
 
+int GetDefaultPerInstanceVsockCid() {
+  constexpr int kFirstGuestCid = 3;
+  return vsoc::HostSupportsVsock() ? GetPerInstanceDefault(kFirstGuestCid) : 0;
+}
+
 std::string DefaultHostArtifactsPath(const std::string& file_name) {
   return (cvd::StringFromEnv("ANDROID_HOST_OUT",
                              cvd::StringFromEnv("HOME", ".")) +
@@ -647,4 +661,11 @@
           "/usr/lib/cuttlefish-common/bin/capability_query.py qemu_cli") == 0;
   return supported;
 }
+
+bool HostSupportsVsock() {
+  static bool supported =
+      std::system(
+          "/usr/lib/cuttlefish-common/bin/capability_query.py vsock") == 0;
+  return supported;
+}
 }  // namespace vsoc
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index fd1a26e..0ecc9be 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -173,6 +173,9 @@
   std::string entropy_source() const;
   void set_entropy_source(const std::string& entropy_source);
 
+  void set_vsock_guest_cid(int vsock_guest_cid);
+  int vsock_guest_cid() const;
+
   std::string uuid() const;
   void set_uuid(const std::string& uuid);
 
@@ -237,6 +240,7 @@
 
 std::string GetDefaultPerInstanceDir();
 std::string GetDefaultMempath();
+int GetDefaultPerInstanceVsockCid();
 
 std::string DefaultHostArtifactsPath(const std::string& file);
 std::string DefaultGuestImagePath(const std::string& file);
@@ -244,4 +248,5 @@
 // Whether the installed host packages support calling qemu directly instead of
 // through libvirt
 bool HostSupportsQemuCli();
+bool HostSupportsVsock();
 }  // namespace vsoc
diff --git a/host/libs/vm_manager/cf_qemu.sh b/host/libs/vm_manager/cf_qemu.sh
index abb9b90..f3e2384 100755
--- a/host/libs/vm_manager/cf_qemu.sh
+++ b/host/libs/vm_manager/cf_qemu.sh
@@ -97,6 +97,11 @@
       -device "virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1,name=cf-gadget-usb-v1"
   )
 fi
+
+if [[ ${vsock_guest_cid:-0} -gt 2 ]]; then
+  args+=(-device "vhost-vsock-pci,guest-cid=${vsock_guest_cid}")
+fi
+
 printf %s "exec ${qemu_binary=/usr/bin/qemu-system-x86_64}"
 for i in "${args[@]}"; do
   case "$i" in
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index 8a46825..a1db7f3 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -79,6 +79,7 @@
   LogAndSetEnv("ivshmem_vector_count",
                       std::to_string(config->ivshmem_vector_count()));
   LogAndSetEnv("usb_v1_socket_name", config->usb_v1_socket_name());
+  LogAndSetEnv("vsock_guest_cid", std::to_string(config->vsock_guest_cid()));
 
   cvd::Command qemu_cmd(vsoc::DefaultHostArtifactsPath("bin/cf_qemu.sh"));
   return qemu_cmd.Start();