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