Merge ab/5111269 into master

Bug: 119522286
Test: TH
Change-Id: I1ff02468380a167100c047d80cc3e91022c359d6
diff --git a/common/libs/fs/shared_fd.h b/common/libs/fs/shared_fd.h
index 32a4a99..33afee2 100644
--- a/common/libs/fs/shared_fd.h
+++ b/common/libs/fs/shared_fd.h
@@ -137,7 +137,8 @@
   static SharedFD Accept(const FileInstance& listener);
   static SharedFD Dup(int unmanaged_fd);
   static SharedFD GetControlSocket(const char* name);
-  // Returns false on failure, true on success.
+  // All SharedFDs have the O_CLOEXEC flag after creation. To remove use the
+  // Fcntl or Dup functions.
   static SharedFD Open(const char* pathname, int flags, mode_t mode = 0);
   static SharedFD Creat(const char* pathname, mode_t mode);
   static bool Pipe(SharedFD* fd0, SharedFD* fd1);
@@ -506,6 +507,9 @@
 
  private:
   FileInstance(int fd, int in_errno) : fd_(fd), errno_(in_errno) {
+    // Ensure every file descriptor managed by a FileInstance has the CLOEXEC
+    // flag
+    TEMP_FAILURE_RETRY(fcntl(fd, F_SETFD, FD_CLOEXEC));
     identity_.PrintF("fd=%d @%p", fd, this);
   }
 
diff --git a/common/libs/utils/Android.bp b/common/libs/utils/Android.bp
index 98c16c7..4785fad 100644
--- a/common/libs/utils/Android.bp
+++ b/common/libs/utils/Android.bp
@@ -27,6 +27,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libcuttlefish_fs",
     ],
     defaults: ["cuttlefish_host_and_guest"],
 }
diff --git a/common/libs/utils/subprocess.cpp b/common/libs/utils/subprocess.cpp
index aae440f..7f7b961 100644
--- a/common/libs/utils/subprocess.cpp
+++ b/common/libs/utils/subprocess.cpp
@@ -23,6 +23,7 @@
 
 #include <glog/logging.h>
 namespace {
+
 pid_t subprocess_impl(const char* const* command, const char* const* envp) {
   pid_t pid = fork();
   if (!pid) {
@@ -53,28 +54,6 @@
   return pid;
 }
 
-int execute_impl(const char* const* command, const char* const* envp) {
-  pid_t pid = subprocess_impl(command, envp);
-  if (pid == -1) {
-    return -1;
-  }
-  int wstatus = 0;
-  waitpid(pid, &wstatus, 0);
-  int retval = 0;
-  if (WIFEXITED(wstatus)) {
-    retval = WEXITSTATUS(wstatus);
-    if (retval) {
-      LOG(ERROR) << "Command " << command[0]
-                 << " exited with error code: " << retval;
-    }
-  } else if (WIFSIGNALED(wstatus)) {
-    LOG(ERROR) << "Command " << command[0]
-               << " was interrupted by a signal: " << WTERMSIG(wstatus);
-    retval = -1;
-  }
-  return retval;
-}
-
 std::vector<const char*> ToCharPointers(
     const std::vector<std::string>& vect) {
   std::vector<const char*> ret = {};
@@ -86,28 +65,101 @@
 }
 }  // namespace
 namespace cvd {
-pid_t subprocess(const std::vector<std::string>& command,
-                 const std::vector<std::string>& env) {
-  auto cmd = ToCharPointers(command);
-  auto envp = ToCharPointers(env);
 
-  return subprocess_impl(cmd.data(), &envp[0]);
+int Subprocess::Wait() {
+  if (pid_ < 0) {
+    LOG(ERROR)
+        << "Attempt to wait on invalid pid(has it been waited on already?): "
+        << pid_;
+    return -1;
+  }
+  int wstatus = 0;
+  auto pid = pid_; // Wait will set pid_ to -1 after waiting
+  auto wait_ret = Wait(&wstatus, 0);
+  if (wait_ret < 0) {
+    LOG(ERROR) << "Error on call to waitpid: " << strerror(errno);
+    return wait_ret;
+  }
+  int retval = 0;
+  if (WIFEXITED(wstatus)) {
+    retval = WEXITSTATUS(wstatus);
+    if (retval) {
+      LOG(ERROR) << "Subprocess " << pid
+                 << " exited with error code: " << retval;
+    }
+  } else if (WIFSIGNALED(wstatus)) {
+    LOG(ERROR) << "Subprocess " << pid
+               << " was interrupted by a signal: " << WTERMSIG(wstatus);
+    retval = -1;
+  }
+  return retval;
 }
-pid_t subprocess(const std::vector<std::string>& command) {
-  auto cmd = ToCharPointers(command);
+pid_t Subprocess::Wait(int* wstatus, int options) {
+  if (pid_ < 0) {
+    LOG(ERROR)
+        << "Attempt to wait on invalid pid(has it been waited on already?): "
+        << pid_;
+    return -1;
+  }
+  auto retval = waitpid(pid_, wstatus, options);
+  // We don't want to wait twice for the same process
+  pid_ = -1;
+  return retval;
+}
 
-  return subprocess_impl(cmd.data(), NULL);
+Command::~Command() {
+  for(const auto& entry: inherited_fds_) {
+    close(entry.second);
+  }
 }
+
+bool Command::BuildParameter(std::stringstream* stream, SharedFD shared_fd) {
+  int fd;
+  if (inherited_fds_.count(shared_fd)) {
+    fd = inherited_fds_[shared_fd];
+  } else {
+    fd = shared_fd->UNMANAGED_Dup();
+    if (fd < 0) {
+      return false;
+    }
+    inherited_fds_[shared_fd] = fd;
+  }
+  *stream << fd;
+  return true;
+}
+
+Subprocess Command::Start() const {
+  auto cmd = ToCharPointers(command_);
+  if (use_parent_env_) {
+    return Subprocess(subprocess_impl(cmd.data(), NULL));
+  } else {
+    auto envp = ToCharPointers(env_);
+    return Subprocess(subprocess_impl(cmd.data(), envp.data()));
+  }
+}
+
 int execute(const std::vector<std::string>& command,
             const std::vector<std::string>& env) {
-  auto cmd = ToCharPointers(command);
-  auto envp = ToCharPointers(env);
-
-  return execute_impl(cmd.data(), &envp[0]);
+  Command cmd(command[0]);
+  for (size_t i = 1; i < command.size(); ++i) {
+    cmd.AddParameter(command[i]);
+  }
+  cmd.SetEnvironment(env);
+  auto subprocess = cmd.Start();
+  if (!subprocess.Started()) {
+    return -1;
+  }
+  return subprocess.Wait();
 }
 int execute(const std::vector<std::string>& command) {
-  auto cmd = ToCharPointers(command);
-
-  return execute_impl(cmd.data(), NULL);
+  Command cmd(command[0]);
+  for (size_t i = 1; i < command.size(); ++i) {
+    cmd.AddParameter(command[i]);
+  }
+  auto subprocess = cmd.Start();
+  if (!subprocess.Started()) {
+    return -1;
+  }
+  return subprocess.Wait();
 }
 }  // namespace cvd
diff --git a/common/libs/utils/subprocess.h b/common/libs/utils/subprocess.h
index cbb61f1..814325b 100644
--- a/common/libs/utils/subprocess.h
+++ b/common/libs/utils/subprocess.h
@@ -17,20 +17,106 @@
 
 #include <sys/types.h>
 
+#include <map>
+#include <string>
+#include <sstream>
 #include <vector>
 
+#include <common/libs/fs/shared_fd.h>
+
 namespace cvd {
+// Keeps track of a running (sub)process. Allows to wait for its completion.
+// It's an error to wait twice for the same subprocess.
+class Subprocess {
+ public:
+  Subprocess(pid_t pid) : pid_(pid), started_(pid > 0) {}
+  Subprocess(Subprocess&&) = default;
+  ~Subprocess() = default;
+  // Waits for the subprocess to complete. Returns zero if completed
+  // successfully, non-zero otherwise.
+  int Wait();
+  // Same as waitpid(2)
+  pid_t Wait(int* wstatus, int options);
+  // Whether the command started successfully. It only says whether the call to
+  // fork() succeeded or not, it says nothing about exec or successful
+  // completion of the command, that's what Wait is for.
+  bool Started() const {return started_;}
 
-// Starts a new child process with the given parameters. Returns the pid of the
-// started process or -1 if failed. The function with no environment arguments
-// launches the subprocess with the same environment as the parent, to have an
-// empty environment just pass an empty vector as second argument.
-pid_t subprocess(const std::vector<std::string>& command,
-                 const std::vector<std::string>& env);
-pid_t subprocess(const std::vector<std::string>& command);
+ private:
+  // Copy is disabled to avoid waiting twice for the same pid (the first wait
+  // frees the pid, which allows the kernel to reuse it so we may end up waiting
+  // for the wrong process)
+  Subprocess(const Subprocess&) = delete;
+  Subprocess& operator=(const Subprocess&) = delete;
+  pid_t pid_ = -1;
+  bool started_= false;
+};
 
-// Same as subprocess, but it waits for the child process before returning.
-// Returns zero if the process completed successfully, non zero otherwise.
+// An executable command. Multiple subprocesses can be started from the same
+// command object. This class owns any file descriptors that the subprocess
+// should inherit.
+class Command {
+ private:
+  template<typename T>
+  // For every type other than SharedFD (for which there is a specialisation)
+  bool BuildParameter(std::stringstream* stream, T t) {
+    *stream << t;
+    return true;
+  }
+  // Special treatment for SharedFD
+  bool BuildParameter(std::stringstream* stream, SharedFD shared_fd);
+  template<typename T, typename...Args>
+  bool BuildParameter(std::stringstream* stream, T t, Args...args) {
+    return BuildParameter(stream, t) &&
+           BuildParameter(stream, args...);
+  }
+ public:
+  Command(const std::string& executable) {
+    command_.push_back(executable);
+  }
+  Command(Command&&) = default;
+  // The default copy constructor is unsafe because it would mean multiple
+  // closing of the inherited file descriptors. If needed it can be implemented
+  // using dup(2)
+  Command(const Command&) = delete;
+  Command& operator=(const Command&) = delete;
+  ~Command();
+
+  // Specify the environment for the subprocesses to be started. By default
+  // subprocesses inherit the parent's environment.
+  void SetEnvironment(const std::vector<std::string>& env) {
+    use_parent_env_ = false;
+    env_ = env;
+  }
+  // Adds a single parameter to the command. All arguments are concatenated into
+  // a single string to form a parameter. If one of those arguments is a
+  // SharedFD a duplicate of it will be used and won't be closed until the
+  // object is destroyed. To add multiple parameters to the command the function
+  // must be called multiple times, one per parameter.
+  template<typename... Args>
+  bool AddParameter(Args... args) {
+    std::stringstream ss;
+    if (BuildParameter(&ss, args...)) {
+      command_.push_back(ss.str());
+      return true;
+    }
+    return false;
+  }
+  // Starts execution of the command. This method can be called multiple times,
+  // effectively staring multiple (possibly concurrent) instances.
+  Subprocess Start() const;
+
+ private:
+  std::vector<std::string> command_;
+  std::map<cvd::SharedFD, int> inherited_fds_{};
+  bool use_parent_env_ = true;
+  std::vector<std::string> env_{};
+};
+
+// Convenience wrapper around Command and Subprocess class, allows to easily
+// execute a command and wait for it to complete. The version without the env
+// parameter starts the command with the same environment as the parent. Returns
+// zero if the command completed successfully, non zero otherwise.
 int execute(const std::vector<std::string>& command,
             const std::vector<std::string>& env);
 int execute(const std::vector<std::string>& command);
diff --git a/guest/hals/gralloc/legacy/region_registry.cpp b/guest/hals/gralloc/legacy/region_registry.cpp
index 7e26c70..f188067 100644
--- a/guest/hals/gralloc/legacy/region_registry.cpp
+++ b/guest/hals/gralloc/legacy/region_registry.cpp
@@ -41,6 +41,10 @@
 
 #include "gralloc_vsoc_priv.h"
 
+#include <deque>
+#include <map>
+#include <mutex>
+
 // TODO(ghartman): Make the configurable through a property
 static const bool g_log_refs = false;
 
@@ -115,11 +119,73 @@
 }
 
 
+/*
+ * surface_flinger can drop its last reference to a gralloc buffer (from the
+ * gralloc HAL's point of view) even though it also has work in flight to the
+ * GPU for that target. This causes segfaults in the swiftshader code.
+ *
+ * We create a compromise solution. On unmap we release the pages by mmaping
+ * anonymous memory over the range, but we don't release the address space.
+ * Instead we mark the address space for recycling into a new gralloc buffer.
+ * This means that the shaders can still write, that the writes won't land in
+ * the gralloc buffer, and the gralloc buffer memory can be released.
+ *
+ * When we're preparing to mmap a new gralloc buffer we see if we can recycle
+ * address space from a prior gralloc buffer.
+ *
+ * The protects the application layer from stray memory writes and pointer
+ * references to freed memory. It does mean that bad pixel data can land in
+ * a buffer in the case of a fast map-unmap-map sequence. However, that
+ * could also happen on a physical GPU.
+ *
+ * The alternative to this would be to create an elaborate reference counting
+ * mechanism below both gralloc and SwiftShader. However, we want to keep the
+ * SwiftShader code clean, so that seems undesirable.
+ *
+ * This problem also comes up for physical GPUs b/62267886. Background fo rthis
+ * solution is in b/118777601
+ */
+
+static std::map<size_t, std::deque<void*>> g_recycled_addrs;
+std::mutex g_recycled_addrs_mutex;
+
+
+
+static void* recycle_mmap(void *addr, size_t length, int prot, int flags,
+                          int fd, off_t offset) {
+  if (!addr) {
+    std::lock_guard<std::mutex> guard(g_recycled_addrs_mutex);
+    auto it = g_recycled_addrs.find(length);
+    if (it != g_recycled_addrs.end()) {
+      if (it->second.size()) {
+        addr = it->second.front();
+        flags |= MAP_FIXED;
+        it->second.pop_front();
+      }
+    }
+  }
+  return mmap(addr, length, prot, flags, fd, offset);
+}
+
+
+static int recycle_munmap(void *addr, size_t length) {
+  // Do this first so we don't hold the mutex during the syscall
+  if (addr != mmap(addr, length, PROT_READ|PROT_WRITE,
+                   MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0)) {
+    // Be conservative. Don't recycle here.
+    return -1;
+  }
+  std::lock_guard<std::mutex> guard(g_recycled_addrs_mutex);
+  g_recycled_addrs[length].push_back(addr);
+  return 0;
+}
+
+
 void* reference_region(const char* op, const private_handle_t* hnd) {
   char name_buf[ASHMEM_NAME_LEN];
   GrallocRegion* region = lock_region_for_handle(hnd, name_buf);
   if (!region->base_) {
-    void* mappedAddress = mmap(
+    void* mappedAddress = recycle_mmap(
         0, hnd->total_size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
     if (mappedAddress == MAP_FAILED) {
       ALOGE("Could not mmap %s", strerror(errno));
@@ -168,7 +234,7 @@
   if (!region->num_references_) {
     ALOGI("Unmapped %s hnd=%p fd=%d base=%p", name_buf, hnd,
           hnd->fd, region->base_);
-    if (munmap(region->base_, hnd->total_size) < 0) {
+    if (recycle_munmap(region->base_, hnd->total_size) < 0) {
       ALOGE("Could not unmap %s", strerror(errno));
     }
     region->base_ = 0;
diff --git a/host/commands/adbshell/Android.bp b/host/commands/adbshell/Android.bp
index 3b169d2..ea84dd4 100644
--- a/host/commands/adbshell/Android.bp
+++ b/host/commands/adbshell/Android.bp
@@ -23,6 +23,11 @@
     ],
     shared_libs: [
         "libbase",
+        "libcuttlefish_utils",
+    ],
+    static_libs: [
+        "libcuttlefish_host_config",
+        "libjsoncpp",
     ],
     defaults: ["cuttlefish_host_only"],
 }
diff --git a/host/commands/adbshell/main.cpp b/host/commands/adbshell/main.cpp
index d1d4392..68ac18e 100644
--- a/host/commands/adbshell/main.cpp
+++ b/host/commands/adbshell/main.cpp
@@ -16,9 +16,12 @@
 
 /* Utility that uses an adb connection as the login shell. */
 
+#include "host/libs/config/cuttlefish_config.h"
+
 #include <array>
 #include <cassert>
 #include <cstdio>
+#include <cstdlib>
 #include <cstring>
 #include <string>
 #include <vector>
@@ -45,56 +48,33 @@
 //
 
 namespace {
-std::string InstanceNumberAsStr() {
-  static const char kUserPrefix[] = "cvd-";
+std::string VsocUser() {
+  const char* user_cstring = std::getenv("USER");
+  assert(user_cstring != nullptr);
+  std::string user(user_cstring);
 
-  std::string user{std::getenv("USER")};
-  return user.rfind(kUserPrefix, 0) == 0  // starts_with
-             ? user.substr(sizeof(kUserPrefix) - 1)
-             : "01";
-}
-
-int InstanceNumberAsInt() {
-  auto instance_str = InstanceNumberAsStr();
-  char* end{};
-  instance_str.push_back('\0');
-  auto result = static_cast<int>(std::strtol(&instance_str[0], &end, 10));
-  return *end || result < 1 ? 1 : result;
-}
-
-std::string TCPInstanceStr() {
-  static constexpr int kFirstPort = 6520;
-  const char kIPPrefix[] = "127.0.0.1:";
-
-  auto instance_port = InstanceNumberAsInt() - 1 + kFirstPort;
-  return std::string{kIPPrefix} + std::to_string(instance_port);
-}
-
-std::string USBInstanceStr() {
-  const char kSerialNumberPrefix[] = "CUTTLEFISHCVD";
-  std::string instance = InstanceNumberAsStr();
-  return std::string{kSerialNumberPrefix} + InstanceNumberAsStr();
-}
-
-std::string InstanceStr() {
-  std::string possible_device_names[] = {TCPInstanceStr(), USBInstanceStr()};
-
-  FILE* adb_devices_cmd_stream = popen("/usr/bin/adb devices", "r");
-  std::array<char, 128> line{};
-  while (fgets(line.data(), line.size(), adb_devices_cmd_stream) != nullptr) {
-    for (const auto& device_name : possible_device_names) {
-      if (std::string{line.data()}.find(device_name) != std::string::npos) {
-        return device_name;
-      }
-    }
+  std::string cvd_prefix = "cvd-";
+  if (user.find(cvd_prefix) == 0) {
+    user.replace(0, cvd_prefix.size(), vsoc::kVsocUserPrefix);
   }
-  return nullptr;
+  return user;
 }
 
+std::string CuttlefishConfigLocation() {
+  return std::string("/home/") + VsocUser() +
+         "/cuttlefish_runtime/cuttlefish_config.json";
+}
+
+void SetCuttlefishConfigEnv() {
+  setenv(vsoc::kCuttlefishConfigEnvVarName, CuttlefishConfigLocation().c_str(),
+         true);
+}
 }  // namespace
 
 int main(int argc, char* argv[]) {
-  auto instance = InstanceStr();
+  SetCuttlefishConfigEnv();
+  auto instance = vsoc::CuttlefishConfig::Get()->adb_device_name();
+
   std::vector<char*> new_argv = {
       const_cast<char*>("/usr/bin/adb"), const_cast<char*>("-s"),
       const_cast<char*>(instance.c_str()), const_cast<char*>("shell"),
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index 7c2cf47..3b685f1 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -303,9 +303,9 @@
   }
 }
 
-int CreateIvServerUnixSocket(const std::string& path) {
+cvd::SharedFD CreateIvServerUnixSocket(const std::string& path) {
   return cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM,
-                                          0666)->UNMANAGED_Dup();
+                                          0666);
 }
 
 bool AdbConnectorEnabled() {
@@ -324,17 +324,9 @@
                << usb_v1_server->StrError();
     std::exit(cvd::LauncherExitCodes::kUsbV1SocketError);
   }
-  int server_fd = usb_v1_server->UNMANAGED_Dup();
-  if (server_fd < 0) {
-    LOG(ERROR) << "Unable to dup USB v1 server socket file descriptor: "
-               << strerror(errno);
-    std::exit(cvd::LauncherExitCodes::kUsbV1SocketError);
-  }
-
-  cvd::subprocess({FLAGS_virtual_usb_manager_binary,
-                   "-usb_v1_fd=" + std::to_string(server_fd)});
-
-  close(server_fd);
+  cvd::Command usb_server(FLAGS_virtual_usb_manager_binary);
+  usb_server.AddParameter("-usb_v1_fd=", usb_v1_server);
+  usb_server.Start();
 }
 
 void LaunchKernelLogMonitor(const vsoc::CuttlefishConfig& config,
@@ -342,18 +334,12 @@
   auto log_name = config.kernel_log_socket_name();
   auto server = cvd::SharedFD::SocketLocalServer(log_name.c_str(), false,
                                                  SOCK_STREAM, 0666);
-  int server_fd = server->UNMANAGED_Dup();
-  int subscriber_fd = -1;
+  cvd::Command kernel_log_monitor(FLAGS_kernel_log_monitor_binary);
+  kernel_log_monitor.AddParameter("-log_server_fd=", server);
   if (boot_events_pipe->IsOpen()) {
-    subscriber_fd = boot_events_pipe->UNMANAGED_Dup();
+    kernel_log_monitor.AddParameter("-subscriber_fd=", boot_events_pipe);
   }
-  cvd::subprocess({FLAGS_kernel_log_monitor_binary,
-                   "-log_server_fd=" + std::to_string(server_fd),
-                   "-subscriber_fd=" + std::to_string(subscriber_fd)});
-  close(server_fd);
-  if (subscriber_fd >= 0) {
-    close(subscriber_fd);
-  }
+  kernel_log_monitor.Start();
 }
 
 void LaunchIvServer(const vsoc::CuttlefishConfig& config) {
@@ -371,30 +357,31 @@
       config.mempath(),
       {{vsoc::layout::screen::ScreenLayout::region_name, screen_buffers_size}});
 
-  auto qemu_channel =
-      CreateIvServerUnixSocket(config.ivshmem_qemu_socket_path());
-  auto client_channel =
-      CreateIvServerUnixSocket(config.ivshmem_client_socket_path());
-  auto qemu_socket_arg = "-qemu_socket_fd=" + std::to_string(qemu_channel);
-  auto client_socket_arg =
-      "-client_socket_fd=" + std::to_string(client_channel);
-  cvd::subprocess({FLAGS_ivserver_binary, qemu_socket_arg, client_socket_arg});
-  close(qemu_channel);
-  close(client_channel);
+
+  cvd::Command ivserver(FLAGS_ivserver_binary);
+  ivserver.AddParameter(
+      "-qemu_socket_fd=",
+      CreateIvServerUnixSocket(config.ivshmem_qemu_socket_path()));
+  ivserver.AddParameter(
+      "-client_socket_fd=",
+      CreateIvServerUnixSocket(config.ivshmem_client_socket_path()));
+  ivserver.Start();
 }
 
 void LaunchAdbConnectorIfEnabled() {
   if (AdbConnectorEnabled()) {
-    cvd::subprocess({FLAGS_adb_connector_binary,
-                     GetAdbConnectorPortArg()});
+    cvd::Command adb_connector(FLAGS_adb_connector_binary);
+    adb_connector.AddParameter(GetAdbConnectorPortArg());
+    adb_connector.Start();
   }
 }
 
 void LaunchSocketForwardProxyIfEnabled() {
   if (AdbTunnelEnabled()) {
-    cvd::subprocess({FLAGS_socket_forward_proxy_binary,
-                     GetGuestPortArg(),
-                     GetHostPortArg()});
+    cvd::Command adb_tunnel(FLAGS_socket_forward_proxy_binary);
+    adb_tunnel.AddParameter(GetGuestPortArg());
+    adb_tunnel.AddParameter(GetHostPortArg());
+    adb_tunnel.Start();
   }
 }
 
@@ -402,7 +389,9 @@
   if (FLAGS_start_vnc_server) {
     // Launch the vnc server, don't wait for it to complete
     auto port_options = "-port=" + std::to_string(FLAGS_vnc_server_port);
-    cvd::subprocess({FLAGS_vnc_server_binary, port_options});
+    cvd::Command vnc_server(FLAGS_vnc_server_binary);
+    vnc_server.AddParameter(port_options);
+    vnc_server.Start();
   }
 }
 
@@ -508,6 +497,7 @@
   tmp_config_obj.set_refresh_rate_hz(FLAGS_refresh_rate_hz);
   tmp_config_obj.set_gdb_flag(FLAGS_qemu_gdb);
   tmp_config_obj.set_adb_mode(FLAGS_adb_mode);
+  tmp_config_obj.set_adb_ip_and_port("127.0.0.1:" + std::to_string(GetHostPort()));
 
   tmp_config_obj.set_device_title(FLAGS_device_title);
   if (FLAGS_kernel_path.size()) {
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index b39e728..1173b1c 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -36,7 +36,6 @@
 
 int InstanceFromEnvironment() {
   static constexpr char kInstanceEnvironmentVariable[] = "CUTTLEFISH_INSTANCE";
-  static constexpr char kVsocUserPrefix[] = "vsoc-";
   static constexpr int kDefaultInstance = 1;
 
   // CUTTLEFISH_INSTANCE environment variable
@@ -44,12 +43,15 @@
   if (!instance_str) {
     // Try to get it from the user instead
     instance_str = std::getenv("USER");
-    if (!instance_str || std::strncmp(instance_str, kVsocUserPrefix,
-                                      sizeof(kVsocUserPrefix) - 1)) {
+
+    if (!instance_str || std::strncmp(instance_str, vsoc::kVsocUserPrefix,
+                                      sizeof(vsoc::kVsocUserPrefix) - 1)) {
       // No user or we don't recognize this user
+      LOG(WARNING) << "No user or non-vsoc user, returning default config";
       return kDefaultInstance;
     }
-    instance_str += sizeof(kVsocUserPrefix) - 1;
+    instance_str += sizeof(vsoc::kVsocUserPrefix) - 1;
+
     // Set the environment variable so that child processes see it
     setenv(kInstanceEnvironmentVariable, instance_str, 0);
   }
@@ -113,6 +115,7 @@
 const char* kCuttlefishEnvPath = "cuttlefish_env_path";
 
 const char* kAdbMode = "adb_mode";
+const char* kAdbIPAndPort = "adb_ip_and_port";
 const char* kSetupWizardMode = "setupwizard_mode";
 
 const char* kLogXml = "log_xml";
@@ -471,6 +474,24 @@
   (*dictionary_)[kAdbMode] = mode;
 }
 
+std::string CuttlefishConfig::adb_ip_and_port() const {
+  return (*dictionary_)[kAdbIPAndPort].asString();
+}
+
+void CuttlefishConfig::set_adb_ip_and_port(const std::string& ip_port) {
+  (*dictionary_)[kAdbIPAndPort] = ip_port;
+}
+
+std::string CuttlefishConfig::adb_device_name() const {
+  if (adb_mode().find("tunnel") != std::string::npos) {
+    return adb_ip_and_port();
+  } else if (adb_mode().find("usb") != std::string::npos) {
+    return serial_number();
+  }
+  LOG(ERROR) << "no adb_mode found, returning bad device name";
+  return "NO_ADB_MODE_SET_NO_VALID_DEVICE_NAME";
+}
+
 std::string CuttlefishConfig::device_title() const {
   return (*dictionary_)[kDeviceTitle].asString();
 }
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 561e7c3..fd1a26e 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -27,6 +27,7 @@
 
 constexpr char kDefaultUuidPrefix[] = "699acfc4-c8c4-11e7-882b-5065f31dc1";
 constexpr char kCuttlefishConfigEnvVarName[] = "CUTTLEFISH_CONFIG_FILE";
+constexpr char kVsocUserPrefix[] = "vsoc-";
 
 // Holds the configuration of the cuttlefish instances.
 class CuttlefishConfig {
@@ -187,6 +188,11 @@
   void set_adb_mode(const std::string& mode);
   std::string adb_mode() const;
 
+  void set_adb_ip_and_port(const std::string& ip_port);
+  std::string adb_ip_and_port() const;
+
+  std::string adb_device_name() const;
+
   void set_device_title(const std::string& title);
   std::string device_title() const;
 
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index ce7e842..8a46825 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -51,7 +51,7 @@
   LOG(INFO) << key << "=" << value;
 }
 
-pid_t BuildAndRunQemuCmd(const vsoc::CuttlefishConfig* config) {
+cvd::Subprocess BuildAndRunQemuCmd(const vsoc::CuttlefishConfig* config) {
   // Set the config values in the environment
   LogAndSetEnv("qemu_binary", config->qemu_binary());
   LogAndSetEnv("instance_name", config->instance_name());
@@ -79,7 +79,9 @@
   LogAndSetEnv("ivshmem_vector_count",
                       std::to_string(config->ivshmem_vector_count()));
   LogAndSetEnv("usb_v1_socket_name", config->usb_v1_socket_name());
-  return cvd::subprocess({vsoc::DefaultHostArtifactsPath("bin/cf_qemu.sh")});
+
+  cvd::Command qemu_cmd(vsoc::DefaultHostArtifactsPath("bin/cf_qemu.sh"));
+  return qemu_cmd.Start();
 }
 
 }  // namespace