Merge "Move Euler rotation state to CF webrtc backend" into main
diff --git a/Android.bp b/Android.bp
index 3109bf3..ee916a9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -68,6 +68,9 @@
host: {
cflags: ["-DCUTTLEFISH_HOST"],
compile_multilib: "64",
+ strip: {
+ keep_symbols_and_debug_frame: true,
+ },
},
linux: {
host_ldlibs: ["-lrt"],
@@ -141,42 +144,6 @@
defaults: ["cuttlefish_base"],
}
-cc_defaults {
- name: "cuttlefish_recovery_available",
- recovery_available : true
-}
-
-cc_defaults {
- name: "enabled_on_p_and_later",
- enabled: true
-}
-
-cc_defaults {
- name: "enabled_on_q_and_later",
- enabled: true
-}
-
-cc_defaults {
- name: "enabled_on_q_internal_and_later",
- enabled: true
-}
-
-cc_defaults {
- name: "cuttlefish_libicuuc",
- target: {
- host: {
- shared_libs: [
- "libicuuc",
- ],
- },
- },
-}
-
-cc_defaults {
- name: "cuttlefish_health_storage",
- defaults: ["enabled_on_q_and_later"],
-}
-
java_test_host {
name: "tombstone_transmit_tests",
@@ -188,8 +155,3 @@
test_suites: ["general-tests"],
}
-
-filegroup {
- name: "cf_dtb",
- srcs: ["dtb.img"],
-}
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
index 1857e3a..55b23bb 100644
--- a/AndroidProducts.mk
+++ b/AndroidProducts.mk
@@ -18,6 +18,7 @@
aosp_cf_arm_minidroid:$(LOCAL_DIR)/vsoc_arm_minidroid/aosp_cf.mk \
aosp_cf_arm64_auto:$(LOCAL_DIR)/vsoc_arm64_only/auto/aosp_cf.mk \
aosp_cf_arm64_phone:$(LOCAL_DIR)/vsoc_arm64/phone/aosp_cf.mk \
+ aosp_cf_arm64_phone_pgagnostic:$(LOCAL_DIR)/vsoc_arm64_only/phone/aosp_cf_pgagnostic.mk \
aosp_cf_arm64_phone_fullmte:$(LOCAL_DIR)/vsoc_arm64_only/phone/aosp_cf_fullmte.mk \
aosp_cf_arm64_phone_hwasan:$(LOCAL_DIR)/vsoc_arm64/phone/aosp_cf_hwasan.mk \
aosp_cf_arm64_only_phone:$(LOCAL_DIR)/vsoc_arm64_only/phone/aosp_cf.mk \
diff --git a/build/Android.bp b/build/Android.bp
index d517ac4..d45d501 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -134,6 +134,12 @@
"vulkan.pastel",
]
+cvd_host_tools_aarch64 = [
+ "aarch64_linux_gnu_crosvm",
+ "aarch64_linux_gnu_libgfxstream_backend.so_for_crosvm",
+ "aarch64_linux_gnu_libminijail.so_for_crosvm",
+]
+
cvd_openwrt_images = [
"openwrt_kernel_x86_64",
"openwrt_rootfs_x86_64",
@@ -341,6 +347,7 @@
},
},
arm64: {
+ deps: cvd_host_tools_aarch64,
multilib: {
common: {
deps: cvd_host_seccomp_policy_aarch64,
diff --git a/common/frontend/socket_vsock_proxy/client.cpp b/common/frontend/socket_vsock_proxy/client.cpp
index 90aee5a..44161fc 100644
--- a/common/frontend/socket_vsock_proxy/client.cpp
+++ b/common/frontend/socket_vsock_proxy/client.cpp
@@ -26,11 +26,11 @@
return address.find(':') != std::string::npos;
}
-SharedFD StartIpv4(const std::string& host, int port) {
- return SharedFD::SocketClient(host, port, SOCK_STREAM);
+SharedFD StartIpv4(const std::string& host, int port, std::chrono::seconds timeout) {
+ return SharedFD::SocketClient(host, port, SOCK_STREAM, timeout);
}
-SharedFD StartIpv6(const std::string& host, int port) {
+SharedFD StartIpv6(const std::string& host, int port, std::chrono::seconds timeout) {
const auto host_parsed = android::base::Tokenize(host, "%");
const auto host_interface_tokens_count = host_parsed.size();
@@ -46,20 +46,23 @@
host_name = host;
}
- return SharedFD::Socket6Client(host_name, interface_name, port, SOCK_STREAM);
+ return SharedFD::Socket6Client(host_name, interface_name, port, SOCK_STREAM, timeout);
}
}
-TcpClient::TcpClient(std::string host, int port) : host_(std::move(host)), port_(port) {}
+TcpClient::TcpClient(std::string host, int port, std::chrono::seconds timeout)
+ : host_(std::move(host)),
+ port_(port),
+ timeout_(timeout) {}
SharedFD TcpClient::Start() {
SharedFD client;
if (IsIpv6(host_)) {
- client = StartIpv6(host_, port_);
+ client = StartIpv6(host_, port_, timeout_);
} else {
- client = StartIpv4(host_, port_);
+ client = StartIpv4(host_, port_, timeout_);
}
if (client->IsOpen()) {
diff --git a/common/frontend/socket_vsock_proxy/client.h b/common/frontend/socket_vsock_proxy/client.h
index ca21005..e45c974 100644
--- a/common/frontend/socket_vsock_proxy/client.h
+++ b/common/frontend/socket_vsock_proxy/client.h
@@ -15,6 +15,8 @@
#pragma once
+#include <chrono>
+
#include "common/libs/fs/shared_fd.h"
namespace cuttlefish {
@@ -29,13 +31,14 @@
class TcpClient : public Client {
public:
- TcpClient(std::string host, int port);
+ TcpClient(std::string host, int port, std::chrono::seconds timeout = std::chrono::seconds(0));
SharedFD Start() override;
std::string Describe() const override;
private:
std::string host_;
int port_;
+ std::chrono::seconds timeout_;
int last_failure_reason_ = 0;
};
diff --git a/common/frontend/socket_vsock_proxy/server.cpp b/common/frontend/socket_vsock_proxy/server.cpp
index 2264442..fcd46f4 100644
--- a/common/frontend/socket_vsock_proxy/server.cpp
+++ b/common/frontend/socket_vsock_proxy/server.cpp
@@ -13,7 +13,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <chrono>
#include <set>
+#include <thread>
#include "common/frontend/socket_vsock_proxy/server.h"
#include "common/libs/utils/contains.h"
@@ -23,7 +25,7 @@
namespace {
bool socketErrorIsRecoverable(int error) {
- std::set<int> unrecoverable{EACCES, EAFNOSUPPORT, EINVAL, EPROTONOSUPPORT};
+ std::set<int> unrecoverable{EACCES, EAFNOSUPPORT, EINVAL, EPROTONOSUPPORT, EADDRINUSE};
return !Contains(unrecoverable, error);
}
@@ -35,15 +37,31 @@
}
-TcpServer::TcpServer(int port) : port_(port) {}
+TcpServer::TcpServer(int port, int retries_count, std::chrono::milliseconds retries_delay)
+ : port_(port),
+ retries_count_(retries_count),
+ retries_delay_(retries_delay) {};
-SharedFD TcpServer::Start() {
+Result<SharedFD> TcpServer::Start() {
SharedFD server;
+ int last_error = 0;
- server = SharedFD::SocketLocalServer(port_, SOCK_STREAM);
- CHECK(server->IsOpen()) << "Could not start server on " << port_;
+ for (int i = 0; i < retries_count_; i++) {
+ server = SharedFD::SocketLocalServer(port_, SOCK_STREAM);
+ if (server->IsOpen()) {
+ return server;
+ }
+ last_error = server->GetErrno();
- return server;
+ LOG(INFO) << "Failed to start TCP server on port: " << port_
+ << " after " << i + 1 << "th attempt (going to have "
+ << retries_count_ << " total attempts" << "). Error: " << last_error;
+
+ std::this_thread::sleep_for(retries_delay_);
+ }
+
+ return CF_ERR("Could not start TCP server on port: " << port_
+ << "after " << retries_count_ << " attempts. Last error: " << last_error);
}
std::string TcpServer::Describe() const {
@@ -53,7 +71,7 @@
VsockServer::VsockServer(int port) : port_(port) {}
// Intended to run in the guest
-SharedFD VsockServer::Start() {
+Result<SharedFD> VsockServer::Start() {
SharedFD server;
do {
@@ -78,8 +96,8 @@
close(fd);
}
-SharedFD DupServer::Start() {
- CHECK(sfd_->IsOpen()) << "Could not start duplicate server for passed fd";
+Result<SharedFD> DupServer::Start() {
+ CF_EXPECT(sfd_->IsOpen(), "Could not start duplicate server for passed fd");
return sfd_;
}
diff --git a/common/frontend/socket_vsock_proxy/server.h b/common/frontend/socket_vsock_proxy/server.h
index 66aaeef..7535852 100644
--- a/common/frontend/socket_vsock_proxy/server.h
+++ b/common/frontend/socket_vsock_proxy/server.h
@@ -15,32 +15,38 @@
#pragma once
+#include <chrono>
+
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/result.h"
namespace cuttlefish {
namespace socket_proxy {
class Server {
public:
- virtual SharedFD Start() = 0;
+ virtual Result<SharedFD> Start() = 0;
virtual std::string Describe() const = 0;
virtual ~Server() = default;
};
class TcpServer : public Server {
public:
- TcpServer(int port);
- SharedFD Start() override;
+ TcpServer(int port, int retries_count = 1,
+ std::chrono::milliseconds retries_delay = std::chrono::milliseconds(0));
+ Result<SharedFD> Start() override;
std::string Describe() const override;
private:
int port_;
+ int retries_count_;
+ std::chrono::milliseconds retries_delay_;
};
class VsockServer : public Server {
public:
VsockServer(int port);
- SharedFD Start() override;
+ Result<SharedFD> Start() override;
std::string Describe() const override;
private:
@@ -50,7 +56,7 @@
class DupServer : public Server {
public:
DupServer(int fd);
- SharedFD Start() override;
+ Result<SharedFD> Start() override;
std::string Describe() const override;
private:
diff --git a/common/frontend/socket_vsock_proxy/socket_vsock_proxy.cpp b/common/frontend/socket_vsock_proxy/socket_vsock_proxy.cpp
index 1851368..43173c3 100644
--- a/common/frontend/socket_vsock_proxy/socket_vsock_proxy.cpp
+++ b/common/frontend/socket_vsock_proxy/socket_vsock_proxy.cpp
@@ -18,12 +18,14 @@
#include <android-base/logging.h>
#include <gflags/gflags.h>
+#include <chrono>
#include <memory>
#include <sstream>
#include "common/frontend/socket_vsock_proxy/client.h"
#include "common/frontend/socket_vsock_proxy/server.h"
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/result.h"
#include "common/libs/utils/socket2socket_proxy.h"
#include "common/libs/utils/tee_logging.h"
#include "host/commands/kernel_log_monitor/utils.h"
@@ -32,8 +34,12 @@
#include "host/libs/config/logging.h"
#endif // CUTTLEFISH_HOST
-constexpr const char TRANSPORT_TCP[] = "tcp";
-constexpr const char TRANSPORT_VSOCK[] = "vsock";
+constexpr int TCP_SERVER_START_RETRIES_COUNT = 10;
+constexpr std::chrono::milliseconds TCP_SERVER_RETRIES_DELAY(1250);
+constexpr std::chrono::seconds TCP_CLIENT_TIMEOUT(1);
+
+constexpr char TRANSPORT_TCP[] = "tcp";
+constexpr char TRANSPORT_VSOCK[] = "vsock";
DEFINE_string(label, "socket_vsock_proxy", "Label which is used only for logging. "
"Log messages will look like [label] message");
@@ -55,12 +61,14 @@
"kernel_log_server.h) that we will listen to start proxy");
DEFINE_uint32(stop_event_id, -1, "Kernel event id (cuttlefish::monitor::Event from "
"kernel_log_server.h) that we will listen to stop proxy");
+DEFINE_bool(start_immediately, false, "A flag to start proxying without waiting for "
+ "initial start event");
namespace cuttlefish {
namespace socket_proxy {
namespace {
-std::unique_ptr<Server> BuildServer() {
+static std::unique_ptr<Server> BuildServer() {
if (FLAGS_server_fd >= 0) {
return std::make_unique<DupServer>(FLAGS_server_fd);
}
@@ -80,7 +88,8 @@
std::unique_ptr<Server> server = nullptr;
if (FLAGS_server_type == TRANSPORT_TCP) {
- server = std::make_unique<TcpServer>(FLAGS_server_tcp_port);
+ server = std::make_unique<TcpServer>(FLAGS_server_tcp_port, TCP_SERVER_START_RETRIES_COUNT,
+ TCP_SERVER_RETRIES_DELAY);
} else if (FLAGS_server_type == TRANSPORT_VSOCK) {
server = std::make_unique<VsockServer>(FLAGS_server_vsock_port);
} else {
@@ -90,7 +99,7 @@
return server;
}
-std::unique_ptr<Client> BuildClient() {
+static std::unique_ptr<Client> BuildClient() {
CHECK(FLAGS_client_type == TRANSPORT_TCP || FLAGS_client_type == TRANSPORT_VSOCK)
<< "Must specify -client_type with tcp or vsock values";
@@ -106,7 +115,8 @@
std::unique_ptr<Client> client = nullptr;
if (FLAGS_client_type == TRANSPORT_TCP) {
- client = std::make_unique<TcpClient>(FLAGS_client_tcp_host, FLAGS_client_tcp_port);
+ client = std::make_unique<TcpClient>(FLAGS_client_tcp_host, FLAGS_client_tcp_port,
+ TCP_CLIENT_TIMEOUT);
} else if (FLAGS_client_type == TRANSPORT_VSOCK) {
client = std::make_unique<VsockClient>(FLAGS_client_vsock_id, FLAGS_client_vsock_port);
} else {
@@ -116,14 +126,26 @@
return client;
}
-void ListenEventsAndProxy(int events_fd, const monitor::Event start, const monitor::Event stop,
- Server& server, Client& client) {
+static Result<std::unique_ptr<ProxyServer>> StartProxyAsync(Server& server, Client& client) {
+ LOG(INFO) << "From: " << server.Describe();
+ LOG(INFO) << "To: " << client.Describe();
+ return ProxyAsync(CF_EXPECT(server.Start()), [&client] { return client.Start(); });
+}
+
+static Result<void> ListenEventsAndProxy(int events_fd,
+ const monitor::Event start, const monitor::Event stop,
+ Server& server, Client& client) {
auto events = SharedFD::Dup(events_fd);
close(events_fd);
- std::unique_ptr<cuttlefish::ProxyServer> proxy;
+ std::unique_ptr<ProxyServer> proxy;
- LOG(DEBUG) << "Start reading ";
+ if (FLAGS_start_immediately) {
+ LOG(INFO) << "start_immediately was set to true, so starting proxying";
+ proxy = std::move(CF_EXPECT(StartProxyAsync(server, client)));
+ }
+
+ LOG(DEBUG) << "Start reading evets to start/stop proxying";
while (events->IsOpen()) {
std::optional<monitor::ReadEventResult> received_event = monitor::ReadEvent(events);
@@ -135,12 +157,7 @@
if (start != -1 && received_event->event == start) {
if (!proxy) {
LOG(INFO) << "Start event (" << start << ") received. Starting proxy";
- LOG(INFO) << "From: " << server.Describe();
- LOG(INFO) << "To: " << client.Describe();
- auto started_proxy = cuttlefish::ProxyAsync(server.Start(), [&client] {
- return client.Start();
- });
- proxy = std::move(started_proxy);
+ proxy = std::move(CF_EXPECT(StartProxyAsync(server, client)));
}
continue;
}
@@ -151,6 +168,28 @@
continue;
}
}
+
+ return {};
+}
+
+Result<void> Main() {
+ auto server = BuildServer();
+ auto client = BuildClient();
+
+ if (FLAGS_events_fd != -1) {
+ CF_EXPECT(FLAGS_start_event_id != -1, "start_event_id is required if events_fd is provided");
+
+ const monitor::Event start_event = static_cast<monitor::Event>(FLAGS_start_event_id);
+ const monitor::Event stop_event = static_cast<monitor::Event>(FLAGS_stop_event_id);
+
+ CF_EXPECT(ListenEventsAndProxy(FLAGS_events_fd, start_event, stop_event,
+ *server, *client));
+ } else {
+ LOG(DEBUG) << "Starting proxy";
+ Proxy(CF_EXPECT(server->Start()), [&client] { return client->Start(); });
+ }
+
+ return {};
}
}
@@ -171,20 +210,10 @@
android::base::SetDefaultTag("proxy_" + FLAGS_label);
}
- auto server = cuttlefish::socket_proxy::BuildServer();
- auto client = cuttlefish::socket_proxy::BuildClient();
-
- if (FLAGS_events_fd != -1) {
- CHECK(FLAGS_start_event_id != -1)
- << "start_event_id is required if events_fd is provided";
-
- const monitor::Event start_event = static_cast<monitor::Event>(FLAGS_start_event_id);
- const monitor::Event stop_event = static_cast<monitor::Event>(FLAGS_stop_event_id);
-
- cuttlefish::socket_proxy::ListenEventsAndProxy(FLAGS_events_fd, start_event, stop_event,
- *server, *client);
- } else {
- LOG(DEBUG) << "Starting proxy";
- cuttlefish::Proxy(server->Start(), [&client] { return client->Start(); });
+ auto result = cuttlefish::socket_proxy::Main();
+ if (!result.ok()) {
+ LOG(FATAL) << "Failed to proxy: " << result.error().Message();
}
+
+ return 0;
}
diff --git a/common/libs/confui/Android.bp b/common/libs/confui/Android.bp
index ca6348a..fca008b 100644
--- a/common/libs/confui/Android.bp
+++ b/common/libs/confui/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_confui",
srcs: [
"packet_types.cpp",
@@ -25,15 +25,14 @@
"protocol_types.cpp",
"protocol.cpp",
],
- static: {
- static_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libteeui",
- ],
- shared_libs: [
- "libcrypto", // libcrypto_static is not accessible from all targets
- ],
- },
+ static_libs: [
+ "libteeui",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcrypto", // libcrypto_static is not accessible from all targets
+ "libcuttlefish_fs",
+ "liblog",
+ ],
defaults: ["cuttlefish_host"],
}
diff --git a/common/libs/fs/Android.bp b/common/libs/fs/Android.bp
index 56cb96e..7285f84 100644
--- a/common/libs/fs/Android.bp
+++ b/common/libs/fs/Android.bp
@@ -24,50 +24,42 @@
"shared_fd.cpp",
"shared_fd_stream.cpp",
],
- shared: {
- shared_libs: [
- "libbase",
- "liblog",
- ],
- },
- static: {
- static_libs: [
- "libbase",
- "liblog",
- ],
- },
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
target: {
+ android: {
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+ },
darwin: {
enabled: true,
},
+ host: {
+ shared: {
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+ },
+ static: {
+ static_libs: [
+ "libbase",
+ "liblog",
+ ],
+ },
+ },
linux: {
srcs: [
"epoll.cpp",
],
},
- vendor: {
- // Liblog does not have a vendor-static variant.
- shared_libs: ["liblog"],
- exclude_static_libs: ["liblog"],
- },
},
defaults: ["cuttlefish_host"],
-}
-
-cc_library_static {
- name: "libcuttlefish_fs_product",
- srcs: [
- "epoll.cpp",
- "shared_buf.cc",
- "shared_fd.cpp",
- "shared_fd_stream.cpp",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- ],
- stl: "libc++_static",
- defaults: ["cuttlefish_guest_product_only"],
+ product_available: true,
}
cc_test {
diff --git a/common/libs/fs/shared_fd.cpp b/common/libs/fs/shared_fd.cpp
index cfdb3c2..51039cf 100644
--- a/common/libs/fs/shared_fd.cpp
+++ b/common/libs/fs/shared_fd.cpp
@@ -525,7 +525,8 @@
return rval;
}
-SharedFD SharedFD::SocketClient(const std::string& host, int port, int type) {
+SharedFD SharedFD::SocketClient(const std::string& host, int port, int type,
+ std::chrono::seconds timeout) {
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
@@ -534,14 +535,16 @@
if (!rval->IsOpen()) {
return rval;
}
- if (rval->Connect(reinterpret_cast<const sockaddr*>(&addr), sizeof addr) < 0) {
+ struct timeval timeout_timeval = {static_cast<time_t>(timeout.count()), 0};
+ if (rval->ConnectWithTimeout(reinterpret_cast<const sockaddr*>(&addr),
+ sizeof addr, &timeout_timeval) < 0) {
return SharedFD::ErrorFD(rval->GetErrno());
}
return rval;
}
SharedFD SharedFD::Socket6Client(const std::string& host, const std::string& interface,
- int port, int type) {
+ int port, int type, std::chrono::seconds timeout) {
sockaddr_in6 addr{};
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(port);
@@ -569,7 +572,9 @@
#endif
}
- if (rval->Connect(reinterpret_cast<const sockaddr*>(&addr), sizeof addr) < 0) {
+ struct timeval timeout_timeval = {static_cast<time_t>(timeout.count()), 0};
+ if (rval->ConnectWithTimeout(reinterpret_cast<const sockaddr*>(&addr),
+ sizeof addr, &timeout_timeval) < 0) {
return SharedFD::ErrorFD(rval->GetErrno());
}
return rval;
diff --git a/common/libs/fs/shared_fd.h b/common/libs/fs/shared_fd.h
index 583db7a..4672ade 100644
--- a/common/libs/fs/shared_fd.h
+++ b/common/libs/fs/shared_fd.h
@@ -33,6 +33,7 @@
#include <sys/uio.h>
#include <sys/un.h>
+#include <chrono>
#include <memory>
#include <sstream>
#include <string>
@@ -156,9 +157,10 @@
static SharedFD SocketLocalClient(const std::string& name, bool is_abstract,
int in_type, int timeout_seconds);
static SharedFD SocketLocalClient(int port, int type);
- static SharedFD SocketClient(const std::string& host, int port, int type);
- static SharedFD Socket6Client(const std::string& host, const std::string& interface,
- int port, int type);
+ static SharedFD SocketClient(const std::string& host, int port,
+ int type, std::chrono::seconds timeout = std::chrono::seconds(0));
+ static SharedFD Socket6Client(const std::string& host, const std::string& interface, int port,
+ int type, std::chrono::seconds timeout = std::chrono::seconds(0));
static SharedFD SocketLocalServer(const std::string& name, bool is_abstract,
int in_type, mode_t mode);
static SharedFD SocketLocalServer(int port, int type);
diff --git a/common/libs/utils/Android.bp b/common/libs/utils/Android.bp
index 6fb8e34..14ff196 100644
--- a/common/libs/utils/Android.bp
+++ b/common/libs/utils/Android.bp
@@ -67,19 +67,7 @@
}
},
defaults: ["cuttlefish_host"],
-}
-
-cc_library_static {
- name: "libcuttlefish_utils_product",
- srcs: [
- "inotify.cpp",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- ],
- stl: "libc++_static",
- defaults: ["cuttlefish_guest_product_only"],
+ product_available: true,
}
cc_test_host {
diff --git a/common/libs/utils/flag_parser.cpp b/common/libs/utils/flag_parser.cpp
index 6cb65c9..aba5236 100644
--- a/common/libs/utils/flag_parser.cpp
+++ b/common/libs/utils/flag_parser.cpp
@@ -123,27 +123,6 @@
return *this;
}
-Flag& Flag::Setter(std::function<bool(const FlagMatch&)> fn) & {
- setter_ = [fn = std::move(fn)](const FlagMatch& match) -> Result<void> {
- if (fn(match)) {
- return {};
- } else {
- return CF_ERR("Flag setter failed");
- }
- };
- return *this;
-}
-Flag Flag::Setter(std::function<bool(const FlagMatch&)> fn) && {
- setter_ = [fn = std::move(fn)](const FlagMatch& match) -> Result<void> {
- if (fn(match)) {
- return {};
- } else {
- return CF_ERR("Flag setter failed");
- }
- };
- return *this;
-}
-
Flag& Flag::Setter(std::function<Result<void>(const FlagMatch&)> setter) & {
setter_ = std::move(setter);
return *this;
@@ -439,15 +418,15 @@
.Help("Used to set the verbosity level for logging.");
}
-Flag HelpFlag(const std::vector<Flag>& flags, const std::string& text) {
- auto setter = [&](FlagMatch) {
+Flag HelpFlag(const std::vector<Flag>& flags, std::string text) {
+ auto setter = [&flags, text](FlagMatch) -> Result<void> {
if (text.size() > 0) {
LOG(INFO) << text;
}
for (const auto& flag : flags) {
LOG(INFO) << flag;
}
- return false;
+ return CF_ERR("user requested early exit");
};
return Flag()
.Alias({FlagAliasMode::kFlagExact, "-help"})
@@ -491,9 +470,9 @@
}
Flag HelpXmlFlag(const std::vector<Flag>& flags, std::ostream& out, bool& value,
- const std::string& text) {
+ std::string text) {
const std::string name = "helpxml";
- auto setter = [name, &out, &value, &text,
+ auto setter = [name, &out, &value, text,
&flags](const FlagMatch& match) -> Result<void> {
bool print_xml = false;
CF_EXPECT(GflagsCompatBoolFlagSetter(name, print_xml, match));
@@ -518,9 +497,8 @@
.Help(
"This executable only supports the flags in `-help`. Positional "
"arguments may be supported.")
- .Setter([](const FlagMatch& match) {
- LOG(ERROR) << "Unknown flag " << match.value;
- return false;
+ .Setter([](const FlagMatch& match) -> Result<void> {
+ return CF_ERRF("Unknown flag \"{}\"", match.value);
});
}
@@ -530,9 +508,8 @@
.Help(
"This executable only supports the flags in `-help`. Positional "
"arguments are not supported.")
- .Setter([](const FlagMatch& match) {
- LOG(ERROR) << "Unexpected argument \"" << match.value << "\"";
- return false;
+ .Setter([](const FlagMatch& match) -> Result<void> {
+ return CF_ERRF("Unexpected argument \"{}\"", match.value);
});
}
@@ -547,9 +524,9 @@
Flag GflagsCompatFlag(const std::string& name, std::string& value) {
return GflagsCompatFlag(name)
.Getter([&value]() { return value; })
- .Setter([&value](const FlagMatch& match) {
+ .Setter([&value](const FlagMatch& match) -> Result<void> {
value = match.value;
- return true;
+ return {};
});
}
@@ -598,9 +575,11 @@
std::vector<std::string>& value) {
return GflagsCompatFlag(name)
.Getter([&value]() { return android::base::Join(value, ','); })
- .Setter([&name, &value](const FlagMatch& match) -> Result<void> {
- CF_EXPECTF(!match.value.empty(), "No values given for flag \"{}\"",
- name);
+ .Setter([&value](const FlagMatch& match) -> Result<void> {
+ if (match.value.empty()) {
+ value.clear();
+ return {};
+ }
std::vector<std::string> str_vals =
android::base::Split(match.value, ",");
value = std::move(str_vals);
@@ -613,8 +592,10 @@
return GflagsCompatFlag(name)
.Getter([&value]() { return fmt::format("{}", fmt::join(value, ",")); })
.Setter([&name, &value, def_val](const FlagMatch& match) -> Result<void> {
- CF_EXPECTF(!match.value.empty(), "No values given for flag \"{}\"",
- name);
+ if (match.value.empty()) {
+ value.clear();
+ return {};
+ }
std::vector<std::string> str_vals =
android::base::Split(match.value, ",");
value.clear();
diff --git a/common/libs/utils/flag_parser.h b/common/libs/utils/flag_parser.h
index e8b045b..3304311 100644
--- a/common/libs/utils/flag_parser.h
+++ b/common/libs/utils/flag_parser.h
@@ -81,9 +81,8 @@
/* Set a loader that displays the current value in help text. Optional. */
Flag& Getter(std::function<std::string()>) &;
Flag Getter(std::function<std::string()>) &&;
- /* Set the callback for matches. The callback be invoked multiple times. */
- Flag& Setter(std::function<bool(const FlagMatch&)>) &;
- Flag Setter(std::function<bool(const FlagMatch&)>) &&;
+ /* Set the callback for matches. The callback may be invoked multiple times.
+ */
Flag& Setter(std::function<Result<void>(const FlagMatch&)>) &;
Flag Setter(std::function<Result<void>(const FlagMatch&)>) &&;
@@ -154,11 +153,11 @@
* unexpected arguments). */
/* If a "-help" or "--help" flag is present, prints all the flags and fails. */
-Flag HelpFlag(const std::vector<Flag>& flags, const std::string& text = "");
+Flag HelpFlag(const std::vector<Flag>& flags, std::string text = "");
/* If a "-helpxml" is present, prints all the flags in XML and fails. */
Flag HelpXmlFlag(const std::vector<Flag>& flags, std::ostream&, bool& value,
- const std::string& text = "");
+ std::string text = "");
/* Catches unrecognized arguments that begin with `-`, and errors out. This
* effectively denies unknown flags. */
diff --git a/common/libs/utils/flag_parser_test.cpp b/common/libs/utils/flag_parser_test.cpp
index 74422e5..26503f7 100644
--- a/common/libs/utils/flag_parser_test.cpp
+++ b/common/libs/utils/flag_parser_test.cpp
@@ -117,9 +117,9 @@
TEST(FlagParser, RepeatedListFlag) {
std::vector<std::string> elems;
auto flag = GflagsCompatFlag("myflag");
- flag.Setter([&elems](const FlagMatch& match) {
+ flag.Setter([&elems](const FlagMatch& match) -> Result<void> {
elems.push_back(match.value);
- return true;
+ return {};
});
ASSERT_THAT(flag.Parse({"-myflag=a", "--myflag", "b"}), IsOk());
ASSERT_EQ(elems, (std::vector<std::string>{"a", "b"}));
@@ -238,7 +238,7 @@
std::vector<std::string> value;
auto flag = GflagsCompatFlag("myflag", value);
- ASSERT_THAT(flag.Parse({"--myflag="}), IsError());
+ ASSERT_THAT(flag.Parse({"--myflag="}), IsOk());
ASSERT_TRUE(value.empty());
ASSERT_THAT(flag.Parse({"--myflag=foo"}), IsOk());
@@ -262,7 +262,7 @@
bool default_value = true;
auto flag = GflagsCompatFlag("myflag", value, default_value);
- ASSERT_THAT(flag.Parse({"--myflag="}), IsError());
+ ASSERT_THAT(flag.Parse({"--myflag="}), IsOk());
ASSERT_TRUE(value.empty());
ASSERT_THAT(flag.Parse({"--myflag=foo"}), IsError());
@@ -391,9 +391,9 @@
elems_.clear();
flag_ = Flag()
.Alias({FlagAliasMode::kFlagConsumesArbitrary, "--flag"})
- .Setter([this](const FlagMatch& match) {
+ .Setter([this](const FlagMatch& match) -> Result<void> {
elems_.push_back(match.value);
- return true;
+ return {};
});
}
Flag flag_;
diff --git a/common/libs/utils/json.h b/common/libs/utils/json.h
index db9581c..89517d85 100644
--- a/common/libs/utils/json.h
+++ b/common/libs/utils/json.h
@@ -15,7 +15,9 @@
#pragma once
+#include <string>
#include <string_view>
+#include <vector>
#include <json/json.h>
@@ -25,4 +27,26 @@
Result<Json::Value> ParseJson(std::string_view input);
+template <typename T>
+Result<T> GetValue(const Json::Value& root,
+ const std::vector<std::string>& selectors) {
+ const Json::Value* traversal = &root;
+ for (const auto& selector : selectors) {
+ CF_EXPECTF(traversal->isMember(selector),
+ "JSON selector \"{}\" does not exist", selector);
+ traversal = &(*traversal)[selector];
+ }
+ return traversal->as<T>();
+}
+
+template <typename T>
+Result<std::vector<T>> GetArrayValues(
+ const Json::Value& array, const std::vector<std::string>& selectors) {
+ std::vector<T> result;
+ for (const auto& element : array) {
+ result.emplace_back(CF_EXPECT(GetValue<T>(element, selectors)));
+ }
+ return result;
+}
+
} // namespace cuttlefish
diff --git a/common/libs/utils/rust/vsock_connection/Android.bp b/common/libs/utils/rust/vsock_connection/Android.bp
index 43a51a0..66f8b79 100644
--- a/common/libs/utils/rust/vsock_connection/Android.bp
+++ b/common/libs/utils/rust/vsock_connection/Android.bp
@@ -2,7 +2,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libvsock_utils_wrapper",
srcs: [
"wrapper.cpp",
@@ -14,9 +14,9 @@
"libbase_headers",
],
shared_libs: [
+ "libcuttlefish_fs",
+ "libjsoncpp", // needed since libjsoncpp_headers isn't available from the vendor partition
"libvsock_utils",
- // needed since libjsoncpp_headers isn't available from the vendor partition
- "libjsoncpp",
],
defaults: ["cuttlefish_guest_only"],
}
diff --git a/common/libs/utils/rust/vsock_connection/lib.rs b/common/libs/utils/rust/vsock_connection/lib.rs
index b6c88e4..59bd099 100644
--- a/common/libs/utils/rust/vsock_connection/lib.rs
+++ b/common/libs/utils/rust/vsock_connection/lib.rs
@@ -14,7 +14,7 @@
//! Rust wrapper for VSockServerConnection.
-use cxx::SharedPtr;
+use cxx::UniquePtr;
/// This module exposes the VsockServerConnection C++ class to Rust.
#[allow(unsafe_op_in_unsafe_fn)]
@@ -24,25 +24,37 @@
include!("wrapper.h");
type VsockServerConnection;
- fn create_shared_vsock_server_connection() -> SharedPtr<VsockServerConnection>;
- fn IsConnected(self: &VsockServerConnection) -> bool;
+ fn create_vsock_server_connection() -> UniquePtr<VsockServerConnection>;
+ fn IsConnected(self: Pin<&mut VsockServerConnection>) -> bool;
+ fn Connect(self: Pin<&mut VsockServerConnection>, port: u32, cid: u32) -> bool;
+ fn ServerShutdown(self: Pin<&mut VsockServerConnection>);
}
}
/// Rust wrapper for a VsockServerConnection.
pub struct VsockServerConnection {
- instance: SharedPtr<ffi::VsockServerConnection>,
+ instance: UniquePtr<ffi::VsockServerConnection>,
}
impl VsockServerConnection {
/// Creates a VsockServerConnection.
pub fn new() -> Self {
- Self { instance: ffi::create_shared_vsock_server_connection() }
+ Self { instance: ffi::create_vsock_server_connection() }
}
/// Returns if the vsock server has an active connection or not.
- pub fn is_connected(&self) -> bool {
- self.instance.IsConnected()
+ pub fn is_connected(&mut self) -> bool {
+ self.instance.pin_mut().IsConnected()
+ }
+
+ /// Start connection using the provided port and cid.
+ pub fn connect(&mut self, port: u32, cid: u32) -> bool {
+ self.instance.pin_mut().Connect(port, cid)
+ }
+
+ /// Shutdown connection.
+ pub fn server_shutdown(&mut self) {
+ self.instance.pin_mut().ServerShutdown();
}
}
@@ -51,3 +63,7 @@
Self::new()
}
}
+
+// SAFETY: VsockServerConnection is a pointer to an `ffi::VsockServerConnection`, which in turn only
+// contains a file descriptor and so is safe to pass between threads.
+unsafe impl Send for VsockServerConnection {}
diff --git a/common/libs/utils/rust/vsock_connection/wrapper.cpp b/common/libs/utils/rust/vsock_connection/wrapper.cpp
index 2b519c7..3dd4d63 100644
--- a/common/libs/utils/rust/vsock_connection/wrapper.cpp
+++ b/common/libs/utils/rust/vsock_connection/wrapper.cpp
@@ -17,8 +17,8 @@
namespace cuttlefish {
-std::shared_ptr<VsockServerConnection> create_shared_vsock_server_connection() {
- return std::make_shared<VsockServerConnection>();
+std::unique_ptr<VsockServerConnection> create_vsock_server_connection() {
+ return std::make_unique<VsockServerConnection>();
}
} // namespace cuttlefish
diff --git a/common/libs/utils/rust/vsock_connection/wrapper.h b/common/libs/utils/rust/vsock_connection/wrapper.h
index 90addca..81fa145 100644
--- a/common/libs/utils/rust/vsock_connection/wrapper.h
+++ b/common/libs/utils/rust/vsock_connection/wrapper.h
@@ -21,6 +21,6 @@
namespace cuttlefish {
-std::shared_ptr<VsockServerConnection> create_shared_vsock_server_connection();
+std::unique_ptr<VsockServerConnection> create_vsock_server_connection();
} // namespace cuttlefish
diff --git a/common/libs/utils/shared_fd_flag.cpp b/common/libs/utils/shared_fd_flag.cpp
index b894147..e50d6d1 100644
--- a/common/libs/utils/shared_fd_flag.cpp
+++ b/common/libs/utils/shared_fd_flag.cpp
@@ -31,18 +31,16 @@
namespace cuttlefish {
-static bool Set(const FlagMatch& match, SharedFD& out) {
+static Result<void> Set(const FlagMatch& match, SharedFD& out) {
int raw_fd;
- if (!android::base::ParseInt(match.value.c_str(), &raw_fd)) {
- LOG(ERROR) << "Failed to parse value \"" << match.value
- << "\" for fd flag \"" << match.key << "\"";
- return false;
- }
+ CF_EXPECTF(android::base::ParseInt(match.value.c_str(), &raw_fd),
+ "Failed to parse value \"{}\" for fd flag \"{}\"", match.value,
+ match.key);
out = SharedFD::Dup(raw_fd);
if (out->IsOpen()) {
close(raw_fd);
}
- return true;
+ return {};
}
Flag SharedFDFlag(SharedFD& out) {
diff --git a/common/libs/utils/vsock_connection.cpp b/common/libs/utils/vsock_connection.cpp
index 9151cf1..161e988 100644
--- a/common/libs/utils/vsock_connection.cpp
+++ b/common/libs/utils/vsock_connection.cpp
@@ -47,6 +47,10 @@
}
void VsockConnection::Disconnect() {
+ // We need to serialize all accesses to the SharedFD.
+ std::lock_guard<std::recursive_mutex> read_lock(read_mutex_);
+ std::lock_guard<std::recursive_mutex> write_lock(write_mutex_);
+
LOG(INFO) << "Disconnecting with fd status:" << fd_->StrError();
fd_->Shutdown(SHUT_RDWR);
if (disconnect_callback_) {
@@ -59,10 +63,21 @@
disconnect_callback_ = callback;
}
-bool VsockConnection::IsConnected() const { return fd_->IsOpen(); }
+bool VsockConnection::IsConnected() {
+ // We need to serialize all accesses to the SharedFD.
+ std::lock_guard<std::recursive_mutex> read_lock(read_mutex_);
+ std::lock_guard<std::recursive_mutex> write_lock(write_mutex_);
-bool VsockConnection::DataAvailable() const {
+ return fd_->IsOpen();
+}
+
+bool VsockConnection::DataAvailable() {
SharedFDSet read_set;
+
+ // We need to serialize all accesses to the SharedFD.
+ std::lock_guard<std::recursive_mutex> read_lock(read_mutex_);
+ std::lock_guard<std::recursive_mutex> write_lock(write_mutex_);
+
read_set.Set(fd_);
struct timeval timeout = {0, 0};
return Select(&read_set, nullptr, nullptr, &timeout) > 0;
diff --git a/common/libs/utils/vsock_connection.h b/common/libs/utils/vsock_connection.h
index c7a796a..0042eb5 100644
--- a/common/libs/utils/vsock_connection.h
+++ b/common/libs/utils/vsock_connection.h
@@ -37,9 +37,8 @@
std::future<bool> ConnectAsync(unsigned int port, unsigned int cid);
void SetDisconnectCallback(std::function<void()> callback);
- bool IsConnected() const;
- bool DataAvailable() const;
-
+ bool IsConnected();
+ bool DataAvailable();
int32_t Read();
bool Read(std::vector<char>& data);
std::vector<char> Read(size_t size);
diff --git a/guest/hals/health/Android.bp b/guest/hals/health/Android.bp
index a452c1e..e43d605 100644
--- a/guest/hals/health/Android.bp
+++ b/guest/hals/health/Android.bp
@@ -47,8 +47,6 @@
"libutils",
"android.hardware.health-V2-ndk",
],
-
- defaults: ["enabled_on_p_and_later"],
}
cc_binary {
@@ -101,6 +99,4 @@
"android.hardware.health@2.0",
"android.hardware.health@2.1",
],
-
- defaults: ["enabled_on_p_and_later"],
}
diff --git a/guest/hals/health/storage/Android.bp b/guest/hals/health/storage/Android.bp
index 1ca807d1..6f26661 100644
--- a/guest/hals/health/storage/Android.bp
+++ b/guest/hals/health/storage/Android.bp
@@ -21,7 +21,7 @@
cc_binary {
name: "android.hardware.health.storage-service.cuttlefish",
vendor: true,
- defaults: ["hidl_defaults", "cuttlefish_health_storage"],
+ defaults: ["hidl_defaults"],
relative_install_path: "hw",
init_rc: ["android.hardware.health.storage-service.cuttlefish.rc"],
vintf_fragments: [
diff --git a/guest/hals/keymint/rust/Android.bp b/guest/hals/keymint/rust/Android.bp
index c073d0a..780d10c 100644
--- a/guest/hals/keymint/rust/Android.bp
+++ b/guest/hals/keymint/rust/Android.bp
@@ -20,12 +20,6 @@
rust_binary {
name: "android.hardware.security.keymint-service.rust",
relative_install_path: "hw",
- init_rc: ["android.hardware.security.keymint-service.rust.rc"],
- vintf_fragments: [
- "android.hardware.security.keymint-service.rust.xml",
- "android.hardware.security.secureclock-service.rust.xml",
- "android.hardware.security.sharedsecret-service.rust.xml",
- ],
vendor: true,
srcs: ["src/keymint_hal_main.rs"],
rustlibs: [
@@ -37,14 +31,65 @@
"liblibc",
"liblog_rust",
],
- required: [
- "android.hardware.hardware_keystore.rust-keymint.xml",
- ],
+ prefer_rlib: true,
}
+// init_rc
+prebuilt_etc {
+ name: "android.hardware.security.keymint-service.rust.rc",
+ vendor: true,
+ src: "android.hardware.security.keymint-service.rust.rc",
+}
+
+// vintf_fragments
+prebuilt_etc {
+ name: "android.hardware.security.keymint-service.rust.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ src: "android.hardware.security.keymint-service.rust.xml",
+}
+
+prebuilt_etc {
+ name: "android.hardware.security.sharedsecret-service.rust.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ src: "android.hardware.security.sharedsecret-service.rust.xml",
+}
+
+prebuilt_etc {
+ name: "android.hardware.security.secureclock-service.rust.xml",
+ sub_dir: "vintf",
+ vendor: true,
+ src: "android.hardware.security.secureclock-service.rust.xml",
+}
+
+// permissions
prebuilt_etc {
name: "android.hardware.hardware_keystore.rust-keymint.xml",
sub_dir: "permissions",
vendor: true,
src: "android.hardware.hardware_keystore.rust-keymint.xml",
}
+
+apex {
+ name: "com.google.cf.keymint.rust",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.google.cf.apex.key",
+ certificate: ":com.google.cf.apex.certificate",
+ soc_specific: true,
+ updatable: false,
+ binaries: [
+ "android.hardware.security.keymint-service.rust",
+ ],
+ prebuilts: [
+ // init_rc
+ "android.hardware.security.keymint-service.rust.rc",
+ // vintf_fragments
+ "android.hardware.security.keymint-service.rust.xml",
+ "android.hardware.security.secureclock-service.rust.xml",
+ "android.hardware.security.sharedsecret-service.rust.xml",
+ // permissions
+ "android.hardware.hardware_keystore.rust-keymint.xml",
+ ],
+}
diff --git a/guest/hals/keymint/rust/android.hardware.security.keymint-service.rust.rc b/guest/hals/keymint/rust/android.hardware.security.keymint-service.rust.rc
index 5c6d1f8..b53859b 100644
--- a/guest/hals/keymint/rust/android.hardware.security.keymint-service.rust.rc
+++ b/guest/hals/keymint/rust/android.hardware.security.keymint-service.rust.rc
@@ -1,4 +1,4 @@
-service vendor.keymint-rust /vendor/bin/hw/android.hardware.security.keymint-service.rust
+service vendor.keymint-rust /apex/com.google.cf.keymint.rust/bin/hw/android.hardware.security.keymint-service.rust
class early_hal
user nobody
# The keymint service is not allowed to restart.
diff --git a/guest/hals/keymint/rust/file_contexts b/guest/hals/keymint/rust/file_contexts
new file mode 100644
index 0000000..b396d14
--- /dev/null
+++ b/guest/hals/keymint/rust/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.security\.keymint-service\.rust u:object_r:hal_keymint_rust_exec:s0
\ No newline at end of file
diff --git a/guest/hals/keymint/rust/manifest.json b/guest/hals/keymint/rust/manifest.json
new file mode 100644
index 0000000..c68870a
--- /dev/null
+++ b/guest/hals/keymint/rust/manifest.json
@@ -0,0 +1,5 @@
+{
+ "name": "com.google.cf.keymint.rust",
+ "version": 1,
+ "vendorBootstrap": true
+}
diff --git a/guest/hals/light/Android.bp b/guest/hals/light/Android.bp
index 13e2607..27f8ed6 100644
--- a/guest/hals/light/Android.bp
+++ b/guest/hals/light/Android.bp
@@ -13,6 +13,8 @@
"liblog_rust",
"libbinder_rs",
"android.hardware.light-V2-rust",
+ "libvsock_utils_rust",
+ "librustutils",
],
srcs: [ "main.rs" ],
}
diff --git a/guest/hals/light/lights-cuttlefish.rc b/guest/hals/light/lights-cuttlefish.rc
index ae68e83..2c73861 100644
--- a/guest/hals/light/lights-cuttlefish.rc
+++ b/guest/hals/light/lights-cuttlefish.rc
@@ -1,4 +1,4 @@
-service vendor.light-default /vendor/bin/hw/android.hardware.lights-service.cuttlefish
+service vendor.light-cuttlefish /vendor/bin/hw/android.hardware.lights-service.cuttlefish
class hal
user nobody
group nobody
diff --git a/guest/hals/light/lights.rs b/guest/hals/light/lights.rs
index 6c8aa3f..944d495 100644
--- a/guest/hals/light/lights.rs
+++ b/guest/hals/light/lights.rs
@@ -15,6 +15,7 @@
*/
//! This module implements the ILights AIDL interface.
+use rustutils::system_properties;
use std::collections::HashMap;
use std::sync::Mutex;
@@ -26,6 +27,9 @@
use binder::{ExceptionCode, Interface, Status};
+mod lights_vsock_server;
+use lights_vsock_server::VsockServer;
+
struct Light {
hw_light: HwLight,
state: HwLightState,
@@ -36,6 +40,8 @@
/// Defined so we can implement the ILights AIDL interface.
pub struct LightsService {
lights: Mutex<HashMap<i32, Light>>,
+ // TODO(b/295543722): Move to a virtio_console transport instead.
+ vsock_server: VsockServer,
}
impl Interface for LightsService {}
@@ -48,7 +54,22 @@
lights_map.insert(hw_light.id, Light { hw_light, state: Default::default() });
}
- Self { lights: Mutex::new(lights_map) }
+ let mut service = Self { lights: Mutex::new(lights_map), vsock_server: VsockServer::new() };
+
+ let lights_server_port: u32 = system_properties::read("ro.boot.vsock_lights_port")
+ .unwrap_or(None)
+ .unwrap_or("0".to_string())
+ .parse()
+ .unwrap();
+ let guest_cid: u32 = system_properties::read("ro.boot.vsock_lights_cid")
+ .unwrap_or(None)
+ .unwrap_or("0".to_string())
+ .parse()
+ .unwrap();
+
+ service.vsock_server.start(lights_server_port, guest_cid);
+
+ service
}
}
diff --git a/guest/hals/light/lights/lights_vsock_server.rs b/guest/hals/light/lights/lights_vsock_server.rs
new file mode 100644
index 0000000..5a3525e
--- /dev/null
+++ b/guest/hals/light/lights/lights_vsock_server.rs
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//! This module provides a Vsock Server helper.
+
+use log::info;
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::{Arc, Mutex};
+use std::thread;
+use vsock_utils::VsockServerConnection;
+
+/// Vsock server helper.
+pub struct VsockServer {
+ vsock_connection: Arc<Mutex<VsockServerConnection>>,
+ is_server_running: Arc<AtomicBool>,
+ thread_handle: Option<thread::JoinHandle<()>>,
+}
+
+impl VsockServer {
+ pub fn new() -> Self {
+ Self {
+ vsock_connection: Arc::new(Mutex::new(VsockServerConnection::new())),
+ is_server_running: Arc::new(AtomicBool::new(false)),
+ thread_handle: None,
+ }
+ }
+
+ /// Spawns a thread to start accepting connections from clients.
+ pub fn start(&mut self, port: u32, cid: u32) {
+ self.stop();
+ info!("Starting vsocks server for Lights service on port {} cid {}", port, cid);
+
+ self.is_server_running.store(true, Ordering::SeqCst);
+
+ let vsock_connection = self.vsock_connection.clone();
+ let is_running = self.is_server_running.clone();
+ self.thread_handle = Some(thread::spawn(move || {
+ while is_running.load(Ordering::SeqCst) {
+ if vsock_connection.lock().unwrap().connect(port, cid) {
+ info!("Lights service Vsock server connection established.");
+ // TODO: finish this once we know the protocol
+ }
+ }
+ }));
+ }
+
+ /// Stops the server thread.
+ pub fn stop(&mut self) {
+ info!("Stopping vsocks server for Lights service");
+
+ self.vsock_connection.lock().unwrap().server_shutdown();
+ self.is_server_running.store(false, Ordering::SeqCst);
+
+ if self.thread_handle.is_some() {
+ let handle = self.thread_handle.take().expect("Thread handle should be valid");
+ if handle.is_finished() {
+ handle.join().expect("Could not join thread");
+ }
+ }
+ }
+}
+
+impl Default for VsockServer {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/guest/hals/ril/reference-libril/ril_service.cpp b/guest/hals/ril/reference-libril/ril_service.cpp
index 96b00fe..f934852 100644
--- a/guest/hals/ril/reference-libril/ril_service.cpp
+++ b/guest/hals/ril/reference-libril/ril_service.cpp
@@ -11061,15 +11061,17 @@
dcResult.ifname = convertCharPtrToHidlString(dcResponse->ifname);
std::vector<::android::hardware::radio::V1_5::LinkAddress> linkAddresses;
- std::stringstream ss(static_cast<std::string>(dcResponse->addresses));
- std::string tok;
- while(getline(ss, tok, ' ')) {
- ::android::hardware::radio::V1_5::LinkAddress la;
- la.address = hidl_string(tok);
- la.properties = 0;
- la.deprecationTime = INT64_MAX; // LinkAddress.java LIFETIME_PERMANENT = Long.MAX_VALUE
- la.expirationTime = INT64_MAX; // --"--
- linkAddresses.push_back(la);
+ if (dcResponse->addresses != NULL) {
+ std::stringstream ss(static_cast<std::string>(dcResponse->addresses));
+ std::string tok;
+ while (getline(ss, tok, ' ')) {
+ ::android::hardware::radio::V1_5::LinkAddress la;
+ la.address = hidl_string(tok);
+ la.properties = 0;
+ la.deprecationTime = INT64_MAX; // LinkAddress.java LIFETIME_PERMANENT = Long.MAX_VALUE
+ la.expirationTime = INT64_MAX; // --"--
+ linkAddresses.push_back(la);
+ }
}
dcResult.addresses = linkAddresses;
diff --git a/guest/hals/uwb/uwb-service.rc b/guest/hals/uwb/uwb-service.rc
deleted file mode 100644
index eb9d205..0000000
--- a/guest/hals/uwb/uwb-service.rc
+++ /dev/null
@@ -1,3 +0,0 @@
-service vendor.uwb_hal /vendor/bin/hw/android.hardware.uwb-service /dev/hvc9
- class hal
- user uwb
diff --git a/guest/monitoring/tombstone_transmit/Android.bp b/guest/monitoring/tombstone_transmit/Android.bp
index 86daf8b..add2ace 100644
--- a/guest/monitoring/tombstone_transmit/Android.bp
+++ b/guest/monitoring/tombstone_transmit/Android.bp
@@ -36,8 +36,8 @@
"tombstone_transmit.cpp",
],
static_libs: [
- "libcuttlefish_fs_product",
- "libcuttlefish_utils_product",
+ "libcuttlefish_fs",
+ "libcuttlefish_utils",
],
defaults: [
"tombstone_transmit_defaults",
diff --git a/host/commands/assemble_cvd/Android.bp b/host/commands/assemble_cvd/Android.bp
index 42fbc0e..f6b1294 100644
--- a/host/commands/assemble_cvd/Android.bp
+++ b/host/commands/assemble_cvd/Android.bp
@@ -22,6 +22,7 @@
srcs: [
"alloc.cc",
"assemble_cvd.cc",
+ "bootconfig_args.cpp",
"boot_config.cc",
"boot_image_utils.cc",
"clean.cc",
@@ -103,5 +104,5 @@
],
},
},
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index ed7b0d3..0266c51 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -14,6 +14,7 @@
// limitations under the License.
#include <iostream>
+#include <string_view>
#include <android-base/logging.h>
#include <android-base/parsebool.h>
@@ -47,19 +48,23 @@
DEFINE_string(instance_dir, CF_DEFAULTS_INSTANCE_DIR,
"This is a directory that will hold the cuttlefish generated"
"files, including both instance-specific and common files");
+DEFINE_string(snapshot_path, "",
+ "Path to snapshot. Must not be empty if the device is to be "
+ "restored from a snapshot");
DEFINE_bool(resume, CF_DEFAULTS_RESUME,
"Resume using the disk from the last session, if "
"possible. i.e., if --noresume is passed, the disk "
"will be reset to the state it was initially launched "
"in. This flag is ignored if the underlying partition "
- "images have been updated since the first launch.");
+ "images have been updated since the first launch."
+ "If the device starts from a snapshot, this will be always true.");
DECLARE_bool(use_overlay);
namespace cuttlefish {
namespace {
-std::string kFetcherConfigFile = "fetcher_config.json";
+static constexpr std::string_view kFetcherConfigFile = "fetcher_config.json";
FetcherConfig FindFetcherConfig(const std::vector<std::string>& files) {
FetcherConfig fetcher_config;
@@ -433,7 +438,7 @@
CF_EXPECT(FlagFeature::ProcessFlags(flag_features, args),
"Failed to parse flags.");
- if (help || help_str != "") {
+ if (help || !help_str.empty()) {
LOG(WARNING) << "TODO(schuffelen): Implement `--help` for assemble_cvd.";
LOG(WARNING) << "In the meantime, call `launch_cvd --help`";
return 1;
@@ -443,6 +448,12 @@
}
return 1; // For parity with gflags
}
+
+ // set --resume=true if --snapshot_path is not empty
+ const std::string snapshot_path(FLAGS_snapshot_path);
+ CF_EXPECT(snapshot_path.empty() || FLAGS_resume,
+ "--resume must be true when restoring from snapshot.");
+
// TODO(schuffelen): Put in "unknown flag" guards after gflags is removed.
// gflags either consumes all arguments that start with - or leaves all of
// them in place, and either errors out on unknown flags or accepts any flags.
diff --git a/host/commands/assemble_cvd/boot_config.cc b/host/commands/assemble_cvd/boot_config.cc
index f46ae6b..4c34deb 100644
--- a/host/commands/assemble_cvd/boot_config.cc
+++ b/host/commands/assemble_cvd/boot_config.cc
@@ -31,7 +31,7 @@
#include "common/libs/utils/result.h"
#include "common/libs/utils/size_utils.h"
#include "common/libs/utils/subprocess.h"
-#include "host/libs/config/bootconfig_args.h"
+#include "host/commands/assemble_cvd/bootconfig_args.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/kernel_args.h"
#include "host/libs/vm_manager/crosvm_manager.h"
diff --git a/host/libs/config/bootconfig_args.cpp b/host/commands/assemble_cvd/bootconfig_args.cpp
similarity index 94%
rename from host/libs/config/bootconfig_args.cpp
rename to host/commands/assemble_cvd/bootconfig_args.cpp
index 77cc621..4e24f74 100644
--- a/host/libs/config/bootconfig_args.cpp
+++ b/host/commands/assemble_cvd/bootconfig_args.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "host/libs/config/bootconfig_args.h"
+#include "host/commands/assemble_cvd/bootconfig_args.h"
#include <array>
#include <sstream>
@@ -60,7 +60,7 @@
// need to mux, and would prefer to retain the kernel dmesg logging, so we
// must work around init falling back to the check for /dev/console (which
// we'll always have).
- //bootconfig_args["androidboot.console"] = "invalid";
+ // bootconfig_args["androidboot.console"] = "invalid";
// The bug above has been fixed in Android 14 and later so we can just
// specify androidboot.serialconsole=0 instead.
bootconfig_args["androidboot.serialconsole"] = "0";
@@ -81,9 +81,7 @@
auto vmm =
vm_manager::GetVmManager(config.vm_manager(), instance.target_arch());
AppendMapWithReplacement(&bootconfig_args,
- CF_EXPECT(vmm->ConfigureBootDevices(
- instance.virtual_disk_paths().size(),
- instance.hwcomposer() != kHwComposerNone)));
+ CF_EXPECT(vmm->ConfigureBootDevices(instance)));
AppendMapWithReplacement(&bootconfig_args,
CF_EXPECT(vmm->ConfigureGraphics(instance)));
@@ -152,6 +150,13 @@
std::to_string(instance.vsock_guest_cid());
}
+ if (instance.lights_server_port()) {
+ bootconfig_args["androidboot.vsock_lights_port"] =
+ std::to_string(instance.lights_server_port());
+ bootconfig_args["androidboot.vsock_lights_cid"] =
+ std::to_string(instance.vsock_guest_cid());
+ }
+
if (instance.enable_modem_simulator() &&
instance.modem_simulator_ports() != "") {
bootconfig_args["androidboot.modem_simulator_ports"] =
diff --git a/host/libs/config/bootconfig_args.h b/host/commands/assemble_cvd/bootconfig_args.h
similarity index 100%
rename from host/libs/config/bootconfig_args.h
rename to host/commands/assemble_cvd/bootconfig_args.h
diff --git a/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp b/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp
index 4624ed4..5682205 100644
--- a/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp
+++ b/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp
@@ -26,7 +26,7 @@
#include "common/libs/utils/files.h"
#include "common/libs/utils/result.h"
#include "common/libs/utils/size_utils.h"
-#include "host/libs/config/bootconfig_args.h"
+#include "host/commands/assemble_cvd/bootconfig_args.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/data_image.h"
#include "host/libs/config/feature.h"
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
index c180550..38f438b 100644
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ b/host/commands/assemble_cvd/disk_flags.cc
@@ -33,12 +33,12 @@
#include "common/libs/utils/subprocess.h"
#include "host/commands/assemble_cvd/boot_config.h"
#include "host/commands/assemble_cvd/boot_image_utils.h"
-#include "host/commands/assemble_cvd/disk_builder.h"
+#include "host/commands/assemble_cvd/bootconfig_args.h"
#include "host/commands/assemble_cvd/disk/disk.h"
+#include "host/commands/assemble_cvd/disk_builder.h"
#include "host/commands/assemble_cvd/flags_defaults.h"
#include "host/commands/assemble_cvd/super_image_mixer.h"
#include "host/commands/assemble_cvd/vendor_dlkm_utils.h"
-#include "host/libs/config/bootconfig_args.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/data_image.h"
#include "host/libs/config/inject.h"
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index 7c89813..21ee4e5 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -141,6 +141,9 @@
DEFINE_vec(enable_gpu_udmabuf,
fmt::format("{}", CF_DEFAULTS_ENABLE_GPU_UDMABUF),
"Use the udmabuf driver for zero-copy virtio-gpu");
+DEFINE_vec(enable_gpu_vhost_user,
+ fmt::format("{}", CF_DEFAULTS_ENABLE_GPU_VHOST_USER),
+ "Run the Virtio GPU worker in a separate process.");
DEFINE_vec(use_allocd, CF_DEFAULTS_USE_ALLOCD?"true":"false",
"Acquire static resources from the resource allocator daemon.");
@@ -174,6 +177,8 @@
DEFINE_bool(netsim_bt, CF_DEFAULTS_NETSIM_BT,
"[Experimental] Connect Bluetooth radio to netsim.");
+DEFINE_string(netsim_args, CF_DEFAULTS_NETSIM_ARGS,
+ "Space-separated list of netsim args.");
/**
* crosvm sandbox feature requires /var/empty and seccomp directory
@@ -423,8 +428,16 @@
DEFINE_vec(use_pmem, "true",
"Make this flag false to disable pmem with crosvm");
-DEFINE_bool(enable_wifi, true,
- "Enables the guest WIFI. Disable this only for Minidroid.");
+/* TODO(kwstephenkim): replace this flag with "--start-from-snapshot" or so.
+ *
+ * This flag only makes sense to be "false" if cuttlefish device starts from
+ * the saved snapshot.
+ */
+DEFINE_vec(sock_vsock_proxy_wait_adbd_start, "true",
+ "Make this flag false for sock_vsock_proxy not to wait for adbd"
+ "This is needed when the device is restored from a snapshot.");
+
+DEFINE_bool(enable_wifi, true, "Enables the guest WIFI. Mainly for Minidroid");
DEFINE_vec(device_external_network, CF_DEFAULTS_DEVICE_EXTERNAL_NETWORK,
"The mechanism to connect to the public internet.");
@@ -432,6 +445,7 @@
DECLARE_string(assembly_dir);
DECLARE_string(boot_image);
DECLARE_string(system_image_dir);
+DECLARE_string(snapshot_path);
namespace cuttlefish {
using vm_manager::QemuManager;
@@ -832,8 +846,8 @@
#endif
Result<std::string> InitializeGpuMode(
- const std::string& gpu_mode_arg, const std::string& vm_manager,
- const GuestConfig& guest_config,
+ const std::string& gpu_mode_arg, const bool gpu_vhost_user_arg,
+ const std::string& vm_manager, const GuestConfig& guest_config,
CuttlefishConfig::MutableInstanceSpecific* instance) {
#ifdef __APPLE__
(void)vm_manager;
@@ -860,8 +874,22 @@
angle_features.angle_feature_overrides_enabled);
instance->set_gpu_angle_feature_overrides_disabled(
angle_features.angle_feature_overrides_disabled);
+
+ if (gpu_vhost_user_arg) {
+ const auto gpu_vhost_user_features =
+ CF_EXPECT(GetNeededVhostUserGpuHostRendererFeatures(
+ CF_EXPECT(GetRenderingMode(gpu_mode)), graphics_availability));
+ instance->set_enable_gpu_external_blob(
+ gpu_vhost_user_features.external_blob);
+ instance->set_enable_gpu_system_blob(gpu_vhost_user_features.system_blob);
+ } else {
+ instance->set_enable_gpu_external_blob(false);
+ instance->set_enable_gpu_system_blob(false);
+ }
+
#endif
instance->set_gpu_mode(gpu_mode);
+ instance->set_enable_gpu_vhost_user(gpu_vhost_user_arg);
return gpu_mode;
}
@@ -913,6 +941,9 @@
tmp_config_obj.set_gem5_debug_flags(FLAGS_gem5_debug_flags);
+ // setting snapshot path
+ tmp_config_obj.set_snapshot_path(FLAGS_snapshot_path);
+
// streaming, webrtc setup
tmp_config_obj.set_webrtc_certs_dir(FLAGS_webrtc_certs_dir);
tmp_config_obj.set_sig_server_secure(FLAGS_webrtc_sig_server_secure);
@@ -1058,6 +1089,8 @@
CF_EXPECT(GET_FLAG_STR_VALUE(hwcomposer));
std::vector<bool> enable_gpu_udmabuf_vec =
CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_gpu_udmabuf));
+ std::vector<bool> enable_gpu_vhost_user_vec =
+ CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_gpu_vhost_user));
std::vector<bool> smt_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(smt));
std::vector<std::string> crosvm_binary_vec =
CF_EXPECT(GET_FLAG_STR_VALUE(crosvm_binary));
@@ -1085,7 +1118,8 @@
std::vector<bool> use_rng_vec =
CF_EXPECT(GET_FLAG_BOOL_VALUE(crosvm_use_rng));
std::vector<bool> use_pmem_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(use_pmem));
-
+ std::vector<bool> sock_vsock_proxy_wait_adbd_vec =
+ CF_EXPECT(GET_FLAG_BOOL_VALUE(sock_vsock_proxy_wait_adbd_start));
std::vector<std::string> device_external_network_vec =
CF_EXPECT(GET_FLAG_STR_VALUE(device_external_network));
@@ -1110,6 +1144,7 @@
int netsim_instance_num = *instance_nums.begin() - 1;
tmp_config_obj.set_netsim_instance_num(netsim_instance_num);
LOG(DEBUG) << "netsim_instance_num: " << netsim_instance_num;
+ tmp_config_obj.set_netsim_args(FLAGS_netsim_args);
// crosvm should create fifos for UWB
auto pica_instance_num = *instance_nums.begin() - 1;
@@ -1147,6 +1182,8 @@
instance.set_crosvm_use_balloon(use_balloon_vec[instance_index]);
instance.set_crosvm_use_rng(use_rng_vec[instance_index]);
instance.set_use_pmem(use_pmem_vec[instance_index]);
+ instance.set_sock_vsock_proxy_wait_adbd_start(
+ sock_vsock_proxy_wait_adbd_vec[instance_index]);
instance.set_bootconfig_supported(guest_configs[instance_index].bootconfig_supported);
instance.set_filename_encryption_mode(
guest_configs[instance_index].hctr2_supported ? "hctr2" : "cts");
@@ -1289,8 +1326,7 @@
instance.set_qemu_vnc_server_port(544 + num - 1);
instance.set_adb_host_port(6520 + num - 1);
instance.set_adb_ip_and_port("0.0.0.0:" + std::to_string(6520 + num - 1));
-
- instance.set_fastboot_host_port(7520 + num - 1);
+ instance.set_fastboot_host_port(const_instance.adb_host_port());
std::uint8_t ethernet_mac[6] = {};
std::uint8_t mobile_mac[6] = {};
@@ -1310,11 +1346,13 @@
instance.set_vehicle_hal_server_port(9300 + num - 1);
instance.set_audiocontrol_server_port(9410); /* OK to use the same port number across instances */
instance.set_config_server_port(calc_vsock_port(6800));
+ instance.set_lights_server_port(calc_vsock_port(6900));
// gpu related settings
const std::string gpu_mode = CF_EXPECT(InitializeGpuMode(
- gpu_mode_vec[instance_index], vm_manager_vec[instance_index],
- guest_configs[instance_index], &instance));
+ gpu_mode_vec[instance_index], enable_gpu_vhost_user_vec[instance_index],
+ vm_manager_vec[instance_index], guest_configs[instance_index],
+ &instance));
instance.set_restart_subprocesses(restart_subprocesses_vec[instance_index]);
instance.set_gpu_capture_binary(gpu_capture_binary_vec[instance_index]);
@@ -1489,7 +1527,7 @@
instance.set_start_rootcanal(is_first_instance && !is_bt_netsim &&
(FLAGS_rootcanal_instance_num <= 0));
- instance.set_start_pica(is_first_instance);
+ instance.set_start_pica(is_first_instance && FLAGS_pica_instance_num <= 0);
if (!FLAGS_ap_rootfs_image.empty() && !FLAGS_ap_kernel_image.empty() && start_wmediumd) {
// TODO(264537774): Ubuntu grub modules / grub monoliths cannot be used to boot
diff --git a/host/commands/assemble_cvd/flags_defaults.h b/host/commands/assemble_cvd/flags_defaults.h
index dcc7078..89eaa3e 100644
--- a/host/commands/assemble_cvd/flags_defaults.h
+++ b/host/commands/assemble_cvd/flags_defaults.h
@@ -133,6 +133,7 @@
#define CF_DEFAULTS_RECORD_SCREEN false
#define CF_DEFAULTS_GPU_CAPTURE_BINARY CF_DEFAULTS_DYNAMIC_STRING
#define CF_DEFAULTS_ENABLE_GPU_UDMABUF false
+#define CF_DEFAULTS_ENABLE_GPU_VHOST_USER false
#define CF_DEFAULTS_DISPLAY0 CF_DEFAULTS_DYNAMIC_STRING
#define CF_DEFAULTS_DISPLAY1 CF_DEFAULTS_DYNAMIC_STRING
#define CF_DEFAULTS_DISPLAY2 CF_DEFAULTS_DYNAMIC_STRING
@@ -147,6 +148,9 @@
#define CF_DEFAULTS_NETSIM false
#define CF_DEFAULTS_NETSIM_BT true
+// Netsim default parameters
+#define CF_DEFAULTS_NETSIM_ARGS ""
+
// Wifi default parameters
#define CF_DEFAULTS_AP_KERNEL_IMAGE CF_DEFAULTS_DYNAMIC_STRING
#define CF_DEFAULTS_AP_ROOTFS_IMAGE CF_DEFAULTS_DYNAMIC_STRING
diff --git a/host/commands/assemble_cvd/proto/Android.bp b/host/commands/assemble_cvd/proto/Android.bp
index 767f728..6b32c5f 100644
--- a/host/commands/assemble_cvd/proto/Android.bp
+++ b/host/commands/assemble_cvd/proto/Android.bp
@@ -18,7 +18,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_launch_cvd_proto",
host_supported: true,
proto: {
@@ -31,5 +31,5 @@
enabled: true,
},
},
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/assemble_cvd/ramdisk_modules.h b/host/commands/assemble_cvd/ramdisk_modules.h
deleted file mode 100644
index 7f23e4a..0000000
--- a/host/commands/assemble_cvd/ramdisk_modules.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-#include <set>
-
-static constexpr auto RAMDISK_MODULES = {
- "failover.ko", "nd_virtio.ko", "net_failover.ko",
- "virtio_blk.ko", "virtio_console.ko", "virtio_dma_buf.ko",
- "virtio-gpu.ko", "virtio_input.ko", "virtio_net.ko",
- "virtio_pci.ko", "virtio-rng.ko", "vmw_vsock_virtio_transport.ko",
-};
\ No newline at end of file
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc
index 2eb937b..7336fa1 100644
--- a/host/commands/assemble_cvd/super_image_mixer.cc
+++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -13,14 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "super_image_mixer.h"
+#include "host/commands/assemble_cvd/super_image_mixer.h"
-#include <errno.h>
#include <sys/stat.h>
#include <algorithm>
-#include <cstdio>
-#include <functional>
+#include <array>
#include <memory>
#include <android-base/strings.h>
@@ -28,6 +26,7 @@
#include "common/libs/fs/shared_buf.h"
#include "common/libs/utils/archive.h"
+#include "common/libs/utils/contains.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/subprocess.h"
#include "host/commands/assemble_cvd/misc_info.h"
@@ -88,20 +87,24 @@
return "";
}
-const std::string kMiscInfoPath = "META/misc_info.txt";
-const std::set<std::string> kDefaultTargetImages = {
- "IMAGES/boot.img", "IMAGES/init_boot.img",
- "IMAGES/odm.img", "IMAGES/odm_dlkm.img",
- "IMAGES/recovery.img", "IMAGES/userdata.img",
- "IMAGES/vbmeta.img", "IMAGES/vendor.img",
- "IMAGES/vendor_dlkm.img", "IMAGES/vbmeta_vendor_dlkm.img",
+constexpr char kMiscInfoPath[] = "META/misc_info.txt";
+constexpr std::array kDefaultTargetImages = {
+ "IMAGES/boot.img",
+ "IMAGES/odm.img",
+ "IMAGES/odm_dlkm.img",
+ "IMAGES/recovery.img",
+ "IMAGES/userdata.img",
+ "IMAGES/vbmeta.img",
+ "IMAGES/vendor.img",
+ "IMAGES/vendor_dlkm.img",
+ "IMAGES/vbmeta_vendor_dlkm.img",
"IMAGES/system_dlkm.img",
};
-const std::set<std::string> kDefaultTargetBuildProp = {
- "ODM/build.prop",
- "ODM/etc/build.prop",
- "VENDOR/build.prop",
- "VENDOR/etc/build.prop",
+constexpr std::array kDefaultTargetBuildProp = {
+ "ODM/build.prop",
+ "ODM/etc/build.prop",
+ "VENDOR/build.prop",
+ "VENDOR/etc/build.prop",
};
void FindImports(Archive* archive, const std::string& build_prop_file) {
@@ -185,7 +188,7 @@
continue;
} else if (!android::base::EndsWith(name, ".img")) {
continue;
- } else if (kDefaultTargetImages.count(name) == 0) {
+ } else if (!Contains(kDefaultTargetImages, name)) {
continue;
}
LOG(INFO) << "Writing " << name;
@@ -195,7 +198,7 @@
for (const auto& name : default_target_contents) {
if (!android::base::EndsWith(name, "build.prop")) {
continue;
- } else if (kDefaultTargetBuildProp.count(name) == 0) {
+ } else if (!Contains(kDefaultTargetBuildProp, name)) {
continue;
}
FindImports(&default_target_archive, name);
@@ -209,7 +212,7 @@
continue;
} else if (!android::base::EndsWith(name, ".img")) {
continue;
- } else if (kDefaultTargetImages.count(name) > 0) {
+ } else if (Contains(kDefaultTargetImages, name)) {
continue;
}
LOG(INFO) << "Writing " << name;
@@ -219,7 +222,7 @@
for (const auto& name : system_target_contents) {
if (!android::base::EndsWith(name, "build.prop")) {
continue;
- } else if (kDefaultTargetBuildProp.count(name) > 0) {
+ } else if (Contains(kDefaultTargetBuildProp, name)) {
continue;
}
FindImports(&system_target_archive, name);
diff --git a/host/commands/assemble_cvd/vendor_dlkm_utils.cc b/host/commands/assemble_cvd/vendor_dlkm_utils.cc
index ed6f7b2..4681da7 100644
--- a/host/commands/assemble_cvd/vendor_dlkm_utils.cc
+++ b/host/commands/assemble_cvd/vendor_dlkm_utils.cc
@@ -13,31 +13,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
#include <fcntl.h>
-#include <fcntl.h>
#include <algorithm>
-#include <iterator>
#include <map>
-#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <fmt/format.h>
+#include "common/libs/utils/contains.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/subprocess.h"
-#include "fmt/core.h"
#include "host/commands/assemble_cvd/boot_image_utils.h"
#include "host/commands/assemble_cvd/kernel_module_parser.h"
-#include "host/commands/assemble_cvd/ramdisk_modules.h"
#include "host/libs/config/cuttlefish_config.h"
namespace cuttlefish {
@@ -108,15 +103,34 @@
std::vector<std::string> GetRamdiskModules(
const std::vector<std::string>& all_modules) {
- static const auto ramdisk_modules_allow_list =
- std::set<std::string>(RAMDISK_MODULES.begin(), RAMDISK_MODULES.end());
+ static constexpr auto kRamdiskModules = {
+ "failover.ko",
+ "nd_virtio.ko",
+ "net_failover.ko",
+ "virtio_blk.ko",
+ "virtio_console.ko",
+ "virtio_dma_buf.ko",
+ "virtio-gpu.ko",
+ "virtio_input.ko",
+ "virtio_net.ko",
+ "virtio_pci.ko",
+ "virtio_pci_legacy_dev.ko",
+ "virtio_pci_modern_dev.ko",
+ "virtio-rng.ko",
+ "vmw_vsock_virtio_transport.ko",
+ "vmw_vsock_virtio_transport_common.ko",
+ "vsock.ko",
+ // TODO(b/176860479) once virt_wifi is deprecated fully,
+ // these following modules can be loaded in second stage init
+ "libarc4.ko",
+ "rfkill.ko",
+ "cfg80211.ko",
+ "mac80211.ko",
+ "mac80211_hwsim.ko",
+ };
std::vector<std::string> ramdisk_modules;
for (const auto& mod_path : all_modules) {
- if (mod_path.empty()) {
- continue;
- }
- const auto mod_name = cpp_basename(mod_path);
- if (ramdisk_modules_allow_list.count(mod_name) != 0) {
+ if (Contains(kRamdiskModules, android::base::Basename(mod_path))) {
ramdisk_modules.emplace_back(mod_path);
}
}
@@ -513,6 +527,17 @@
<< vendor_dlkm_modules.size() << " vendor_dlkm modules, "
<< system_dlkm_modules.size() << " system_dlkm modules.";
+ // transfer blocklist in whole to the vendor dlkm partition. It currently
+ // only contains one module that is loaded during second stage init.
+ // We can split the blocklist at a later date IF it contains modules in
+ // different partitions.
+ const auto initramfs_blocklist_path = module_base_dir + "/modules.blocklist";
+ if (FileExists(initramfs_blocklist_path)) {
+ const auto vendor_dlkm_blocklist_path =
+ fmt::format("{}/{}", vendor_modules_dir, "modules.blocklist");
+ RenameFile(initramfs_blocklist_path, vendor_dlkm_blocklist_path);
+ }
+
// Write updated modules.dep and modules.load files
CHECK(WriteDepsToFile(FilterDependencies(deps, ramdisk_modules),
module_base_dir + "/modules.dep"));
diff --git a/host/commands/control_env_proxy_server/Android.bp b/host/commands/control_env_proxy_server/Android.bp
index de6cf54..2923fac 100644
--- a/host/commands/control_env_proxy_server/Android.bp
+++ b/host/commands/control_env_proxy_server/Android.bp
@@ -16,7 +16,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_host_static {
+cc_library {
name: "libcontrol_env_proxy_server",
shared_libs: [
"libprotobuf-cpp-full",
@@ -51,6 +51,7 @@
"libcuttlefish_utils",
"libprotobuf-cpp-full",
"libgrpc++",
+ "libjsoncpp",
],
static_libs: [
"grpc_cli_libs",
diff --git a/host/commands/control_env_proxy_server/control_env_proxy.proto b/host/commands/control_env_proxy_server/control_env_proxy.proto
index 68bf46a..b6c85dc 100644
--- a/host/commands/control_env_proxy_server/control_env_proxy.proto
+++ b/host/commands/control_env_proxy_server/control_env_proxy.proto
@@ -16,8 +16,14 @@
package controlenvproxyserver;
+import "google/protobuf/empty.proto";
+
service ControlEnvProxyService {
rpc CallUnaryMethod (CallUnaryMethodRequest) returns (CallUnaryMethodReply) {}
+ rpc ListServices (google.protobuf.Empty) returns (ListServicesReply) {}
+ rpc ListMethods (ListMethodsRequest) returns (ListMethodsReply) {}
+ rpc ListReqResType (ListReqResTypeRequest) returns (ListReqResTypeReply) {}
+ rpc TypeInformation (TypeInformationRequest) returns (TypeInformationReply) {}
}
message CallUnaryMethodRequest {
@@ -29,3 +35,34 @@
message CallUnaryMethodReply {
string json_formatted_proto = 1;
}
+
+message ListServicesReply {
+ repeated string services = 1;
+}
+
+message ListMethodsRequest {
+ string service_name = 1;
+}
+
+message ListMethodsReply {
+ repeated string methods = 1;
+}
+
+message ListReqResTypeRequest {
+ string service_name = 1;
+ string method_name = 2;
+}
+
+message ListReqResTypeReply {
+ string request_type_name = 1;
+ string response_type_name = 2;
+}
+
+message TypeInformationRequest {
+ string service_name = 1;
+ string type_name = 2;
+}
+
+message TypeInformationReply {
+ string text_formatted_type_info = 1;
+}
diff --git a/host/commands/control_env_proxy_server/main.cpp b/host/commands/control_env_proxy_server/main.cpp
index ab8455a..2434ce2 100644
--- a/host/commands/control_env_proxy_server/main.cpp
+++ b/host/commands/control_env_proxy_server/main.cpp
@@ -1,7 +1,6 @@
/*
*
- * Copyright 2015 gRPC authors.
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +24,7 @@
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>
+#include <json/json.h>
#include "common/libs/utils/files.h"
#include "common/libs/utils/result.h"
@@ -34,6 +34,14 @@
using controlenvproxyserver::CallUnaryMethodReply;
using controlenvproxyserver::CallUnaryMethodRequest;
using controlenvproxyserver::ControlEnvProxyService;
+using controlenvproxyserver::ListMethodsReply;
+using controlenvproxyserver::ListMethodsRequest;
+using controlenvproxyserver::ListReqResTypeReply;
+using controlenvproxyserver::ListReqResTypeRequest;
+using controlenvproxyserver::ListServicesReply;
+using controlenvproxyserver::TypeInformationReply;
+using controlenvproxyserver::TypeInformationRequest;
+using google::protobuf::Empty;
using google::protobuf::RepeatedPtrField;
using grpc::Server;
using grpc::ServerBuilder;
@@ -53,16 +61,104 @@
std::vector<std::string> args{request->service_name(),
request->method_name(),
request->json_formatted_proto()};
- std::vector<std::string> options;
-
- auto result =
- cuttlefish::HandleCmds(FLAGS_grpc_socket_path, "call", args, options);
-
+ auto result = cuttlefish::HandleCmds(FLAGS_grpc_socket_path, "call", args);
if (!TypeIsSuccess(result)) {
- return Status(StatusCode::FAILED_PRECONDITION, "Call gRPC method failed");
+ return Status(StatusCode::FAILED_PRECONDITION,
+ "Calling gRPC method failed");
+ }
+ reply->set_json_formatted_proto(*result);
+
+ return Status::OK;
+ }
+
+ Status ListServices(ServerContext* context, const Empty* request,
+ ListServicesReply* reply) override {
+ std::vector<std::string> args;
+ auto result = cuttlefish::HandleCmds(FLAGS_grpc_socket_path, "ls", args);
+ if (!TypeIsSuccess(result)) {
+ return Status(StatusCode::FAILED_PRECONDITION,
+ "Listing gRPC services failed");
}
- reply->set_json_formatted_proto(*result);
+ Json::Value value;
+ if (!reader.parse(*result, value)) {
+ return parsing_json_failure_status;
+ }
+ if (!value["services"].isArray()) {
+ return parsing_json_failure_status;
+ }
+ for (auto& service : value["services"]) {
+ if (!service.isString()) {
+ return parsing_json_failure_status;
+ }
+ reply->add_services(service.asString());
+ }
+
+ return Status::OK;
+ }
+
+ Status ListMethods(ServerContext* context, const ListMethodsRequest* request,
+ ListMethodsReply* reply) override {
+ std::vector<std::string> args{request->service_name()};
+ auto result = cuttlefish::HandleCmds(FLAGS_grpc_socket_path, "ls", args);
+ if (!TypeIsSuccess(result)) {
+ return Status(StatusCode::FAILED_PRECONDITION,
+ "Listing gRPC methods failed");
+ }
+
+ Json::Value value;
+ if (!reader.parse(*result, value)) {
+ return parsing_json_failure_status;
+ }
+ if (!value["methods"].isArray()) {
+ return parsing_json_failure_status;
+ }
+ for (auto& method : value["methods"]) {
+ if (!method.isString()) {
+ return parsing_json_failure_status;
+ }
+ reply->add_methods(method.asString());
+ }
+
+ return Status::OK;
+ }
+
+ Status ListReqResType(ServerContext* context,
+ const ListReqResTypeRequest* request,
+ ListReqResTypeReply* reply) override {
+ std::vector<std::string> args{request->service_name(),
+ request->method_name()};
+ auto result = cuttlefish::HandleCmds(FLAGS_grpc_socket_path, "ls", args);
+ if (!TypeIsSuccess(result)) {
+ return Status(StatusCode::FAILED_PRECONDITION,
+ "Listing gRPC request and response message type failed");
+ }
+
+ Json::Value value;
+ if (!reader.parse(*result, value)) {
+ return parsing_json_failure_status;
+ }
+ if (!value["request_type"].isString() ||
+ !value["response_type"].isString()) {
+ return parsing_json_failure_status;
+ }
+ reply->set_request_type_name(value["request_type"].asString());
+ reply->set_response_type_name(value["response_type"].asString());
+
+ return Status::OK;
+ }
+
+ Status TypeInformation(ServerContext* context,
+ const TypeInformationRequest* request,
+ TypeInformationReply* reply) override {
+ std::vector<std::string> args{request->service_name(),
+ request->type_name()};
+ auto result = cuttlefish::HandleCmds(FLAGS_grpc_socket_path, "type", args);
+ if (!TypeIsSuccess(result)) {
+ return Status(StatusCode::FAILED_PRECONDITION,
+ "Calling gRPC method failed");
+ }
+ reply->set_text_formatted_type_info(*result);
return Status::OK;
}
@@ -76,6 +172,10 @@
}
return vec;
}
+
+ Json::Reader reader;
+ Status parsing_json_failure_status = Status(
+ StatusCode::FAILED_PRECONDITION, "Parsing result into json failed");
};
void RunServer() {
diff --git a/host/commands/cvd/acloud/converter.cpp b/host/commands/cvd/acloud/converter.cpp
index 6c90b6e..b3638d5 100644
--- a/host/commands/cvd/acloud/converter.cpp
+++ b/host/commands/cvd/acloud/converter.cpp
@@ -182,36 +182,36 @@
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot-build-id"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot_build_id"})
- .Setter([&boot_build_id](const FlagMatch& m) {
+ .Setter([&boot_build_id](const FlagMatch& m) -> Result<void> {
boot_build_id = m.value;
- return true;
+ return {};
}));
std::optional<std::string> boot_build_target;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot-build-target"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot_build_target"})
- .Setter([&boot_build_target](const FlagMatch& m) {
+ .Setter([&boot_build_target](const FlagMatch& m) -> Result<void> {
boot_build_target = m.value;
- return true;
+ return {};
}));
std::optional<std::string> boot_branch;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot-branch"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot_branch"})
- .Setter([&boot_branch](const FlagMatch& m) {
+ .Setter([&boot_branch](const FlagMatch& m) -> Result<void> {
boot_branch = m.value;
- return true;
+ return {};
}));
std::optional<std::string> boot_artifact;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot-artifact"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--boot_artifact"})
- .Setter([&boot_artifact](const FlagMatch& m) {
+ .Setter([&boot_artifact](const FlagMatch& m) -> Result<void> {
boot_artifact = m.value;
- return true;
+ return {};
}));
std::optional<std::string> ota_build_id;
@@ -219,90 +219,92 @@
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--ota-build-id"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--ota_build_id"})
- .Setter([&ota_build_id](const FlagMatch& m) {
+ .Setter([&ota_build_id](const FlagMatch& m) -> Result<void> {
ota_build_id = m.value;
- return true;
+ return {};
}));
std::optional<std::string> ota_build_target;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--ota-build-target"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--ota_build_target"})
- .Setter([&ota_build_target](const FlagMatch& m) {
+ .Setter([&ota_build_target](const FlagMatch& m) -> Result<void> {
ota_build_target = m.value;
- return true;
+ return {};
}));
std::optional<std::string> ota_branch;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--ota-branch"})
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--ota_branch"})
- .Setter([&ota_branch](const FlagMatch& m) {
+ .Setter([&ota_branch](const FlagMatch& m) -> Result<void> {
ota_branch = m.value;
- return true;
+ return {};
}));
std::optional<std::string> launch_args;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--launch-args"})
- .Setter([&launch_args](const FlagMatch& m) {
+ .Setter([&launch_args](const FlagMatch& m) -> Result<void> {
launch_args = m.value;
- return true;
+ return {};
}));
std::optional<std::string> system_branch;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--system-branch"})
- .Setter([&system_branch](const FlagMatch& m) {
+ .Setter([&system_branch](const FlagMatch& m) -> Result<void> {
system_branch = m.value;
- return true;
+ return {};
}));
std::optional<std::string> system_build_target;
- flags.emplace_back(Flag()
- .Alias({FlagAliasMode::kFlagConsumesFollowing,
- "--system-build-target"})
- .Setter([&system_build_target](const FlagMatch& m) {
- system_build_target = m.value;
- return true;
- }));
+ flags.emplace_back(
+ Flag()
+ .Alias(
+ {FlagAliasMode::kFlagConsumesFollowing, "--system-build-target"})
+ .Setter([&system_build_target](const FlagMatch& m) -> Result<void> {
+ system_build_target = m.value;
+ return {};
+ }));
std::optional<std::string> system_build_id;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--system-build-id"})
- .Setter([&system_build_id](const FlagMatch& m) {
+ .Setter([&system_build_id](const FlagMatch& m) -> Result<void> {
system_build_id = m.value;
- return true;
+ return {};
}));
std::optional<std::string> kernel_branch;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--kernel-branch"})
- .Setter([&kernel_branch](const FlagMatch& m) {
+ .Setter([&kernel_branch](const FlagMatch& m) -> Result<void> {
kernel_branch = m.value;
- return true;
+ return {};
}));
std::optional<std::string> kernel_build_target;
- flags.emplace_back(Flag()
- .Alias({FlagAliasMode::kFlagConsumesFollowing,
- "--kernel-build-target"})
- .Setter([&kernel_build_target](const FlagMatch& m) {
- kernel_build_target = m.value;
- return true;
- }));
+ flags.emplace_back(
+ Flag()
+ .Alias(
+ {FlagAliasMode::kFlagConsumesFollowing, "--kernel-build-target"})
+ .Setter([&kernel_build_target](const FlagMatch& m) -> Result<void> {
+ kernel_build_target = m.value;
+ return {};
+ }));
std::optional<std::string> kernel_build_id;
flags.emplace_back(
Flag()
.Alias({FlagAliasMode::kFlagConsumesFollowing, "--kernel-build-id"})
- .Setter([&kernel_build_id](const FlagMatch& m) {
+ .Setter([&kernel_build_id](const FlagMatch& m) -> Result<void> {
kernel_build_id = m.value;
- return true;
+ return {};
}));
bool use_16k = false;
flags.emplace_back(Flag()
@@ -310,9 +312,9 @@
.Alias({FlagAliasMode::kFlagExact, "--16K"})
.Alias({FlagAliasMode::kFlagExact, "--use-16k"})
.Alias({FlagAliasMode::kFlagExact, "--use-16K"})
- .Setter([&use_16k](const FlagMatch&) {
+ .Setter([&use_16k](const FlagMatch&) -> Result<void> {
use_16k = true;
- return true;
+ return {};
}));
std::optional<std::string> pet_name;
@@ -320,9 +322,9 @@
flags.emplace_back(
GflagsCompatFlag("pet-name")
.Getter([&pet_name]() { return (pet_name ? *pet_name : ""); })
- .Setter([&pet_name](const FlagMatch& match) {
+ .Setter([&pet_name](const FlagMatch& match) -> Result<void> {
pet_name = match.value;
- return true;
+ return {};
}));
CF_EXPECT(ParseFlags(flags, arguments));
diff --git a/host/commands/cvd/acloud/converter_parser_common.h b/host/commands/cvd/acloud/converter_parser_common.h
index 8274145..f3422d5 100644
--- a/host/commands/cvd/acloud/converter_parser_common.h
+++ b/host/commands/cvd/acloud/converter_parser_common.h
@@ -42,9 +42,9 @@
for (const auto& alias_name : alias_names) {
new_flag.Alias({FlagAliasMode::kFlagConsumesFollowing, "--" + alias_name});
}
- new_flag.Setter([&opt](const FlagMatch& m) {
+ new_flag.Setter([&opt](const FlagMatch& m) -> Result<void> {
opt = m.value;
- return true;
+ return {};
});
return new_flag;
}
diff --git a/host/commands/cvd/acloud/create_converter_parser.cpp b/host/commands/cvd/acloud/create_converter_parser.cpp
index 816e58d..ba9a527 100644
--- a/host/commands/cvd/acloud/create_converter_parser.cpp
+++ b/host/commands/cvd/acloud/create_converter_parser.cpp
@@ -32,22 +32,21 @@
auto local_instance_flag = Flag();
local_instance_flag.Alias(
{FlagAliasMode::kFlagConsumesArbitrary, "--local-instance"});
- local_instance_flag.Setter(
- [&local_instance_set, &local_instance](const FlagMatch& m) {
- local_instance_set = true;
- if (m.value != "" && local_instance) {
- LOG(ERROR) << "Instance number already set, was \"" << *local_instance
- << "\", now set to \"" << m.value << "\"";
- return false;
- } else if (m.value != "" && !local_instance) {
- int value = -1;
- if (!android::base::ParseInt(m.value, &value)) {
- return false;
- }
- local_instance = value;
- }
- return true;
- });
+ local_instance_flag.Setter([&local_instance_set, &local_instance](
+ const FlagMatch& m) -> Result<void> {
+ local_instance_set = true;
+ if (m.value != "" && local_instance) {
+ return CF_ERRF(
+ "Instance number already set, was \"{}\", now set to \"{}\"",
+ *local_instance, m.value);
+ } else if (m.value != "" && !local_instance) {
+ int value = -1;
+ CF_EXPECTF(android::base::ParseInt(m.value, &value),
+ "Failed to parse \"{}\"", m.value);
+ local_instance = value;
+ }
+ return {};
+ });
return local_instance_flag;
}
@@ -56,9 +55,9 @@
.Alias({FlagAliasMode::kFlagExact, "-v"})
.Alias({FlagAliasMode::kFlagExact, "-vv"})
.Alias({FlagAliasMode::kFlagExact, "--verbose"})
- .Setter([&verbose](const FlagMatch&) {
+ .Setter([&verbose](const FlagMatch&) -> Result<void> {
verbose = true;
- return true;
+ return {};
});
return verbose_flag;
}
@@ -67,12 +66,13 @@
std::optional<std::string>& local_image_path) {
return Flag()
.Alias({FlagAliasMode::kFlagConsumesArbitrary, "--local-image"})
- .Setter([&local_image_given, &local_image_path](const FlagMatch& m) {
+ .Setter([&local_image_given,
+ &local_image_path](const FlagMatch& m) -> Result<void> {
local_image_given = true;
if (m.value != "") {
local_image_path = m.value;
}
- return true;
+ return {};
});
}
diff --git a/host/commands/cvd/client.cpp b/host/commands/cvd/client.cpp
index 5b1ef51..3ad4288 100644
--- a/host/commands/cvd/client.cpp
+++ b/host/commands/cvd/client.cpp
@@ -28,13 +28,32 @@
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/environment.h"
+#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
#include "host/commands/cvd/common_utils.h"
+#include "host/commands/cvd/flag.h"
+#include "host/commands/cvd/frontline_parser.h"
+#include "host/commands/cvd/handle_reset.h"
#include "host/libs/config/host_tools_version.h"
namespace cuttlefish {
namespace {
+Result<FlagCollection> CvdFlags() {
+ FlagCollection cvd_flags;
+ cvd_flags.EnrollFlag(CvdFlag<bool>("clean", false));
+ cvd_flags.EnrollFlag(CvdFlag<bool>("help", false));
+ cvd_flags.EnrollFlag(CvdFlag<std::string>("verbosity"));
+ return cvd_flags;
+}
+
+Result<bool> FilterDriverHelpOptions(const FlagCollection& cvd_flags,
+ cvd_common::Args& cvd_args) {
+ auto help_flag = CF_EXPECT(cvd_flags.GetFlag("help"));
+ bool is_help = CF_EXPECT(help_flag.CalculateFlag<bool>(cvd_args));
+ return is_help;
+}
+
[[noreturn]] void CallPythonAcloud(std::vector<std::string>& args) {
auto android_top = StringFromEnv("ANDROID_BUILD_TOP", "");
if (android_top == "") {
@@ -55,6 +74,102 @@
abort();
}
+cvd_common::Args AllArgs(const std::string& prog_path,
+ const cvd_common::Args& cvd_args,
+ const std::optional<std::string>& subcmd,
+ const cvd_common::Args& subcmd_args) {
+ std::vector<std::string> all_args;
+ all_args.push_back(prog_path);
+ all_args.insert(all_args.end(), cvd_args.begin(), cvd_args.end());
+ if (subcmd) {
+ all_args.push_back(*subcmd);
+ }
+ all_args.insert(all_args.end(), subcmd_args.begin(), subcmd_args.end());
+ return all_args;
+}
+
+enum class VersionCommandReport : std::uint32_t {
+ kNonVersion,
+ kVersion,
+};
+Result<VersionCommandReport> HandleVersionCommand(
+ CvdClient& client, const cvd_common::Args& all_args) {
+ std::vector<std::string> version_command{"version"};
+ FlagCollection cvd_flags = CF_EXPECT(CvdFlags());
+ FrontlineParser::ParserParam version_param{
+ .server_supported_subcmds = std::vector<std::string>{},
+ .internal_cmds = version_command,
+ .all_args = all_args,
+ .cvd_flags = cvd_flags};
+ auto version_parser_result = FrontlineParser::Parse(version_param);
+ if (!version_parser_result.ok()) {
+ return VersionCommandReport::kNonVersion;
+ }
+
+ auto version_parser = std::move(*version_parser_result);
+ CF_EXPECT(version_parser != nullptr);
+ const auto subcmd = version_parser->SubCmd().value_or("");
+ auto cvd_args = version_parser->CvdArgs();
+ CF_EXPECT(subcmd == "version" || subcmd.empty(),
+ "subcmd is expected to be \"version\" or empty but is " << subcmd);
+
+ if (subcmd == "version") {
+ auto version_msg = CF_EXPECT(client.HandleVersion());
+ std::cout << version_msg;
+ return VersionCommandReport::kVersion;
+ }
+ return VersionCommandReport::kNonVersion;
+}
+
+struct ClientCommandCheckResult {
+ bool was_client_command_;
+ cvd_common::Args new_all_args;
+};
+Result<ClientCommandCheckResult> HandleClientCommands(
+ CvdClient& client, const cvd_common::Args& all_args) {
+ ClientCommandCheckResult output;
+ std::vector<std::string> client_internal_commands{"kill-server",
+ "server-kill", "reset"};
+ FlagCollection cvd_flags = CF_EXPECT(CvdFlags());
+ FrontlineParser::ParserParam client_param{
+ .server_supported_subcmds = std::vector<std::string>{},
+ .internal_cmds = client_internal_commands,
+ .all_args = all_args,
+ .cvd_flags = cvd_flags};
+ auto client_parser_result = FrontlineParser::Parse(client_param);
+ if (!client_parser_result.ok()) {
+ return ClientCommandCheckResult{.was_client_command_ = false,
+ .new_all_args = all_args};
+ }
+
+ auto client_parser = std::move(*client_parser_result);
+ CF_EXPECT(client_parser != nullptr);
+ auto cvd_args = client_parser->CvdArgs();
+ auto is_help = CF_EXPECT(FilterDriverHelpOptions(cvd_flags, cvd_args));
+
+ output.new_all_args =
+ AllArgs(client_parser->ProgPath(), cvd_args, client_parser->SubCmd(),
+ client_parser->SubCmdArgs());
+ output.was_client_command_ = (!is_help && client_parser->SubCmd());
+ if (!output.was_client_command_) {
+ // could be simply "cvd"
+ output.new_all_args = cvd_common::Args{"cvd", "help"};
+ return output;
+ }
+
+ // Special case for `cvd kill-server`, handled by directly
+ // stopping the cvd_server.
+ std::vector<std::string> kill_server_cmds{"kill-server", "server-kill"};
+ std::string subcmd = client_parser->SubCmd().value_or("");
+ if (Contains(kill_server_cmds, subcmd)) {
+ CF_EXPECT(client.StopCvdServer(/*clear=*/true));
+ return output;
+ }
+ CF_EXPECT_EQ(subcmd, "reset", "unsupported subcmd: " << subcmd);
+ CF_EXPECT(HandleReset(client, client_parser->SubCmdArgs()));
+ return output;
+}
+
} // end of namespace
Result<SharedFD> CvdClient::ConnectToServer() {
@@ -319,6 +434,30 @@
return {};
}
+Result<void> CvdClient::HandleCvdCommand(
+ const std::vector<std::string>& all_args,
+ const std::unordered_map<std::string, std::string>& env) {
+ auto [was_client_command, new_all_args] =
+ CF_EXPECT(HandleClientCommands(*this, all_args));
+ if (was_client_command) {
+ return {};
+ }
+
+ auto version_command_handle_report =
+ CF_EXPECT(HandleVersionCommand(*this, new_all_args));
+ if (version_command_handle_report == VersionCommandReport::kVersion) {
+ return {};
+ }
+
+ const cvd_common::Args new_cmd_args{"cvd", "process"};
+ CF_EXPECT(!new_all_args.empty());
+ const cvd_common::Args new_selector_args{new_all_args.begin(),
+ new_all_args.end()};
+ // TODO(schuffelen): Deduplicate when calls to setenv are removed.
+ CF_EXPECT(HandleCommand(new_cmd_args, env, new_selector_args));
+ return {};
+}
+
Result<std::string> CvdClient::HandleVersion() {
using google::protobuf::TextFormat;
std::stringstream result;
diff --git a/host/commands/cvd/client.h b/host/commands/cvd/client.h
index 71ee03a..52564e7 100644
--- a/host/commands/cvd/client.h
+++ b/host/commands/cvd/client.h
@@ -50,6 +50,9 @@
Result<void> HandleAcloud(
const std::vector<std::string>& args,
const std::unordered_map<std::string, std::string>& env);
+ Result<void> HandleCvdCommand(
+ const std::vector<std::string>& args,
+ const std::unordered_map<std::string, std::string>& env);
Result<cvd::Response> HandleCommand(
const std::vector<std::string>& args,
const std::unordered_map<std::string, std::string>& env,
diff --git a/host/commands/cvd/fetch/fetch_cvd.cc b/host/commands/cvd/fetch/fetch_cvd.cc
index c76be71..fd7d8cf 100644
--- a/host/commands/cvd/fetch/fetch_cvd.cc
+++ b/host/commands/cvd/fetch/fetch_cvd.cc
@@ -30,6 +30,7 @@
#include <vector>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <curl/curl.h>
#include <gflags/gflags.h>
@@ -57,7 +58,6 @@
const std::string OTA_TOOLS_DIR = "/otatools/";
const std::string DEFAULT_DIR = "/default";
const std::string SYSTEM_DIR = "/system";
-const int DEFAULT_RETRY_PERIOD = 20;
const std::string USAGE_MESSAGE =
"<flags>\n"
"\n"
@@ -70,21 +70,13 @@
"\"build_id\" - build \"build_id\" for \"aosp_cf_x86_phone-userdebug\"\n";
const mode_t RWX_ALL_MODE = S_IRWXU | S_IRWXG | S_IRWXO;
const bool OVERRIDE_ENTRIES = true;
-const bool DOWNLOAD_IMG_ZIP_DEFAULT = true;
-const bool DOWNLOAD_TARGET_FILES_ZIP_DEFAULT = false;
const std::string LOG_FILENAME = "fetch.log";
struct BuildApiFlags {
- std::string api_key = "";
- std::string credential_source = "";
- std::chrono::seconds wait_retry_period =
- std::chrono::seconds(DEFAULT_RETRY_PERIOD);
- bool external_dns_resolver =
-#ifdef __BIONIC__
- true;
-#else
- false;
-#endif
+ std::string api_key = kDefaultApiKey;
+ std::string credential_source = kDefaultCredentialSource;
+ std::chrono::seconds wait_retry_period = kDefaultWaitRetryPeriod;
+ bool external_dns_resolver = kDefaultExternalDnsResolver;
};
struct VectorFlags {
@@ -117,9 +109,9 @@
};
struct FetchFlags {
- std::string target_directory = "";
+ std::string target_directory = kDefaultTargetDirectory;
std::vector<std::string> target_subdirectory;
- bool keep_downloaded_archives = false;
+ bool keep_downloaded_archives = kDefaultKeepDownloadedArchives;
android::base::LogSeverity verbosity = android::base::INFO;
bool helpxml = false;
BuildApiFlags build_api_flags;
@@ -144,9 +136,22 @@
std::string system_target_files;
};
+Flag GflagsCompatFlagSeconds(const std::string& name,
+ std::chrono::seconds& value) {
+ return GflagsCompatFlag(name)
+ .Getter([&value]() { return std::to_string(value.count()); })
+ .Setter([&value](const FlagMatch& match) -> Result<void> {
+ int parsed_int;
+ CF_EXPECTF(android::base::ParseInt(match.value, &parsed_int),
+ "Failed to parse \"{}\" as an integer", match.value);
+ value = std::chrono::seconds(parsed_int);
+ return {};
+ });
+}
+
std::vector<Flag> GetFlagsVector(FetchFlags& fetch_flags,
BuildApiFlags& build_api_flags,
- VectorFlags& vector_flags, int& retry_period,
+ VectorFlags& vector_flags,
std::string& directory) {
std::vector<Flag> flags;
flags.emplace_back(
@@ -172,7 +177,8 @@
flags.emplace_back(
GflagsCompatFlag("credential_source", build_api_flags.credential_source)
.Help("Build API credential source"));
- flags.emplace_back(GflagsCompatFlag("wait_retry_period", retry_period)
+ flags.emplace_back(GflagsCompatFlagSeconds("wait_retry_period",
+ build_api_flags.wait_retry_period)
.Help("Retry period for pending builds given in "
"seconds. Set to 0 to not wait."));
flags.emplace_back(
@@ -204,12 +210,12 @@
.Help("name of the boot image in boot_build"));
flags.emplace_back(GflagsCompatFlag("download_img_zip",
vector_flags.download_img_zip,
- DOWNLOAD_IMG_ZIP_DEFAULT)
+ kDefaultDownloadImgZip)
.Help("Whether to fetch the -img-*.zip file."));
flags.emplace_back(
GflagsCompatFlag("download_target_files_zip",
vector_flags.download_target_files_zip,
- DOWNLOAD_TARGET_FILES_ZIP_DEFAULT)
+ kDefaultDownloadTargetFilesZip)
.Help("Whether to fetch the -target_files-*.zip file."));
flags.emplace_back(HelpFlag(flags, USAGE_MESSAGE));
@@ -264,26 +270,28 @@
num_builds);
for (int i = 0; i < result.size(); ++i) {
auto build_source = BuildSourceFlags{
- .default_build =
- AccessOrDefault<std::string>(flags.default_build, i, ""),
- .system_build = AccessOrDefault<std::string>(flags.system_build, i, ""),
- .kernel_build = AccessOrDefault<std::string>(flags.kernel_build, i, ""),
- .boot_build = AccessOrDefault<std::string>(flags.boot_build, i, ""),
- .bootloader_build =
- AccessOrDefault<std::string>(flags.bootloader_build, i, ""),
- .otatools_build =
- AccessOrDefault<std::string>(flags.otatools_build, i, ""),
- .host_package_build =
- AccessOrDefault<std::string>(flags.host_package_build, i, ""),
+ .default_build = AccessOrDefault<std::string>(flags.default_build, i,
+ kDefaultBuildString),
+ .system_build = AccessOrDefault<std::string>(flags.system_build, i,
+ kDefaultBuildString),
+ .kernel_build = AccessOrDefault<std::string>(flags.kernel_build, i,
+ kDefaultBuildString),
+ .boot_build = AccessOrDefault<std::string>(flags.boot_build, i,
+ kDefaultBuildString),
+ .bootloader_build = AccessOrDefault<std::string>(
+ flags.bootloader_build, i, kDefaultBuildString),
+ .otatools_build = AccessOrDefault<std::string>(flags.otatools_build, i,
+ kDefaultBuildString),
+ .host_package_build = AccessOrDefault<std::string>(
+ flags.host_package_build, i, kDefaultBuildString),
};
auto download = DownloadFlags{
.boot_artifact =
AccessOrDefault<std::string>(flags.boot_artifact, i, ""),
.download_img_zip = AccessOrDefault<bool>(flags.download_img_zip, i,
- DOWNLOAD_IMG_ZIP_DEFAULT),
- .download_target_files_zip =
- AccessOrDefault<bool>(flags.download_target_files_zip, i,
- DOWNLOAD_TARGET_FILES_ZIP_DEFAULT),
+ kDefaultDownloadImgZip),
+ .download_target_files_zip = AccessOrDefault<bool>(
+ flags.download_target_files_zip, i, kDefaultDownloadTargetFilesZip),
};
result[i] = {build_source, download, i};
}
@@ -294,22 +302,20 @@
FetchFlags fetch_flags;
BuildApiFlags build_api_flags;
VectorFlags vector_flags;
- int retry_period = DEFAULT_RETRY_PERIOD;
- std::string directory = "";
+ std::string directory;
- std::vector<Flag> flags = GetFlagsVector(
- fetch_flags, build_api_flags, vector_flags, retry_period, directory);
+ std::vector<Flag> flags =
+ GetFlagsVector(fetch_flags, build_api_flags, vector_flags, directory);
std::vector<std::string> args = ArgsToVec(argc - 1, argv + 1);
CF_EXPECT(ParseFlags(flags, args), "Could not process command line flags.");
- build_api_flags.wait_retry_period = std::chrono::seconds(retry_period);
- if (directory != "") {
+ if (!directory.empty()) {
LOG(ERROR) << "Please use --target_directory instead of --directory";
- if (fetch_flags.target_directory == "") {
+ if (fetch_flags.target_directory.empty()) {
fetch_flags.target_directory = directory;
}
} else {
- if (fetch_flags.target_directory == "") {
+ if (fetch_flags.target_directory.empty()) {
fetch_flags.target_directory = CurrentDirectory();
}
}
@@ -713,17 +719,8 @@
return {};
}
-} // namespace
-
-Result<void> FetchCvdMain(int argc, char** argv) {
- android::base::InitLogging(argv, android::base::StderrLogger);
- const FetchFlags flags = CF_EXPECT(GetFlagValues(argc, argv));
- const std::string fetch_root_directory = AbsolutePath(flags.target_directory);
- CF_EXPECT(EnsureDirectoryExists(fetch_root_directory, RWX_ALL_MODE));
- android::base::SetLogger(
- LogToStderrAndFiles({fetch_root_directory + "/" + LOG_FILENAME}));
- android::base::SetMinimumLogSeverity(flags.verbosity);
-
+Result<void> InnerMain(const FetchFlags& flags,
+ const std::string& fetch_root_directory) {
#ifdef __BIONIC__
// TODO(schuffelen): Find a better way to deal with tzdata
setenv("ANDROID_TZDATA_ROOT", "/", /* overwrite */ 0);
@@ -763,4 +760,22 @@
return {};
}
+} // namespace
+
+Result<void> FetchCvdMain(int argc, char** argv) {
+ android::base::InitLogging(argv, android::base::StderrLogger);
+ const FetchFlags flags = CF_EXPECT(GetFlagValues(argc, argv));
+ const std::string fetch_root_directory = AbsolutePath(flags.target_directory);
+ CF_EXPECT(EnsureDirectoryExists(fetch_root_directory, RWX_ALL_MODE));
+ android::base::SetLogger(
+ LogToStderrAndFiles({fetch_root_directory + "/" + LOG_FILENAME}));
+ android::base::SetMinimumLogSeverity(flags.verbosity);
+
+ auto result = InnerMain(flags, fetch_root_directory);
+ if (!result.ok()) {
+ LOG(ERROR) << result.error().Trace();
+ }
+ return result;
+}
+
} // namespace cuttlefish
diff --git a/host/commands/cvd/fetch/fetch_cvd.h b/host/commands/cvd/fetch/fetch_cvd.h
index e99395f..9ff6c91 100644
--- a/host/commands/cvd/fetch/fetch_cvd.h
+++ b/host/commands/cvd/fetch/fetch_cvd.h
@@ -13,9 +13,29 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#pragma once
+
+#include <chrono>
+
#include "common/libs/utils/result.h"
namespace cuttlefish {
+inline constexpr char kDefaultApiKey[] = "";
+inline constexpr char kDefaultCredentialSource[] = "";
+inline constexpr std::chrono::seconds kDefaultWaitRetryPeriod =
+ std::chrono::seconds(20);
+inline constexpr bool kDefaultExternalDnsResolver =
+#ifdef __BIONIC__
+ true;
+#else
+ false;
+#endif
+inline constexpr char kDefaultBuildString[] = "";
+inline constexpr bool kDefaultDownloadImgZip = true;
+inline constexpr bool kDefaultDownloadTargetFilesZip = false;
+inline constexpr char kDefaultTargetDirectory[] = "";
+inline constexpr bool kDefaultKeepDownloadedArchives = false;
+
Result<void> FetchCvdMain(int argc, char** argv);
}
diff --git a/host/commands/cvd/handle_reset.cpp b/host/commands/cvd/handle_reset.cpp
index 2c11a81..73b653b 100644
--- a/host/commands/cvd/handle_reset.cpp
+++ b/host/commands/cvd/handle_reset.cpp
@@ -58,19 +58,20 @@
bool is_confirmed_by_flag = false;
std::string verbosity_flag_value;
- Flag y_flag = Flag()
- .Alias({FlagAliasMode::kFlagExact, "-y"})
- .Alias({FlagAliasMode::kFlagExact, "--yes"})
- .Setter([&is_confirmed_by_flag](const FlagMatch&) {
- is_confirmed_by_flag = true;
- return true;
- });
+ Flag y_flag =
+ Flag()
+ .Alias({FlagAliasMode::kFlagExact, "-y"})
+ .Alias({FlagAliasMode::kFlagExact, "--yes"})
+ .Setter([&is_confirmed_by_flag](const FlagMatch&) -> Result<void> {
+ is_confirmed_by_flag = true;
+ return {};
+ });
Flag help_flag = Flag()
.Alias({FlagAliasMode::kFlagExact, "-h"})
.Alias({FlagAliasMode::kFlagExact, "--help"})
- .Setter([&is_help](const FlagMatch&) {
+ .Setter([&is_help](const FlagMatch&) -> Result<void> {
is_help = true;
- return true;
+ return {};
});
std::vector<Flag> flags{
GflagsCompatFlag("device-by-cvd-only", device_by_cvd_only),
diff --git a/host/commands/cvd/instance_manager.cpp b/host/commands/cvd/instance_manager.cpp
index a87e87e..6a18c12 100644
--- a/host/commands/cvd/instance_manager.cpp
+++ b/host/commands/cvd/instance_manager.cpp
@@ -23,7 +23,9 @@
#include <sstream>
#include <android-base/file.h>
+#include "fmt/format.h"
#include <fruit/fruit.h>
+#include "json/value.h"
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
@@ -224,7 +226,7 @@
return command_result;
}
-Result<InstanceManager::StatusCommandOutput>
+Result<Json::Value>
InstanceManager::IssueStatusCommand(const selector::LocalInstanceGroup& group,
const SharedFD& err) {
std::string not_supported_version_msg = " does not comply with cvd fleet.\n";
@@ -234,38 +236,44 @@
.op = "status",
}));
const auto prog_path = host_android_out + "/bin/" + status_bin;
- Command with_args = GetCommand(prog_path, "--all_instances", "--print");
- with_args.SetEnvironment({ConcatToString("HOME=", group.HomeDir())});
- auto command_result = ExecCommand(std::move(with_args));
- if (command_result.ok()) {
- StatusCommandOutput output;
- if (command_result->stdout_buf.empty()) {
- WriteAll(err, ConcatToString(group.GroupName(), "-*",
- not_supported_version_msg));
- Json::Reader().parse("{}", output.stdout_json);
- return output;
- }
- output.stdout_json = CF_EXPECT(ParseJson(command_result->stdout_buf));
- return output;
- }
- StatusCommandOutput output;
- int index = 0;
+
+ Json::Value output(Json::arrayValue);
for (const auto& instance_ref : CF_EXPECT(group.FindAllInstances())) {
const auto id = instance_ref.Get().InstanceId();
- Command without_args = GetCommand(prog_path);
+ Command status_cmd = GetCommand(prog_path, "-print");
std::vector<std::string> new_envs{
ConcatToString("HOME=", group.HomeDir()),
ConcatToString(kCuttlefishInstanceEnvVarName, "=", std::to_string(id))};
- without_args.SetEnvironment(new_envs);
- auto second_command_result =
- CF_EXPECT(ExecCommand(std::move(without_args)));
- if (second_command_result.stdout_buf.empty()) {
+ status_cmd.SetEnvironment(new_envs);
+ auto cmd_result = CF_EXPECT(ExecCommand(std::move(status_cmd)));
+ if (cmd_result.stdout_buf.empty()) {
WriteAll(err,
instance_ref.Get().DeviceName() + not_supported_version_msg);
- second_command_result.stdout_buf.append("{}");
+ cmd_result.stdout_buf.append("{}");
}
- output.stdout_json[index] =
- CF_EXPECT(ParseJson(second_command_result.stdout_buf));
+ auto status = CF_EXPECT(ParseJson(cmd_result.stdout_buf));
+ if (status.isArray()) {
+ // cvd_internal_status returns an array even when limited to a single
+ // instance.
+ CF_EXPECT(status.size() == 1,
+ status_bin << " returned unexpected number of instances: "
+ << status.size());
+ status = status[0];
+ }
+ static constexpr auto kWebrtcProp = "webrtc_device_id";
+ static constexpr auto kNameProp = "instance_name";
+ // Check for isObject first, calling isMember on anything else causes a
+ // runtime error
+ if (status.isObject() && !status.isMember(kWebrtcProp) &&
+ status.isMember(kNameProp)) {
+ // b/296644913 some cuttlefish versions printed the webrtc device id as
+ // the instance name.
+ status[kWebrtcProp] = status[kNameProp];
+ }
+ // The instance doesn't know the name under which it was created on the
+ // server.
+ status[kNameProp] = instance_ref.Get().PerInstanceName();
+ output.append(status);
}
return output;
}
@@ -275,33 +283,34 @@
const SharedFD& err) {
std::lock_guard assemblies_lock(instance_db_mutex_);
auto& instance_db = GetInstanceDB(uid);
- const char _GroupDeviceInfoStart[] = "[\n";
- const char _GroupDeviceInfoSeparate[] = ",\n";
- const char _GroupDeviceInfoEnd[] = "]\n";
- WriteAll(out, _GroupDeviceInfoStart);
auto&& instance_groups = instance_db.InstanceGroups();
-
- for (const auto& group : instance_groups) {
- CF_EXPECT(group != nullptr);
- auto result = IssueStatusCommand(*group, err);
- if (!result.ok()) {
- WriteAll(err, " (unknown instance status error)");
- } else {
- const auto [stderr_msg, stdout_json] = *result;
- WriteAll(err, stderr_msg);
- // TODO(kwstephenkim): build a data structure that also includes
- // selector-related information, etc.
- WriteAll(out, stdout_json.toStyledString());
- }
- // move on
- if (group == *instance_groups.crbegin()) {
- continue;
- }
- WriteAll(out, _GroupDeviceInfoSeparate);
- }
- WriteAll(out, _GroupDeviceInfoEnd);
cvd::Status status;
status.set_code(cvd::Status::OK);
+
+ Json::Value groups_json(Json::arrayValue);
+ for (const auto& group : instance_groups) {
+ CF_EXPECT(group != nullptr);
+ Json::Value group_json(Json::objectValue);
+ group_json["group_name"] = group->GroupName();
+ auto result = IssueStatusCommand(*group, err);
+ if (!result.ok()) {
+ WriteAll(err, fmt::format("Group '{}' status error: '{}'",
+ group->GroupName(), result.error().Message()));
+ status.set_code(cvd::Status::INTERNAL);
+ continue;
+ }
+ group_json["instances"] = *result;
+ groups_json.append(group_json);
+ }
+ Json::Value output(Json::objectValue);
+ output["groups"] = groups_json;
+ // Calling toStyledString here puts the string representation of all instance
+ // groups into a single string in memory. That sounds large, but the host's
+ // RAM should be able to handle it if it can handle that many instances
+ // running simultaneously.
+ // The alternative is probably to create an std::ostream from
+ // cuttlefish::SharedFD and use Json::Value's operator<< to print it.
+ WriteAll(out, output.toStyledString());
return status;
}
diff --git a/host/commands/cvd/instance_manager.h b/host/commands/cvd/instance_manager.h
index a7bc7e9..41c7ac6 100644
--- a/host/commands/cvd/instance_manager.h
+++ b/host/commands/cvd/instance_manager.h
@@ -114,11 +114,7 @@
private:
Result<cvd::Status> CvdFleetImpl(const uid_t uid, const SharedFD& out,
const SharedFD& err);
- struct StatusCommandOutput {
- std::string stderr_msg;
- Json::Value stdout_json;
- };
- Result<StatusCommandOutput> IssueStatusCommand(
+ Result<Json::Value> IssueStatusCommand(
const selector::LocalInstanceGroup& group, const SharedFD& err);
Result<void> IssueStopCommand(const SharedFD& out, const SharedFD& err,
const std::string& config_file_path,
diff --git a/host/commands/cvd/main.cc b/host/commands/cvd/main.cc
index 0e1f1ed..28c735d 100644
--- a/host/commands/cvd/main.cc
+++ b/host/commands/cvd/main.cc
@@ -38,21 +38,6 @@
namespace cuttlefish {
namespace {
-Result<FlagCollection> CvdFlags() {
- FlagCollection cvd_flags;
- cvd_flags.EnrollFlag(CvdFlag<bool>("clean", false));
- cvd_flags.EnrollFlag(CvdFlag<bool>("help", false));
- cvd_flags.EnrollFlag(CvdFlag<std::string>("verbosity"));
- return cvd_flags;
-}
-
-Result<bool> FilterDriverHelpOptions(const FlagCollection& cvd_flags,
- cvd_common::Args& cvd_args) {
- auto help_flag = CF_EXPECT(cvd_flags.GetFlag("help"));
- bool is_help = CF_EXPECT(help_flag.CalculateFlag<bool>(cvd_args));
- return is_help;
-}
-
/**
* Returns --verbosity value if ever exist in the entire commandline args
*
@@ -84,102 +69,6 @@
return (encoded_verbosity.ok() ? *encoded_verbosity : GetMinimumVerbosity());
}
-cvd_common::Args AllArgs(const std::string& prog_path,
- const cvd_common::Args& cvd_args,
- const std::optional<std::string>& subcmd,
- const cvd_common::Args& subcmd_args) {
- std::vector<std::string> all_args;
- all_args.push_back(prog_path);
- all_args.insert(all_args.end(), cvd_args.begin(), cvd_args.end());
- if (subcmd) {
- all_args.push_back(*subcmd);
- }
- all_args.insert(all_args.end(), subcmd_args.begin(), subcmd_args.end());
- return all_args;
-}
-
-struct ClientCommandCheckResult {
- bool was_client_command_;
- cvd_common::Args new_all_args;
-};
-Result<ClientCommandCheckResult> HandleClientCommands(
- CvdClient& client, const cvd_common::Args& all_args) {
- ClientCommandCheckResult output;
- std::vector<std::string> client_internal_commands{"kill-server",
- "server-kill", "reset"};
- FlagCollection cvd_flags = CF_EXPECT(CvdFlags());
- FrontlineParser::ParserParam client_param{
- .server_supported_subcmds = std::vector<std::string>{},
- .internal_cmds = client_internal_commands,
- .all_args = all_args,
- .cvd_flags = cvd_flags};
- auto client_parser_result = FrontlineParser::Parse(client_param);
- if (!client_parser_result.ok()) {
- return ClientCommandCheckResult{.was_client_command_ = false,
- .new_all_args = all_args};
- }
-
- auto client_parser = std::move(*client_parser_result);
- CF_EXPECT(client_parser != nullptr);
- auto cvd_args = client_parser->CvdArgs();
- auto is_help = CF_EXPECT(FilterDriverHelpOptions(cvd_flags, cvd_args));
-
- output.new_all_args =
- AllArgs(client_parser->ProgPath(), cvd_args, client_parser->SubCmd(),
- client_parser->SubCmdArgs());
- output.was_client_command_ = (!is_help && client_parser->SubCmd());
- if (!output.was_client_command_) {
- // could be simply "cvd"
- output.new_all_args = cvd_common::Args{"cvd", "help"};
- return output;
- }
-
- // Special case for `cvd kill-server`, handled by directly
- // stopping the cvd_server.
- std::vector<std::string> kill_server_cmds{"kill-server", "server-kill"};
- std::string subcmd = client_parser->SubCmd().value_or("");
- if (Contains(kill_server_cmds, subcmd)) {
- CF_EXPECT(client.StopCvdServer(/*clear=*/true));
- return output;
- }
- CF_EXPECT_EQ(subcmd, "reset", "unsupported subcmd: " << subcmd);
- CF_EXPECT(HandleReset(client, client_parser->SubCmdArgs()));
- return output;
-}
-
-enum class VersionCommandReport : std::uint32_t {
- kNonVersion,
- kVersion,
-};
-Result<VersionCommandReport> HandleVersionCommand(
- CvdClient& client, const cvd_common::Args& all_args) {
- std::vector<std::string> version_command{"version"};
- FlagCollection cvd_flags = CF_EXPECT(CvdFlags());
- FrontlineParser::ParserParam version_param{
- .server_supported_subcmds = std::vector<std::string>{},
- .internal_cmds = version_command,
- .all_args = all_args,
- .cvd_flags = cvd_flags};
- auto version_parser_result = FrontlineParser::Parse(version_param);
- if (!version_parser_result.ok()) {
- return VersionCommandReport::kNonVersion;
- }
-
- auto version_parser = std::move(*version_parser_result);
- CF_EXPECT(version_parser != nullptr);
- const auto subcmd = version_parser->SubCmd().value_or("");
- auto cvd_args = version_parser->CvdArgs();
- CF_EXPECT(subcmd == "version" || subcmd.empty(),
- "subcmd is expected to be \"version\" or empty but is " << subcmd);
-
- if (subcmd == "version") {
- auto version_msg = CF_EXPECT(client.HandleVersion());
- std::cout << version_msg;
- return VersionCommandReport::kVersion;
- }
- return VersionCommandReport::kNonVersion;
-}
-
/**
* Terminates a cvd server listening on "cvd_server"
*
@@ -234,17 +123,6 @@
.acloud_translator_optout = parsed.acloud_translator_optout});
}
- CF_EXPECT_EQ(android::base::Basename(all_args[0]), "cvd");
-
- // TODO(kwstephenkim): --help should be handled here.
- // And, the FrontlineParser takes any positional argument as
- // a valid subcommand.
-
- auto [was_client_command, new_all_args] =
- CF_EXPECT(HandleClientCommands(client, all_args));
- if (was_client_command) {
- return {};
- }
/*
* For now, the parser needs a running server. The parser will
* be moved to the server side, and then it won't.
@@ -253,18 +131,13 @@
CF_EXPECT(client.ValidateServerVersion(),
"Unable to ensure cvd_server is running.");
- auto version_command_handle_report =
- CF_EXPECT(HandleVersionCommand(client, new_all_args));
- if (version_command_handle_report == VersionCommandReport::kVersion) {
+ if (android::base::Basename(all_args[0]) == "cvd") {
+ CF_EXPECT(client.HandleCvdCommand(all_args, env));
return {};
}
- const cvd_common::Args new_cmd_args{"cvd", "process"};
- CF_EXPECT(!new_all_args.empty());
- const cvd_common::Args new_selector_args{new_all_args.begin(),
- new_all_args.end()};
- // TODO(schuffelen): Deduplicate when calls to setenv are removed.
- CF_EXPECT(client.HandleCommand(new_cmd_args, env, new_selector_args));
+ CF_EXPECT(client.HandleCommand(all_args, env, {}));
+
return {};
}
diff --git a/host/commands/cvd/parser/Android.bp b/host/commands/cvd/parser/Android.bp
index d90e8fd..c724a80 100644
--- a/host/commands/cvd/parser/Android.bp
+++ b/host/commands/cvd/parser/Android.bp
@@ -20,23 +20,23 @@
cc_library_host_static {
name: "libcvd_parser",
srcs: [
- "instance/cf_vm_configs.cpp",
- "instance/cf_disk_configs.cpp",
- "instance/cf_boot_configs.cpp",
- "instance/cf_security_configs.cpp",
- "instance/cf_graphics_configs.cpp",
- "instance/cf_metrics_configs.cpp",
"cf_configs_common.cpp",
"cf_configs_instances.cpp",
+ "cf_flags_validator.cpp",
+ "cf_metrics_configs.cpp",
+ "fetch_cvd_parser.cpp",
+ "instance/cf_boot_configs.cpp",
+ "instance/cf_disk_configs.cpp",
+ "instance/cf_graphics_configs.cpp",
+ "instance/cf_security_configs.cpp",
+ "instance/cf_vm_configs.cpp",
"launch_cvd_templates.cpp",
"launch_cvd_parser.cpp",
- "cf_flags_validator.cpp",
- "fetch_cvd_parser.cpp",
"load_configs_parser.cpp",
],
static_libs: [
- "libprotobuf-cpp-full",
"libcuttlefish_launch_cvd_proto",
+ "libprotobuf-cpp-full",
],
defaults: ["cvd_lib_defaults"],
}
diff --git a/host/commands/cvd/parser/cf_configs_common.cpp b/host/commands/cvd/parser/cf_configs_common.cpp
index b931cee..c58906c 100644
--- a/host/commands/cvd/parser/cf_configs_common.cpp
+++ b/host/commands/cvd/parser/cf_configs_common.cpp
@@ -21,8 +21,10 @@
#include <vector>
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <json/json.h>
+#include "common/libs/utils/json.h"
#include "common/libs/utils/result.h"
namespace cuttlefish {
@@ -47,46 +49,36 @@
const std::string& json_flag,
int default_value) {
// Allocate and initialize with default values
- for (int i = 0; i < instances.size(); i++) {
- if (!instances[i].isMember(group) ||
- (!instances[i][group].isMember(subgroup)) ||
- (instances[i][group][subgroup].size() == 0)) {
- instances[i][group][subgroup][0][json_flag] = default_value;
+ for (auto& instance : instances) {
+ if (!instance.isMember(group) || (!instance[group].isMember(subgroup)) ||
+ (instance[group][subgroup].size() == 0)) {
+ instance[group][subgroup][0][json_flag] = default_value;
} else {
// Check the whole array
- int vector_size = instances[i][group][subgroup].size();
- for (int j = 0; j < vector_size; j++) {
- if (!instances[i][group][subgroup][j].isMember(json_flag)) {
- instances[i][group][subgroup][j][json_flag] = default_value;
+ for (auto& subgroup_member : instance[group][subgroup]) {
+ if (!subgroup_member.isMember(json_flag)) {
+ subgroup_member[json_flag] = default_value;
}
}
}
}
}
+std::string GenerateGflag(const std::string& gflag_name,
+ const std::vector<std::string>& values) {
+ std::stringstream buff;
+ buff << "--" << gflag_name << "=";
+ buff << android::base::Join(values, ',');
+ return buff.str();
+}
+
Result<std::string> GenerateGflag(const Json::Value& instances,
const std::string& gflag_name,
const std::vector<std::string>& selectors) {
- std::stringstream buff;
- buff << "--" << gflag_name << "=";
-
- int size = instances.size();
- for (int i = 0; i < size; i++) {
- const Json::Value* traversal = &instances[i];
- for (const auto& selector : selectors) {
- CF_EXPECTF(traversal->isMember(selector),
- "JSON selector \"{}\" does not exist when trying to create "
- "gflag \"{}\"",
- selector, gflag_name);
- traversal = &(*traversal)[selector];
- }
- buff << traversal->asString();
- if (i != size - 1) {
- buff << ",";
- }
- }
- return buff.str();
+ auto values = CF_EXPECTF(GetArrayValues<std::string>(instances, selectors),
+ "Unable to get values for gflag \"{}\"", gflag_name);
+ return GenerateGflag(gflag_name, values);
}
std::vector<std::string> MergeResults(std::vector<std::string> first_list,
@@ -106,7 +98,6 @@
* @param src : input json object tree to be merged
*/
void MergeTwoJsonObjs(Json::Value& dst, const Json::Value& src) {
- // Merge all members of src into dst
for (const auto& key : src.getMemberNames()) {
if (src[key].type() == Json::arrayValue) {
for (int i = 0; i < src[key].size(); i++) {
diff --git a/host/commands/cvd/parser/cf_configs_common.h b/host/commands/cvd/parser/cf_configs_common.h
index 8f39aac..643ac64 100644
--- a/host/commands/cvd/parser/cf_configs_common.h
+++ b/host/commands/cvd/parser/cf_configs_common.h
@@ -27,8 +27,6 @@
#include "common/libs/utils/result.h"
-#define GENERATE_MVP_FLAGS_ONLY true
-
namespace cuttlefish {
Result<void> ValidateTypo(const Json::Value& root,
@@ -86,6 +84,8 @@
const std::string& json_flag,
int default_value);
+std::string GenerateGflag(const std::string& gflag_name,
+ const std::vector<std::string>& values);
Result<std::string> GenerateGflag(const Json::Value& instances,
const std::string& gflag_name,
const std::vector<std::string>& selectors);
diff --git a/host/commands/cvd/parser/cf_configs_instances.cpp b/host/commands/cvd/parser/cf_configs_instances.cpp
index d9a24db..405d9b4 100644
--- a/host/commands/cvd/parser/cf_configs_instances.cpp
+++ b/host/commands/cvd/parser/cf_configs_instances.cpp
@@ -16,39 +16,39 @@
#include "host/commands/cvd/parser/cf_configs_instances.h"
-#include <android-base/logging.h>
#include <iostream>
+#include <string>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <json/json.h>
#include "common/libs/utils/result.h"
#include "host/commands/cvd/parser/cf_configs_common.h"
#include "host/commands/cvd/parser/instance/cf_boot_configs.h"
#include "host/commands/cvd/parser/instance/cf_disk_configs.h"
#include "host/commands/cvd/parser/instance/cf_graphics_configs.h"
-#include "host/commands/cvd/parser/instance/cf_metrics_configs.h"
#include "host/commands/cvd/parser/instance/cf_security_configs.h"
#include "host/commands/cvd/parser/instance/cf_vm_configs.h"
namespace cuttlefish {
-Result<void> InitInstancesConfigs(Json::Value& root) {
- CF_EXPECT(InitVmConfigs(root));
- CF_EXPECT(InitDiskConfigs(root));
- CF_EXPECT(InitBootConfigs(root));
- CF_EXPECT(InitSecurityConfigs(root));
- InitGraphicsConfigs(root);
+Result<void> InitInstancesConfigs(Json::Value& instances) {
+ CF_EXPECT(InitBootConfigs(instances));
+ CF_EXPECT(InitDiskConfigs(instances));
+ CF_EXPECT(InitGraphicsConfigs(instances));
+ CF_EXPECT(InitSecurityConfigs(instances));
+ CF_EXPECT(InitVmConfigs(instances));
return {};
}
Result<std::vector<std::string>> GenerateInstancesFlags(
- const Json::Value& root) {
- std::vector<std::string> result = CF_EXPECT(GenerateVmFlags(root));
- result = MergeResults(result, CF_EXPECT(GenerateDiskFlags(root)));
- if (!GENERATE_MVP_FLAGS_ONLY) {
- result = MergeResults(result, CF_EXPECT(GenerateBootFlags(root)));
- }
- result = MergeResults(result, CF_EXPECT(GenerateSecurityFlags(root)));
- result = MergeResults(result, GenerateGraphicsFlags(root));
- result = MergeResults(result, GenerateMetricsFlags(root));
+ const Json::Value& instances) {
+ std::vector<std::string> result = CF_EXPECT(GenerateBootFlags(instances));
+ result = MergeResults(result, CF_EXPECT(GenerateDiskFlags(instances)));
+ result = MergeResults(result, CF_EXPECT(GenerateGraphicsFlags(instances)));
+ result = MergeResults(result, CF_EXPECT(GenerateSecurityFlags(instances)));
+ result = MergeResults(result, CF_EXPECT(GenerateVmFlags(instances)));
return result;
}
diff --git a/host/commands/cvd/parser/cf_flags_validator.cpp b/host/commands/cvd/parser/cf_flags_validator.cpp
index d6209cb..c50f98a 100644
--- a/host/commands/cvd/parser/cf_flags_validator.cpp
+++ b/host/commands/cvd/parser/cf_flags_validator.cpp
@@ -30,17 +30,21 @@
namespace cuttlefish {
namespace {
-// json main parameters definitions
static std::map<std::string, Json::ValueType> kConfigsKeyMap = {
+ {"netsim_bt", Json::ValueType::booleanValue},
+ {"instances", Json::ValueType::arrayValue},
+ {"fetch", Json::ValueType::objectValue},
+ {"metrics", Json::ValueType::objectValue},
+};
+
+static std::map<std::string, Json::ValueType> kFetchKeyMap = {
{"api_key", Json::ValueType::stringValue},
{"credential", Json::ValueType::stringValue},
{"wait_retry_period", Json::ValueType::uintValue},
{"external_dns_resolver", Json::ValueType::booleanValue},
{"keep_downloaded_archives", Json::ValueType::booleanValue},
- {"netsim_bt", Json::ValueType::booleanValue},
- {"instances", Json::ValueType::arrayValue}};
+};
-// instance object parameters definitions
static std::map<std::string, Json::ValueType> kInstanceKeyMap = {
{"@import", Json::ValueType::stringValue},
{"vm", Json::ValueType::objectValue},
@@ -56,11 +60,9 @@
{"vehicle", Json::ValueType::objectValue},
{"location", Json::ValueType::objectValue}};
-// supported import values for @import key
static std::unordered_set<std::string> kSupportedImportValues = {
"phone", "tablet", "tv", "wearable", "auto", "slim", "go", "foldable"};
-// supported import values for vm category and crosvm subcategory
static std::map<std::string, Json::ValueType> kVmKeyMap = {
{"cpus", Json::ValueType::uintValue},
{"memory_mb", Json::ValueType::uintValue},
@@ -76,19 +78,25 @@
{"enable_sandbox", Json::ValueType::booleanValue},
};
-// supported import values for boot category and kernel subcategory
static std::map<std::string, Json::ValueType> kBootKeyMap = {
- {"extra_bootconfig_args", Json::ValueType::stringValue},
{"kernel", Json::ValueType::objectValue},
{"enable_bootanimation", Json::ValueType::booleanValue},
-};
-static std::map<std::string, Json::ValueType> kernelkeyMap = {
- {"extra_kernel_cmdline", Json::ValueType::stringValue},
+ {"build", Json::ValueType::stringValue},
+ {"bootloader", Json::ValueType::objectValue},
};
-// supported import values for graphics category and displays subcategory
+static std::map<std::string, Json::ValueType> kKernelKeyMap = {
+ {"extra_kernel_cmdline", Json::ValueType::stringValue},
+ {"build", Json::ValueType::stringValue},
+};
+
+static std::map<std::string, Json::ValueType> kBootloaderKeyMap = {
+ {"build", Json::ValueType::stringValue},
+};
+
static std::map<std::string, Json::ValueType> kGraphicsKeyMap = {
{"displays", Json::ValueType::arrayValue},
+ {"record_screen", Json::ValueType::booleanValue},
};
static std::map<std::string, Json::ValueType> kDisplayKeyMap = {
{"width", Json::ValueType::uintValue},
@@ -97,23 +105,26 @@
{"refresh_rate_hertz", Json::ValueType::uintValue},
};
-// supported import values for security category
static std::map<std::string, Json::ValueType> kSecurityKeyMap = {
{"serial_number", Json::ValueType::stringValue},
+ {"use_random_serial", Json::ValueType::stringValue},
{"guest_enforce_security", Json::ValueType::booleanValue},
};
-// supported import values for disk category
static std::map<std::string, Json::ValueType> kDiskKeyMap = {
{"default_build", Json::ValueType::stringValue},
- {"system_build", Json::ValueType::stringValue},
- {"kernel_build", Json::ValueType::stringValue},
+ {"super", Json::ValueType::objectValue},
{"download_img_zip", Json::ValueType::booleanValue},
{"download_target_zip_files", Json::ValueType::booleanValue},
{"blank_data_image_mb", Json::ValueType::uintValue},
+ {"otatools", Json::ValueType::stringValue},
+ {"host_package", Json::ValueType::stringValue},
};
-// Validate the security json parameters
+static std::map<std::string, Json::ValueType> kSuperKeyMap = {
+ {"system", Json::ValueType::stringValue},
+};
+
Result<void> ValidateSecurityConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kSecurityKeyMap),
"ValidateSecurityConfigs ValidateTypo fail");
@@ -122,33 +133,32 @@
Result<void> ValidateDiskConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kDiskKeyMap),
"ValidateDiskConfigs ValidateTypo fail");
+ if (root.isMember("super")) {
+ CF_EXPECT(ValidateTypo(root["super"], kSuperKeyMap),
+ "ValidateDiskSuperConfigs ValidateTypo fail");
+ }
return {};
}
-// Validate the displays json parameters
Result<void> ValidateDisplaysConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kDisplayKeyMap),
"ValidateDisplaysConfigs ValidateTypo fail");
return {};
}
-// Validate the graphics json parameters
Result<void> ValidateGraphicsConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kGraphicsKeyMap),
"ValidateGraphicsConfigs ValidateTypo fail");
if (root.isMember("displays") && root["displays"].size() != 0) {
- int num_displays = root["displays"].size();
- for (int i = 0; i < num_displays; i++) {
- CF_EXPECT(ValidateDisplaysConfigs(root["displays"][i]),
- "ValidateDisplaysConfigs fail");
+ for (const auto& display : root["displays"]) {
+ CF_EXPECT(ValidateDisplaysConfigs(display));
}
}
return {};
}
-// Validate the vm json parameters
Result<void> ValidateVmConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kVmKeyMap),
"ValidateVmConfigs ValidateTypo fail");
@@ -159,62 +169,59 @@
return {};
}
-// Validate the kernel json parameters
Result<void> ValidateKernelConfigs(const Json::Value& root) {
- CF_EXPECT(ValidateTypo(root, kernelkeyMap),
+ CF_EXPECT(ValidateTypo(root, kKernelKeyMap),
"ValidateKernelConfigs ValidateTypo fail");
return {};
}
-// Validate the boot json parameters
+Result<void> ValidateBootloaderConfigs(const Json::Value& root) {
+ CF_EXPECT(ValidateTypo(root, kBootloaderKeyMap),
+ "ValidateBootloaderConfigs ValidateTypo fail");
+ return {};
+}
+
Result<void> ValidateBootConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kBootKeyMap),
"ValidateBootConfigs ValidateTypo fail");
if (root.isMember("kernel")) {
- CF_EXPECT(ValidateKernelConfigs(root["kernel"]),
- "ValidateKernelConfigs fail");
+ CF_EXPECT(ValidateKernelConfigs(root["kernel"]));
}
-
+ if (root.isMember("bootloader")) {
+ CF_EXPECT(ValidateBootloaderConfigs(root["bootloader"]));
+ }
return {};
}
-// Validate the instances json parameters
Result<void> ValidateInstancesConfigs(const Json::Value& instances) {
- int num_instances = instances.size();
- for (unsigned int i = 0; i < num_instances; i++) {
- CF_EXPECT(ValidateTypo(instances[i], kInstanceKeyMap),
- "vm ValidateTypo fail");
+ for (const auto& instance : instances) {
+ CF_EXPECT(ValidateTypo(instance, kInstanceKeyMap),
+ "instance ValidateTypo fail");
- if (instances[i].isMember("vm")) {
- CF_EXPECT(ValidateVmConfigs(instances[i]["vm"]),
- "ValidateVmConfigs fail");
+ if (instance.isMember("vm")) {
+ CF_EXPECT(ValidateVmConfigs(instance["vm"]));
}
- // Validate @import flag values are supported or not
- if (instances[i].isMember("@import")) {
+ if (instance.isMember("@import")) {
CF_EXPECT(
- kSupportedImportValues.count(instances[i]["@import"].asString()) > 0,
+ kSupportedImportValues.count(instance["@import"].asString()) > 0,
"@Import flag values are not supported");
}
- if (instances[i].isMember("boot")) {
- CF_EXPECT(ValidateBootConfigs(instances[i]["boot"]),
- "ValidateBootConfigs fail");
+ if (instance.isMember("boot")) {
+ CF_EXPECT(ValidateBootConfigs(instance["boot"]));
}
- if (instances[i].isMember("security")) {
- CF_EXPECT(ValidateSecurityConfigs(instances[i]["security"]),
- "ValidateSecurityConfigs fail");
+ if (instance.isMember("security")) {
+ CF_EXPECT(ValidateSecurityConfigs(instance["security"]));
}
- if (instances[i].isMember("disk")) {
- CF_EXPECT(ValidateDiskConfigs(instances[i]["disk"]),
- "ValidateDiskConfigs fail");
+ if (instance.isMember("disk")) {
+ CF_EXPECT(ValidateDiskConfigs(instance["disk"]));
}
- if (instances[i].isMember("graphics")) {
- CF_EXPECT(ValidateGraphicsConfigs(instances[i]["graphics"]),
- "ValidateGraphicsConfigs fail");
+ if (instance.isMember("graphics")) {
+ CF_EXPECT(ValidateGraphicsConfigs(instance["graphics"]));
}
- CF_EXPECT(ValidateConfig<std::string>(instances[i], ValidateSetupWizardMode,
+ CF_EXPECT(ValidateConfig<std::string>(instance, ValidateSetupWizardMode,
{"vm", "setupwizard_mode"}),
"Invalid value for setupwizard_mode flag");
}
@@ -224,10 +231,17 @@
} // namespace
-// Validate cuttlefish config json parameters
Result<void> ValidateCfConfigs(const Json::Value& root) {
+ static const auto& kMetricsMap = *new std::map<std::string, Json::ValueType>{
+ {"enable", Json::ValueType::booleanValue},
+ };
+
CF_EXPECT(ValidateTypo(root, kConfigsKeyMap),
"Typo in config main parameters");
+ CF_EXPECT(ValidateTypo(root["fetch"], kFetchKeyMap),
+ "Typo in config fetch parameters");
+ CF_EXPECT(ValidateTypo(root["metrics"], kMetricsMap),
+ "Typo in config metrics parameters");
CF_EXPECT(root.isMember("instances"), "instances object is missing");
CF_EXPECT(ValidateInstancesConfigs(root["instances"]),
"ValidateInstancesConfigs failed");
diff --git a/host/commands/cvd/parser/cf_metrics_configs.cpp b/host/commands/cvd/parser/cf_metrics_configs.cpp
new file mode 100644
index 0000000..ff1909e
--- /dev/null
+++ b/host/commands/cvd/parser/cf_metrics_configs.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "host/commands/cvd/parser/cf_metrics_configs.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <json/json.h>
+
+#include "common/libs/utils/json.h"
+#include "common/libs/utils/result.h"
+#include "host/commands/cvd/parser/cf_configs_common.h"
+
+namespace cuttlefish {
+namespace {
+
+constexpr bool kEnableMetricsDefault = false;
+
+std::string EnabledToReportAnonUsageStats(const bool enabled) {
+ return enabled ? "y" : "n";
+}
+
+} // namespace
+
+Result<void> InitMetricsConfigs(Json::Value& root) {
+ CF_EXPECT(InitConfig(root, kEnableMetricsDefault, {"metrics", "enable"}));
+ return {};
+}
+
+Result<std::vector<std::string>> GenerateMetricsFlags(const Json::Value& root) {
+ std::vector<std::string> result;
+ auto report_flag_value = EnabledToReportAnonUsageStats(
+ CF_EXPECT(GetValue<bool>(root, {"metrics", "enable"})));
+ result.emplace_back(
+ GenerateGflag("report_anonymous_usage_stats", {report_flag_value}));
+ return result;
+}
+
+} // namespace cuttlefish
diff --git a/host/commands/cvd/parser/instance/cf_metrics_configs.h b/host/commands/cvd/parser/cf_metrics_configs.h
similarity index 81%
rename from host/commands/cvd/parser/instance/cf_metrics_configs.h
rename to host/commands/cvd/parser/cf_metrics_configs.h
index d4d0ae2..7159125 100644
--- a/host/commands/cvd/parser/instance/cf_metrics_configs.h
+++ b/host/commands/cvd/parser/cf_metrics_configs.h
@@ -15,10 +15,17 @@
*/
#pragma once
-#include <json/json.h>
+
#include <string>
#include <vector>
+#include <json/json.h>
+
+#include "common/libs/utils/result.h"
+
namespace cuttlefish {
-std::vector<std::string> GenerateMetricsFlags(const Json::Value& root);
+
+Result<void> InitMetricsConfigs(Json::Value& root);
+Result<std::vector<std::string>> GenerateMetricsFlags(const Json::Value& root);
+
}; // namespace cuttlefish
diff --git a/host/commands/cvd/parser/fetch_cvd_parser.cpp b/host/commands/cvd/parser/fetch_cvd_parser.cpp
index 76f1455..3ebb5db 100644
--- a/host/commands/cvd/parser/fetch_cvd_parser.cpp
+++ b/host/commands/cvd/parser/fetch_cvd_parser.cpp
@@ -16,99 +16,178 @@
#include "host/commands/cvd/parser/fetch_cvd_parser.h"
-#include <algorithm>
-#include <optional>
#include <string>
+#include <string_view>
#include <vector>
+#include <android-base/strings.h>
#include <json/json.h>
+#include "common/libs/utils/json.h"
#include "common/libs/utils/result.h"
+#include "host/commands/cvd/fetch/fetch_cvd.h"
#include "host/commands/cvd/parser/cf_configs_common.h"
namespace cuttlefish {
namespace {
+constexpr std::string_view kFetchPrefix = "@ab/";
+
Result<void> InitFetchInstanceConfigs(Json::Value& instance) {
- CF_EXPECT(InitConfig(instance, Json::Value::nullSingleton(),
- {"disk", "default_build"}));
- CF_EXPECT(InitConfig(instance, Json::Value::nullSingleton(),
- {"disk", "system_build"}));
- CF_EXPECT(InitConfig(instance, Json::Value::nullSingleton(),
- {"disk", "kernel_build"}));
- CF_EXPECT(InitConfig(instance, Json::Value::nullSingleton(),
+ CF_EXPECT(
+ InitConfig(instance, kDefaultBuildString, {"disk", "default_build"}));
+ CF_EXPECT(
+ InitConfig(instance, kDefaultBuildString, {"disk", "super", "system"}));
+ CF_EXPECT(
+ InitConfig(instance, kDefaultBuildString, {"boot", "kernel", "build"}));
+ CF_EXPECT(InitConfig(instance, kDefaultBuildString, {"boot", "build"}));
+ CF_EXPECT(InitConfig(instance, kDefaultBuildString,
+ {"boot", "bootloader", "build"}));
+ CF_EXPECT(InitConfig(instance, kDefaultBuildString, {"disk", "otatools"}));
+ CF_EXPECT(
+ InitConfig(instance, kDefaultBuildString, {"disk", "host_package"}));
+ CF_EXPECT(InitConfig(instance, kDefaultDownloadImgZip,
{"disk", "download_img_zip"}));
- CF_EXPECT(InitConfig(instance, Json::Value::nullSingleton(),
+ CF_EXPECT(InitConfig(instance, kDefaultDownloadTargetFilesZip,
{"disk", "download_target_files_zip"}));
return {};
}
Result<void> InitFetchCvdConfigs(Json::Value& root) {
- CF_EXPECT(InitConfig(root, Json::Value::nullSingleton(), {"api_key"}));
- CF_EXPECT(
- InitConfig(root, Json::Value::nullSingleton(), {"credential_source"}));
- CF_EXPECT(
- InitConfig(root, Json::Value::nullSingleton(), {"wait_retry_period"}));
- CF_EXPECT(InitConfig(root, Json::Value::nullSingleton(),
- {"external_dns_resolver"}));
- CF_EXPECT(InitConfig(root, Json::Value::nullSingleton(),
- {"keep_downloaded_archives"}));
- Json::Value& instances = root["instances"];
- const int size = instances.size();
- for (int i = 0; i < size; i++) {
- CF_EXPECT(InitFetchInstanceConfigs(instances[i]));
+ CF_EXPECT(InitConfig(root, kDefaultApiKey, {"fetch", "api_key"}));
+ CF_EXPECT(InitConfig(root, kDefaultCredentialSource,
+ {"fetch", "credential_source"}));
+ CF_EXPECT(InitConfig(root, static_cast<int>(kDefaultWaitRetryPeriod.count()),
+ {"fetch", "wait_retry_period"}));
+ CF_EXPECT(InitConfig(root, kDefaultExternalDnsResolver,
+ {"fetch", "external_dns_resolver"}));
+ CF_EXPECT(InitConfig(root, kDefaultKeepDownloadedArchives,
+ {"fetch", "keep_downloaded_archives"}));
+ for (auto& instance : root["instances"]) {
+ CF_EXPECT(InitFetchInstanceConfigs(instance));
}
return {};
}
-std::optional<std::string> OptString(const Json::Value& value) {
- if (value.isNull()) {
- return std::nullopt;
+bool ShouldFetch(const Json::Value& instance) {
+ for (const auto& value :
+ {instance["disk"]["default_build"], instance["disk"]["super"]["system"],
+ instance["boot"]["kernel"]["build"], instance["boot"]["build"],
+ instance["boot"]["bootloader"]["build"], instance["disk"]["otatools"],
+ instance["disk"]["host_package"]}) {
+ // expects non-prefixed build strings already converted to empty strings
+ if (!value.empty()) {
+ return true;
+ }
}
- return value.asString();
+ return false;
}
-bool ShouldFetch(const std::vector<std::optional<std::string>>& values) {
- return std::any_of(std::begin(values), std::end(values),
- [](const std::optional<std::string>& value) {
- return value.has_value();
- });
+Result<std::string> GetFetchBuildString(const Json::Value& value) {
+ std::string strVal = value.asString();
+ std::string_view view = strVal;
+ if (!android::base::ConsumePrefix(&view, kFetchPrefix)) {
+ // intentionally return an empty string when there are local, non-prefixed
+ // paths. Fetch does not process the local paths
+ return "";
+ }
+ CF_EXPECTF(!view.empty(),
+ "\"{}\" prefixed build string was not followed by a value",
+ kFetchPrefix);
+ return std::string(view);
}
-FetchCvdInstanceConfig ParseFetchInstanceConfigs(const Json::Value& instance) {
- auto result = FetchCvdInstanceConfig{
- .default_build = OptString(instance["disk"]["default_build"]),
- .system_build = OptString(instance["disk"]["system_build"]),
- .kernel_build = OptString(instance["disk"]["kernel_build"]),
- .download_img_zip = OptString(instance["disk"]["download_img_zip"]),
- .download_target_files_zip =
- OptString(instance["disk"]["download_target_files_zip"])};
- result.should_fetch = ShouldFetch(
- {result.default_build, result.system_build, result.kernel_build});
+Result<Json::Value> RemoveNonPrefixedBuildStrings(const Json::Value& instance) {
+ auto result = Json::Value(instance);
+ result["disk"]["default_build"] =
+ CF_EXPECT(GetFetchBuildString(result["disk"]["default_build"]));
+ result["disk"]["super"]["system"] =
+ CF_EXPECT(GetFetchBuildString(result["disk"]["super"]["system"]));
+ result["boot"]["kernel"]["build"] =
+ CF_EXPECT(GetFetchBuildString(result["boot"]["kernel"]["build"]));
+ result["boot"]["build"] =
+ CF_EXPECT(GetFetchBuildString(result["boot"]["build"]));
+ result["boot"]["bootloader"]["build"] =
+ CF_EXPECT(GetFetchBuildString(result["boot"]["bootloader"]["build"]));
+ result["disk"]["otatools"] =
+ CF_EXPECT(GetFetchBuildString(result["disk"]["otatools"]));
+ result["disk"]["host_package"] =
+ CF_EXPECT(GetFetchBuildString(result["disk"]["host_package"]));
return result;
}
-FetchCvdConfig GenerateFetchCvdFlags(const Json::Value& root) {
- auto result = FetchCvdConfig{
- .api_key = OptString(root["api_key"]),
- .credential_source = OptString(root["credential_source"]),
- .wait_retry_period = OptString(root["wait_retry_period"]),
- .external_dns_resolver = OptString(root["external_dns_resolver"]),
- .keep_downloaded_archives = OptString(root["keep_downloaded_archives"])};
-
- const int num_instances = root["instances"].size();
- for (unsigned int i = 0; i < num_instances; i++) {
- result.instances.emplace_back(
- ParseFetchInstanceConfigs(root["instances"][i]));
+Result<std::vector<std::string>> GenerateFetchFlags(
+ const Json::Value& root, const std::string& target_directory,
+ const std::vector<std::string>& target_subdirectories) {
+ Json::Value fetch_instances = Json::Value(Json::ValueType::arrayValue);
+ std::vector<std::string> fetch_subdirectories;
+ const auto& instances = root["instances"];
+ CF_EXPECT_EQ(instances.size(), target_subdirectories.size(),
+ "Mismatched sizes between number of subdirectories and number "
+ "of instances");
+ for (int i = 0; i < instances.size(); i++) {
+ const auto prefix_filtered =
+ CF_EXPECT(RemoveNonPrefixedBuildStrings(instances[i]));
+ if (ShouldFetch(prefix_filtered)) {
+ fetch_instances.append(prefix_filtered);
+ fetch_subdirectories.emplace_back(target_subdirectories[i]);
+ }
}
+
+ std::vector<std::string> result;
+ if (fetch_subdirectories.empty()) {
+ return result;
+ }
+ result.emplace_back(GenerateGflag("target_directory", {target_directory}));
+ result.emplace_back(GenerateGflag(
+ "api_key",
+ {CF_EXPECT(GetValue<std::string>(root, {"fetch", "api_key"}))}));
+ result.emplace_back(GenerateGflag(
+ "credential_source", {CF_EXPECT(GetValue<std::string>(
+ root, {"fetch", "credential_source"}))}));
+ result.emplace_back(GenerateGflag(
+ "wait_retry_period", {CF_EXPECT(GetValue<std::string>(
+ root, {"fetch", "wait_retry_period"}))}));
+ result.emplace_back(
+ GenerateGflag("external_dns_resolver",
+ {CF_EXPECT(GetValue<std::string>(
+ root, {"fetch", "external_dns_resolver"}))}));
+ result.emplace_back(
+ GenerateGflag("keep_downloaded_archives",
+ {CF_EXPECT(GetValue<std::string>(
+ root, {"fetch", "keep_downloaded_archives"}))}));
+
+ result.emplace_back(
+ GenerateGflag("target_subdirectory", fetch_subdirectories));
+ result.emplace_back(CF_EXPECT(GenerateGflag(fetch_instances, "default_build",
+ {"disk", "default_build"})));
+ result.emplace_back(CF_EXPECT(GenerateGflag(fetch_instances, "system_build",
+ {"disk", "super", "system"})));
+ result.emplace_back(CF_EXPECT(GenerateGflag(fetch_instances, "kernel_build",
+ {"boot", "kernel", "build"})));
+ result.emplace_back(CF_EXPECT(
+ GenerateGflag(fetch_instances, "boot_build", {"boot", "build"})));
+ result.emplace_back(CF_EXPECT(GenerateGflag(
+ fetch_instances, "bootloader_build", {"boot", "bootloader", "build"})));
+ result.emplace_back(CF_EXPECT(
+ GenerateGflag(fetch_instances, "otatools_build", {"disk", "otatools"})));
+ result.emplace_back(CF_EXPECT(GenerateGflag(
+ fetch_instances, "host_package_build", {"disk", "host_package"})));
+ result.emplace_back(CF_EXPECT(GenerateGflag(
+ fetch_instances, "download_img_zip", {"disk", "download_img_zip"})));
+ result.emplace_back(
+ CF_EXPECT(GenerateGflag(fetch_instances, "download_target_files_zip",
+ {"disk", "download_target_files_zip"})));
return result;
}
} // namespace
-Result<FetchCvdConfig> ParseFetchCvdConfigs(Json::Value& root) {
+Result<std::vector<std::string>> ParseFetchCvdConfigs(
+ Json::Value& root, const std::string& target_directory,
+ const std::vector<std::string>& target_subdirectories) {
CF_EXPECT(InitFetchCvdConfigs(root));
- return {GenerateFetchCvdFlags(root)};
+ return GenerateFetchFlags(root, target_directory, target_subdirectories);
}
} // namespace cuttlefish
diff --git a/host/commands/cvd/parser/fetch_cvd_parser.h b/host/commands/cvd/parser/fetch_cvd_parser.h
index d51fc73..f2258b3 100644
--- a/host/commands/cvd/parser/fetch_cvd_parser.h
+++ b/host/commands/cvd/parser/fetch_cvd_parser.h
@@ -16,7 +16,6 @@
#pragma once
-#include <optional>
#include <string>
#include <vector>
@@ -26,27 +25,8 @@
namespace cuttlefish {
-struct FetchCvdInstanceConfig {
- bool should_fetch = false;
- // this subdirectory is relative to FetchCvdConfig::target_directory
- std::string target_subdirectory;
- std::optional<std::string> default_build;
- std::optional<std::string> system_build;
- std::optional<std::string> kernel_build;
- std::optional<std::string> download_img_zip;
- std::optional<std::string> download_target_files_zip;
-};
-
-struct FetchCvdConfig {
- std::string target_directory;
- std::optional<std::string> api_key;
- std::optional<std::string> credential_source;
- std::optional<std::string> wait_retry_period;
- std::optional<std::string> external_dns_resolver;
- std::optional<std::string> keep_downloaded_archives;
- std::vector<FetchCvdInstanceConfig> instances;
-};
-
-Result<FetchCvdConfig> ParseFetchCvdConfigs(Json::Value& root);
+Result<std::vector<std::string>> ParseFetchCvdConfigs(
+ Json::Value& root, const std::string& target_directory,
+ const std::vector<std::string>& target_subdirectories);
}; // namespace cuttlefish
diff --git a/host/commands/cvd/parser/instance/cf_boot_configs.cpp b/host/commands/cvd/parser/instance/cf_boot_configs.cpp
index 7a8446c..b1250d4 100644
--- a/host/commands/cvd/parser/instance/cf_boot_configs.cpp
+++ b/host/commands/cvd/parser/instance/cf_boot_configs.cpp
@@ -27,13 +27,10 @@
namespace cuttlefish {
Result<void> InitBootConfigs(Json::Value& instances) {
- const int size = instances.size();
- for (int i = 0; i < size; i++) {
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_EXTRA_BOOTCONFIG_ARGS,
- {"boot", "extra_bootconfig_args"}));
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_ENABLE_BOOTANIMATION,
+ for (auto& instance : instances) {
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_ENABLE_BOOTANIMATION,
{"boot", "enable_bootanimation"}));
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_EXTRA_KERNEL_CMDLINE,
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_EXTRA_KERNEL_CMDLINE,
{"boot", "kernel", "extra_kernel_cmdline"}));
}
return {};
@@ -43,8 +40,6 @@
const Json::Value& instances) {
std::vector<std::string> result;
result.emplace_back(CF_EXPECT(GenerateGflag(
- instances, "extra_bootconfig_args", {"boot", "extra_bootconfig_args"})));
- result.emplace_back(CF_EXPECT(GenerateGflag(
instances, "enable_bootanimation", {"boot", "enable_bootanimation"})));
result.emplace_back(
CF_EXPECT(GenerateGflag(instances, "extra_kernel_cmdline",
diff --git a/host/commands/cvd/parser/instance/cf_disk_configs.cpp b/host/commands/cvd/parser/instance/cf_disk_configs.cpp
index 43d3b63..aad71e6 100644
--- a/host/commands/cvd/parser/instance/cf_disk_configs.cpp
+++ b/host/commands/cvd/parser/instance/cf_disk_configs.cpp
@@ -28,9 +28,8 @@
namespace cuttlefish {
Result<void> InitDiskConfigs(Json::Value& instances) {
- const int size = instances.size();
- for (int i = 0; i < size; i++) {
- CF_EXPECT(InitConfig(instances[i], DEFAULT_BLANK_DATA_IMAGE_SIZE,
+ for (auto& instance : instances) {
+ CF_EXPECT(InitConfig(instance, DEFAULT_BLANK_DATA_IMAGE_SIZE,
{"disk", "blank_data_image_mb"}));
}
return {};
diff --git a/host/commands/cvd/parser/instance/cf_graphics_configs.cpp b/host/commands/cvd/parser/instance/cf_graphics_configs.cpp
index 1e17684..1c8eb43 100644
--- a/host/commands/cvd/parser/instance/cf_graphics_configs.cpp
+++ b/host/commands/cvd/parser/instance/cf_graphics_configs.cpp
@@ -28,7 +28,7 @@
namespace cuttlefish {
-void InitGraphicsConfigs(Json::Value& instances) {
+Result<void> InitGraphicsConfigs(Json::Value& instances) {
InitIntConfigSubGroupVector(instances, "graphics", "displays", "width",
CF_DEFAULTS_DISPLAY_WIDTH);
InitIntConfigSubGroupVector(instances, "graphics", "displays", "height",
@@ -38,18 +38,20 @@
InitIntConfigSubGroupVector(instances, "graphics", "displays",
"refresh_rate_hertz",
CF_DEFAULTS_DISPLAY_REFRESH_RATE);
+ for (auto& instance : instances) {
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_RECORD_SCREEN,
+ {"graphics", "record_screen"}));
+ }
+ return {};
}
std::string GenerateDisplayFlag(const Json::Value& instances_json) {
using google::protobuf::TextFormat;
cuttlefish::InstancesDisplays all_instances_displays;
- int num_instances = instances_json.size();
- for (int i = 0; i < num_instances; i++) {
+ for (const auto& instance_json : instances_json) {
auto* instance = all_instances_displays.add_instances();
- int num_displays = instances_json[i]["graphics"]["displays"].size();
- for (int j = 0; j < num_displays; j++) {
- Json::Value display_json = instances_json[i]["graphics"]["displays"][j];
+ for (const auto& display_json : instance_json["graphics"]["displays"]) {
auto* display = instance->add_displays();
display->set_width(display_json["width"].asInt());
display->set_height(display_json["height"].asInt());
@@ -74,9 +76,12 @@
return "--displays_binproto=" + base64_output;
}
-std::vector<std::string> GenerateGraphicsFlags(const Json::Value& instances) {
+Result<std::vector<std::string>> GenerateGraphicsFlags(
+ const Json::Value& instances) {
std::vector<std::string> result;
result.emplace_back(GenerateDisplayFlag(instances));
+ result.emplace_back(CF_EXPECT(GenerateGflag(instances, "record_screen",
+ {"graphics", "record_screen"})));
return result;
}
diff --git a/host/commands/cvd/parser/instance/cf_graphics_configs.h b/host/commands/cvd/parser/instance/cf_graphics_configs.h
index c0bdccd..f577fed 100644
--- a/host/commands/cvd/parser/instance/cf_graphics_configs.h
+++ b/host/commands/cvd/parser/instance/cf_graphics_configs.h
@@ -20,6 +20,6 @@
#include <vector>
namespace cuttlefish {
-void InitGraphicsConfigs(Json::Value& root);
-std::vector<std::string> GenerateGraphicsFlags(const Json::Value& root);
+Result<void> InitGraphicsConfigs(Json::Value& root);
+Result<std::vector<std::string>> GenerateGraphicsFlags(const Json::Value& root);
}; // namespace cuttlefish
diff --git a/host/commands/cvd/parser/instance/cf_metrics_configs.cpp b/host/commands/cvd/parser/instance/cf_metrics_configs.cpp
deleted file mode 100644
index d708343..0000000
--- a/host/commands/cvd/parser/instance/cf_metrics_configs.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "host/commands/cvd/parser/instance/cf_metrics_configs.h"
-
-#include <android-base/logging.h>
-
-#include "host/commands/assemble_cvd/flags_defaults.h"
-#include "host/commands/cvd/parser/cf_configs_common.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-// Metrics collection will be disabled by default for canonical configs MVP
-#define DEFAULT_ENABLE_REPORTING "n"
-
-namespace cuttlefish {
-
-static std::string GenerateReportFlag() {
- std::stringstream result_flag;
- result_flag << "--report_anonymous_usage_stats=" << DEFAULT_ENABLE_REPORTING;
- return result_flag.str();
-}
-
-std::vector<std::string> GenerateMetricsFlags(const Json::Value&) {
- std::vector<std::string> result;
- result.emplace_back(GenerateReportFlag());
- return result;
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/cvd/parser/instance/cf_security_configs.cpp b/host/commands/cvd/parser/instance/cf_security_configs.cpp
index f2bc19c..7e2a78a 100644
--- a/host/commands/cvd/parser/instance/cf_security_configs.cpp
+++ b/host/commands/cvd/parser/instance/cf_security_configs.cpp
@@ -26,29 +26,13 @@
namespace cuttlefish {
-/*
-This function is created to cover the initiation use_random_serial flag
-when the json value of serial_number equal "@random"
-*/
-void InitRandomSerialNumber(Json::Value& instance) {
- std::string serial_number_str =
- instance["security"]["serial_number"].asString();
- if (serial_number_str == "@random") {
- instance["security"]["use_random_serial"] = true;
- } else {
- instance["security"]["use_random_serial"] = false;
- }
-}
-
Result<void> InitSecurityConfigs(Json::Value& instances) {
- const int size = instances.size();
- for (int i = 0; i < size; i++) {
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_SERIAL_NUMBER,
+ for (auto& instance : instances) {
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_SERIAL_NUMBER,
{"security", "serial_number"}));
- // This init should be called after the InitSecurityConfigs call, since it
- // depends on serial_number flag
- InitRandomSerialNumber(instances[i]);
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_GUEST_ENFORCE_SECURITY,
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_USE_RANDOM_SERIAL,
+ {"security", "use_random_serial"}));
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_GUEST_ENFORCE_SECURITY,
{"security", "guest_enforce_security"}));
}
return {};
@@ -57,12 +41,10 @@
Result<std::vector<std::string>> GenerateSecurityFlags(
const Json::Value& instances) {
std::vector<std::string> result;
- if (!GENERATE_MVP_FLAGS_ONLY) {
- result.emplace_back(CF_EXPECT(GenerateGflag(
- instances, "serial_number", {"security", "serial_number"})));
- result.emplace_back(CF_EXPECT(GenerateGflag(
- instances, "use_random_serial", {"security", "use_random_serial"})));
- }
+ result.emplace_back(CF_EXPECT(GenerateGflag(instances, "serial_number",
+ {"security", "serial_number"})));
+ result.emplace_back(CF_EXPECT(GenerateGflag(
+ instances, "use_random_serial", {"security", "use_random_serial"})));
result.emplace_back(
CF_EXPECT(GenerateGflag(instances, "guest_enforce_security",
{"security", "guest_enforce_security"})));
diff --git a/host/commands/cvd/parser/instance/cf_vm_configs.cpp b/host/commands/cvd/parser/instance/cf_vm_configs.cpp
index 1064a57..44bc990 100644
--- a/host/commands/cvd/parser/instance/cf_vm_configs.cpp
+++ b/host/commands/cvd/parser/instance/cf_vm_configs.cpp
@@ -28,38 +28,37 @@
#define UI_DEFAULTS_MEMORY_MB 2048
namespace cuttlefish {
+namespace {
-void InitVmManagerConfig(Json::Value& instance) {
- if (instance.isMember("vm")) {
- if (instance["vm"].isMember("crosvm")) {
- instance["vm"]["vm_manager"] = "crosvm";
- } else if (instance["vm"].isMember("qemu")) {
- instance["vm"]["vm_manager"] = "qemu_cli";
- } else if (instance["vm"].isMember("gem5")) {
- instance["vm"]["vm_manager"] = "gem5";
- } else {
- // Set vm manager to default value (crosvm)
- instance["vm"]["vm_manager"] = "crosvm";
- }
+std::string GetVmManagerDefault(Json::Value& instance_vm) {
+ if (instance_vm.isNull()) {
+ return "crosvm";
+ }
+ if (instance_vm.isMember("crosvm")) {
+ return "crosvm";
+ } else if (instance_vm.isMember("qemu")) {
+ return "qemu_cli";
+ } else if (instance_vm.isMember("gem5")) {
+ return "gem5";
} else {
- // vm object doesn't exist, set the default vm manager to crosvm
- instance["vm"]["vm_manager"] = "crosvm";
+ return "crosvm";
}
}
+} // namespace
+
Result<void> InitVmConfigs(Json::Value& instances) {
- const int size = instances.size();
- for (int i = 0; i < size; i++) {
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_CPUS, {"vm", "cpus"}));
+ for (auto& instance : instances) {
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_CPUS, {"vm", "cpus"}));
+ CF_EXPECT(InitConfig(instance, UI_DEFAULTS_MEMORY_MB, {"vm", "memory_mb"}));
CF_EXPECT(
- InitConfig(instances[i], UI_DEFAULTS_MEMORY_MB, {"vm", "memory_mb"}));
- CF_EXPECT(
- InitConfig(instances[i], CF_DEFAULTS_USE_SDCARD, {"vm", "use_sdcard"}));
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_SETUPWIZARD_MODE,
+ InitConfig(instance, CF_DEFAULTS_USE_SDCARD, {"vm", "use_sdcard"}));
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_SETUPWIZARD_MODE,
{"vm", "setupwizard_mode"}));
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_UUID, {"vm", "uuid"}));
- InitVmManagerConfig(instances[i]);
- CF_EXPECT(InitConfig(instances[i], CF_DEFAULTS_ENABLE_SANDBOX,
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_UUID, {"vm", "uuid"}));
+ CF_EXPECT(InitConfig(instance, GetVmManagerDefault(instance["vm"]),
+ {"vm", "vm_manager"}));
+ CF_EXPECT(InitConfig(instance, CF_DEFAULTS_ENABLE_SANDBOX,
{"vm", "crosvm", "enable_sandbox"}));
}
return {};
@@ -68,13 +67,11 @@
std::vector<std::string> GenerateCustomConfigsFlags(
const Json::Value& instances) {
std::vector<std::string> result;
- const int size = instances.size();
- for (int i = 0; i < size; i++) {
- if (instances[i].isMember("vm") &&
- instances[i]["vm"].isMember("custom_actions")) {
+ for (auto& instance : instances) {
+ if (instance.isMember("vm") && instance["vm"].isMember("custom_actions")) {
Json::StreamWriterBuilder factory;
std::string mapped_text =
- Json::writeString(factory, instances[i]["vm"]["custom_actions"]);
+ Json::writeString(factory, instance["vm"]["custom_actions"]);
// format json string string to match aosp/2374890 input format
mapped_text = android::base::StringReplace(mapped_text, "\n", "", true);
mapped_text = android::base::StringReplace(mapped_text, "\r", "", true);
@@ -103,10 +100,8 @@
CF_EXPECT(GenerateGflag(instances, "vm_manager", {"vm", "vm_manager"})));
result.emplace_back(CF_EXPECT(GenerateGflag(instances, "setupwizard_mode",
{"vm", "setupwizard_mode"})));
- if (!GENERATE_MVP_FLAGS_ONLY) {
- result.emplace_back(
- CF_EXPECT(GenerateGflag(instances, "uuid", {"vm", "uuid"})));
- }
+ result.emplace_back(
+ CF_EXPECT(GenerateGflag(instances, "uuid", {"vm", "uuid"})));
result.emplace_back(CF_EXPECT(GenerateGflag(
instances, "enable_sandbox", {"vm", "crosvm", "enable_sandbox"})));
diff --git a/host/commands/cvd/parser/launch_cvd_parser.cpp b/host/commands/cvd/parser/launch_cvd_parser.cpp
index 9c18b0c..f65fd5a 100644
--- a/host/commands/cvd/parser/launch_cvd_parser.cpp
+++ b/host/commands/cvd/parser/launch_cvd_parser.cpp
@@ -13,60 +13,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "host/commands/cvd/parser/launch_cvd_parser.h"
-#include <android-base/file.h>
-#include <gflags/gflags.h>
-
-#include <stdio.h>
-#include <fstream>
#include <string>
+#include <vector>
-#include "common/libs/utils/files.h"
+#include <json/json.h>
+
#include "common/libs/utils/json.h"
#include "common/libs/utils/result.h"
#include "host/commands/assemble_cvd/flags_defaults.h"
#include "host/commands/cvd/parser/cf_configs_common.h"
#include "host/commands/cvd/parser/cf_configs_instances.h"
-#include "host/commands/cvd/parser/launch_cvd_parser.h"
+#include "host/commands/cvd/parser/cf_metrics_configs.h"
#include "host/commands/cvd/parser/launch_cvd_templates.h"
namespace cuttlefish {
-
-std::string GenerateNumInstancesFlag(const Json::Value& root) {
- int num_instances = root["instances"].size();
- LOG(DEBUG) << "num_instances = " << num_instances;
- std::string result = "--num_instances=" + std::to_string(num_instances);
- return result;
-}
-
-std::string GenerateCommonGflag(const Json::Value& root,
- const std::string& gflag_name,
- const std::string& json_flag) {
- std::stringstream buff;
- // Append Header
- buff << "--" << gflag_name << "=" << root[json_flag].asString();
- return buff.str();
-}
+namespace {
Result<std::vector<std::string>> GenerateCfFlags(const Json::Value& root) {
std::vector<std::string> result;
- result.emplace_back(GenerateNumInstancesFlag(root));
- result.emplace_back(GenerateCommonGflag(root, "netsim_bt", "netsim_bt"));
-
+ result.emplace_back(GenerateGflag(
+ "num_instances", {std::to_string(root["instances"].size())}));
+ result.emplace_back(GenerateGflag(
+ "netsim_bt", {CF_EXPECT(GetValue<std::string>(root, {"netsim_bt"}))}));
+ result = MergeResults(result, CF_EXPECT(GenerateMetricsFlags(root)));
result = MergeResults(result,
CF_EXPECT(GenerateInstancesFlags(root["instances"])));
return result;
}
Result<void> InitCvdConfigs(Json::Value& root) {
- // Handle common flags
- if (!root.isMember("netsim_bt")) {
- root["netsim_bt"] = CF_DEFAULTS_NETSIM_BT;
- }
+ CF_EXPECT(InitConfig(root, CF_DEFAULTS_NETSIM_BT, {"netsim_bt"}));
+ CF_EXPECT(InitMetricsConfigs(root));
CF_EXPECT(InitInstancesConfigs(root["instances"]));
return {};
}
+} // namespace
+
Result<std::vector<std::string>> ParseLaunchCvdConfigs(Json::Value& root) {
ExtractLaunchTemplates(root["instances"]);
CF_EXPECT(InitCvdConfigs(root));
diff --git a/host/commands/cvd/parser/load_configs_parser.cpp b/host/commands/cvd/parser/load_configs_parser.cpp
index 1aac010..8faa46c 100644
--- a/host/commands/cvd/parser/load_configs_parser.cpp
+++ b/host/commands/cvd/parser/load_configs_parser.cpp
@@ -16,21 +16,142 @@
#include "host/commands/cvd/parser/load_configs_parser.h"
-#include <android-base/file.h>
-#include <gflags/gflags.h>
+#include <unistd.h>
-#include <stdio.h>
+#include <chrono>
+#include <cstdio>
#include <fstream>
#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <json/json.h>
#include "common/libs/utils/files.h"
#include "common/libs/utils/json.h"
#include "common/libs/utils/result.h"
+#include "host/commands/cvd/parser/cf_configs_common.h"
#include "host/commands/cvd/parser/cf_flags_validator.h"
#include "host/commands/cvd/parser/fetch_cvd_parser.h"
#include "host/commands/cvd/parser/launch_cvd_parser.h"
namespace cuttlefish {
+namespace {
+
+Result<void> ValidateArgFormat(const std::string& str) {
+ auto equalsPos = str.find('=');
+ CF_EXPECT(equalsPos != std::string::npos,
+ "equal value is not provided in the argument");
+ std::string prefix = str.substr(0, equalsPos);
+ CF_EXPECT(!prefix.empty(), "argument value should not be empty");
+ CF_EXPECT(prefix.find('.') != std::string::npos,
+ "argument value must be dot separated");
+ CF_EXPECT(prefix[0] != '.', "argument value should not start with a dot");
+ CF_EXPECT(prefix.find("..") == std::string::npos,
+ "argument value should not contain two consecutive dots");
+ CF_EXPECT(prefix.back() != '.', "argument value should not end with a dot");
+ return {};
+}
+
+Result<void> ValidateArgsFormat(const std::vector<std::string>& strings) {
+ for (const auto& str : strings) {
+ CF_EXPECT(ValidateArgFormat(str),
+ "Invalid argument format. " << str << " Please use arg=value");
+ }
+ return {};
+}
+
+// TODO(moelsherif): expand this enum in the future to support more types (
+// double , float , etc) if neeeded
+enum ArgValueType { UINTEGER, BOOLEAN, TEXT };
+
+bool IsUnsignedInteger(const std::string& str) {
+ return !str.empty() && std::all_of(str.begin(), str.end(),
+ [](char c) { return std::isdigit(c); });
+}
+
+ArgValueType GetArgValueType(const std::string& str) {
+ if (IsUnsignedInteger(str)) {
+ return UINTEGER;
+ }
+
+ if (str == "true" || str == "false") {
+ return BOOLEAN;
+ }
+
+ // Otherwise, treat the string as text
+ return TEXT;
+}
+
+Json::Value ConvertArgToJson(const std::string& key,
+ const std::string& leafValue) {
+ std::stack<std::string> levels;
+ std::stringstream ks(key);
+ std::string token;
+ while (std::getline(ks, token, '.')) {
+ levels.push(token);
+ }
+
+ // assign the leaf value based on the type of input value
+ Json::Value leaf;
+ if (GetArgValueType(leafValue) == UINTEGER) {
+ std::uint32_t leaf_val{};
+ if (!android::base::ParseUint(leafValue, &leaf_val)) {
+ LOG(ERROR) << "Failed to parse unsigned integer " << leafValue;
+ return Json::Value::null;
+ };
+ leaf = leaf_val;
+ } else if (GetArgValueType(leafValue) == BOOLEAN) {
+ leaf = (leafValue == "true");
+ } else {
+ leaf = leafValue;
+ }
+
+ while (!levels.empty()) {
+ Json::Value curr;
+ std::string index = levels.top();
+
+ if (GetArgValueType(index) == UINTEGER) {
+ std::uint32_t index_val{};
+ if (!android::base::ParseUint(index, &index_val)) {
+ LOG(ERROR) << "Failed to parse unsigned integer " << index;
+ return Json::Value::null;
+ }
+ curr[index_val] = leaf;
+ } else {
+ curr[index] = leaf;
+ }
+
+ leaf = curr;
+ levels.pop();
+ }
+
+ return leaf;
+}
+
+Json::Value ParseArgsToJson(const std::vector<std::string>& strings) {
+ Json::Value jsonValue;
+ for (const auto& str : strings) {
+ std::string key;
+ std::string value;
+ size_t equals_pos = str.find('=');
+ if (equals_pos != std::string::npos) {
+ key = str.substr(0, equals_pos);
+ value = str.substr(equals_pos + 1);
+ } else {
+ key = str;
+ value.clear();
+ LOG(WARNING) << "No value provided for key " << key;
+ return Json::Value::null;
+ }
+ MergeTwoJsonObjs(jsonValue, ConvertArgToJson(key, value));
+ }
+ return jsonValue;
+}
+
+} // namespace
Result<Json::Value> ParseJsonFile(const std::string& file_path) {
CF_EXPECT(FileExists(file_path), "provided File to cvd load does not exist");
@@ -44,10 +165,56 @@
return root;
}
-Result<CvdFlags> ParseCvdConfigs(Json::Value& root) {
+Result<Json::Value> GetOverridedJsonConfig(
+ const std::string& config_path,
+ const std::vector<std::string>& override_flags) {
+ Json::Value result = CF_EXPECT(ParseJsonFile(config_path),
+ "Parsing json config input file failed");
+
+ if (override_flags.size() > 0) {
+ CF_EXPECT(ValidateArgsFormat(override_flags),
+ "override parameters are not in the correct format");
+ auto args_tree = ParseArgsToJson(override_flags);
+ MergeTwoJsonObjs(result, args_tree);
+ }
+
+ return result;
+}
+
+Result<LoadDirectories> GenerateLoadDirectories(const int num_instances) {
+ CF_EXPECT_GT(num_instances, 0, "No instances in config to load");
+
+ auto parent_directory = "/tmp/cvd/" + std::to_string(getuid()) + "/";
+ auto time = std::chrono::system_clock::now().time_since_epoch().count();
+ auto result = LoadDirectories{
+ .target_directory = parent_directory + std::to_string(time),
+ .launch_home_directory =
+ parent_directory + std::to_string(time) + "_home/"};
+
+ std::vector<std::string> system_image_directories;
+ for (int i = 0; i < num_instances; i++) {
+ LOG(INFO) << "Instance " << i << " directory is " << result.target_directory
+ << "/" << std::to_string(i);
+ auto target_subdirectory = std::to_string(i);
+ result.target_subdirectories.emplace_back(target_subdirectory);
+ system_image_directories.emplace_back(result.target_directory + "/" +
+ target_subdirectory);
+ }
+ result.first_instance_directory =
+ result.target_directory + "/" + result.target_subdirectories[0];
+ result.system_image_directory_flag =
+ "--system_image_dir=" +
+ android::base::Join(system_image_directories, ',');
+ return result;
+}
+
+Result<CvdFlags> ParseCvdConfigs(Json::Value& root,
+ const LoadDirectories& load_directories) {
CF_EXPECT(ValidateCfConfigs(root), "Loaded Json validation failed");
return CvdFlags{.launch_cvd_flags = CF_EXPECT(ParseLaunchCvdConfigs(root)),
- .fetch_cvd_flags = CF_EXPECT(ParseFetchCvdConfigs(root))};
+ .fetch_cvd_flags = CF_EXPECT(ParseFetchCvdConfigs(
+ root, load_directories.target_directory,
+ load_directories.target_subdirectories))};
}
} // namespace cuttlefish
diff --git a/host/commands/cvd/parser/load_configs_parser.h b/host/commands/cvd/parser/load_configs_parser.h
index caf271a..bcbec10 100644
--- a/host/commands/cvd/parser/load_configs_parser.h
+++ b/host/commands/cvd/parser/load_configs_parser.h
@@ -28,11 +28,26 @@
typedef struct _CvdFlags {
std::vector<std::string> launch_cvd_flags;
- FetchCvdConfig fetch_cvd_flags;
+ std::vector<std::string> fetch_cvd_flags;
} CvdFlags;
+struct LoadDirectories {
+ std::string target_directory;
+ std::vector<std::string> target_subdirectories;
+ std::string launch_home_directory;
+ std::string first_instance_directory;
+ std::string system_image_directory_flag;
+};
+
Result<Json::Value> ParseJsonFile(const std::string& file_path);
-Result<CvdFlags> ParseCvdConfigs(Json::Value& root);
+Result<Json::Value> GetOverridedJsonConfig(
+ const std::string& config_path,
+ const std::vector<std::string>& override_flags);
+
+Result<LoadDirectories> GenerateLoadDirectories(const int num_instances);
+
+Result<CvdFlags> ParseCvdConfigs(Json::Value& root,
+ const LoadDirectories& load_directories);
}; // namespace cuttlefish
diff --git a/host/commands/cvd/selector/creation_analyzer.cpp b/host/commands/cvd/selector/creation_analyzer.cpp
index 19b407e..16c773e 100644
--- a/host/commands/cvd/selector/creation_analyzer.cpp
+++ b/host/commands/cvd/selector/creation_analyzer.cpp
@@ -42,7 +42,7 @@
if (cmd.empty()) {
return false;
}
- return cmd == "start";
+ return cmd == "start" || cmd == "launch_cvd";
}
Result<GroupCreationInfo> CreationAnalyzer::Analyze(
diff --git a/host/commands/cvd/selector/start_selector_parser.cpp b/host/commands/cvd/selector/start_selector_parser.cpp
index 4a6e6ad..d7de75f 100644
--- a/host/commands/cvd/selector/start_selector_parser.cpp
+++ b/host/commands/cvd/selector/start_selector_parser.cpp
@@ -125,19 +125,6 @@
return parsed.ok() ? std::optional(*parsed) : std::nullopt;
}
-std::optional<unsigned> TryFromUser(const cvd_common::Envs& envs) {
- if (!Contains(envs, "USER")) {
- return std::nullopt;
- }
- std::string_view user{envs.at("USER")};
- if (user.empty() || !android::base::ConsumePrefix(&user, kVsocUserPrefix)) {
- return std::nullopt;
- }
- const auto& vsoc_num = user;
- auto vsoc_id = ParseNaturalNumber(vsoc_num.data());
- return vsoc_id.ok() ? std::optional(*vsoc_id) : std::nullopt;
-}
-
} // namespace
std::optional<std::vector<unsigned>>
@@ -441,8 +428,7 @@
.num_instances = std::move(num_instances),
.instance_nums = std::move(instance_nums),
.base_instance_num = std::move(base_instance_num),
- .cuttlefish_instance_env = TryFromCuttlefishInstance(envs_),
- .vsoc_suffix = TryFromUser(envs_)};
+ .cuttlefish_instance_env = TryFromCuttlefishInstance(envs_)};
auto parsed_ids = CF_EXPECT(HandleInstanceIds(instance_nums_param));
requested_num_instances_ = parsed_ids.GetNumOfInstances();
instance_ids_ = std::move(parsed_ids.GetInstanceIds());
diff --git a/host/commands/cvd/server.cc b/host/commands/cvd/server.cc
index 4619364..95db580 100644
--- a/host/commands/cvd/server.cc
+++ b/host/commands/cvd/server.cc
@@ -58,10 +58,9 @@
#include "host/commands/cvd/server_command/load_configs.h"
#include "host/commands/cvd/server_command/power.h"
#include "host/commands/cvd/server_command/reset.h"
+#include "host/commands/cvd/server_command/snapshot.h"
#include "host/commands/cvd/server_command/start.h"
#include "host/commands/cvd/server_command/subcmd.h"
-#include "host/commands/cvd/server_command/suspend_resume.h"
-#include "host/commands/cvd/server_command/vm_control.h"
#include "host/commands/cvd/server_constants.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/inject.h"
@@ -128,11 +127,10 @@
.install(CvdHelpComponent)
.install(CvdResetComponent)
.install(CvdRestartComponent)
+ .install(CvdSnapshotComponent)
.install(cvdShutdownComponent)
.install(CvdStartCommandComponent)
- .install(CvdSuspendResumeComponent)
.install(cvdVersionComponent)
- .install(CvdVmControlComponent)
.install(DemoMultiVdComponent)
.install(LoadConfigsComponent);
}
diff --git a/host/commands/cvd/server_command/Android.bp b/host/commands/cvd/server_command/Android.bp
index 0fd5927..6fd426b 100644
--- a/host/commands/cvd/server_command/Android.bp
+++ b/host/commands/cvd/server_command/Android.bp
@@ -45,13 +45,12 @@
"serial_launch.cpp",
"serial_preset.cpp",
"shutdown.cpp",
+ "snapshot.cpp",
"start.cpp",
"start_impl.cpp",
"subprocess_waiter.cpp",
- "suspend_resume.cpp",
"try_acloud.cpp",
"version.cpp",
- "vm_control.cpp",
],
static_libs: [
"libcvd_acloud",
diff --git a/host/commands/cvd/server_command/acloud_mixsuperimage.cpp b/host/commands/cvd/server_command/acloud_mixsuperimage.cpp
index c3d3138..25d45c2 100644
--- a/host/commands/cvd/server_command/acloud_mixsuperimage.cpp
+++ b/host/commands/cvd/server_command/acloud_mixsuperimage.cpp
@@ -48,6 +48,8 @@
const std::string _TARGET_FILES_META_DIR_NAME = "META";
const std::string _TARGET_FILES_IMAGES_DIR_NAME = "IMAGES";
const std::string _SYSTEM_IMAGE_NAME_PATTERN = "system.img";
+const std::string _SYSTEM_EXT_IMAGE_NAME_PATTERN = "system_ext.img";
+const std::string _PRODUCT_IMAGE_NAME_PATTERN = "product.img";
/*
* Find misc info in build output dir or extracted target files.
@@ -289,14 +291,20 @@
system_image_path = FindImage(local_system_image, {_SYSTEM_IMAGE_NAME_PATTERN});
CF_EXPECT(system_image_path != "",
"Cannot find system.img in " << local_system_image);
+ std::string system_ext_image_path =
+ FindImage(local_system_image, {_SYSTEM_EXT_IMAGE_NAME_PATTERN});
+ std::string product_image_path =
+ FindImage(local_system_image, {_PRODUCT_IMAGE_NAME_PATTERN});
return BuildSuperImage(
super_image, misc_info, callback_unlock,
- [&image_dir,
- &system_image_path](const std::string& partition) -> Result<std::string> {
- return GetImageForPartition(
- partition, image_dir,
- {{"system", system_image_path}});
+ [&](const std::string& partition) -> Result<std::string> {
+ return GetImageForPartition(partition, image_dir,
+ {
+ {"system", system_image_path},
+ {"system_ext", system_ext_image_path},
+ {"product", product_image_path},
+ });
});
}
diff --git a/host/commands/cvd/server_command/host_tool_target.cpp b/host/commands/cvd/server_command/host_tool_target.cpp
index 91fb3de..8afc317 100644
--- a/host/commands/cvd/server_command/host_tool_target.cpp
+++ b/host/commands/cvd/server_command/host_tool_target.cpp
@@ -41,6 +41,7 @@
{"powerwash", {"powerwash_cvd"}},
{"suspend", {"snapshot_util_cvd"}},
{"resume", {"snapshot_util_cvd"}},
+ {"snapshot_take", {"snapshot_util_cvd"}},
};
return map;
}
diff --git a/host/commands/cvd/server_command/load_configs.cpp b/host/commands/cvd/server_command/load_configs.cpp
index b84e1b4..5d3821d 100644
--- a/host/commands/cvd/server_command/load_configs.cpp
+++ b/host/commands/cvd/server_command/load_configs.cpp
@@ -15,15 +15,12 @@
*/
#include "host/commands/cvd/server_command/load_configs.h"
-#include <chrono>
#include <iostream>
#include <mutex>
-#include <optional>
#include <sstream>
#include <string>
#include <vector>
-#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <fruit/fruit.h>
#include <json/json.h>
@@ -33,8 +30,6 @@
#include "common/libs/utils/result.h"
#include "host/commands/cvd/command_sequence.h"
#include "host/commands/cvd/common_utils.h"
-#include "host/commands/cvd/parser/cf_configs_common.h"
-#include "host/commands/cvd/parser/fetch_cvd_parser.h"
#include "host/commands/cvd/parser/load_configs_parser.h"
#include "host/commands/cvd/selector/selector_constants.h"
#include "host/commands/cvd/server_client.h"
@@ -42,131 +37,6 @@
#include "host/commands/cvd/types.h"
namespace cuttlefish {
-namespace {
-
-std::string JoinBySelector(
- const std::vector<FetchCvdInstanceConfig>& collection,
- const std::function<std::string(const FetchCvdInstanceConfig&)>& selector) {
- std::vector<std::string> selected;
- selected.reserve(collection.size());
- for (const auto& instance : collection) {
- selected.emplace_back(selector(instance));
- }
- return android::base::Join(selected, ',');
-}
-
-std::optional<std::string> JoinBySelectorOptional(
- const std::vector<FetchCvdInstanceConfig>& collection,
- const std::function<std::string(const FetchCvdInstanceConfig&)>& selector) {
- std::string result = JoinBySelector(collection, selector);
- // no values, empty or only ',' separators
- if (result.size() == collection.size() - 1) {
- return std::nullopt;
- }
- return result;
-}
-
-std::string GenerateSystemImageFlag(const FetchCvdConfig& config) {
- auto get_full_path = [&target_directory = config.target_directory](
- const FetchCvdInstanceConfig& instance_config) {
- return target_directory + "/" + instance_config.target_subdirectory;
- };
- return "--system_image_dir=" +
- JoinBySelector(config.instances, get_full_path);
-}
-
-std::string GenerateParentDirectory() {
- const uid_t uid = getuid();
- // Prefix for the parent directory.
- constexpr char kParentDirPrefix[] = "/tmp/cvd/";
- std::stringstream ss;
-
- // Constructs the full directory path.
- ss << kParentDirPrefix << uid << "/";
-
- return ss.str();
-}
-
-std::string GenerateHostArtifactsDirectory(int64_t time) {
- return GenerateParentDirectory() + std::to_string(time);
-}
-
-std::string GenerateHomeDirectoryName(int64_t time) {
- return GenerateParentDirectory() + std::to_string(time) + "_home/";
-}
-
-using DemoCommandSequence = std::vector<RequestWithStdio>;
-
-void AddFetchCommandArgs(
- cvd::CommandRequest& command, const FetchCvdConfig& config,
- const std::vector<FetchCvdInstanceConfig>& fetch_instances) {
- command.add_args("cvd");
- command.add_args("fetch");
- command.add_args("--target_directory=" + config.target_directory);
- if (config.api_key) {
- command.add_args("--api_key=" + *config.api_key);
- }
- if (config.credential_source) {
- command.add_args("--credential_source=" + *config.credential_source);
- }
- if (config.wait_retry_period) {
- command.add_args("--wait_retry_period=" + *config.wait_retry_period);
- }
- if (config.external_dns_resolver) {
- command.add_args("--external_dns_resolver=" +
- *config.external_dns_resolver);
- }
- if (config.keep_downloaded_archives) {
- command.add_args("--keep_downloaded_archives=" +
- *config.keep_downloaded_archives);
- }
-
- command.add_args(
- "--target_subdirectory=" +
- JoinBySelector(fetch_instances,
- [](const FetchCvdInstanceConfig& instance_config) {
- return instance_config.target_subdirectory;
- }));
- std::optional<std::string> default_build_params = JoinBySelectorOptional(
- fetch_instances, [](const FetchCvdInstanceConfig& instance_config) {
- return instance_config.default_build.value_or("");
- });
- if (default_build_params) {
- command.add_args("--default_build=" + *default_build_params);
- }
- std::optional<std::string> system_build_params = JoinBySelectorOptional(
- fetch_instances, [](const FetchCvdInstanceConfig& instance_config) {
- return instance_config.system_build.value_or("");
- });
- if (system_build_params) {
- command.add_args("--system_build=" + *system_build_params);
- }
- std::optional<std::string> kernel_build_params = JoinBySelectorOptional(
- fetch_instances, [](const FetchCvdInstanceConfig& instance_config) {
- return instance_config.kernel_build.value_or("");
- });
- if (kernel_build_params) {
- command.add_args("--kernel_build=" + *kernel_build_params);
- }
- std::optional<std::string> download_img_zip_params = JoinBySelectorOptional(
- fetch_instances, [](const FetchCvdInstanceConfig& instance_config) {
- return instance_config.download_img_zip.value_or("");
- });
- if (download_img_zip_params) {
- command.add_args("--download_img_zip=" + *download_img_zip_params);
- }
- std::optional<std::string> download_target_files_zip_params =
- JoinBySelectorOptional(
- fetch_instances, [](const FetchCvdInstanceConfig& instance_config) {
- return instance_config.download_target_files_zip.value_or("");
- });
- if (download_target_files_zip_params) {
- command.add_args("--download_target_files_zip=" +
- *download_target_files_zip_params);
- }
-}
-
-} // namespace
class LoadConfigsCommand : public CvdServerHandler {
public:
@@ -192,6 +62,7 @@
response.mutable_command_response();
return response;
}
+
Result<void> Interrupt() override {
std::scoped_lock interrupt_lock(interrupt_mutex_);
interrupted_ = true;
@@ -201,119 +72,7 @@
cvd_common::Args CmdList() const override { return {kLoadSubCmd}; }
- // TODO(moelsherif): expand this enum in the future to support more types ( double , float
- // , etc) if neeeded
- enum ArgValueType { UINTEGER, BOOLEAN, TEXT };
-
- bool IsUnsignedInteger(const std::string& str) {
- return !str.empty() && std::all_of(str.begin(), str.end(),
- [](char c) { return std::isdigit(c); });
- }
-
- ArgValueType GetArgValueType(const std::string& str) {
- if (IsUnsignedInteger(str)) {
- return UINTEGER;
- }
-
- if (str == "true" || str == "false") {
- return BOOLEAN;
- }
-
- // Otherwise, treat the string as text
- return TEXT;
- }
-
- Json::Value ConvertArgToJson(const std::string& key,
- const std::string& leafValue) {
- std::stack<std::string> levels;
- std::stringstream ks(key);
- std::string token;
- while (std::getline(ks, token, '.')) {
- levels.push(token);
- }
-
- // assign the leaf value based on the type of input value
- Json::Value leaf;
- if (GetArgValueType(leafValue) == UINTEGER) {
- std::uint32_t leaf_val{};
- if (!android::base::ParseUint(leafValue ,&leaf_val)){
- LOG(ERROR) << "Failed to parse unsigned integer " << leafValue;
- return Json::Value::null;
- };
- leaf = leaf_val;
- } else if (GetArgValueType(leafValue) == BOOLEAN) {
- leaf = (leafValue == "true");
- } else {
- leaf = leafValue;
- }
-
- while (!levels.empty()) {
- Json::Value curr;
- std::string index = levels.top();
-
- if (GetArgValueType(index) == UINTEGER) {
- std::uint32_t index_val{};
- if (!android::base::ParseUint(index, &index_val)){
- LOG(ERROR) << "Failed to parse unsigned integer " << index;
- return Json::Value::null;
- }
- curr[index_val] = leaf;
- } else {
- curr[index] = leaf;
- }
-
- leaf = curr;
- levels.pop();
- }
-
- return leaf;
- }
-
- Json::Value ParseArgsToJson(const std::vector<std::string>& strings) {
- Json::Value jsonValue;
- for (const auto& str : strings) {
- std::string key;
- std::string value;
- size_t equals_pos = str.find('=');
- if (equals_pos != std::string::npos) {
- key = str.substr(0, equals_pos);
- value = str.substr(equals_pos + 1);
- } else {
- key = str;
- value.clear();
- LOG(WARNING) << "No value provided for key " << key;
- return Json::Value::null;
- }
- MergeTwoJsonObjs(jsonValue, ConvertArgToJson(key, value));
- }
-
- return jsonValue;
- }
-
- Result<void> ValidateArgFormat(const std::string& str) {
- auto equalsPos = str.find('=');
- CF_EXPECT(equalsPos != std::string::npos,
- "equal value is not provided in the argument");
- std::string prefix = str.substr(0, equalsPos);
- CF_EXPECT(!prefix.empty(), "argument value should not be empty");
- CF_EXPECT(prefix.find('.') != std::string::npos,
- "argument value must be dot separated");
- CF_EXPECT(prefix[0] != '.', "argument value should not start with a dot");
- CF_EXPECT(prefix.find("..") == std::string::npos,
- "argument value should not contain two consecutive dots");
- CF_EXPECT(prefix.back() != '.', "argument value should not end with a dot");
- return {};
- }
-
- Result<void> ValidateArgsFormat(const std::vector<std::string>& strings) {
- for (const auto& str : strings) {
- CF_EXPECT(ValidateArgFormat(str),
- "Invalid argument format. " << str << " Please use arg=value");
- }
- return {};
- }
-
- Result<DemoCommandSequence> CreateCommandSequence(
+ Result<std::vector<RequestWithStdio>> CreateCommandSequence(
const RequestWithStdio& request) {
bool help = false;
@@ -321,10 +80,10 @@
flags.emplace_back(GflagsCompatFlag("help", help));
std::vector<std::string> overrides;
FlagAlias alias = {FlagAliasMode::kFlagPrefix, "--override="};
- flags.emplace_back(
- Flag().Alias(alias).Setter([&overrides](const FlagMatch& m) {
+ flags.emplace_back(Flag().Alias(alias).Setter(
+ [&overrides](const FlagMatch& m) -> Result<void> {
overrides.push_back(m.value);
- return true;
+ return {};
}));
auto args = ParseInvocation(request.Message()).arguments;
CF_EXPECT(ParseFlags(flags, args));
@@ -340,82 +99,46 @@
return {};
}
- // Extract the config_path from the arguments
std::string config_path = args.front();
- Json::Value json_configs =
- CF_EXPECT(ParseJsonFile(config_path), "parsing input file failed");
-
- // remove the config_path from the arguments
- args.erase(args.begin());
-
- // Handle the rest of the arguments (Overrides)
- if (overrides.size() > 0) {
- // Validate all arguments follow specific pattern
- CF_EXPECT(ValidateArgsFormat(overrides),
- "override parameters are not in the correct format");
-
- // Convert all arguments to json tree
- auto args_tree = ParseArgsToJson(overrides);
- MergeTwoJsonObjs(json_configs, args_tree);
+ if (config_path[0] != '/') {
+ config_path = request.Message().command_request().working_directory() +
+ "/" + config_path;
}
-
- auto cvd_flags =
- CF_EXPECT(ParseCvdConfigs(json_configs), "parsing json configs failed");
-
- int num_instances = cvd_flags.fetch_cvd_flags.instances.size();
- CF_EXPECT_GT(num_instances, 0, "No instances to load");
-
+ Json::Value json_configs =
+ CF_EXPECT(GetOverridedJsonConfig(config_path, overrides));
+ const auto load_directories =
+ CF_EXPECT(GenerateLoadDirectories(json_configs["instances"].size()));
+ auto cvd_flags = CF_EXPECT(ParseCvdConfigs(json_configs, load_directories),
+ "parsing json configs failed");
std::vector<cvd::Request> req_protos;
-
const auto& client_env = request.Message().command_request().env();
- auto time = std::chrono::system_clock::now().time_since_epoch().count();
- cvd_flags.fetch_cvd_flags.target_directory =
- GenerateHostArtifactsDirectory(time);
- for (int instance_index = 0; instance_index < num_instances;
- instance_index++) {
- LOG(INFO) << "Instance " << instance_index << " directory is "
- << cvd_flags.fetch_cvd_flags.target_directory << "/"
- << std::to_string(instance_index);
- cvd_flags.fetch_cvd_flags.instances[instance_index].target_subdirectory =
- std::to_string(instance_index);
- }
-
- std::vector<FetchCvdInstanceConfig> fetch_instances;
- for (const auto& instance : cvd_flags.fetch_cvd_flags.instances) {
- if (instance.should_fetch) {
- fetch_instances.emplace_back(instance);
- }
- }
- if (fetch_instances.size() > 0) {
+ if (!cvd_flags.fetch_cvd_flags.empty()) {
auto& fetch_cmd = *req_protos.emplace_back().mutable_command_request();
*fetch_cmd.mutable_env() = client_env;
- AddFetchCommandArgs(fetch_cmd, cvd_flags.fetch_cvd_flags,
- fetch_instances);
+ fetch_cmd.add_args("cvd");
+ fetch_cmd.add_args("fetch");
+ for (const auto& flag : cvd_flags.fetch_cvd_flags) {
+ fetch_cmd.add_args(flag);
+ }
}
- // Create the launch home directory
- std::string launch_home_dir = GenerateHomeDirectoryName(time);
auto& mkdir_cmd = *req_protos.emplace_back().mutable_command_request();
*mkdir_cmd.mutable_env() = client_env;
mkdir_cmd.add_args("cvd");
mkdir_cmd.add_args("mkdir");
mkdir_cmd.add_args("-p");
- mkdir_cmd.add_args(launch_home_dir);
+ mkdir_cmd.add_args(load_directories.launch_home_directory);
- // Handle the launch command
auto& launch_cmd = *req_protos.emplace_back().mutable_command_request();
-
- auto first_instance_dir =
- cvd_flags.fetch_cvd_flags.target_directory + "/" +
- cvd_flags.fetch_cvd_flags.instances[0].target_subdirectory;
+ launch_cmd.set_working_directory(load_directories.first_instance_directory);
*launch_cmd.mutable_env() = client_env;
- launch_cmd.set_working_directory(first_instance_dir);
- (*launch_cmd.mutable_env())["HOME"] = launch_home_dir;
-
- (*launch_cmd.mutable_env())[kAndroidHostOut] = first_instance_dir;
- (*launch_cmd.mutable_env())[kAndroidSoongHostOut] = first_instance_dir;
-
+ (*launch_cmd.mutable_env())["HOME"] =
+ load_directories.launch_home_directory;
+ (*launch_cmd.mutable_env())[kAndroidHostOut] =
+ load_directories.first_instance_directory;
+ (*launch_cmd.mutable_env())[kAndroidSoongHostOut] =
+ load_directories.first_instance_directory;
if (Contains(*launch_cmd.mutable_env(), kAndroidProductOut)) {
(*launch_cmd.mutable_env()).erase(kAndroidProductOut);
}
@@ -427,11 +150,11 @@
launch_cmd.add_args("cvd");
launch_cmd.add_args("start");
launch_cmd.add_args("--daemon");
- for (auto& parsed_flag : cvd_flags.launch_cvd_flags) {
+ for (const auto& parsed_flag : cvd_flags.launch_cvd_flags) {
launch_cmd.add_args(parsed_flag);
}
// Add system flag for multi-build scenario
- launch_cmd.add_args(GenerateSystemImageFlag(cvd_flags.fetch_cvd_flags));
+ launch_cmd.add_args(load_directories.system_image_directory_flag);
launch_cmd.mutable_selector_opts()->add_args(
std::string("--") + selector::SelectorFlags::kDisableDefaultGroup);
@@ -440,7 +163,7 @@
auto dev_null = SharedFD::Open("/dev/null", O_RDWR);
CF_EXPECT(dev_null->IsOpen(), dev_null->StrError());
std::vector<SharedFD> fds = {dev_null, dev_null, dev_null};
- DemoCommandSequence ret;
+ std::vector<RequestWithStdio> ret;
for (auto& request_proto : req_protos) {
ret.emplace_back(RequestWithStdio(request.Client(), request_proto, fds,
diff --git a/host/commands/cvd/server_command/serial_launch.cpp b/host/commands/cvd/server_command/serial_launch.cpp
index 65cd527..b78a5a7 100644
--- a/host/commands/cvd/server_command/serial_launch.cpp
+++ b/host/commands/cvd/server_command/serial_launch.cpp
@@ -69,34 +69,31 @@
/** Returns a `Flag` object that accepts comma-separated unsigned integers. */
template <typename T>
-Flag DeviceSpecificUintFlag(const std::string& name, std::vector<T>& values,
- const RequestWithStdio& request) {
+Flag DeviceSpecificUintFlag(const std::string& name, std::vector<T>& values) {
return GflagsCompatFlag(name).Setter(
- [&request, &values](const FlagMatch& match) {
+ [&values](const FlagMatch& match) -> Result<void> {
auto parsed_values = android::base::Tokenize(match.value, ", ");
for (auto& parsed_value : parsed_values) {
std::uint32_t num = 0;
- if (!android::base::ParseUint(parsed_value, &num)) {
- constexpr char kError[] = "Failed to parse integer";
- WriteAll(request.Out(), kError, sizeof(kError));
- return false;
- }
+ CF_EXPECTF(android::base::ParseUint(parsed_value, &num),
+ "Failed to parse {} as an integer", parsed_value);
values.push_back(num);
}
- return true;
+ return {};
});
}
/** Returns a `Flag` object that accepts comma-separated strings. */
Flag DeviceSpecificStringFlag(const std::string& name,
std::vector<std::string>& values) {
- return GflagsCompatFlag(name).Setter([&values](const FlagMatch& match) {
- auto parsed_values = android::base::Tokenize(match.value, ", ");
- for (auto& parsed_value : parsed_values) {
- values.push_back(parsed_value);
- }
- return true;
- });
+ return GflagsCompatFlag(name).Setter(
+ [&values](const FlagMatch& match) -> Result<void> {
+ auto parsed_values = android::base::Tokenize(match.value, ", ");
+ for (auto& parsed_value : parsed_values) {
+ values.push_back(parsed_value);
+ }
+ return {};
+ });
}
std::string ParentDir(const uid_t uid) {
@@ -167,19 +164,19 @@
flags.emplace_back(GflagsCompatFlag("verbose", verbose));
std::vector<std::uint32_t> x_res;
- flags.emplace_back(DeviceSpecificUintFlag("x_res", x_res, request));
+ flags.emplace_back(DeviceSpecificUintFlag("x_res", x_res));
std::vector<std::uint32_t> y_res;
- flags.emplace_back(DeviceSpecificUintFlag("y_res", y_res, request));
+ flags.emplace_back(DeviceSpecificUintFlag("y_res", y_res));
std::vector<std::uint32_t> dpi;
- flags.emplace_back(DeviceSpecificUintFlag("dpi", dpi, request));
+ flags.emplace_back(DeviceSpecificUintFlag("dpi", dpi));
std::vector<std::uint32_t> cpus;
- flags.emplace_back(DeviceSpecificUintFlag("cpus", cpus, request));
+ flags.emplace_back(DeviceSpecificUintFlag("cpus", cpus));
std::vector<std::uint32_t> memory_mb;
- flags.emplace_back(DeviceSpecificUintFlag("memory_mb", memory_mb, request));
+ flags.emplace_back(DeviceSpecificUintFlag("memory_mb", memory_mb));
std::vector<std::string> setupwizard_mode;
flags.emplace_back(
@@ -207,27 +204,20 @@
auto& device_flag = flags.emplace_back();
device_flag.Alias({FlagAliasMode::kFlagPrefix, "--device="});
device_flag.Alias({FlagAliasMode::kFlagConsumesFollowing, "--device"});
- device_flag.Setter(
- [this, time, client_uid, &devices, &request](const FlagMatch& mat) {
- auto lock = lock_file_manager_.TryAcquireUnusedLock();
- if (!lock.ok()) {
- WriteAll(request.Err(), lock.error().Message());
- return false;
- } else if (!lock->has_value()) {
- constexpr char kError[] = "could not acquire instance lock";
- WriteAll(request.Err(), kError, sizeof(kError));
- return false;
- }
- int num = (*lock)->Instance();
- std::string home_dir = ParentDir(client_uid) + std::to_string(time) +
- "_" + std::to_string(num) + "/";
- devices.emplace_back(Device{
- .build = mat.value,
- .home_dir = std::move(home_dir),
- .ins_lock = std::move(**lock),
- });
- return true;
- });
+ device_flag.Setter([this, time, client_uid,
+ &devices](const FlagMatch& mat) -> Result<void> {
+ auto lock = CF_EXPECT(lock_file_manager_.TryAcquireUnusedLock());
+ CF_EXPECT(lock.has_value(), "could not acquire instance lock");
+ int num = lock->Instance();
+ std::string home_dir = ParentDir(client_uid) + std::to_string(time) +
+ "_" + std::to_string(num) + "/";
+ devices.emplace_back(Device{
+ .build = mat.value,
+ .home_dir = std::move(home_dir),
+ .ins_lock = std::move(*lock),
+ });
+ return {};
+ });
auto args = ParseInvocation(request.Message()).arguments;
for (const auto& arg : args) {
diff --git a/host/commands/cvd/server_command/suspend_resume.cpp b/host/commands/cvd/server_command/snapshot.cpp
similarity index 73%
rename from host/commands/cvd/server_command/suspend_resume.cpp
rename to host/commands/cvd/server_command/snapshot.cpp
index 3856561..9470923 100644
--- a/host/commands/cvd/server_command/suspend_resume.cpp
+++ b/host/commands/cvd/server_command/snapshot.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "host/commands/cvd/server_command/suspend_resume.h"
+#include "host/commands/cvd/server_command/snapshot.h"
#include <android-base/file.h>
#include <android-base/strings.h>
@@ -41,17 +41,17 @@
namespace cuttlefish {
-static constexpr char kSuspendResume[] =
+static constexpr char kSnapshot[] =
R"(Cuttlefish Virtual Device (CVD) CLI.
-Suspend/resume the cuttlefish device
+Suspend/resume the cuttlefish device, or take snapshot of the device
-usage: cvd [selector flags] suspend/resume [--help]
+usage: cvd [selector flags] suspend/resume/snapshot_take [--help]
Common:
Selector Flags:
--group_name=<name> The name of the instance group
- --instance_name=<names> The comma-separated list of the instance names
+ --snapshot_path=<path>> Directory that contains saved snapshot files
Args:
--help print this message
@@ -64,19 +64,19 @@
)";
-class CvdSuspendResumeCommandHandler : public CvdServerHandler {
+class CvdSnapshotCommandHandler : public CvdServerHandler {
public:
- INJECT(CvdSuspendResumeCommandHandler(
+ INJECT(CvdSnapshotCommandHandler(
InstanceManager& instance_manager, SubprocessWaiter& subprocess_waiter,
HostToolTargetManager& host_tool_target_manager))
: instance_manager_{instance_manager},
subprocess_waiter_(subprocess_waiter),
host_tool_target_manager_(host_tool_target_manager),
- cvd_suspend_resume_operations_{"suspend", "resume"} {}
+ cvd_snapshot_operations_{"suspend", "resume", "snapshot_take"} {}
Result<bool> CanHandle(const RequestWithStdio& request) const {
auto invocation = ParseInvocation(request.Message());
- return Contains(cvd_suspend_resume_operations_, invocation.command);
+ return Contains(cvd_snapshot_operations_, invocation.command);
}
Result<cvd::Response> Handle(const RequestWithStdio& request) override {
@@ -125,13 +125,13 @@
}
cvd_common::Args CmdList() const override {
- return cvd_common::Args(cvd_suspend_resume_operations_.begin(),
- cvd_suspend_resume_operations_.end());
+ return cvd_common::Args(cvd_snapshot_operations_.begin(),
+ cvd_snapshot_operations_.end());
}
private:
Result<cvd::Response> HandleHelp(const SharedFD& client_stderr) {
- std::string help_message(kSuspendResume);
+ std::string help_message(kSnapshot);
help_message.append("\n");
CF_EXPECT(WriteAll(client_stderr, help_message) == help_message.size(),
"Failed to write the help message");
@@ -145,32 +145,23 @@
const uid_t uid, const std::string& subcmd,
cvd_common::Args& subcmd_args,
cvd_common::Envs envs) {
- // test if there is --instance_num flag
- CvdFlag<std::int32_t> instance_num_flag("instance_num");
- auto instance_num_opt =
- CF_EXPECT(instance_num_flag.FilterFlag(subcmd_args));
- selector::Queries extra_queries;
- if (instance_num_opt) {
- extra_queries.emplace_back(selector::kInstanceIdField, *instance_num_opt);
- }
-
const auto& selector_opts =
request.Message().command_request().selector_opts();
const auto selector_args = cvd_common::ConvertToArgs(selector_opts.args());
- auto instance = CF_EXPECT(instance_manager_.SelectInstance(
- selector_args, extra_queries, envs, uid));
- const auto& instance_group = instance.ParentGroup();
- const auto& home = instance_group.HomeDir();
+ // create a string that is comma-separated instance IDs
+ auto instance_group =
+ CF_EXPECT(instance_manager_.SelectGroup(selector_args, envs, uid));
+ const auto& home = instance_group.HomeDir();
const auto& android_host_out = instance_group.HostArtifactsPath();
- auto cvd_suspend_resume_bin_path =
- CF_EXPECT(GetBin(android_host_out, subcmd));
- cvd_common::Args cvd_suspend_resume_args{"--subcmd=" + subcmd};
- cvd_suspend_resume_args.insert(cvd_suspend_resume_args.end(),
- subcmd_args.begin(), subcmd_args.end());
- cvd_suspend_resume_args.push_back(
- ConcatToString("--instance_num=", instance.InstanceId()));
+ auto cvd_snapshot_bin_path = CF_EXPECT(GetBin(android_host_out, subcmd));
+ const std::string& snapshot_util_cmd = subcmd;
+ cvd_common::Args cvd_snapshot_args{"--subcmd=" + snapshot_util_cmd};
+ cvd_snapshot_args.insert(cvd_snapshot_args.end(), subcmd_args.begin(),
+ subcmd_args.end());
+ // This helps snapshot_util find CuttlefishConfig and figure out
+ // the instance ids
envs["HOME"] = home;
envs[kAndroidHostOut] = android_host_out;
envs[kAndroidSoongHostOut] = android_host_out;
@@ -178,20 +169,19 @@
std::stringstream command_to_issue;
command_to_issue << "HOME=" << home << " " << kAndroidHostOut << "="
<< android_host_out << " " << kAndroidSoongHostOut << "="
- << android_host_out << " " << cvd_suspend_resume_bin_path
- << " ";
- for (const auto& arg : cvd_suspend_resume_args) {
+ << android_host_out << " " << cvd_snapshot_bin_path << " ";
+ for (const auto& arg : cvd_snapshot_args) {
command_to_issue << arg << " ";
}
WriteAll(request.Err(), command_to_issue.str());
ConstructCommandParam construct_cmd_param{
- .bin_path = cvd_suspend_resume_bin_path,
+ .bin_path = cvd_snapshot_bin_path,
.home = home,
- .args = cvd_suspend_resume_args,
+ .args = cvd_snapshot_args,
.envs = envs,
.working_dir = request.Message().command_request().working_directory(),
- .command_name = android::base::Basename(cvd_suspend_resume_bin_path),
+ .command_name = android::base::Basename(cvd_snapshot_bin_path),
.in = request.In(),
.out = request.Out(),
.err = request.Err()};
@@ -208,11 +198,11 @@
Result<std::string> GetBin(const std::string& host_artifacts_path,
const std::string& op) const {
- auto suspend_resume_bin = CF_EXPECT(host_tool_target_manager_.ExecBaseName({
+ auto snapshot_bin = CF_EXPECT(host_tool_target_manager_.ExecBaseName({
.artifacts_path = host_artifacts_path,
.op = op,
}));
- return suspend_resume_bin;
+ return snapshot_bin;
}
InstanceManager& instance_manager_;
@@ -220,14 +210,14 @@
HostToolTargetManager& host_tool_target_manager_;
std::mutex interruptible_;
bool interrupted_ = false;
- std::vector<std::string> cvd_suspend_resume_operations_;
+ std::vector<std::string> cvd_snapshot_operations_;
};
fruit::Component<
fruit::Required<InstanceManager, SubprocessWaiter, HostToolTargetManager>>
-CvdSuspendResumeComponent() {
+CvdSnapshotComponent() {
return fruit::createComponent()
- .addMultibinding<CvdServerHandler, CvdSuspendResumeCommandHandler>();
+ .addMultibinding<CvdServerHandler, CvdSnapshotCommandHandler>();
}
} // namespace cuttlefish
diff --git a/host/commands/cvd/server_command/suspend_resume.h b/host/commands/cvd/server_command/snapshot.h
similarity index 96%
rename from host/commands/cvd/server_command/suspend_resume.h
rename to host/commands/cvd/server_command/snapshot.h
index f0f6168..b72a8fd 100644
--- a/host/commands/cvd/server_command/suspend_resume.h
+++ b/host/commands/cvd/server_command/snapshot.h
@@ -26,6 +26,6 @@
fruit::Component<
fruit::Required<InstanceManager, SubprocessWaiter, HostToolTargetManager>>
-CvdSuspendResumeComponent();
+CvdSnapshotComponent();
} // namespace cuttlefish
diff --git a/host/commands/cvd/server_command/vm_control.cpp b/host/commands/cvd/server_command/vm_control.cpp
deleted file mode 100644
index dc8ee58..0000000
--- a/host/commands/cvd/server_command/vm_control.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "host/commands/cvd/server_command/vm_control.h"
-
-#include <android-base/strings.h>
-
-#include <future>
-#include <iostream>
-#include <mutex>
-#include <optional>
-#include <sstream>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include "common/libs/fs/shared_buf.h"
-#include "common/libs/utils/contains.h"
-#include "common/libs/utils/files.h"
-#include "common/libs/utils/subprocess.h"
-#include "host/commands/cvd/flag.h"
-#include "host/commands/cvd/selector/instance_group_record.h"
-#include "host/commands/cvd/selector/instance_record.h"
-#include "host/commands/cvd/selector/selector_constants.h"
-#include "host/commands/cvd/server_command/server_handler.h"
-#include "host/commands/cvd/server_command/subprocess_waiter.h"
-#include "host/commands/cvd/server_command/utils.h"
-#include "host/commands/cvd/types.h"
-#include "host/libs/config/cuttlefish_config.h"
-
-namespace cuttlefish {
-
-static constexpr char kSnapshot[] =
- R"(Cuttlefish Virtual Device (CVD) CLI.
-
-Take a snapshot of a cuttlefish device or
-Create/restore a cuttlefish device from a snapshot
-
-usage: cvd [selector flags] snapshot take/restore <snapshot path> [vm args]
- cvd snapshot take/restore --help
-
-Common:
-
- Selector Flags:
- --group_name=<name> The name of the instance group
- --instance_name=<names> The comma-separated list of the instance names
-
- Commands:
- take Take the snapshot to the <snapshot path>
- restore Restore the device from <snapshot path>
-
- Args:
- --help print this message
-
-Crosvm:
- <snapshot path>:
- Path to the snapshot file
-
-QEMU:
- No QEMU-specific vm arguments yet
-)";
-
-class CvdVmControlCommandHandler : public CvdServerHandler {
- public:
- INJECT(CvdVmControlCommandHandler(InstanceManager& instance_manager))
- : instance_manager_{instance_manager},
- vm_operations_{{"snapshot", kSnapshot}} {}
-
- Result<bool> CanHandle(const RequestWithStdio& request) const {
- auto invocation = ParseInvocation(request.Message());
- return Contains(vm_operations_, invocation.command);
- }
-
- Result<cvd::Response> Handle(const RequestWithStdio& request) override {
- std::unique_lock interrupt_lock(interruptible_);
- CF_EXPECT(!interrupted_, "Interrupted");
- CF_EXPECT(CanHandle(request));
- CF_EXPECT(VerifyPrecondition(request));
- const uid_t uid = request.Credentials()->uid;
- cvd_common::Envs envs =
- cvd_common::ConvertToEnvs(request.Message().command_request().env());
-
- auto [vm_op, subcmd_args] = ParseInvocation(request.Message());
- /*
- * crosvm suspend/resume/snapshot support --help only. Not --helpxml, etc.
- *
- * Otherwise, IsHelpSubcmd() should be used here instead.
- */
- auto help_flag = CvdFlag("help", false);
- cvd_common::Args subcmd_args_copy{subcmd_args};
- auto help_parse_result = help_flag.CalculateFlag(subcmd_args_copy);
- bool is_help = help_parse_result.ok() && (*help_parse_result);
-
- if (is_help) {
- auto help_response = CF_EXPECT(HandleHelp(request.Err(), vm_op));
- return help_response;
- }
-
- /*
- * TODO(kwstephenkim): Support QEMU
- *
- * We should add a field that indicates the vm type in the instance
- * database. Then, we should check the field here to set/unset is_crosvm.
- */
- const bool is_crosvm = true;
- CF_EXPECT(is_crosvm == true, "QEMU is not yet supported");
-
- auto commands =
- CF_EXPECT(CrosvmCommand(request, uid, vm_op, subcmd_args, envs));
- subprocess_waiters_ = std::vector<SubprocessWaiter>(commands.size());
-
- interrupt_lock.unlock();
- return CF_EXPECT(ConstructResponse(std::move(commands)));
- }
-
- Result<void> Interrupt() override {
- std::scoped_lock interrupt_lock(interruptible_);
- interrupted_ = true;
- for (auto& subprocess_waiter : subprocess_waiters_) {
- CF_EXPECT(subprocess_waiter.Interrupt());
- }
- return {};
- }
-
- cvd_common::Args CmdList() const override {
- cvd_common::Args cmd_list;
- cmd_list.reserve(vm_operations_.size());
- for (const auto& [op, _] : vm_operations_) {
- cmd_list.push_back(op);
- }
- return cmd_list;
- }
-
- private:
- Result<cvd::Response> ConstructResponse(std::vector<Command> commands) {
- std::vector<std::future<Result<siginfo_t>>> infop_futures;
- infop_futures.reserve(commands.size());
- auto worker = [this](const int idx, Command command) -> Result<siginfo_t> {
- std::unique_lock interrupt_lock(interruptible_);
- CF_EXPECT(!interrupted_, "Interrupted");
- SubprocessOptions options;
- auto& subprocess_waiter = subprocess_waiters_[idx];
- CF_EXPECT(subprocess_waiter.Setup(command.Start(options)));
- interrupt_lock.unlock();
- return CF_EXPECT(subprocess_waiter.Wait());
- };
- size_t idx = 0;
- for (auto& command : commands) {
- std::future<Result<siginfo_t>> infop_future =
- std::async(std::launch::async, worker, idx, std::move(command));
- infop_futures.push_back(std::move(infop_future));
- idx++;
- }
- commands.clear();
-
- bool ok = true;
- std::stringstream error_msg;
- for (auto& infop_future : infop_futures) {
- auto infop = std::move(infop_future.get());
- if (!infop.ok()) {
- LOG(ERROR) << infop.error().Trace();
- ok = false;
- continue;
- }
- if (infop->si_code == CLD_EXITED && infop->si_status == 0) {
- continue;
- }
- // error
- ok = false;
- std::string status_code_str = std::to_string(infop->si_status);
- if (infop->si_code == CLD_EXITED) {
- error_msg << "Exited with code " << status_code_str << std::endl;
- } else if (infop->si_code == CLD_KILLED) {
- error_msg << "Exited with signal " << status_code_str << std::endl;
- } else {
- error_msg << "Quit with code " << status_code_str << std::endl;
- }
- }
-
- cvd::Response response;
- response.mutable_command_response(); // set oneof field
- auto& status = *response.mutable_status();
- if (ok) {
- status.set_code(cvd::Status::OK);
- } else {
- status.set_code(cvd::Status::INTERNAL);
- status.set_message(error_msg.str());
- }
- return response;
- }
-
- Result<cvd::Response> HandleHelp(const SharedFD& client_stderr,
- const std::string& vm_op) {
- CF_EXPECT(Contains(vm_operations_, vm_op));
- std::string help_message = ConcatToString(vm_operations_.at(vm_op), "\n");
- CF_EXPECT(WriteAll(client_stderr, help_message) == help_message.size(),
- "Failed to write the help message");
- cvd::Response response;
- response.mutable_command_response();
- response.mutable_status()->set_code(cvd::Status::OK);
- return response;
- }
-
- Result<std::vector<Command>> CrosvmCommand(
- const RequestWithStdio& request, const uid_t uid,
- const std::string& crosvm_op, const cvd_common::Args& subcmd_args,
- const cvd_common::Envs& envs) {
- const auto& selector_opts =
- request.Message().command_request().selector_opts();
- const auto selector_args = cvd_common::ConvertToArgs(selector_opts.args());
-
- if (CF_EXPECT(HasInstanceSpecificOption(selector_args, envs))) {
- auto instance =
- CF_EXPECT(instance_manager_.SelectInstance(selector_args, envs, uid));
- return CF_EXPECT(CrosvmInstanceCommand(request, instance, crosvm_op,
- subcmd_args, envs));
- }
- auto instance_group =
- CF_EXPECT(instance_manager_.SelectGroup(selector_args, envs, uid));
- return CF_EXPECT(CrosvmGroupCommand(request, instance_group, crosvm_op,
- subcmd_args, envs));
- }
-
- Result<std::vector<Command>> CrosvmGroupCommand(
- const RequestWithStdio& request,
- const InstanceManager::LocalInstanceGroup& instance_group,
- const std::string& crosvm_op, const cvd_common::Args& subcmd_args,
- const cvd_common::Envs& envs) {
- std::vector<Command> commands;
- auto& instances = instance_group.Instances();
- for (const auto& instance : instances) {
- auto instance_commands = CF_EXPECT(CrosvmInstanceCommand(
- request, instance->GetCopy(), crosvm_op, subcmd_args, envs));
- CF_EXPECT_EQ(instance_commands.size(), 1);
- commands.push_back(std::move(instance_commands.front()));
- }
- return commands;
- }
-
- Result<std::vector<Command>> CrosvmInstanceCommand(
- const RequestWithStdio& request,
- const InstanceManager::LocalInstance::Copy& instance,
- const std::string& crosvm_op, const cvd_common::Args& subcmd_args,
- const cvd_common::Envs& envs) {
- const auto& instance_group = instance.ParentGroup();
- const auto instance_id = instance.InstanceId();
- const auto& internal_name = instance.InternalDeviceName();
- auto home = instance_group.HomeDir();
-
- // Use /tmp/cf_avd as crosvm_control.sock UDS path, if it does not exist,
- // fallback to HOME directory(legacy).
- const auto defaultPath =
- ConcatToString("/tmp/cf_avd_", getuid(), "/", internal_name,
- "/internal/"
- "crosvm_control.sock");
- const auto fallbackPath =
- ConcatToString(home, "/cuttlefish_runtime.", instance_id,
- "/internal/"
- "crosvm_control.sock");
-
- const auto socket_file_path =
- FileExists(defaultPath) ? defaultPath : fallbackPath;
-
- auto android_host_out = instance_group.HostArtifactsPath();
- auto crosvm_bin_path = ConcatToString(android_host_out, "/bin/crosvm");
-
- cvd_common::Args crosvm_args{crosvm_op};
- crosvm_args.insert(crosvm_args.end(), subcmd_args.begin(),
- subcmd_args.end());
- crosvm_args.push_back(socket_file_path);
- Command non_help_command = CF_EXPECT(
- ConstructCvdGenericNonHelpCommand({.bin_file = "crosvm",
- .envs = envs,
- .cmd_args = std::move(crosvm_args),
- .android_host_out = android_host_out,
- .home = home,
- .verbose = true},
- request));
- std::vector<Command> non_help_command_in_vector;
- non_help_command_in_vector.push_back(std::move(non_help_command));
- return non_help_command_in_vector;
- }
-
- Result<bool> HasInstanceSpecificOption(cvd_common::Args selector_args,
- const cvd_common::Envs& envs) const {
- auto instance_name_flag = CF_EXPECT(selector::SelectorFlags::Get().GetFlag(
- selector::SelectorFlags::kInstanceName));
- std::optional<std::string> instance_name_opt =
- CF_EXPECT(instance_name_flag.FilterFlag<std::string>(selector_args));
- if (instance_name_opt) {
- return true;
- }
- return Contains(envs, kCuttlefishInstanceEnvVarName);
- }
-
- InstanceManager& instance_manager_;
- std::vector<SubprocessWaiter> subprocess_waiters_;
- std::mutex interruptible_;
- bool interrupted_ = false;
- std::unordered_map<std::string, const char*> vm_operations_;
-};
-
-fruit::Component<fruit::Required<InstanceManager>> CvdVmControlComponent() {
- return fruit::createComponent()
- .addMultibinding<CvdServerHandler, CvdVmControlCommandHandler>();
-}
-
-} // namespace cuttlefish
diff --git a/host/commands/cvd/server_command/vm_control.h b/host/commands/cvd/server_command/vm_control.h
deleted file mode 100644
index 3613189..0000000
--- a/host/commands/cvd/server_command/vm_control.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <fruit/fruit.h>
-
-#include "host/commands/cvd/instance_manager.h"
-
-namespace cuttlefish {
-
-fruit::Component<fruit::Required<InstanceManager>> CvdVmControlComponent();
-
-} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/parser/Android.bp b/host/commands/cvd/unittests/parser/Android.bp
index cead23e..f7566f2 100644
--- a/host/commands/cvd/unittests/parser/Android.bp
+++ b/host/commands/cvd/unittests/parser/Android.bp
@@ -41,10 +41,10 @@
"configs_inheritance_test.cc",
"fetch_cvd_parser_tests.cpp",
"flags_parser_test.cc",
+ "metrics_configs_test.cc",
"instance/vm_configs_test.cc",
"instance/boot_configs_test.cc",
"instance/disk_configs_test.cc",
- "instance/metrics_configs_test.cc",
"instance/graphics_configs_test.cc",
"test_common.cc",
],
diff --git a/host/commands/cvd/unittests/parser/cf_configs_common_tests.cpp b/host/commands/cvd/unittests/parser/cf_configs_common_tests.cpp
index bb3a15f..c372e50 100644
--- a/host/commands/cvd/unittests/parser/cf_configs_common_tests.cpp
+++ b/host/commands/cvd/unittests/parser/cf_configs_common_tests.cpp
@@ -22,6 +22,7 @@
#include <json/json.h>
#include "common/libs/utils/result.h"
+#include "common/libs/utils/result_matchers.h"
#include "host/commands/cvd/unittests/parser/test_common.h"
namespace cuttlefish {
@@ -54,7 +55,8 @@
[](const std::string&) -> Result<void> { return {}; });
auto result = ValidateConfig(json_config["instances"][0], success_validator,
{"vm", "cpus"});
- EXPECT_TRUE(result.ok());
+
+ EXPECT_THAT(result, IsOk());
}
TEST(CfConfigsCommonTests, ValidateConfigValidationFailure) {
@@ -85,7 +87,8 @@
[](const std::string&) -> Result<void> { return CF_ERR("placeholder"); });
auto result = ValidateConfig(json_config["instances"][0], error_validator,
{"vm", "cpus"});
- EXPECT_FALSE(result.ok());
+
+ EXPECT_THAT(result, IsError());
}
TEST(CfConfigsCommonTests, ValidateConfigFieldDoesNotExist) {
@@ -115,7 +118,8 @@
[](const std::string&) -> Result<void> { return {}; });
auto result = ValidateConfig(json_config["instances"][0], success_validator,
{"disk", "cpus"});
- EXPECT_TRUE(result.ok());
+
+ EXPECT_THAT(result, IsOk());
}
TEST(CfConfigsCommonTests, InitConfigTopLevel) {
@@ -149,7 +153,8 @@
auto result =
InitConfig(json_config, Json::Value::nullSingleton(), {"api_key"});
- EXPECT_TRUE(result.ok());
+
+ EXPECT_THAT(result, IsOk());
EXPECT_TRUE(json_config.isMember("api_key"));
EXPECT_TRUE(json_config["api_key"].isNull());
}
@@ -190,7 +195,8 @@
auto result =
InitConfig(json_config["instances"][0], Json::Value::nullSingleton(),
{"disk", "download_target_files_zip"});
- EXPECT_TRUE(result.ok());
+
+ EXPECT_THAT(result, IsOk());
EXPECT_TRUE(json_config["instances"][0]["disk"].isMember(
"download_target_files_zip"));
EXPECT_TRUE(json_config["instances"][0]["disk"]["download_target_files_zip"]
@@ -227,7 +233,8 @@
auto result =
InitConfig(json_config["instances"][0], Json::Value::nullSingleton(),
{"disk", "download_target_files_zip"});
- EXPECT_TRUE(result.ok());
+
+ EXPECT_THAT(result, IsOk());
ASSERT_TRUE(json_config["instances"][0].isMember("disk"));
EXPECT_TRUE(json_config["instances"][0]["disk"].isMember(
"download_target_files_zip"));
@@ -264,8 +271,7 @@
ASSERT_TRUE(json_config["instances"][0]["vm"].isMember("cpus"));
auto result = GenerateGflag(json_config["instances"], "cpus", {"vm", "cpus"});
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(result.value(), "--cpus=4");
+ EXPECT_THAT(result, IsOkAndValue("--cpus=4"));
}
TEST(CfConfigsCommonTests, GenerateGflagMultiInstance) {
@@ -308,8 +314,7 @@
ASSERT_TRUE(json_config["instances"][1]["vm"].isMember("cpus"));
auto result = GenerateGflag(json_config["instances"], "cpus", {"vm", "cpus"});
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(result.value(), "--cpus=4,2");
+ EXPECT_THAT(result, IsOkAndValue("--cpus=4,2"));
}
TEST(CfConfigsCommonTests, GenerateGflagMissingValue) {
@@ -340,7 +345,7 @@
auto result = GenerateGflag(json_config["instances"], "setupwizard_mode",
{"vm", "setupwizard_mode"});
- EXPECT_FALSE(result.ok());
+ EXPECT_THAT(result, IsError());
}
} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/parser/fetch_cvd_parser_tests.cpp b/host/commands/cvd/unittests/parser/fetch_cvd_parser_tests.cpp
index e7fae7c..bf3aef2 100644
--- a/host/commands/cvd/unittests/parser/fetch_cvd_parser_tests.cpp
+++ b/host/commands/cvd/unittests/parser/fetch_cvd_parser_tests.cpp
@@ -17,14 +17,21 @@
#include "host/commands/cvd/parser/fetch_cvd_parser.h"
#include <string>
+#include <vector>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <json/json.h>
#include "common/libs/utils/result.h"
+#include "common/libs/utils/result_matchers.h"
#include "host/commands/cvd/parser/cf_flags_validator.h"
#include "host/commands/cvd/unittests/parser/test_common.h"
+using ::testing::Contains;
+using ::testing::Eq;
+using ::testing::Not;
+
namespace cuttlefish {
namespace {
@@ -35,9 +42,11 @@
return json_config;
}
-Result<FetchCvdConfig> FetchCvdParserTestHelper(Json::Value& root) {
+Result<std::vector<std::string>> FetchCvdParserTestHelper(
+ Json::Value& root, const std::string& target_directory,
+ const std::vector<std::string>& target_subdirectories) {
CF_EXPECT(ValidateCfConfigs(root), "Loaded Json validation failed");
- return ParseFetchCvdConfigs(root);
+ return ParseFetchCvdConfigs(root, target_directory, target_subdirectories);
}
} // namespace
@@ -54,21 +63,85 @@
"cpus" : 4
},
"disk" : {
- "default_build" : "git_master/cf_x86_64_phone-userdebug",
- "download_img_zip" : true
+ "default_build" : "@ab/git_master/cf_x86_64_phone-userdebug",
+ "download_img_zip" : true,
+ "otatools" : "@ab/git_master/cf_x86_64_phone-userdebug",
+ "host_package" : "@ab/git_master/cf_x86_64_phone-userdebug"
+ },
+ "boot" : {
+ "build" : "@ab/git_master/cf_x86_64_phone-userdebug",
+ "kernel" : {
+ "build" : "@ab/git_master/cf_x86_64_phone-userdebug"
+ },
+ "bootloader" : {
+ "build" : "@ab/git_master/cf_x86_64_phone-userdebug"
+ }
}
}
],
- "wait_retry_period" : 20,
- "keep_downloaded_archives" : false
+ "fetch":{
+ "wait_retry_period" : 20,
+ "keep_downloaded_archives" : false
+ }
}
)"""";
Json::Value json_config = GetTestJson(raw_json);
- auto result_config = FetchCvdParserTestHelper(json_config);
+ auto result_flags = FetchCvdParserTestHelper(json_config, "/target", {"0"});
+ ASSERT_THAT(result_flags, IsOk())
+ << "Parsing config failed: " << result_flags.error().Trace();
- EXPECT_TRUE(result_config.ok())
- << "Parsing config failed: " << result_config.error().Trace();
+ const auto flags = result_flags.value();
+ EXPECT_THAT(flags, Contains("--wait_retry_period=20"));
+ EXPECT_THAT(flags, Contains("--keep_downloaded_archives=false"));
+ EXPECT_THAT(flags, Contains("--target_directory=/target"));
+ EXPECT_THAT(flags, Contains("--target_subdirectory=0"));
+ EXPECT_THAT(flags,
+ Contains("--default_build=git_master/cf_x86_64_phone-userdebug"));
+ EXPECT_THAT(flags, Contains("--download_img_zip=true"));
+ EXPECT_THAT(
+ flags, Contains("--otatools_build=git_master/cf_x86_64_phone-userdebug"));
+ EXPECT_THAT(
+ flags,
+ Contains("--host_package_build=git_master/cf_x86_64_phone-userdebug"));
+ EXPECT_THAT(flags,
+ Contains("--boot_build=git_master/cf_x86_64_phone-userdebug"));
+ EXPECT_THAT(flags,
+ Contains("--kernel_build=git_master/cf_x86_64_phone-userdebug"));
+ EXPECT_THAT(
+ flags,
+ Contains("--bootloader_build=git_master/cf_x86_64_phone-userdebug"));
+}
+
+TEST(FetchCvdParserTests, SingleFetchNoPrefix) {
+ const char* raw_json = R""""(
+{
+ "instances" : [
+ {
+ "@import" : "phone",
+ "disk" : {
+ "default_build" : "git_master/cf_x86_64_phone-userdebug",
+ "otatools" : "git_master/cf_x86_64_phone-userdebug",
+ "host_package" : "git_master/cf_x86_64_phone-userdebug"
+ },
+ "boot" : {
+ "build" : "git_master/cf_x86_64_phone-userdebug",
+ "kernel" : {
+ "build" : "git_master/cf_x86_64_phone-userdebug"
+ },
+ "bootloader" : {
+ "build" : "git_master/cf_x86_64_phone-userdebug"
+ }
+ }
+ }
+ ]
+}
+ )"""";
+ Json::Value json_config = GetTestJson(raw_json);
+
+ auto result_flags = FetchCvdParserTestHelper(json_config, "/target", {"0"});
+ ASSERT_THAT(result_flags, IsOk())
+ << "Parsing config failed: " << result_flags.error().Trace();
}
TEST(FetchCvdParserTests, MultiFetch) {
@@ -83,8 +156,19 @@
"cpus" : 4
},
"disk" : {
- "default_build" : "git_master/cf_x86_64_phone-userdebug",
- "download_img_zip" : true
+ "default_build" : "@ab/git_master/cf_x86_64_phone-userdebug",
+ "download_img_zip" : true,
+ "otatools" : "@ab/git_master/cf_x86_64_phone-userdebug",
+ "host_package" : "@ab/git_master/cf_x86_64_phone-userdebug"
+ },
+ "boot" : {
+ "build" : "@ab/git_master/cf_x86_64_phone-userdebug",
+ "kernel" : {
+ "build" : "@ab/git_master/cf_x86_64_phone-userdebug"
+ },
+ "bootloader" : {
+ "build" : "@ab/git_master/cf_x86_64_phone-userdebug"
+ }
}
},
{
@@ -95,21 +179,47 @@
"cpus" : 4
},
"disk" : {
- "default_build" : "git_master/cf_gwear_x86-userdebug",
+ "default_build" : "@ab/git_master/cf_gwear_x86-userdebug",
"download_img_zip" : true
}
}
],
- "wait_retry_period" : 20,
- "keep_downloaded_archives" : false
+ "fetch":{
+ "wait_retry_period" : 20,
+ "keep_downloaded_archives" : false
+ }
}
)"""";
Json::Value json_config = GetTestJson(raw_json);
- auto result_config = FetchCvdParserTestHelper(json_config);
+ auto result_flags =
+ FetchCvdParserTestHelper(json_config, "/target", {"0", "1"});
+ ASSERT_THAT(result_flags, IsOk())
+ << "Parsing config failed: " << result_flags.error().Trace();
- EXPECT_TRUE(result_config.ok())
- << "Parsing config failed: " << result_config.error().Trace();
+ const auto flags = result_flags.value();
+ EXPECT_THAT(flags, Contains("--wait_retry_period=20"));
+ EXPECT_THAT(flags, Contains("--keep_downloaded_archives=false"));
+ EXPECT_THAT(flags, Contains("--target_directory=/target"));
+ EXPECT_THAT(flags, Contains("--target_subdirectory=0,1"));
+ EXPECT_THAT(
+ flags,
+ Contains("--default_build=git_master/"
+ "cf_x86_64_phone-userdebug,git_master/cf_gwear_x86-userdebug"));
+ EXPECT_THAT(flags, Contains("--download_img_zip=true,true"));
+ EXPECT_THAT(
+ flags,
+ Contains("--otatools_build=git_master/cf_x86_64_phone-userdebug,"));
+ EXPECT_THAT(
+ flags,
+ Contains("--host_package_build=git_master/cf_x86_64_phone-userdebug,"));
+ EXPECT_THAT(flags,
+ Contains("--boot_build=git_master/cf_x86_64_phone-userdebug,"));
+ EXPECT_THAT(flags,
+ Contains("--kernel_build=git_master/cf_x86_64_phone-userdebug,"));
+ EXPECT_THAT(
+ flags,
+ Contains("--bootloader_build=git_master/cf_x86_64_phone-userdebug,"));
}
} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc b/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc
index 13daad9..6e767bb 100644
--- a/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc
+++ b/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc
@@ -19,116 +19,6 @@
#include "host/commands/cvd/unittests/parser/test_common.h"
namespace cuttlefish {
-#ifndef GENERATE_MVP_FLAGS_ONLY
-TEST(BootFlagsParserTest, ParseTwoInstancesExtraBootConfigFlagEmptyJson) {
- const char* test_string = R""""(
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- }
- }
- ]
-}
- )"""";
-
- Json::Value json_configs;
- std::string json_text(test_string);
-
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
- << "Invalid Json string";
- auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(FindConfig(*serialized_data, R"(--extra_bootconfig_args=,)"))
- << "extra_bootconfig_args flag is missing or wrongly formatted";
-}
-
-TEST(BootFlagsParserTest, ParseTwoInstancesExtraBootConfigFlagPartialJson) {
- const char* test_string = R""""(
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- },
- "boot": {
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- },
- "boot": {
- "extra_bootconfig_args": "androidboot.X=Y"
- }
- }
- ]
-}
- )"""";
-
- Json::Value json_configs;
- std::string json_text(test_string);
-
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
- << "Invalid Json string";
- auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(FindConfig(*serialized_data,
- R"(--extra_bootconfig_args=,androidboot.X=Y)"))
- << "extra_bootconfig_args flag is missing or wrongly formatted";
-}
-
-TEST(BootFlagsParserTest, ParseTwoInstancesExtraBootConfigFlagFullJson) {
- const char* test_string = R""""(
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- },
- "boot": {
- "extra_bootconfig_args": "androidboot.X=Y"
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- },
- "boot": {
- "extra_bootconfig_args": "androidboot.X=Z"
- }
- }
- ]
-}
- )"""";
-
- Json::Value json_configs;
- std::string json_text(test_string);
-
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
- << "Invalid Json string";
- auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(
- FindConfig(*serialized_data,
- R"(--extra_bootconfig_args=androidboot.X=Y,androidboot.X=Z)"))
- << "extra_bootconfig_args flag is missing or wrongly formatted";
-}
TEST(BootFlagsParserTest, ParseTwoInstancesBootAnimationFlagEmptyJson) {
const char* test_string = R""""(
@@ -350,116 +240,6 @@
<< "serial_number flag is missing or wrongly formatted";
}
-TEST(BootFlagsParserTest, ParseTwoInstancesRandomSerialFlagEmptyJson) {
- const char* test_string = R""""(
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- }
- }
- ]
-}
- )"""";
-
- Json::Value json_configs;
- std::string json_text(test_string);
-
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
- << "Invalid Json string";
- auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(
- FindConfig(*serialized_data, R"(--use_random_serial=false,false)"))
- << "use_random_serial flag is missing or wrongly formatted";
-}
-
-TEST(BootFlagsParserTest, ParseTwoInstancesRandomSerialFlagPartialJson) {
- const char* test_string = R""""(
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- },
- "security": {
- "serial_number": "CUTTLEFISHCVD101"
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- },
- "security": {
- "serial_number": "@random"
- }
- }
- ]
-}
- )"""";
-
- Json::Value json_configs;
- std::string json_text(test_string);
-
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
- << "Invalid Json string";
- auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(FindConfig(*serialized_data, R"(--use_random_serial=false,true)"))
- << "use_random_serial flag is missing or wrongly formatted";
-}
-
-TEST(BootFlagsParserTest, ParseTwoInstancesRandomSerialFlagFullJson) {
- const char* test_string = R""""(
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- },
- "security": {
- "serial_number": "@random"
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- },
- "security": {
- "serial_number": "@random"
- }
- }
- ]
-}
- )"""";
-
- Json::Value json_configs;
- std::string json_text(test_string);
-
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
- << "Invalid Json string";
- auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(FindConfig(*serialized_data, R"(--use_random_serial=true,true)"))
- << "use_random_serial flag is missing or wrongly formatted";
-}
-#endif
-
TEST(BootFlagsParserTest, ParseTwoInstancesEnforceSecurityFlagEmptyJson) {
const char* test_string = R""""(
{
@@ -570,7 +350,6 @@
<< "guest_enforce_security flag is missing or wrongly formatted";
}
-#ifndef GENERATE_MVP_FLAGS_ONLY
TEST(BootFlagsParserTest, ParseTwoInstancesKernelCmdFlagEmptyJson) {
const char* test_string = R""""(
{
@@ -689,6 +468,5 @@
R"(--extra_kernel_cmdline=androidboot.selinux=permissive,lpm_levels.sleep_disabled=1)"))
<< "extra_kernel_cmdline flag is missing or wrongly formatted";
}
-#endif
} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/parser/instance/vm_configs_test.cc b/host/commands/cvd/unittests/parser/instance/vm_configs_test.cc
index f72e551..605d82e 100644
--- a/host/commands/cvd/unittests/parser/instance/vm_configs_test.cc
+++ b/host/commands/cvd/unittests/parser/instance/vm_configs_test.cc
@@ -554,7 +554,6 @@
<< "setupwizard_mode flag is missing or wrongly formatted";
}
-#ifndef GENERATE_MVP_FLAGS_ONLY
TEST(VmFlagsParserTest, ParseTwoInstancesUuidFlagEmptyJson) {
const char* test_string = R""""(
{
@@ -659,7 +658,6 @@
R"(--uuid=870acfc4-c8c4-11e7-99ac-5065f31dc250,870acfc4-c8c4-11e7-99ac-5065f31dc251)"))
<< "uuid flag is missing or wrongly formatted";
}
-#endif
TEST(VmFlagsParserTest, ParseTwoInstancesSandboxFlagEmptyJson) {
const char* test_string = R""""(
diff --git a/host/commands/cvd/unittests/parser/instance/metrics_configs_test.cc b/host/commands/cvd/unittests/parser/metrics_configs_test.cc
similarity index 63%
rename from host/commands/cvd/unittests/parser/instance/metrics_configs_test.cc
rename to host/commands/cvd/unittests/parser/metrics_configs_test.cc
index 44c7bf7..56aedb8 100644
--- a/host/commands/cvd/unittests/parser/instance/metrics_configs_test.cc
+++ b/host/commands/cvd/unittests/parser/metrics_configs_test.cc
@@ -14,31 +14,64 @@
* limitations under the License.
*/
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <json/json.h>
+
+#include "common/libs/utils/result.h"
+#include "common/libs/utils/result_matchers.h"
#include "host/commands/cvd/parser/launch_cvd_parser.h"
#include "host/commands/cvd/unittests/parser/test_common.h"
namespace cuttlefish {
-TEST(MetricsFlagsParserTest, ParseOneInstanceMetricsReportInvalidValue) {
+
+using ::testing::IsTrue;
+using ::testing::Not;
+
+TEST(MetricsFlagsParserTest, ParseOneInstanceMetricsReportValidValue) {
const char* test_string = R""""(
{
"instances" :
[
{
- "metrics": {
- }
}
- ]
+ ],
+ "metrics": {
+ "enable": true
+ }
}
)"""";
Json::Value json_configs;
std::string json_text(test_string);
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
+ EXPECT_THAT(ParseJsonString(json_text, json_configs), IsTrue())
<< "Invalid Json string";
auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_FALSE(serialized_data.ok()) << serialized_data.error().Trace();
+ EXPECT_THAT(serialized_data, IsOk()) << serialized_data.error().Trace();
+}
+
+TEST(MetricsFlagsParserTest, ParseOneInstanceMetricsReportInvalidValue) {
+ const char* test_string = R""""(
+{
+ "instances" :
+ [
+ {
+ }
+ ],
+ "metrics": {
+ "enable": "foo"
+ }
+}
+ )"""";
+
+ Json::Value json_configs;
+ std::string json_text(test_string);
+
+ EXPECT_THAT(ParseJsonString(json_text, json_configs), IsTrue())
+ << "Invalid Json string";
+ auto serialized_data = LaunchCvdParserTester(json_configs);
+ EXPECT_THAT(serialized_data, Not(IsOk()));
}
TEST(MetricsFlagsParserTest, ParseOneInstancesMetricsReportFlagEmptyJson) {
@@ -55,12 +88,13 @@
Json::Value json_configs;
std::string json_text(test_string);
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
+ EXPECT_THAT(ParseJsonString(json_text, json_configs), IsTrue())
<< "Invalid Json string";
auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(
- FindConfig(*serialized_data, R"(--report_anonymous_usage_stats=n)"))
+ EXPECT_THAT(serialized_data, IsOk()) << serialized_data.error().Trace();
+ EXPECT_THAT(
+ FindConfig(*serialized_data, R"(--report_anonymous_usage_stats=n)"),
+ IsTrue())
<< "report_anonymous_usage_stats flag is missing or wrongly formatted";
}
@@ -80,12 +114,13 @@
Json::Value json_configs;
std::string json_text(test_string);
- EXPECT_TRUE(ParseJsonString(json_text, json_configs))
+ EXPECT_THAT(ParseJsonString(json_text, json_configs), IsTrue())
<< "Invalid Json string";
auto serialized_data = LaunchCvdParserTester(json_configs);
- EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
- EXPECT_TRUE(
- FindConfig(*serialized_data, R"(--report_anonymous_usage_stats=n)"))
+ EXPECT_THAT(serialized_data, IsOk()) << serialized_data.error().Trace();
+ EXPECT_THAT(
+ FindConfig(*serialized_data, R"(--report_anonymous_usage_stats=n)"),
+ IsTrue())
<< "report_anonymous_usage_stats flag is missing or wrongly formatted";
}
diff --git a/host/commands/cvd/unittests/parser/test_common.h b/host/commands/cvd/unittests/parser/test_common.h
index 41aec34..2d1dcc0 100644
--- a/host/commands/cvd/unittests/parser/test_common.h
+++ b/host/commands/cvd/unittests/parser/test_common.h
@@ -23,7 +23,6 @@
#include "common/libs/utils/result.h"
-#define GENERATE_MVP_FLAGS_ONLY true
namespace cuttlefish {
bool ParseJsonString(std::string& json_text, Json::Value& root);
diff --git a/host/commands/cvd_env/Android.bp b/host/commands/cvd_env/Android.bp
index 243153b..9589060 100644
--- a/host/commands/cvd_env/Android.bp
+++ b/host/commands/cvd_env/Android.bp
@@ -42,4 +42,9 @@
],
cpp_std: "c++17",
defaults: ["cuttlefish_host"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
diff --git a/host/commands/cvd_env/main.cc b/host/commands/cvd_env/main.cc
index bd1ca32..b0e215b 100644
--- a/host/commands/cvd_env/main.cc
+++ b/host/commands/cvd_env/main.cc
@@ -34,7 +34,6 @@
" Usage: cvd [selector options] env ls [service] [method] [-l]\n"
" service(optional) : gRPC service name\n"
" method(optional) : method name for given service\n"
- " -l(optional) : Use a long listing format\n"
" type: get detailed information for given request/reply type\n"
" Usage: cvd [selector options] env type [service] [method] [type]\n"
" service : gRPC service name\n"
@@ -47,6 +46,7 @@
" request : Protobuffer with json format\n\n"
"* \"cvd [selector_options] env\" can be replaced with:\n"
" \"cvd_internal_env [internal device name]\"\n";
+constexpr char kServiceControlEnvProxy[] = "ControlEnvProxyService";
bool ContainHelpOption(int argc, char** argv) {
for (int i = 0; i < argc; i++) {
@@ -68,15 +68,17 @@
const auto& receiver = argv[1];
const auto& cmd = argv[2];
- std::vector<std::string> options;
std::vector<std::string> args;
for (int i = 3; i < argc; i++) {
- if (android::base::StartsWith(argv[i], '-')) {
- options.push_back(argv[i]);
- } else {
+ // Ignore options, not to be applied when calling grpc_cli.
+ if (!android::base::StartsWith(argv[i], '-')) {
args.push_back(argv[i]);
}
}
+ if (args.size() > 0) {
+ CF_EXPECT(args[0].compare(kServiceControlEnvProxy) != 0,
+ "Prohibited service name");
+ }
const auto* config = CuttlefishConfig::Get();
CF_EXPECT(config != nullptr, "Unable to find the config");
@@ -90,10 +92,8 @@
"there is no instance of which name is "
<< receiver << ". please check instance name by cvd fleet");
- // TODO(265747873): Check if argument contains ControlEnvProxyService, not to
- // use this service by cvd env CLI.
- auto command_output = CF_EXPECT(
- HandleCmds(receiver_instance->grpc_socket_path(), cmd, args, options));
+ auto command_output =
+ CF_EXPECT(HandleCmds(receiver_instance->grpc_socket_path(), cmd, args));
std::cout << command_output;
diff --git a/host/commands/cvd_import_locations/Android.bp b/host/commands/cvd_import_locations/Android.bp
index a41f947..4f152c3 100644
--- a/host/commands/cvd_import_locations/Android.bp
+++ b/host/commands/cvd_import_locations/Android.bp
@@ -23,7 +23,6 @@
"libbase",
"libcuttlefish_fs",
"liblog",
- "libicuuc",
"libprotobuf-cpp-full",
"libgrpc++_unsecure",
],
@@ -55,6 +54,11 @@
"-D_XOPEN_SOURCE",
],
defaults: ["cvd_import_locations_defaults"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
cc_test_host {
@@ -79,4 +83,9 @@
"-D_XOPEN_SOURCE",
],
defaults: ["cvd_import_locations_defaults"],
-}
\ No newline at end of file
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
+}
diff --git a/host/commands/cvd_load_tester/defaults.json b/host/commands/cvd_load_tester/defaults.json
deleted file mode 100644
index 5a77af1..0000000
--- a/host/commands/cvd_load_tester/defaults.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048
- }
- },
- {
- "vm": {
- "memory_mb": 4096
- },
- "graphics":{
- "displays":[
- {
- "width": 1080,
- "height": 600,
- "dpi": 120
- },
- {
- "width": 400,
- "height": 600,
- "dpi": 150
- }
- ]
- }
- },
- {
- "vm": {
- "memory_mb": 4096
- },
- "graphics":{
- "displays":[
- {
- "width": 2560,
- "height": 1800,
- "dpi": 320
- }
- ]
- }
- }
- ]
- }
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/end_to_end_test/multi/TC1.json b/host/commands/cvd_load_tester/end_to_end_test/multi/TC1.json
deleted file mode 100644
index a0cb406..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/multi/TC1.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048
- }
- },
- {
- "vm": {
- "memory_mb": 4096
- },
- "graphics":{
- "displays":[
- {
- "width": 1080,
- "height": 600,
- "dpi": 120
- },
- {
- "width": 400,
- "height": 600,
- "dpi": 150
- }
- ]
- }
- },
- {
- "vm": {
- "memory_mb": 4096
- },
- "graphics":{
- "displays":[
- {
- "width": 2560,
- "height": 1800,
- "dpi": 320
- }
- ]
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_auto.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_auto.json
deleted file mode 100644
index 8f787fb..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_auto.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 4096
- },
- "graphics":{
- "displays":[
- {
- "width": 1080,
- "height": 600,
- "dpi": 120
- },
- {
- "width": 400,
- "height": 600,
- "dpi": 120
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_foldable.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_foldable.json
deleted file mode 100644
index 5419c22..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_foldable.json
+++ /dev/null
@@ -1,65 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 4096,
- "custom_actions" : [
- {
- "device_states": [
- {
- "lid_switch_open": false,
- "hinge_angle_value": 0
- }
- ],
- "button":{
- "command":"device_state_closed",
- "title":"Device State Closed",
- "icon_name":"smartphone"
- }
- },
- {
- "device_states": [
- {
- "lid_switch_open": true,
- "hinge_angle_value": 90
- }
- ],
- "button":{
- "command":"device_state_half_opened",
- "title":"Device State Half-Opened",
- "icon_name":"laptop"
- }
- },
- {
- "device_states": [
- {
- "lid_switch_open": true,
- "hinge_angle_value": 180
- }
- ],
- "button":{
- "command":"device_state_opened",
- "title":"Device State Opened",
- "icon_name":"tablet"
- }
- }
- ]
- },
- "graphics":{
- "displays":[
- {
- "width": 1768,
- "height": 2208,
- "dpi": 374
- },
- {
- "width": 832,
- "height": 2268,
- "dpi": 387
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_go.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_go.json
deleted file mode 100644
index ef24d44..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_go.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048
- },
- "graphics":{
- "displays":[
- {
- "width": 720,
- "height": 1280,
- "dpi": 320
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_phone.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_phone.json
deleted file mode 100644
index ef24d44..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_phone.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048
- },
- "graphics":{
- "displays":[
- {
- "width": 720,
- "height": 1280,
- "dpi": 320
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_slim.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_slim.json
deleted file mode 100644
index 19c4760..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_slim.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048,
- "use_sdcard" : false
- },
- "graphics":{
- "displays":[
- {
- "width": 720,
- "height": 1280,
- "dpi": 320
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_tablet.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_tablet.json
deleted file mode 100644
index fe6217e..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_tablet.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 4096
- },
- "graphics":{
- "displays":[
- {
- "width": 2560,
- "height": 1800,
- "dpi": 320
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_tv.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_tv.json
deleted file mode 100644
index 7f288f4..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_tv.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048
- },
- "graphics":{
- "displays":[
- {
- "width": 1920,
- "height": 1080,
- "dpi": 213
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/end_to_end_test/single/TC_wear.json b/host/commands/cvd_load_tester/end_to_end_test/single/TC_wear.json
deleted file mode 100644
index 311c01f..0000000
--- a/host/commands/cvd_load_tester/end_to_end_test/single/TC_wear.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 1536,
- "use_sdcard" : false
- },
- "graphics":{
- "displays":[
- {
- "width": 450,
- "height": 450,
- "dpi": 320
- }
- ]
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/main.cc b/host/commands/cvd_load_tester/main.cc
deleted file mode 100644
index 28a35dd..0000000
--- a/host/commands/cvd_load_tester/main.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <fstream>
-#include <iostream>
-#include <string>
-
-#include <android-base/logging.h>
-#include <gflags/gflags.h>
-
-#include "host/commands/cvd/parser/load_configs_parser.h"
-
-DEFINE_string(config_file_path, "", "config file path for default configs");
-
-namespace cuttlefish {
-int CvdLoadParserMain(int argc, char** argv) {
- ::android::base::InitLogging(argv, android::base::StderrLogger);
- google::ParseCommandLineFlags(&argc, &argv, true);
-
- auto json_configs = cuttlefish::ParseJsonFile(FLAGS_config_file_path);
- if (!json_configs.ok()) {
- LOG(INFO) << "parsing input file failed";
- return 1;
- }
-
- auto cvd_flags = cuttlefish::ParseCvdConfigs(*json_configs);
- if (!cvd_flags.ok()) {
- LOG(INFO) << "parsing json configs failed";
- return 1;
- }
- LOG(INFO) << "Parsing succeeded";
- for (auto& parsed_launch_flag : cvd_flags->launch_cvd_flags) {
- LOG(INFO) << parsed_launch_flag;
- }
-
- LOG(INFO) << "credential_source = "
- << cvd_flags->fetch_cvd_flags.credential_source.value_or("");
-
- int i = 0;
- for (const auto& parsed_fetch_instance_flag :
- cvd_flags->fetch_cvd_flags.instances) {
- LOG(INFO) << i << " -- "
- << parsed_fetch_instance_flag.default_build.value_or("") << ","
- << parsed_fetch_instance_flag.system_build.value_or("") << ","
- << parsed_fetch_instance_flag.kernel_build.value_or("") << ","
- << parsed_fetch_instance_flag.should_fetch;
- i++;
- }
-
- return 0;
-}
-} // namespace cuttlefish
-int main(int argc, char** argv) {
- return cuttlefish::CvdLoadParserMain(argc, argv);
-}
diff --git a/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC1.json b/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC1.json
deleted file mode 100644
index 3718bb7..0000000
--- a/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC1.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "instances" :
- [
- {
- "graphics": {
- }
- },
- {
- "graphics": {
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC2.json b/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC2.json
deleted file mode 100644
index c147f4a..0000000
--- a/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC2.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "instances" :
- [
- {
- "graphics":{
- "displays":[
- {
- }
- ]
- }
- },
- {
- "graphics":{
- "displays":[
- {
- },
- {
- }
- ]
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC3.json b/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC3.json
deleted file mode 100644
index 4e9195e..0000000
--- a/host/commands/cvd_load_tester/mvp_features/graphics/displays/TC3.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "instances" :
- [
- {
- "graphics":{
- "displays":[
- {
- "width": 1080,
- "height": 600,
- "dpi": 120,
- "refresh_rate_hertz": 60
- },
- {
- "width": 400,
- "height": 600,
- "dpi": 120,
- "refresh_rate_hertz": 60
- }
- ]
- }
- },
- {
- "graphics":{
- "displays":[
- {
- "width": 2560,
- "height": 1800,
- "dpi": 320,
- "refresh_rate_hertz": 60
- }
- ]
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/security/guest_enforce_security/TC1.json b/host/commands/cvd_load_tester/mvp_features/security/guest_enforce_security/TC1.json
deleted file mode 100644
index da19f0f..0000000
--- a/host/commands/cvd_load_tester/mvp_features/security/guest_enforce_security/TC1.json
+++ /dev/null
@@ -1,17 +0,0 @@
-
-{
- "instances" :
- [
- {
- "security": {
- }
- },
- {
- "vm": {
- },
- "security": {
- "guest_enforce_security": false
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/security/guest_enforce_security/TC2.json b/host/commands/cvd_load_tester/mvp_features/security/guest_enforce_security/TC2.json
deleted file mode 100644
index a237082..0000000
--- a/host/commands/cvd_load_tester/mvp_features/security/guest_enforce_security/TC2.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "instances" :
- [
- {
- "security": {
- "guest_enforce_security": false
- }
- },
- {
- "security": {
- "guest_enforce_security": false
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/cpus/TC1.json b/host/commands/cvd_load_tester/mvp_features/vm/cpus/TC1.json
deleted file mode 100644
index 7c8cf89..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/cpus/TC1.json
+++ /dev/null
@@ -1,15 +0,0 @@
-
-{
- "instances" :
- [
- {
- "vm": {
- }
- },
- {
- "vm": {
- "cpus": 4
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/cpus/TC2.json b/host/commands/cvd_load_tester/mvp_features/vm/cpus/TC2.json
deleted file mode 100644
index a975433..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/cpus/TC2.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "cpus": 4
- }
- },
- {
- "vm": {
- "cpus": 6
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/custom_actions/TC1.json b/host/commands/cvd_load_tester/mvp_features/vm/custom_actions/TC1.json
deleted file mode 100644
index 239e0d4..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/custom_actions/TC1.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 2048
- }
- },
- {
- "vm": {
- "memory_mb": 2048,
- "custom_actions" : [
- {
- "shell_command":"am start -a android.intent.action.VIEW -d https://www.android1.com/",
- "button":{
- "command":"web",
- "title":"Web Page",
- "icon_name":"language"
- }
- },
- {
- "server":"cuttlefish_example_action_server",
- "buttons":[
- {
- "command":"settings",
- "title":"Quick Settings",
- "icon_name":"settings"
- },
- {
- "command":"alert",
- "title":"Do Not Disturb",
- "icon_name":"notifications_paused"
- }
- ]
- }
- ]
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC1.json b/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC1.json
deleted file mode 100644
index 090e179..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC1.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC2.json b/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC2.json
deleted file mode 100644
index d88c7b9..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC2.json
+++ /dev/null
@@ -1,19 +0,0 @@
-
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- "enable_sandbox": true
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC3.json b/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC3.json
deleted file mode 100644
index 03055b9..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/enable_sandbox/TC3.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- "enable_sandbox": true
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- "enable_sandbox": true
- }
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/memory_mb/TC1.json b/host/commands/cvd_load_tester/mvp_features/vm/memory_mb/TC1.json
deleted file mode 100644
index a4156a7..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/memory_mb/TC1.json
+++ /dev/null
@@ -1,15 +0,0 @@
-
-{
- "instances" :
- [
- {
- "vm": {
- }
- },
- {
- "vm": {
- "memory_mb": 4096
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/memory_mb/TC2.json b/host/commands/cvd_load_tester/mvp_features/vm/memory_mb/TC2.json
deleted file mode 100644
index c2a0730..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/memory_mb/TC2.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "memory_mb": 4096
- }
- },
- {
- "vm": {
- "memory_mb": 8192
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC1.json b/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC1.json
deleted file mode 100644
index aba722d..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC1.json
+++ /dev/null
@@ -1,13 +0,0 @@
-
- {
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- },
- "setupwizard_mode": "ENABLED"
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC2.json b/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC2.json
deleted file mode 100644
index eb8815d..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC2.json
+++ /dev/null
@@ -1,18 +0,0 @@
-
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC3.json b/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC3.json
deleted file mode 100644
index 4b19f60..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC3.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- },
- "setupwizard_mode": "REQUIRED"
- }
- }
- ]
-}
-
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC4.json b/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC4.json
deleted file mode 100644
index d052087..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/setupwizard_mode/TC4.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- },
- "setupwizard_mode": "OPTIONAL"
- }
- },
- {
- "vm": {
- "crosvm":{
- },
- "setupwizard_mode": "REQUIRED"
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC1.json b/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC1.json
deleted file mode 100644
index 01e4963..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC1.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- }
- },
- {
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC2.json b/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC2.json
deleted file mode 100644
index 9b25147..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC2.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "qemu":{
- }
- }
- },
- {
- "vm": {
- "crosvm":{
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC3.json b/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC3.json
deleted file mode 100644
index fe2d4ec..0000000
--- a/host/commands/cvd_load_tester/mvp_features/vm/vm_manager/TC3.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "instances" :
- [
- {
- "vm": {
- "crosvm":{
- }
- }
- },
- {
- "vm": {
- "gem5":{
- }
- }
- }
- ]
-}
\ No newline at end of file
diff --git a/host/commands/cvd_load_tester/templates_inheritance/custom/TC1.json b/host/commands/cvd_load_tester/templates_inheritance/custom/TC1.json
deleted file mode 100644
index 60fae2c..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/custom/TC1.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "phone",
- "vm": {
- "memory_mb": 4096
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/custom/TC2.json b/host/commands/cvd_load_tester/templates_inheritance/custom/TC2.json
deleted file mode 100644
index 280d7f3..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/custom/TC2.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "phone",
- "vm": {
- "memory_mb": 4096
- }
- },
- {
- "@import" : "tablet",
- "vm": {
- "memory_mb": 8192,
- "cpus": 4
- }
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/multi/TC1.json b/host/commands/cvd_load_tester/templates_inheritance/multi/TC1.json
deleted file mode 100644
index 7c4b158..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/multi/TC1.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "auto"
- },
- {
- "@import" : "go"
- },
- {
- "@import" : "phone"
- },
- {
- "@import" : "slim"
- },
- {
- "@import" : "tablet"
- },
- {
- "@import" : "tv"
- },
- {
- "@import" : "wearable"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/multi/TC2.json b/host/commands/cvd_load_tester/templates_inheritance/multi/TC2.json
deleted file mode 100644
index bb4c7fb..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/multi/TC2.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "auto"
- },
- {
- "@import" : "foldable"
- },
- {
- "@import" : "go"
- },
- {
- "@import" : "phone"
- },
- {
- "@import" : "slim"
- },
- {
- "@import" : "tablet"
- },
- {
- "@import" : "tv"
- },
- {
- "@import" : "wearable"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_auto.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_auto.json
deleted file mode 100644
index ded6c15..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_auto.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "auto"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_foldable.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_foldable.json
deleted file mode 100644
index 1df8e1a..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_foldable.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "foldable"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_go.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_go.json
deleted file mode 100644
index b554eaa..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_go.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "go"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_phone.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_phone.json
deleted file mode 100644
index 13c5f4b..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_phone.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "phone"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_slim.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_slim.json
deleted file mode 100644
index a0ab45f..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_slim.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "slim"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_tablet.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_tablet.json
deleted file mode 100644
index f62fcee..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_tablet.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "tablet"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_tv.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_tv.json
deleted file mode 100644
index bfbae34..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_tv.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "tv"
- }
- ]
-}
diff --git a/host/commands/cvd_load_tester/templates_inheritance/single/TC_wear.json b/host/commands/cvd_load_tester/templates_inheritance/single/TC_wear.json
deleted file mode 100644
index 06c85ab..0000000
--- a/host/commands/cvd_load_tester/templates_inheritance/single/TC_wear.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "instances" :
- [
- {
- "@import" : "wearable"
- }
- ]
-}
diff --git a/host/commands/cvd_send_sms/Android.bp b/host/commands/cvd_send_sms/Android.bp
index 739aecd..d280cd6 100644
--- a/host/commands/cvd_send_sms/Android.bp
+++ b/host/commands/cvd_send_sms/Android.bp
@@ -28,7 +28,7 @@
defaults: ["cuttlefish_buildhost_only"],
}
-cc_library_static {
+cc_library {
name: "libcvd_send_sms",
srcs: [
"sms_sender.cc",
diff --git a/host/commands/cvd_send_sms/main.cc b/host/commands/cvd_send_sms/main.cc
index 8ada47d..19efe14 100644
--- a/host/commands/cvd_send_sms/main.cc
+++ b/host/commands/cvd_send_sms/main.cc
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "gflags/gflags.h"
-#include "android-base/logging.h"
+#include <android-base/logging.h>
+#include <gflags/gflags.h>
+
#include "common/libs/fs/shared_fd.h"
#include "host/commands/cvd_send_sms/sms_sender.h"
-const std::string kUsage = R"(
+constexpr char kUsage[] = R"(
NAME
cvd_send_sms - send SMSs to cvds.
diff --git a/host/commands/cvd_update_location/Android.bp b/host/commands/cvd_update_location/Android.bp
index 7b9bf66..19fb4e9 100644
--- a/host/commands/cvd_update_location/Android.bp
+++ b/host/commands/cvd_update_location/Android.bp
@@ -23,7 +23,6 @@
"libbase",
"libcuttlefish_fs",
"liblog",
- "libicuuc",
"libprotobuf-cpp-full",
"libgrpc++_unsecure",
],
@@ -54,4 +53,9 @@
"-D_XOPEN_SOURCE",
],
defaults: ["cvd_update_location_defaults"],
-}
\ No newline at end of file
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
+}
diff --git a/host/commands/display/main.cpp b/host/commands/display/main.cpp
index 87f1dab..d41ba78 100644
--- a/host/commands/display/main.cpp
+++ b/host/commands/display/main.cpp
@@ -189,9 +189,9 @@
const std::vector<Flag> remove_displays_flags = {
GflagsCompatFlag(kDisplayFlag)
.Help("Display id of a display to remove.")
- .Setter([&](const FlagMatch& match) {
+ .Setter([&](const FlagMatch& match) -> Result<void> {
displays.push_back(match.value);
- return true;
+ return {};
}),
};
auto parse_res = ParseFlags(remove_displays_flags, args);
diff --git a/host/commands/echo_server/Android.bp b/host/commands/echo_server/Android.bp
index a69ba62..504d6c8 100644
--- a/host/commands/echo_server/Android.bp
+++ b/host/commands/echo_server/Android.bp
@@ -16,7 +16,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_host_static {
+cc_library {
name: "libecho_server",
shared_libs: [
"libprotobuf-cpp-full",
@@ -42,6 +42,11 @@
"external/grpc-grpc/include",
"external/protobuf/src",
],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
cc_binary_host {
@@ -63,6 +68,11 @@
"-Wno-unused-parameter",
],
defaults: ["cuttlefish_host"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
filegroup {
diff --git a/host/commands/gnss_grpc_proxy/Android.bp b/host/commands/gnss_grpc_proxy/Android.bp
index 58fd6a1..2b4ac84 100644
--- a/host/commands/gnss_grpc_proxy/Android.bp
+++ b/host/commands/gnss_grpc_proxy/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcvd_gnss_grpc_proxy",
shared_libs: [
"libbase",
@@ -49,6 +49,11 @@
"external/grpc-grpc/include",
"external/protobuf/src",
],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
cc_binary_host {
@@ -75,6 +80,11 @@
"-D_XOPEN_SOURCE",
],
defaults: ["cuttlefish_host"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
filegroup {
diff --git a/host/commands/health/Android.bp b/host/commands/health/Android.bp
index 142c79f..2ebb022 100644
--- a/host/commands/health/Android.bp
+++ b/host/commands/health/Android.bp
@@ -36,5 +36,5 @@
"libcuttlefish_vm_manager",
"libgflags",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/health/health.cpp b/host/commands/health/health.cpp
index aad9869..9bb01a2 100644
--- a/host/commands/health/health.cpp
+++ b/host/commands/health/health.cpp
@@ -28,7 +28,7 @@
"crosvm_control.sock");
}
-std::string USAGE_MESSAGE =
+static constexpr char kUsageMessage[] =
"<key> [value]\n"
"Excluding the value will enumerate the possible values to set\n"
"\n"
@@ -74,13 +74,13 @@
}
int usage() {
- std::cout << "health " << USAGE_MESSAGE;
+ std::cout << "health " << kUsageMessage;
return 1;
}
int main(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
- gflags::SetUsageMessage(USAGE_MESSAGE);
+ gflags::SetUsageMessage(kUsageMessage);
auto config = cuttlefish::CuttlefishConfig::Get();
if (!config) {
diff --git a/host/commands/host_bugreport/Android.bp b/host/commands/host_bugreport/Android.bp
index 392f104..1f87457 100644
--- a/host/commands/host_bugreport/Android.bp
+++ b/host/commands/host_bugreport/Android.bp
@@ -38,5 +38,5 @@
"libcuttlefish_vm_manager",
"libgflags",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/kernel_log_monitor/kernel_log_server.cc b/host/commands/kernel_log_monitor/kernel_log_server.cc
index a67d0f9..2ced97a 100644
--- a/host/commands/kernel_log_monitor/kernel_log_server.cc
+++ b/host/commands/kernel_log_monitor/kernel_log_server.cc
@@ -57,7 +57,8 @@
{cuttlefish::kWifiConnectedMessage, Event::WifiNetworkConnected, kBare},
{cuttlefish::kEthernetConnectedMessage, Event::EthernetNetworkConnected, kBare},
{cuttlefish::kAdbdStartedMessage, Event::AdbdStarted, kBare},
- {cuttlefish::kFastbootdStartedMessage, Event::FastbootdStarted, kBare},
+ {cuttlefish::kFastbootdStartedMessage, Event::FastbootStarted, kBare},
+ {cuttlefish::kFastbootStartedMessage, Event::FastbootStarted, kBare},
{cuttlefish::kScreenChangedMessage, Event::ScreenChanged, kKeyValuePair},
{cuttlefish::kBootloaderLoadedMessage, Event::BootloaderLoaded, kBare},
{cuttlefish::kKernelLoadedMessage, Event::KernelLoaded, kBare},
diff --git a/host/commands/kernel_log_monitor/kernel_log_server.h b/host/commands/kernel_log_monitor/kernel_log_server.h
index cdbd9f0..ec33f71 100644
--- a/host/commands/kernel_log_monitor/kernel_log_server.h
+++ b/host/commands/kernel_log_monitor/kernel_log_server.h
@@ -42,7 +42,7 @@
* that we're booting a device.
*/
DisplayPowerModeChanged = 10,
- FastbootdStarted = 11
+ FastbootStarted = 11
};
enum class SubscriptionAction {
diff --git a/host/commands/log_tee/Android.bp b/host/commands/log_tee/Android.bp
index 72bc93d..ca2ea98 100644
--- a/host/commands/log_tee/Android.bp
+++ b/host/commands/log_tee/Android.bp
@@ -30,12 +30,16 @@
"libcuttlefish_utils",
"libfruit",
"libjsoncpp",
- "libnl",
],
static_libs: [
"libgflags",
"libcuttlefish_host_config",
"libcuttlefish_vm_manager",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/log_tee/log_tee.cpp b/host/commands/log_tee/log_tee.cpp
index cdfc4a0..3c3661f 100644
--- a/host/commands/log_tee/log_tee.cpp
+++ b/host/commands/log_tee/log_tee.cpp
@@ -14,7 +14,9 @@
// limitations under the License.
#include <signal.h>
+#ifdef __linux__
#include <sys/signalfd.h>
+#endif
#include <regex>
@@ -84,10 +86,12 @@
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, NULL) == 0)
<< "sigprocmask failed: " << strerror(errno);
+#ifdef __linux__
int sfd = signalfd(-1, &mask, 0);
CHECK(sfd >= 0) << "signalfd failed: " << strerror(errno);
auto int_fd = cuttlefish::SharedFD::Dup(sfd);
close(sfd);
+#endif
auto poll_fds = std::vector<cuttlefish::PollSharedFd>{
cuttlefish::PollSharedFd{
@@ -95,11 +99,13 @@
.events = POLL_IN,
.revents = 0,
},
+#ifdef __linux__
cuttlefish::PollSharedFd{
.fd = int_fd,
.events = POLL_IN,
.revents = 0,
},
+#endif
};
LOG(DEBUG) << "Starting to read from process " << FLAGS_process_name;
@@ -168,6 +174,7 @@
// handle any signals yet.
continue;
}
+#ifdef __linux__
if (poll_fds[1].revents) {
struct signalfd_siginfo siginfo;
int s = int_fd->Read(&siginfo, sizeof(siginfo));
@@ -177,6 +184,7 @@
<< "unexpected signal: " << siginfo.ssi_signo;
break;
}
+#endif
}
LOG(DEBUG) << "Finished reading from process " << FLAGS_process_name;
diff --git a/host/commands/mkenvimage_slim/Android.bp b/host/commands/mkenvimage_slim/Android.bp
index ead2647..53656c9 100644
--- a/host/commands/mkenvimage_slim/Android.bp
+++ b/host/commands/mkenvimage_slim/Android.bp
@@ -19,7 +19,7 @@
cc_binary {
name: "mkenvimage_slim",
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
srcs: [
"mkenvimage_slim.cc",
],
diff --git a/host/commands/mkenvimage_slim/mkenvimage_slim.cc b/host/commands/mkenvimage_slim/mkenvimage_slim.cc
index 704d429..bffd3a0 100644
--- a/host/commands/mkenvimage_slim/mkenvimage_slim.cc
+++ b/host/commands/mkenvimage_slim/mkenvimage_slim.cc
@@ -17,8 +17,6 @@
// https://github.com/u-boot/u-boot/blob/master/tools/mkenvimage.c The bare
// minimum amount of functionality for our application is replicated.
-#include <iostream>
-
#include <zlib.h>
#include <android-base/logging.h>
@@ -40,19 +38,18 @@
DEFINE_string(output_path, "", "output file path");
DEFINE_string(input_path, "", "input file path");
namespace cuttlefish {
-namespace {
-std::string USAGE_MESSAGE =
+
+static constexpr char kUsageMessage[] =
"<flags>\n"
"\n"
"env_size - length in bytes of the resulting env image. Defaults to 4kb.\n"
"input_path - path to input key value mapping as a text file\n"
"output_path - path to write resulting environment image including CRC "
"to\n";
-} // namespace
Result<int> MkenvimageSlimMain(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
- gflags::SetUsageMessage(USAGE_MESSAGE);
+ gflags::SetUsageMessage(kUsageMessage);
gflags::ParseCommandLineFlags(&argc, &argv, true);
CF_EXPECT(FLAGS_output_path != "", "Output env path isn't defined.");
CF_EXPECT(FLAGS_env_size != 0, "env size can't be 0.");
diff --git a/host/commands/modem_simulator/call_service.cpp b/host/commands/modem_simulator/call_service.cpp
index 7e40870..c809e03 100644
--- a/host/commands/modem_simulator/call_service.cpp
+++ b/host/commands/modem_simulator/call_service.cpp
@@ -189,6 +189,7 @@
ss << port;
auto remote_port = ss.str();
auto remote_client = ConnectToRemoteCvd(remote_port);
+ auto client_id = ClientId();
if (!remote_client->IsOpen()) {
client.SendCommandResponse(kCmeErrorNoNetworkService);
return;
@@ -200,21 +201,21 @@
}
if (channel_monitor_) {
- channel_monitor_->SetRemoteClient(remote_client, false);
+ client_id = channel_monitor_->SetRemoteClient(remote_client, false);
}
ss.clear();
ss.str("");
ss << "AT+REMOTECALL=4,0,0,\"" << local_host_port << "\",129";
- SendCommandToRemote(remote_client, "REM0");
- SendCommandToRemote(remote_client, ss.str());
+ SendCommandToRemote(client_id, "REM0");
+ SendCommandToRemote(client_id, ss.str());
CallStatus call_status(remote_port);
call_status.is_remote_call = true;
call_status.is_mobile_terminated = false;
call_status.call_state = CallStatus::CALL_STATE_DIALING;
- call_status.remote_client = remote_client;
+ call_status.remote_client = client_id;
auto index = FindFreeCallIndex();
auto call_token = std::make_pair(index, call_status.number);
@@ -693,7 +694,7 @@
if (network_service_) {
if (network_service_->isRadioOff()) {
LOG(DEBUG) << " radio is off, reject incoming call from: " << number;
- client.client_fd->Close();
+ network_service_->CloseRemoteConnection(client.Id());
return;
}
}
@@ -703,7 +704,7 @@
call_status.is_multi_party = mpty;
call_status.is_mobile_terminated = true;
call_status.is_international = (num_type == 145);
- call_status.remote_client = client.client_fd;
+ call_status.remote_client = client.Id();
call_status.call_state = CallStatus::CALL_STATE_INCOMING;
auto index = FindFreeCallIndex();
diff --git a/host/commands/modem_simulator/call_service.h b/host/commands/modem_simulator/call_service.h
index f57eb05..c3396c0 100644
--- a/host/commands/modem_simulator/call_service.h
+++ b/host/commands/modem_simulator/call_service.h
@@ -135,7 +135,7 @@
bool is_voice_mode;
bool is_multi_party;
bool is_remote_call;
- std::optional<cuttlefish::SharedFD> remote_client;
+ std::optional<ClientId> remote_client;
std::optional<int32_t> timeout_serial;
std::string number;
bool can_present_number;
diff --git a/host/commands/modem_simulator/channel_monitor.cpp b/host/commands/modem_simulator/channel_monitor.cpp
index 31bc5f3..2dc032c 100644
--- a/host/commands/modem_simulator/channel_monitor.cpp
+++ b/host/commands/modem_simulator/channel_monitor.cpp
@@ -16,20 +16,33 @@
#include "host/commands/modem_simulator/channel_monitor.h"
+#include <algorithm>
+
#include <android-base/logging.h>
#include <android-base/strings.h>
-#include <algorithm>
-
+#include "common/libs/fs/shared_buf.h"
+#include "common/libs/fs/shared_select.h"
#include "host/commands/modem_simulator/modem_simulator.h"
namespace cuttlefish {
constexpr int32_t kMaxCommandLength = 4096;
-Client::Client(cuttlefish::SharedFD fd) : client_fd(fd) {}
+size_t ClientId::next_id_ = 0;
-Client::Client(cuttlefish::SharedFD fd, ClientType client_type)
+ClientId::ClientId() {
+ id_ = next_id_;
+ next_id_++;
+}
+
+bool ClientId::operator==(const ClientId& other) const {
+ return id_ == other.id_;
+}
+
+Client::Client(SharedFD fd) : client_fd(fd) {}
+
+Client::Client(SharedFD fd, ClientType client_type)
: type(client_type), client_fd(fd) {}
bool Client::operator==(const Client& other) const {
@@ -47,8 +60,8 @@
}
LOG(VERBOSE) << " AT< " << response;
- std::lock_guard<std::mutex> autolock(const_cast<Client*>(this)->write_mutex);
- client_fd->Write(response.data(), response.size());
+ std::lock_guard<std::mutex> lock(write_mutex);
+ WriteAll(client_fd, response);
}
void Client::SendCommandResponse(
@@ -58,19 +71,20 @@
}
}
-ChannelMonitor::ChannelMonitor(ModemSimulator* modem,
- cuttlefish::SharedFD server)
- : modem_(modem), server_(server) {
- if (!cuttlefish::SharedFD::Pipe(&read_pipe_, &write_pipe_)) {
+ChannelMonitor::ChannelMonitor(ModemSimulator& modem, SharedFD server)
+ : modem_(modem), server_(std::move(server)) {
+ if (!SharedFD::Pipe(&read_pipe_, &write_pipe_)) {
LOG(ERROR) << "Unable to create pipe, ignore";
}
- if (server_->IsOpen())
+ if (server_->IsOpen()) {
monitor_thread_ = std::thread([this]() { MonitorLoop(); });
+ }
}
-void ChannelMonitor::SetRemoteClient(cuttlefish::SharedFD client, bool is_accepted) {
+ClientId ChannelMonitor::SetRemoteClient(SharedFD client, bool is_accepted) {
auto remote_client = std::make_unique<Client>(client, Client::REMOTE);
+ auto id = remote_client->Id();
if (is_accepted) {
// There may be new data from remote client before select.
@@ -90,10 +104,11 @@
} else {
LOG(ERROR) << "Pipe created fail, can't trigger monitor loop";
}
+ return id;
}
void ChannelMonitor::AcceptIncomingConnection() {
- auto client_fd = cuttlefish::SharedFD::Accept(*server_);
+ auto client_fd = SharedFD::Accept(*server_);
if (!client_fd->IsOpen()) {
LOG(ERROR) << "Error accepting connection on socket: " << client_fd->StrError();
} else {
@@ -102,7 +117,7 @@
clients_.push_back(std::move(client));
if (clients_.size() == 1) {
// The first connected client default to be the unsolicited commands channel
- modem_->OnFirstClientConnected();
+ modem_.OnFirstClientConnected();
}
}
}
@@ -145,7 +160,7 @@
// Split into commands and dispatch
size_t pos = 0, r_pos = 0; // '\r' or '\n'
while (r_pos != std::string::npos) {
- if (modem_->IsWaitingSmsPdu()) {
+ if (modem_.IsWaitingSmsPdu()) {
r_pos = commands.find('\032', pos); // In sms, find ctrl-z
} else {
r_pos = commands.find('\r', pos);
@@ -154,7 +169,7 @@
auto command = commands.substr(pos, r_pos - pos);
if (command.size() > 0) { // "\r\r" ?
LOG(VERBOSE) << "AT> " << command;
- modem_->DispatchCommand(client, command);
+ modem_.DispatchCommand(client, command);
}
pos = r_pos + 1; // Skip '\r'
} else if (pos < commands.length()) { // Incomplete command
@@ -174,10 +189,10 @@
}
}
-void ChannelMonitor::SendRemoteCommand(cuttlefish::SharedFD client, std::string& response) {
+void ChannelMonitor::SendRemoteCommand(ClientId client, std::string& response) {
auto iter = remote_clients_.begin();
for (; iter != remote_clients_.end(); ++iter) {
- if (iter->get()->client_fd == client) {
+ if (iter->get()->Id() == client) {
iter->get()->SendCommandResponse(response);
return;
}
@@ -185,10 +200,10 @@
LOG(DEBUG) << "Remote client has closed.";
}
-void ChannelMonitor::CloseRemoteConnection(cuttlefish::SharedFD client) {
+void ChannelMonitor::CloseRemoteConnection(ClientId client) {
auto iter = remote_clients_.begin();
for (; iter != remote_clients_.end(); ++iter) {
- if (iter->get()->client_fd == client) {
+ if (iter->get()->Id() == client) {
iter->get()->client_fd->Close();
iter->get()->is_valid = false;
@@ -216,7 +231,8 @@
}
}
-static void removeInvalidClients(std::vector<std::unique_ptr<Client>>& clients) {
+void ChannelMonitor::removeInvalidClients(
+ std::vector<std::unique_ptr<Client>>& clients) {
auto iter = clients.begin();
for (; iter != clients.end();) {
if (iter->get()->is_valid) {
diff --git a/host/commands/modem_simulator/channel_monitor.h b/host/commands/modem_simulator/channel_monitor.h
index 6dc7c4a..1e86bf5 100644
--- a/host/commands/modem_simulator/channel_monitor.h
+++ b/host/commands/modem_simulator/channel_monitor.h
@@ -19,7 +19,9 @@
#include <thread>
#include <vector>
-#include "common/libs/fs/shared_select.h"
+#include "common/libs/fs/shared_fd.h"
+
+class ModemServiceTest;
namespace cuttlefish {
@@ -31,6 +33,17 @@
kServerError = 2,
};
+class ClientId {
+ public:
+ ClientId();
+
+ bool operator==(const ClientId&) const;
+
+ private:
+ static size_t next_id_;
+ size_t id_;
+};
+
/**
* Client object managed by ChannelMonitor, contains two types, the RIL client
* and the remote client of other cuttlefish instance.
@@ -41,17 +54,10 @@
public:
enum ClientType { RIL, REMOTE };
- ClientType type = RIL;
- cuttlefish::SharedFD client_fd;
- std::string incomplete_command;
- std::mutex write_mutex;
- bool first_read_command_; // Only used when ClientType::REMOTE
- bool is_valid = true;
-
Client() = default;
~Client() = default;
- Client(cuttlefish::SharedFD fd);
- Client(cuttlefish::SharedFD fd, ClientType client_type);
+ Client(SharedFD fd);
+ Client(SharedFD fd, ClientType client_type);
Client(const Client& client) = delete;
Client(Client&& client) = delete;
@@ -61,25 +67,40 @@
void SendCommandResponse(std::string response) const;
void SendCommandResponse(const std::vector<std::string>& responses) const;
+
+ ClientId Id() const { return id_; }
+ ClientType Type() const { return type; }
+
+ private:
+ friend class ChannelMonitor;
+ friend class ::ModemServiceTest;
+
+ ClientId id_;
+ ClientType type = RIL;
+ SharedFD client_fd;
+ std::string incomplete_command;
+ mutable std::mutex write_mutex;
+ bool first_read_command_; // Only used when ClientType::REMOTE
+ bool is_valid = true;
};
class ChannelMonitor {
public:
- ChannelMonitor(ModemSimulator* modem, cuttlefish::SharedFD server);
+ ChannelMonitor(ModemSimulator& modem, cuttlefish::SharedFD server);
~ChannelMonitor();
ChannelMonitor(const ChannelMonitor&) = delete;
ChannelMonitor& operator=(const ChannelMonitor&) = delete;
- void SetRemoteClient(cuttlefish::SharedFD client, bool is_accepted);
- void SendRemoteCommand(cuttlefish::SharedFD client, std::string& response);
- void CloseRemoteConnection(cuttlefish::SharedFD client);
+ ClientId SetRemoteClient(SharedFD client, bool is_accepted);
+ void SendRemoteCommand(ClientId client, std::string& response);
+ void CloseRemoteConnection(ClientId client);
// For modem services to send unsolicited commands
void SendUnsolicitedCommand(std::string& response);
private:
- ModemSimulator* modem_;
+ ModemSimulator& modem_;
std::thread monitor_thread_;
cuttlefish::SharedFD server_;
cuttlefish::SharedFD read_pipe_;
@@ -92,6 +113,8 @@
void ReadCommand(Client& client);
void MonitorLoop();
+ static void removeInvalidClients(
+ std::vector<std::unique_ptr<Client>>& clients);
};
} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/main.cpp b/host/commands/modem_simulator/main.cpp
index 41ab6ce..a979c36 100644
--- a/host/commands/modem_simulator/main.cpp
+++ b/host/commands/modem_simulator/main.cpp
@@ -13,16 +13,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
#include <signal.h>
#include <unistd.h>
-#include <limits>
+#include <android-base/strings.h>
+#include <fmt/format.h>
+#include <gflags/gflags.h>
-#include "common/libs/device_config/device_config.h"
#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/fs/shared_select.h"
#include "common/libs/utils/tee_logging.h"
#include "host/commands/modem_simulator/modem_simulator.h"
#include "host/libs/config/cuttlefish_config.h"
@@ -33,7 +33,10 @@
DEFINE_string(server_fds, "", "A comma separated list of file descriptors");
DEFINE_int32(sim_type, 1, "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
-std::vector<cuttlefish::SharedFD> ServerFdsFromCmdline() {
+namespace cuttlefish {
+namespace {
+
+std::vector<SharedFD> ServerFdsFromCmdline() {
// Validate the parameter
std::string fd_list = FLAGS_server_fds;
for (auto c: fd_list) {
@@ -44,10 +47,10 @@
}
auto fds = android::base::Split(fd_list, ",");
- std::vector<cuttlefish::SharedFD> shared_fds;
+ std::vector<SharedFD> shared_fds;
for (auto& fd_str: fds) {
auto fd = std::stoi(fd_str);
- auto shared_fd = cuttlefish::SharedFD::Dup(fd);
+ auto shared_fd = SharedFD::Dup(fd);
close(fd);
shared_fds.push_back(shared_fd);
}
@@ -55,12 +58,12 @@
return shared_fds;
}
-int main(int argc, char** argv) {
+int ModemSimulatorMain(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
google::ParseCommandLineFlags(&argc, &argv, false);
// Modem simulator log saved in cuttlefish_runtime
- auto config = cuttlefish::CuttlefishConfig::Get();
+ auto config = CuttlefishConfig::Get();
auto instance = config->ForDefaultInstance();
auto modem_log_path = instance.PerInstanceLogPath("modem_simulator.log");
@@ -68,7 +71,7 @@
{
auto log_path = instance.launcher_log_path();
std::vector<std::string> log_files{log_path, modem_log_path};
- android::base::SetLogger(cuttlefish::LogToStderrAndFiles(log_files));
+ android::base::SetLogger(LogToStderrAndFiles(log_files));
}
LOG(INFO) << "Start modem simulator, server_fds: " << FLAGS_server_fds
@@ -81,60 +84,58 @@
return -1;
}
- cuttlefish::NvramConfig::InitNvramConfigService(server_fds.size(), FLAGS_sim_type);
+ NvramConfig::InitNvramConfigService(server_fds.size(), FLAGS_sim_type);
// Don't get a SIGPIPE from the clients
if (sigaction(SIGPIPE, nullptr, nullptr) != 0) {
LOG(ERROR) << "Failed to set SIGPIPE to be ignored: " << strerror(errno);
}
- auto nvram_config = cuttlefish::NvramConfig::Get();
+ auto nvram_config = NvramConfig::Get();
auto nvram_config_file = nvram_config->ConfigFileLocation();
// Start channel monitor, wait for RIL to connect
int32_t modem_id = 0;
- std::vector<std::shared_ptr<cuttlefish::ModemSimulator>> modem_simulators;
+ std::vector<std::unique_ptr<ModemSimulator>> modem_simulators;
for (auto& fd : server_fds) {
CHECK(fd->IsOpen()) << "Error creating or inheriting modem simulator server: "
<< fd->StrError();
- auto modem_simulator = std::make_shared<cuttlefish::ModemSimulator>(modem_id);
+ auto modem_simulator = std::make_unique<ModemSimulator>(modem_id);
auto channel_monitor =
- std::make_unique<cuttlefish::ChannelMonitor>(modem_simulator.get(), fd);
+ std::make_unique<ChannelMonitor>(*modem_simulator.get(), fd);
modem_simulator->Initialize(std::move(channel_monitor));
- modem_simulators.push_back(modem_simulator);
+ modem_simulators.emplace_back(std::move(modem_simulator));
modem_id++;
}
// Monitor exit request and
// remote call, remote sms from other cuttlefish instance
- std::string monitor_socket_name = "modem_simulator";
- std::stringstream ss;
- ss << instance.modem_simulator_host_id();
- monitor_socket_name.append(ss.str());
+ std::string monitor_socket_name =
+ fmt::format("modem_simulator{}", instance.modem_simulator_host_id());
- auto monitor_socket = cuttlefish::SharedFD::SocketLocalServer(
- monitor_socket_name.c_str(), true, SOCK_STREAM, 0666);
+ auto monitor_socket = SharedFD::SocketLocalServer(monitor_socket_name.c_str(),
+ true, SOCK_STREAM, 0666);
if (!monitor_socket->IsOpen()) {
LOG(ERROR) << "Unable to create monitor socket for modem simulator";
- std::exit(cuttlefish::kServerError);
+ std::exit(kServerError);
}
// Server loop
while (true) {
- cuttlefish::SharedFDSet read_set;
+ SharedFDSet read_set;
read_set.Set(monitor_socket);
- int num_fds = cuttlefish::Select(&read_set, nullptr, nullptr, nullptr);
+ int num_fds = Select(&read_set, nullptr, nullptr, nullptr);
if (num_fds <= 0) { // Ignore select error
LOG(ERROR) << "Select call returned error : " << strerror(errno);
} else if (read_set.IsSet(monitor_socket)) {
- auto conn = cuttlefish::SharedFD::Accept(*monitor_socket);
+ auto conn = SharedFD::Accept(*monitor_socket);
std::string buf(4, ' ');
- auto read = cuttlefish::ReadExact(conn, &buf);
+ auto read = ReadExact(conn, &buf);
if (read <= 0) {
conn->Close();
LOG(WARNING) << "Detected close from the other side";
@@ -143,11 +144,11 @@
if (buf == "STOP") { // Exit request from parent process
LOG(INFO) << "Exit request from parent process";
nvram_config->SaveToFile(nvram_config_file);
- for (auto modem : modem_simulators) {
+ for (auto& modem : modem_simulators) {
modem->SaveModemState();
}
- cuttlefish::WriteAll(conn, "OK"); // Ignore the return value. Exit anyway.
- std::exit(cuttlefish::kSuccess);
+ WriteAll(conn, "OK"); // Ignore the return value. Exit anyway.
+ std::exit(kSuccess);
} else if (buf.compare(0, 3, "REM") == 0) { // REMO for modem id 0 ...
// Remote request from other cuttlefish instance
int id = std::stoi(buf.substr(3, 1));
@@ -161,3 +162,10 @@
}
// Until kill or exit
}
+
+} // namespace
+} // namespace cuttlefish
+
+int main(int argc, char** argv) {
+ return cuttlefish::ModemSimulatorMain(argc, argv);
+}
diff --git a/host/commands/modem_simulator/modem_service.cpp b/host/commands/modem_simulator/modem_service.cpp
index 7996e31..ea32f16 100644
--- a/host/commands/modem_simulator/modem_service.cpp
+++ b/host/commands/modem_simulator/modem_service.cpp
@@ -15,39 +15,14 @@
#include "host/commands/modem_simulator/modem_service.h"
-#include <android-base/logging.h>
-
#include <cstring>
+#include <android-base/logging.h>
+
#include "host/commands/modem_simulator/device_config.h"
namespace cuttlefish {
-const std::string ModemService::kCmeErrorOperationNotAllowed = "+CME ERROR: 3";
-const std::string ModemService::kCmeErrorOperationNotSupported = "+CME ERROR: 4";
-const std::string ModemService::kCmeErrorSimNotInserted = "+CME ERROR: 10";
-const std::string ModemService::kCmeErrorSimPinRequired = "+CME ERROR: 11";
-const std::string ModemService::kCmeErrorSimPukRequired = "+CME ERROR: 12";
-const std::string ModemService::kCmeErrorSimBusy = "+CME ERROR: 14";
-const std::string ModemService::kCmeErrorIncorrectPassword = "+CME ERROR: 16";
-const std::string ModemService::kCmeErrorMemoryFull = "+CME ERROR: 20";
-const std::string ModemService::kCmeErrorInvalidIndex = "+CME ERROR: 21";
-const std::string ModemService::kCmeErrorNotFound = "+CME ERROR: 22";
-const std::string ModemService::kCmeErrorInvalidCharactersInTextString = "+CME ERROR: 27";
-const std::string ModemService::kCmeErrorNoNetworkService = "+CME ERROR: 30";
-const std::string ModemService::kCmeErrorNetworkNotAllowedEmergencyCallsOnly = "+CME ERROR: 32";
-const std::string ModemService::kCmeErrorInCorrectParameters = "+CME ERROR: 50";
-const std::string ModemService::kCmeErrorNetworkNotAttachedDueToMTFunctionalRestrictions = "+CME ERROR: 53";
-const std::string ModemService::kCmeErrorFixedDialNumberOnlyAllowed = "+CME ERROR: 56";
-
-const std::string ModemService::kCmsErrorOperationNotAllowed = "+CMS ERROR: 302";
-const std::string ModemService::kCmsErrorOperationNotSupported = "+CMS ERROR: 303";
-const std::string ModemService::kCmsErrorInvalidPDUModeParam = "+CMS ERROR: 304";
-const std::string ModemService::kCmsErrorSCAddressUnknown = "+CMS ERROR: 304";
-
-const std::pair<int, int> ModemService::kRemotePortRange =
- std::make_pair(6520, 6527);
-
CommandHandler::CommandHandler(const std::string& command, f_func handler)
: command_prefix(command),
match_mode(FULL_MATCH),
@@ -123,14 +98,15 @@
return remote_sock;
}
-void ModemService::SendCommandToRemote(cuttlefish::SharedFD remote_client, std::string response) {
+void ModemService::SendCommandToRemote(ClientId remote_client,
+ std::string response) {
if (channel_monitor_) {
channel_monitor_->SendRemoteCommand(remote_client, response);
;
}
}
-void ModemService::CloseRemoteConnection(cuttlefish::SharedFD remote_client) {
+void ModemService::CloseRemoteConnection(ClientId remote_client) {
if (channel_monitor_) {
channel_monitor_->CloseRemoteConnection(remote_client);
;
diff --git a/host/commands/modem_simulator/modem_service.h b/host/commands/modem_simulator/modem_service.h
index 744f618..bc85302 100644
--- a/host/commands/modem_simulator/modem_service.h
+++ b/host/commands/modem_simulator/modem_service.h
@@ -70,29 +70,36 @@
bool HandleModemCommand(const Client& client, std::string command);
- static const std::string kCmeErrorOperationNotAllowed;
- static const std::string kCmeErrorOperationNotSupported;
- static const std::string kCmeErrorSimNotInserted;
- static const std::string kCmeErrorSimPinRequired;
- static const std::string kCmeErrorSimPukRequired;
- static const std::string kCmeErrorSimBusy;
- static const std::string kCmeErrorIncorrectPassword;
- static const std::string kCmeErrorMemoryFull;
- static const std::string kCmeErrorInvalidIndex;
- static const std::string kCmeErrorNotFound;
- static const std::string kCmeErrorInvalidCharactersInTextString;
- static const std::string kCmeErrorNoNetworkService;
- static const std::string kCmeErrorNetworkNotAllowedEmergencyCallsOnly;
- static const std::string kCmeErrorInCorrectParameters;
- static const std::string kCmeErrorNetworkNotAttachedDueToMTFunctionalRestrictions;
- static const std::string kCmeErrorFixedDialNumberOnlyAllowed;
+ static constexpr char kCmeErrorOperationNotAllowed[] = "+CME ERROR: 3";
+ static constexpr char kCmeErrorOperationNotSupported[] = "+CME ERROR: 4";
+ static constexpr char kCmeErrorSimNotInserted[] = "+CME ERROR: 10";
+ static constexpr char kCmeErrorSimPinRequired[] = "+CME ERROR: 11";
+ static constexpr char kCmeErrorSimPukRequired[] = "+CME ERROR: 12";
+ static constexpr char kCmeErrorSimBusy[] = "+CME ERROR: 14";
+ static constexpr char kCmeErrorIncorrectPassword[] = "+CME ERROR: 16";
+ static constexpr char kCmeErrorMemoryFull[] = "+CME ERROR: 20";
+ static constexpr char kCmeErrorInvalidIndex[] = "+CME ERROR: 21";
+ static constexpr char kCmeErrorNotFound[] = "+CME ERROR: 22";
+ static constexpr char kCmeErrorInvalidCharactersInTextString[] =
+ "+CME ERROR: 27";
+ static constexpr char kCmeErrorNoNetworkService[] = "+CME ERROR: 30";
+ static constexpr char kCmeErrorNetworkNotAllowedEmergencyCallsOnly[] =
+ "+CME ERROR: 32";
+ static constexpr char kCmeErrorInCorrectParameters[] = "+CME ERROR: 50";
+ static constexpr char
+ kCmeErrorNetworkNotAttachedDueToMTFunctionalRestrictions[] =
+ "+CME ERROR: 53";
+ static constexpr char kCmeErrorFixedDialNumberOnlyAllowed[] =
+ "+CME ERROR: 56";
- static const std::string kCmsErrorOperationNotAllowed;
- static const std::string kCmsErrorOperationNotSupported;
- static const std::string kCmsErrorInvalidPDUModeParam;
- static const std::string kCmsErrorSCAddressUnknown;
+ static constexpr char kCmsErrorOperationNotAllowed[] = "+CMS ERROR: 302";
+ static constexpr char kCmsErrorOperationNotSupported[] = "+CMS ERROR: 303";
+ static constexpr char kCmsErrorInvalidPDUModeParam[] = "+CMS ERROR: 304";
+ static constexpr char kCmsErrorSCAddressUnknown[] = "+CMS ERROR: 304";
- static const std::pair<int, int> kRemotePortRange;
+ static constexpr std::pair<int, int> kRemotePortRange{6520, 6527};
+
+ void CloseRemoteConnection(ClientId remote_client);
protected:
ModemService(int32_t service_id, std::vector<CommandHandler> command_handlers,
@@ -101,9 +108,7 @@
void SendUnsolicitedCommand(std::string unsol_command);
cuttlefish::SharedFD ConnectToRemoteCvd(std::string port);
- void SendCommandToRemote(cuttlefish::SharedFD remote_client,
- std::string response);
- void CloseRemoteConnection(cuttlefish::SharedFD remote_client);
+ void SendCommandToRemote(ClientId remote_client, std::string response);
static std::string GetHostId();
int32_t service_id_;
diff --git a/host/commands/modem_simulator/modem_simulator.cpp b/host/commands/modem_simulator/modem_simulator.cpp
index ceb94a1..ed657ab 100644
--- a/host/commands/modem_simulator/modem_simulator.cpp
+++ b/host/commands/modem_simulator/modem_simulator.cpp
@@ -113,7 +113,7 @@
}
}
- if (!success && client.type != Client::REMOTE) {
+ if (!success && client.Type() != Client::REMOTE) {
LOG(DEBUG) << "Not supported AT command: " << command;
client.SendCommandResponse(ModemService::kCmeErrorOperationNotSupported);
}
diff --git a/host/commands/modem_simulator/nvram_config.cpp b/host/commands/modem_simulator/nvram_config.cpp
index f61f96f..ad06f94 100644
--- a/host/commands/modem_simulator/nvram_config.cpp
+++ b/host/commands/modem_simulator/nvram_config.cpp
@@ -20,26 +20,23 @@
#include <fstream>
#include <mutex>
-#include <sstream>
#include "common/libs/utils/files.h"
#include "host/commands/modem_simulator/device_config.h"
namespace cuttlefish {
-const char* kInstances = "instances";
-const char* kNetworkSelectionMode = "network_selection_mode";
-const char* kOperatorNumeric = "operator_numeric";
-const char* kModemTechnoloy = "modem_technoloy";
-const char* kPreferredNetworkMode = "preferred_network_mode";
-const char* kEmergencyMode = "emergency_mode";
-const char* kSimType = "sim_type";
+static constexpr char kInstances[] = "instances";
+static constexpr char kNetworkSelectionMode[] = "network_selection_mode";
+static constexpr char kOperatorNumeric[] = "operator_numeric";
+static constexpr char kModemTechnoloy[] = "modem_technoloy";
+static constexpr char kPreferredNetworkMode[] = "preferred_network_mode";
+static constexpr char kEmergencyMode[] = "emergency_mode";
-const int kDefaultNetworkSelectionMode = 0; // AUTOMATIC
-const std::string kDefaultOperatorNumeric = "";
-const int kDefaultModemTechnoloy = 0x10; // LTE
-const int kDefaultPreferredNetworkMode = 0x13; // LTE | WCDMA | GSM
-const bool kDefaultEmergencyMode = false;
+static constexpr int kDefaultNetworkSelectionMode = 0; // AUTOMATIC
+static constexpr int kDefaultModemTechnoloy = 0x10; // LTE
+static constexpr int kDefaultPreferredNetworkMode = 0x13; // LTE | WCDMA | GSM
+static constexpr bool kDefaultEmergencyMode = false;
/**
* Creates the (initially empty) config object and populates it with values from
diff --git a/host/commands/modem_simulator/unittest/service_test.cpp b/host/commands/modem_simulator/unittest/service_test.cpp
index 2d6289f..179174c 100644
--- a/host/commands/modem_simulator/unittest/service_test.cpp
+++ b/host/commands/modem_simulator/unittest/service_test.cpp
@@ -87,7 +87,7 @@
cuttlefish::SharedFD server;
auto channel_monitor =
- std::make_unique<ChannelMonitor>(modem_simulator_, server);
+ std::make_unique<ChannelMonitor>(*modem_simulator_, server);
modem_simulator_->Initialize(std::move(channel_monitor));
}
@@ -106,7 +106,8 @@
void ReadCommandResponse(std::vector<std::string>& response) {
do {
std::vector<char> buffer(4096); // kMaxCommandLength
- auto bytes_read = ril_side_->client_fd->Read(buffer.data(), buffer.size());
+ auto bytes_read =
+ ril_side_->client_fd->Read(buffer.data(), buffer.size());
if (bytes_read <= 0) {
// Close here to ensure the other side gets reset if it's still
// connected
diff --git a/host/commands/openwrt_control_server/Android.bp b/host/commands/openwrt_control_server/Android.bp
index 8f32cf9..5458cb4 100644
--- a/host/commands/openwrt_control_server/Android.bp
+++ b/host/commands/openwrt_control_server/Android.bp
@@ -16,7 +16,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_host_static {
+cc_library {
name: "libopenwrt_control_server",
shared_libs: [
"libprotobuf-cpp-full",
diff --git a/host/commands/powerwash_cvd/Android.bp b/host/commands/powerwash_cvd/Android.bp
index e089156..fb85e61 100644
--- a/host/commands/powerwash_cvd/Android.bp
+++ b/host/commands/powerwash_cvd/Android.bp
@@ -33,5 +33,5 @@
"libcuttlefish_host_config",
"libgflags",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/record_cvd/Android.bp b/host/commands/record_cvd/Android.bp
index 150e04c..109b62e 100644
--- a/host/commands/record_cvd/Android.bp
+++ b/host/commands/record_cvd/Android.bp
@@ -35,6 +35,6 @@
"libgflags",
"libprotobuf-cpp-full",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/restart_cvd/Android.bp b/host/commands/restart_cvd/Android.bp
index fd52336..66a1c15 100644
--- a/host/commands/restart_cvd/Android.bp
+++ b/host/commands/restart_cvd/Android.bp
@@ -33,5 +33,5 @@
"libcuttlefish_host_config",
"libgflags",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/run_cvd/Android.bp b/host/commands/run_cvd/Android.bp
index ec9035a..925b6e5 100644
--- a/host/commands/run_cvd/Android.bp
+++ b/host/commands/run_cvd/Android.bp
@@ -75,9 +75,13 @@
],
required: [
"console_forwarder",
+ "echo_server",
+ "gnss_grpc_proxy",
"kernel_log_monitor",
"logcat_receiver",
+ "log_tee",
"secure_env",
+ "tcp_connector",
],
target: {
darwin: {
@@ -98,7 +102,6 @@
},
defaults: [
"cuttlefish_host",
- "cuttlefish_libicuuc",
"cvd_cc_defaults",
],
use_version_lib: true,
diff --git a/host/commands/run_cvd/launch/netsim_server.cpp b/host/commands/run_cvd/launch/netsim_server.cpp
index 543cc51..d854102 100644
--- a/host/commands/run_cvd/launch/netsim_server.cpp
+++ b/host/commands/run_cvd/launch/netsim_server.cpp
@@ -99,6 +99,11 @@
// Netsim instance number.
netsimd.AddParameter("--instance_num=", config_.netsim_instance_num());
+ // Add parameters from passthrough option --netsim-args.
+ for (auto const& arg : config_.netsim_args()) {
+ netsimd.AddParameter(arg);
+ }
+
// Add command for forwarding the HCI port to a vsock server.
Command hci_vsock_proxy(SocketVsockProxyBinary());
hci_vsock_proxy.AddParameter("--server_type=vsock");
diff --git a/host/commands/run_cvd/proto/Android.bp b/host/commands/run_cvd/proto/Android.bp
index c84590b..cbf09f1 100644
--- a/host/commands/run_cvd/proto/Android.bp
+++ b/host/commands/run_cvd/proto/Android.bp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-cc_library_static {
+cc_library {
name: "libcuttlefish_run_cvd_proto",
host_supported: true,
proto: {
@@ -31,7 +31,6 @@
},
defaults: [
"cuttlefish_host",
- "cuttlefish_libicuuc",
"cvd_cc_defaults",
],
}
diff --git a/host/commands/run_cvd/proto/run_cvd.proto b/host/commands/run_cvd/proto/run_cvd.proto
index 74148e9..7f6afa6 100644
--- a/host/commands/run_cvd/proto/run_cvd.proto
+++ b/host/commands/run_cvd/proto/run_cvd.proto
@@ -24,6 +24,7 @@
Resume resume = 6;
StartScreenRecording start_screen_recording = 7;
StopScreenRecording stop_screen_recording = 8;
+ SnapshotTake snapshot_take = 9;
}
string verbosity = 20;
}
@@ -31,3 +32,6 @@
message Resume {}
message StartScreenRecording {}
message StopScreenRecording {}
+message SnapshotTake {
+ repeated string snapshot_path = 1;
+}
diff --git a/host/commands/run_cvd/runner_defs.h b/host/commands/run_cvd/runner_defs.h
index 8bdc744..3080642 100644
--- a/host/commands/run_cvd/runner_defs.h
+++ b/host/commands/run_cvd/runner_defs.h
@@ -75,6 +75,7 @@
kStartScreenRecording = 7,
kStopScreenRecording = 8,
// TODO(kwstephenkim): extend the list of operations to cover snapshot
+ kSnapshotTake = 9,
};
} // namespace cuttlefish
diff --git a/host/commands/run_cvd/server_loop_impl.cpp b/host/commands/run_cvd/server_loop_impl.cpp
index aee7691..a79b18c 100644
--- a/host/commands/run_cvd/server_loop_impl.cpp
+++ b/host/commands/run_cvd/server_loop_impl.cpp
@@ -104,10 +104,19 @@
HandleActionWithNoData(launcher_action.action, client, process_monitor);
continue;
}
- auto result = HandleExtended(launcher_action, client);
+ auto result = HandleExtended(launcher_action, process_monitor);
+ const auto launcher_action_type_code =
+ static_cast<std::uint32_t>(launcher_action.type);
+ auto response = LauncherResponse::kSuccess;
if (!result.ok()) {
LOG(ERROR) << "Failed to handle extended action request.";
LOG(DEBUG) << result.error().Trace();
+ response = LauncherResponse::kError;
+ }
+ const auto n_written = client->Write(&response, sizeof(response));
+ if (n_written != sizeof(response)) {
+ LOG(ERROR) << "Failed to write response to "
+ << launcher_action_type_code;
}
// extended operations for now are 1 time request-response exchanges.
// thus, we will close the client FD.
@@ -126,28 +135,32 @@
}
Result<void> ServerLoopImpl::HandleExtended(
- const LauncherActionInfo& action_info, const SharedFD& client) {
+ const LauncherActionInfo& action_info, ProcessMonitor& process_monitor) {
CF_EXPECT(action_info.action == LauncherAction::kExtended);
switch (action_info.type) {
case ExtendedActionType::kSuspend: {
LOG(DEBUG) << "Run_cvd received suspend request.";
- CF_EXPECT(HandleSuspend(action_info.serialized_data, client));
+ CF_EXPECT(HandleSuspend(action_info.serialized_data, process_monitor));
return {};
}
case ExtendedActionType::kResume: {
LOG(DEBUG) << "Run_cvd received resume request.";
- CF_EXPECT(HandleResume(action_info.serialized_data, client));
+ CF_EXPECT(HandleResume(action_info.serialized_data, process_monitor));
+ return {};
+ }
+ case ExtendedActionType::kSnapshotTake: {
+ LOG(DEBUG) << "Run_cvd received resume request.";
+ CF_EXPECT(HandleSnapshotTake(action_info.serialized_data));
return {};
}
case ExtendedActionType::kStartScreenRecording: {
LOG(DEBUG) << "Run_cvd received start screen recording request.";
- CF_EXPECT(
- HandleStartScreenRecording(action_info.serialized_data, client));
+ CF_EXPECT(HandleStartScreenRecording(action_info.serialized_data));
return {};
}
case ExtendedActionType::kStopScreenRecording: {
LOG(DEBUG) << "Run_cvd received stop screen recording request.";
- CF_EXPECT(HandleStopScreenRecording(action_info.serialized_data, client));
+ CF_EXPECT(HandleStopScreenRecording(action_info.serialized_data));
return {};
}
default:
diff --git a/host/commands/run_cvd/server_loop_impl.h b/host/commands/run_cvd/server_loop_impl.h
index 4c1bf7f..bda3e5d 100644
--- a/host/commands/run_cvd/server_loop_impl.h
+++ b/host/commands/run_cvd/server_loop_impl.h
@@ -57,15 +57,14 @@
std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
Result<void> ResultSetup() override;
Result<void> HandleExtended(const LauncherActionInfo& action_info,
- const SharedFD& client);
+ ProcessMonitor& process_monitor);
Result<void> HandleSuspend(const std::string& serialized_data,
- const SharedFD& client);
+ ProcessMonitor& process_monitor);
Result<void> HandleResume(const std::string& serialized_data,
- const SharedFD& client);
- Result<void> HandleStartScreenRecording(const std::string& serialized_data,
- const SharedFD& client);
- Result<void> HandleStopScreenRecording(const std::string& serialized_data,
- const SharedFD& client);
+ ProcessMonitor& process_monitor);
+ Result<void> HandleSnapshotTake(const std::string& serialized_data);
+ Result<void> HandleStartScreenRecording(const std::string& serialized_data);
+ Result<void> HandleStopScreenRecording(const std::string& serialized_data);
void HandleActionWithNoData(const LauncherAction action,
const SharedFD& client,
diff --git a/host/commands/run_cvd/server_loop_impl_record.cpp b/host/commands/run_cvd/server_loop_impl_record.cpp
index cdc94f5..0346581 100644
--- a/host/commands/run_cvd/server_loop_impl_record.cpp
+++ b/host/commands/run_cvd/server_loop_impl_record.cpp
@@ -16,7 +16,6 @@
#include "host/commands/run_cvd/server_loop_impl.h"
-#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/result.h"
#include "host/commands/run_cvd/runner_defs.h"
#include "host/libs/command_util/util.h"
@@ -26,7 +25,7 @@
namespace run_cvd_impl {
Result<void> ServerLoopImpl::HandleStartScreenRecording(
- const std::string& serialized_data, const SharedFD& client) {
+ const std::string& serialized_data) {
run_cvd::ExtendedLauncherAction extended_action;
CF_EXPECT(extended_action.ParseFromString(serialized_data),
"Failed to load ExtendedLauncherAction proto.");
@@ -34,14 +33,11 @@
extended_action.actions_case(),
run_cvd::ExtendedLauncherAction::ActionsCase::kStartScreenRecording);
LOG(INFO) << "Sending the request to start screen recording.";
- auto response = LauncherResponse::kSuccess;
- CF_EXPECT_EQ(client->Write(&response, sizeof(response)), sizeof(response),
- "Failed to write the screen record response.");
return {};
}
Result<void> ServerLoopImpl::HandleStopScreenRecording(
- const std::string& serialized_data, const SharedFD& client) {
+ const std::string& serialized_data) {
run_cvd::ExtendedLauncherAction extended_action;
CF_EXPECT(extended_action.ParseFromString(serialized_data),
"Failed to load ExtendedLauncherAction proto.");
@@ -49,9 +45,6 @@
extended_action.actions_case(),
run_cvd::ExtendedLauncherAction::ActionsCase::kStopScreenRecording);
LOG(INFO) << "Sending the request to stop screen recording.";
- auto response = LauncherResponse::kSuccess;
- CF_EXPECT_EQ(client->Write(&response, sizeof(response)), sizeof(response),
- "Failed to write the screen record response.");
return {};
}
diff --git a/host/commands/run_cvd/server_loop_impl_snapshot.cpp b/host/commands/run_cvd/server_loop_impl_snapshot.cpp
index e2cb3d4..f700ea2 100644
--- a/host/commands/run_cvd/server_loop_impl_snapshot.cpp
+++ b/host/commands/run_cvd/server_loop_impl_snapshot.cpp
@@ -103,36 +103,55 @@
}
Result<void> ServerLoopImpl::HandleSuspend(const std::string& serialized_data,
- const SharedFD& client) {
+ ProcessMonitor& process_monitor) {
run_cvd::ExtendedLauncherAction extended_action;
CF_EXPECT(extended_action.ParseFromString(serialized_data),
"Failed to load ExtendedLauncherAction proto.");
CF_EXPECT_EQ(extended_action.actions_case(),
run_cvd::ExtendedLauncherAction::ActionsCase::kSuspend);
- LOG(INFO) << "Suspending the guest..";
+ // right order: guest -> host
+ LOG(DEBUG) << "Suspending the guest..";
CF_EXPECT(SuspendGuest());
- LOG(INFO) << "The guest is suspended.";
- LOG(INFO) << "Suspend host is not yet implemented.";
- auto response = LauncherResponse::kSuccess;
- CF_EXPECT_EQ(client->Write(&response, sizeof(response)), sizeof(response),
- "Failed to wrote the suspend response.");
+ LOG(DEBUG) << "The guest is suspended.";
+ CF_EXPECT(process_monitor.SuspendMonitoredProcesses(),
+ "Failed to suspend host processes.");
+ LOG(DEBUG) << "The host processes are suspended.";
return {};
}
Result<void> ServerLoopImpl::HandleResume(const std::string& serialized_data,
- const SharedFD& client) {
+ ProcessMonitor& process_monitor) {
run_cvd::ExtendedLauncherAction extended_action;
CF_EXPECT(extended_action.ParseFromString(serialized_data),
"Failed to load ExtendedLauncherAction proto.");
CF_EXPECT_EQ(extended_action.actions_case(),
run_cvd::ExtendedLauncherAction::ActionsCase::kResume);
- LOG(INFO) << "Resuming the guest..";
+ // right order: host -> guest
+ CF_EXPECT(process_monitor.ResumeMonitoredProcesses(),
+ "Failed to resume host processes.");
+ LOG(DEBUG) << "The host processes are resumed.";
+ LOG(DEBUG) << "Resuming the guest..";
CF_EXPECT(ResumeGuest());
- LOG(INFO) << "The guest resumed.";
- LOG(INFO) << "Resuming host is not yet implemented.";
- auto response = LauncherResponse::kSuccess;
- CF_EXPECT_EQ(client->Write(&response, sizeof(response)), sizeof(response),
- "Failed to wrote the suspend response.");
+ LOG(DEBUG) << "The guest resumed.";
+ return {};
+}
+
+Result<void> ServerLoopImpl::HandleSnapshotTake(
+ const std::string& serialized_data) {
+ run_cvd::ExtendedLauncherAction extended_action;
+ CF_EXPECT(extended_action.ParseFromString(serialized_data),
+ "Failed to load ExtendedLauncherAction proto.");
+ CF_EXPECT_EQ(extended_action.actions_case(),
+ run_cvd::ExtendedLauncherAction::ActionsCase::kSnapshotTake);
+ // implement snapshot take
+ std::vector<std::string> path_to_snapshots;
+ for (const auto& path : extended_action.snapshot_take().snapshot_path()) {
+ path_to_snapshots.push_back(path);
+ }
+ CF_EXPECT_EQ(path_to_snapshots.size(), 1);
+ const auto& path_to_snapshot = path_to_snapshots.front();
+ LOG(DEBUG) << "run_cvd server loop will take snapshot to "
+ << path_to_snapshot;
return {};
}
diff --git a/host/commands/secure_env/Android.bp b/host/commands/secure_env/Android.bp
index 10ea480..c401ce7 100644
--- a/host/commands/secure_env/Android.bp
+++ b/host/commands/secure_env/Android.bp
@@ -104,7 +104,7 @@
// 1. Missing transport implementation
// 2. Missing file utils
// 3. Base64 isn't supported (need for software oemlock implementation)
-cc_library_host_static {
+cc_library {
name: "libsecure_env_not_windows",
srcs: common_libsecure_srcs + [
"confui_sign_server.cpp",
diff --git a/host/commands/snapshot_util_cvd/Android.bp b/host/commands/snapshot_util_cvd/Android.bp
index 7ff1e8f..a4ce525 100644
--- a/host/commands/snapshot_util_cvd/Android.bp
+++ b/host/commands/snapshot_util_cvd/Android.bp
@@ -36,5 +36,5 @@
"libgflags",
"libprotobuf-cpp-full",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/snapshot_util_cvd/main.cc b/host/commands/snapshot_util_cvd/main.cc
index d48c609..3f40a6f 100644
--- a/host/commands/snapshot_util_cvd/main.cc
+++ b/host/commands/snapshot_util_cvd/main.cc
@@ -22,6 +22,7 @@
#include <fmt/core.h>
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/files.h"
#include "common/libs/utils/flag_parser.h"
#include "common/libs/utils/result.h"
#include "host/commands/snapshot_util_cvd/parse.h"
@@ -50,11 +51,23 @@
return serialized;
}
+Result<std::string> SerializeSnapshotTakeRequest(
+ const std::string& snapshot_path) {
+ run_cvd::ExtendedLauncherAction action_proto;
+ auto* snapshot_take_request = action_proto.mutable_snapshot_take();
+ snapshot_take_request->add_snapshot_path(snapshot_path);
+ std::string serialized;
+ CF_EXPECT(action_proto.SerializeToString(&serialized),
+ "Failed to serialize Resume Request protobuf.");
+ return serialized;
+}
+
struct RequestInfo {
std::string serialized_data;
ExtendedActionType extended_action_type;
};
-Result<RequestInfo> SerializeRequest(const SnapshotCmd subcmd) {
+Result<RequestInfo> SerializeRequest(const SnapshotCmd subcmd,
+ const std::string& snapshot_path) {
switch (subcmd) {
case SnapshotCmd::kSuspend: {
return RequestInfo{
@@ -70,35 +83,59 @@
};
break;
}
+ case SnapshotCmd::kSnapshotTake: {
+ CF_EXPECT(!snapshot_path.empty(),
+ "Snapshot operation requires snapshot_path");
+ return RequestInfo{
+ .serialized_data =
+ CF_EXPECT(SerializeSnapshotTakeRequest(snapshot_path)),
+ .extended_action_type = ExtendedActionType::kSnapshotTake,
+ };
+ break;
+ }
default:
return CF_ERR("Operation not supported.");
}
}
-Result<void> SuspendCvdMain(std::vector<std::string> args) {
+Result<void> SnapshotCvdMain(std::vector<std::string> args) {
CF_EXPECT(!args.empty(), "No arguments was given");
const auto prog_path = args.front();
args.erase(args.begin());
auto parsed = CF_EXPECT(Parse(args));
+ // make sure the snapshot directory exists
+ if (parsed.cmd == SnapshotCmd::kSnapshotTake) {
+ CF_EXPECT(!parsed.snapshot_path.empty(),
+ "Snapshot operation requires snapshot path.");
+ CF_EXPECTF(EnsureDirectoryExists(parsed.snapshot_path),
+ "Failed to ensure that snapshot directory {} exists",
+ parsed.snapshot_path);
+ }
+
const CuttlefishConfig* config =
CF_EXPECT(CuttlefishConfig::Get(), "Failed to obtain config object");
- SharedFD monitor_socket = CF_EXPECT(GetLauncherMonitor(
- *config, parsed.instance_num, parsed.wait_for_launcher));
+ // TODO(kwstephenkim): copy host files that are shared by the instance group
+ for (const auto instance_num : parsed.instance_nums) {
+ SharedFD monitor_socket = CF_EXPECT(
+ GetLauncherMonitor(*config, instance_num, parsed.wait_for_launcher));
- LOG(INFO) << "Requesting " << parsed.cmd;
- auto [serialized_data, extended_type] =
- CF_EXPECT(SerializeRequest(parsed.cmd));
- CF_EXPECT(
- WriteLauncherActionWithData(monitor_socket, LauncherAction::kExtended,
- extended_type, std::move(serialized_data)));
-
- LauncherResponse response = CF_EXPECT(ReadLauncherResponse(monitor_socket));
- CF_EXPECTF(response == LauncherResponse::kSuccess,
- "Received \"{}\" response from launcher monitor for \""
- "{}\" request.",
- static_cast<char>(response), static_cast<int>(parsed.cmd));
- LOG(INFO) << parsed.cmd << " was successful.";
+ LOG(INFO) << "Requesting " << parsed.cmd << " for instance #"
+ << instance_num;
+ auto [serialized_data, extended_type] =
+ CF_EXPECT(SerializeRequest(parsed.cmd, parsed.snapshot_path));
+ CF_EXPECT(
+ WriteLauncherActionWithData(monitor_socket, LauncherAction::kExtended,
+ extended_type, std::move(serialized_data)));
+ LOG(INFO) << "Wrote the extended serialized data and reading response";
+ LauncherResponse response = CF_EXPECT(ReadLauncherResponse(monitor_socket));
+ LOG(INFO) << "Read the response: " << (int)LauncherResponse::kSuccess;
+ CF_EXPECTF(response == LauncherResponse::kSuccess,
+ "Received \"{}\" response from launcher monitor for \""
+ "{}\" request.",
+ static_cast<char>(response), static_cast<int>(parsed.cmd));
+ LOG(INFO) << parsed.cmd << " was successful for instance #" << instance_num;
+ }
return {};
}
@@ -108,7 +145,7 @@
int main(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
std::vector<std::string> all_args = cuttlefish::ArgsToVec(argc, argv);
- auto result = cuttlefish::SuspendCvdMain(std::move(all_args));
+ auto result = cuttlefish::SnapshotCvdMain(std::move(all_args));
if (!result.ok()) {
LOG(ERROR) << result.error().Trace();
return EXIT_FAILURE;
diff --git a/host/commands/snapshot_util_cvd/parse.cc b/host/commands/snapshot_util_cvd/parse.cc
index f8e21ef..249867f 100644
--- a/host/commands/snapshot_util_cvd/parse.cc
+++ b/host/commands/snapshot_util_cvd/parse.cc
@@ -16,9 +16,13 @@
#include "host/commands/snapshot_util_cvd/parse.h"
+#include <cstdlib>
#include <iostream>
#include <unordered_map>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+
#include "common/libs/utils/contains.h"
#include "common/libs/utils/flag_parser.h"
#include "common/libs/utils/result.h"
@@ -29,14 +33,15 @@
constexpr char snapshot_cmd_help[] =
"Command to control regarding the snapshot operations: "
- "suspend/resume/take";
-
-constexpr char instance_num_help[] = "Which instance to suspend.";
+ "suspend/resume/snapshot_take";
constexpr char wait_for_launcher_help[] =
"How many seconds to wait for the launcher to respond to the status "
"command. A value of zero means wait indefinitely.";
+constexpr char snapshot_path_help[] =
+ "Path to the directory the taken snapshot files are saved";
+
Flag SnapshotCmdFlag(std::string& value_buf) {
return GflagsCompatFlag("subcmd", value_buf).Help(snapshot_cmd_help);
}
@@ -46,15 +51,15 @@
return GflagsCompatFlag(name, value_buf).Help(help_msg);
}
-Flag InstanceNumFlag(int& instance_num) {
- return GetInt32Flag("instance_num", instance_num, instance_num_help);
-}
-
Flag WaitForLauncherFlag(int& wait_for_launcher) {
return GetInt32Flag("wait_for_launcher", wait_for_launcher,
wait_for_launcher_help);
}
+Flag SnapshotPathFlag(std::string& path_buf) {
+ return GflagsCompatFlag("snapshot_path", path_buf).Help(snapshot_path_help);
+}
+
} // namespace
Result<Parsed> Parse(int argc, char** argv) {
@@ -65,30 +70,51 @@
Result<SnapshotCmd> ConvertToSnapshotCmd(const std::string& input) {
std::unordered_map<std::string, SnapshotCmd> mapping{
- {"suspend", SnapshotCmd::kSuspend}, {"resume", SnapshotCmd::kResume},
- {"take", SnapshotCmd::kSnapshotTake}, {"unset", SnapshotCmd::kUnknown},
+ {"suspend", SnapshotCmd::kSuspend},
+ {"resume", SnapshotCmd::kResume},
+ {"snapshot_take", SnapshotCmd::kSnapshotTake},
{"unknown", SnapshotCmd::kUnknown},
};
CF_EXPECT(Contains(mapping, input));
return mapping.at(input);
}
+static Result<std::vector<int>> InstanceNums() {
+ CF_EXPECT(getenv("HOME") != nullptr, "\"HOME\" must be set properly.");
+ const auto* config = CuttlefishConfig::Get();
+ CF_EXPECT(config != nullptr, "CuttlefishConfig::Get() returned nullptr");
+
+ const auto instances = config->Instances();
+ std::vector<int> instance_nums;
+ CF_EXPECT(!instances.empty(), "CuttlefishConfig has no instance in it.");
+ instance_nums.reserve(instances.size());
+ for (const auto& instance : instances) {
+ int id;
+ CF_EXPECTF(android::base::ParseInt(instance.id(), &id),
+ "Parsing filed for {}", id);
+ instance_nums.push_back(id);
+ }
+ return instance_nums;
+}
+
Result<Parsed> Parse(std::vector<std::string>& args) {
Parsed parsed{
- .instance_num = GetInstance(),
.wait_for_launcher = 30,
};
std::vector<Flag> flags;
bool help_xml = false;
std::string snapshot_op("unknown");
+ std::string snapshot_path;
flags.push_back(SnapshotCmdFlag(snapshot_op));
- flags.push_back(InstanceNumFlag(parsed.instance_num));
flags.push_back(WaitForLauncherFlag(parsed.wait_for_launcher));
+ flags.push_back(SnapshotPathFlag(snapshot_path));
flags.push_back(HelpFlag(flags));
flags.push_back(HelpXmlFlag(flags, std::cout, help_xml));
flags.push_back(UnexpectedArgumentGuard());
CF_EXPECT(ParseFlags(flags, args), "Flag parsing failed");
parsed.cmd = CF_EXPECT(ConvertToSnapshotCmd(snapshot_op));
+ parsed.snapshot_path = snapshot_path;
+ parsed.instance_nums = CF_EXPECT(InstanceNums());
return parsed;
}
@@ -104,7 +130,7 @@
out << "resume";
break;
case SnapshotCmd::kSnapshotTake:
- out << "snapshot take";
+ out << "snapshot_take";
break;
default:
out << "unknown";
diff --git a/host/commands/snapshot_util_cvd/parse.h b/host/commands/snapshot_util_cvd/parse.h
index 42ec492..f802072 100644
--- a/host/commands/snapshot_util_cvd/parse.h
+++ b/host/commands/snapshot_util_cvd/parse.h
@@ -38,8 +38,9 @@
struct Parsed {
SnapshotCmd cmd;
- int instance_num;
+ std::vector<int> instance_nums;
int wait_for_launcher;
+ std::string snapshot_path;
std::optional<android::base::LogSeverity> verbosity_level;
};
Result<Parsed> Parse(int argc, char** argv);
diff --git a/host/commands/start/Android.bp b/host/commands/start/Android.bp
index 73ba0fc..1195906 100644
--- a/host/commands/start/Android.bp
+++ b/host/commands/start/Android.bp
@@ -47,5 +47,5 @@
enabled: true,
},
},
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/start/main.cc b/host/commands/start/main.cc
index f02a18e..2787778 100644
--- a/host/commands/start/main.cc
+++ b/host/commands/start/main.cc
@@ -247,7 +247,7 @@
"enable_sandbox",
"restart_subprocesses",
"enable_gpu_udmabuf",
- "enable_gpu_angle",
+ "enable_gpu_vhost_user",
"enable_audio",
"enable_vehicle_hal_grpc_server",
"start_gnss_proxy",
diff --git a/host/commands/status/Android.bp b/host/commands/status/Android.bp
index edde718..708e3f3 100644
--- a/host/commands/status/Android.bp
+++ b/host/commands/status/Android.bp
@@ -34,5 +34,5 @@
"libcuttlefish_host_config",
"libgflags",
],
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/status/main.cc b/host/commands/status/main.cc
index c4ecf53..3760b02 100644
--- a/host/commands/status/main.cc
+++ b/host/commands/status/main.cc
@@ -73,31 +73,31 @@
struct WebAccessUrlParam {
std::string sig_server_addr;
- std::string device_name;
+ std::string webrtc_device_id;
};
std::string CalcWebAccessUrl(const WebAccessUrlParam& web_access_url_param) {
if (!FileIsSocket(web_access_url_param.sig_server_addr)) {
return "";
}
return std::string("https://") + "localhost" + ":" + "1443" + "/devices/" +
- web_access_url_param.device_name + "/files" + "/client.html";
+ web_access_url_param.webrtc_device_id + "/files" + "/client.html";
}
Json::Value PopulateDevicesInfoFromInstance(
const CuttlefishConfig& config,
const CuttlefishConfig::InstanceSpecific& instance_config) {
Json::Value device_info;
- std::string device_name = instance_config.webrtc_device_id();
- if (device_name.empty()) {
- device_name = instance_config.instance_name();
+ std::string webrtc_device_id = instance_config.webrtc_device_id();
+ if (webrtc_device_id.empty()) {
+ webrtc_device_id = instance_config.instance_name();
}
device_info["assembly_dir"] = config.assembly_dir();
- device_info["instance_name"] = device_name;
+ device_info["webrtc_device_id"] = webrtc_device_id;
device_info["instance_dir"] = instance_config.instance_dir();
// 1443 is the port of the global webrtc "operator" service
device_info["web_access"] =
CalcWebAccessUrl({.sig_server_addr = config.sig_server_address(),
- .device_name = device_name});
+ .webrtc_device_id = webrtc_device_id});
device_info["adb_serial"] = instance_config.adb_ip_and_port();
device_info["webrtc_port"] = std::to_string(config.sig_server_port());
for (int i = 0; i < instance_config.display_configs().size(); i++) {
diff --git a/host/commands/stop/Android.bp b/host/commands/stop/Android.bp
index 07c88e9..7d9fa5f 100644
--- a/host/commands/stop/Android.bp
+++ b/host/commands/stop/Android.bp
@@ -40,5 +40,5 @@
enabled: true,
},
},
- defaults: ["cuttlefish_host", "cuttlefish_libicuuc"],
+ defaults: ["cuttlefish_host"],
}
diff --git a/host/commands/tcp_connector/Android.bp b/host/commands/tcp_connector/Android.bp
index a7148ef..8a3791e 100644
--- a/host/commands/tcp_connector/Android.bp
+++ b/host/commands/tcp_connector/Android.bp
@@ -34,5 +34,10 @@
"libcuttlefish_host_config",
"libgflags",
],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
defaults: ["cuttlefish_buildhost_only"]
}
diff --git a/host/commands/test_gce_driver/Android.bp b/host/commands/test_gce_driver/Android.bp
index 6b2bfb6..e8a2ca2 100644
--- a/host/commands/test_gce_driver/Android.bp
+++ b/host/commands/test_gce_driver/Android.bp
@@ -67,7 +67,7 @@
defaults: ["cuttlefish_host"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_test_gce_proto_cpp",
proto: {
export_proto_headers: true,
diff --git a/host/cvd_test_configs/end_to_end_test/multi/TC1.json b/host/cvd_test_configs/end_to_end_test/multi/TC1.json
new file mode 100644
index 0000000..a359439
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/multi/TC1.json
@@ -0,0 +1,43 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 2048
+ }
+ },
+ {
+ "vm": {
+ "memory_mb": 4096
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 1080,
+ "height": 600,
+ "dpi": 120
+ },
+ {
+ "width": 400,
+ "height": 600,
+ "dpi": 150
+ }
+ ]
+ }
+ },
+ {
+ "vm": {
+ "memory_mb": 4096
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 2560,
+ "height": 1800,
+ "dpi": 320
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_auto.json b/host/cvd_test_configs/end_to_end_test/single/TC_auto.json
new file mode 100644
index 0000000..9db9453
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_auto.json
@@ -0,0 +1,24 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 4096
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 1080,
+ "height": 600,
+ "dpi": 120
+ },
+ {
+ "width": 400,
+ "height": 600,
+ "dpi": 120
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_foldable.json b/host/cvd_test_configs/end_to_end_test/single/TC_foldable.json
new file mode 100644
index 0000000..1ade717
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_foldable.json
@@ -0,0 +1,65 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 4096,
+ "custom_actions": [
+ {
+ "device_states": [
+ {
+ "lid_switch_open": false,
+ "hinge_angle_value": 0
+ }
+ ],
+ "button": {
+ "command": "device_state_closed",
+ "title": "Device State Closed",
+ "icon_name": "smartphone"
+ }
+ },
+ {
+ "device_states": [
+ {
+ "lid_switch_open": true,
+ "hinge_angle_value": 90
+ }
+ ],
+ "button": {
+ "command": "device_state_half_opened",
+ "title": "Device State Half-Opened",
+ "icon_name": "laptop"
+ }
+ },
+ {
+ "device_states": [
+ {
+ "lid_switch_open": true,
+ "hinge_angle_value": 180
+ }
+ ],
+ "button": {
+ "command": "device_state_opened",
+ "title": "Device State Opened",
+ "icon_name": "tablet"
+ }
+ }
+ ]
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 1768,
+ "height": 2208,
+ "dpi": 374
+ },
+ {
+ "width": 832,
+ "height": 2268,
+ "dpi": 387
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_go.json b/host/cvd_test_configs/end_to_end_test/single/TC_go.json
new file mode 100644
index 0000000..0d67c91
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_go.json
@@ -0,0 +1,19 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 2048
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 720,
+ "height": 1280,
+ "dpi": 320
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_phone.json b/host/cvd_test_configs/end_to_end_test/single/TC_phone.json
new file mode 100644
index 0000000..0d67c91
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_phone.json
@@ -0,0 +1,19 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 2048
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 720,
+ "height": 1280,
+ "dpi": 320
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_slim.json b/host/cvd_test_configs/end_to_end_test/single/TC_slim.json
new file mode 100644
index 0000000..925c7fd
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_slim.json
@@ -0,0 +1,20 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 2048,
+ "use_sdcard": false
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 720,
+ "height": 1280,
+ "dpi": 320
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_tablet.json b/host/cvd_test_configs/end_to_end_test/single/TC_tablet.json
new file mode 100644
index 0000000..939757f
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_tablet.json
@@ -0,0 +1,19 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 4096
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 2560,
+ "height": 1800,
+ "dpi": 320
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_tv.json b/host/cvd_test_configs/end_to_end_test/single/TC_tv.json
new file mode 100644
index 0000000..741f7d4
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_tv.json
@@ -0,0 +1,19 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 2048
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 1920,
+ "height": 1080,
+ "dpi": 213
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/end_to_end_test/single/TC_wear.json b/host/cvd_test_configs/end_to_end_test/single/TC_wear.json
new file mode 100644
index 0000000..84e886fa
--- /dev/null
+++ b/host/cvd_test_configs/end_to_end_test/single/TC_wear.json
@@ -0,0 +1,20 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 1536,
+ "use_sdcard": false
+ },
+ "graphics": {
+ "displays": [
+ {
+ "width": 450,
+ "height": 450,
+ "dpi": 320
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/main_phone-main_watch.json b/host/cvd_test_configs/main_phone-main_watch.json
new file mode 100644
index 0000000..2b8881d
--- /dev/null
+++ b/host/cvd_test_configs/main_phone-main_watch.json
@@ -0,0 +1,26 @@
+{
+ "instances": [
+ {
+ "@import": "phone",
+ "vm": {
+ "memory_mb": 8192,
+ "setupwizard_mode": "OPTIONAL",
+ "cpus": 4
+ },
+ "disk": {
+ "default_build": "@ab/git_main/cf_x86_64_phone-trunk_staging-userdebug"
+ }
+ },
+ {
+ "@import": "wearable",
+ "vm": {
+ "memory_mb": 8192,
+ "setupwizard_mode": "REQUIRED",
+ "cpus": 4
+ },
+ "disk": {
+ "default_build": "@ab/git_main/cf_gwear_x86-trunk_staging-userdebug"
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/main_phone.json b/host/cvd_test_configs/main_phone.json
new file mode 100644
index 0000000..9451dd2
--- /dev/null
+++ b/host/cvd_test_configs/main_phone.json
@@ -0,0 +1,15 @@
+{
+ "instances": [
+ {
+ "@import": "phone",
+ "vm": {
+ "memory_mb": 8192,
+ "setupwizard_mode": "OPTIONAL",
+ "cpus": 4
+ },
+ "disk": {
+ "default_build": "@ab/git_main/cf_x86_64_phone-trunk_staging-userdebug"
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/mvp_features/graphics/displays/TC1.json b/host/cvd_test_configs/mvp_features/graphics/displays/TC1.json
new file mode 100644
index 0000000..3f023a0
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/graphics/displays/TC1.json
@@ -0,0 +1,11 @@
+{
+ "instances":
+ [
+ {
+ "graphics": {}
+ },
+ {
+ "graphics": {}
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/graphics/displays/TC2.json b/host/cvd_test_configs/mvp_features/graphics/displays/TC2.json
new file mode 100644
index 0000000..1d41551
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/graphics/displays/TC2.json
@@ -0,0 +1,20 @@
+{
+ "instances":
+ [
+ {
+ "graphics": {
+ "displays": [
+ {}
+ ]
+ }
+ },
+ {
+ "graphics": {
+ "displays": [
+ {},
+ {}
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/graphics/displays/TC3.json b/host/cvd_test_configs/mvp_features/graphics/displays/TC3.json
new file mode 100644
index 0000000..64a3c1d
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/graphics/displays/TC3.json
@@ -0,0 +1,35 @@
+{
+ "instances":
+ [
+ {
+ "graphics": {
+ "displays": [
+ {
+ "width": 1080,
+ "height": 600,
+ "dpi": 120,
+ "refresh_rate_hertz": 60
+ },
+ {
+ "width": 400,
+ "height": 600,
+ "dpi": 120,
+ "refresh_rate_hertz": 60
+ }
+ ]
+ }
+ },
+ {
+ "graphics": {
+ "displays": [
+ {
+ "width": 2560,
+ "height": 1800,
+ "dpi": 320,
+ "refresh_rate_hertz": 60
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/security/guest_enforce_security/TC1.json b/host/cvd_test_configs/mvp_features/security/guest_enforce_security/TC1.json
new file mode 100644
index 0000000..32536ef
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/security/guest_enforce_security/TC1.json
@@ -0,0 +1,14 @@
+{
+ "instances":
+ [
+ {
+ "security": {}
+ },
+ {
+ "vm": {},
+ "security": {
+ "guest_enforce_security": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/security/guest_enforce_security/TC2.json b/host/cvd_test_configs/mvp_features/security/guest_enforce_security/TC2.json
new file mode 100644
index 0000000..f69ed8d
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/security/guest_enforce_security/TC2.json
@@ -0,0 +1,15 @@
+{
+ "instances":
+ [
+ {
+ "security": {
+ "guest_enforce_security": false
+ }
+ },
+ {
+ "security": {
+ "guest_enforce_security": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/cpus/TC1.json b/host/cvd_test_configs/mvp_features/vm/cpus/TC1.json
new file mode 100644
index 0000000..edcb91e
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/cpus/TC1.json
@@ -0,0 +1,13 @@
+{
+ "instances":
+ [
+ {
+ "vm": {}
+ },
+ {
+ "vm": {
+ "cpus": 4
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/cpus/TC2.json b/host/cvd_test_configs/mvp_features/vm/cpus/TC2.json
new file mode 100644
index 0000000..5dc89a4
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/cpus/TC2.json
@@ -0,0 +1,15 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "cpus": 4
+ }
+ },
+ {
+ "vm": {
+ "cpus": 6
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/custom_actions/TC1.json b/host/cvd_test_configs/mvp_features/vm/custom_actions/TC1.json
new file mode 100644
index 0000000..502ed1c
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/custom_actions/TC1.json
@@ -0,0 +1,40 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 2048
+ }
+ },
+ {
+ "vm": {
+ "memory_mb": 2048,
+ "custom_actions": [
+ {
+ "shell_command": "am start -a android.intent.action.VIEW -d https://www.android1.com/",
+ "button": {
+ "command": "web",
+ "title": "Web Page",
+ "icon_name": "language"
+ }
+ },
+ {
+ "server": "cuttlefish_example_action_server",
+ "buttons": [
+ {
+ "command": "settings",
+ "title": "Quick Settings",
+ "icon_name": "settings"
+ },
+ {
+ "command": "alert",
+ "title": "Do Not Disturb",
+ "icon_name": "notifications_paused"
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC1.json b/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC1.json
new file mode 100644
index 0000000..00a8422
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC1.json
@@ -0,0 +1,13 @@
+{
+ "instances":
+ [
+ {
+ "vm": {}
+ },
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC2.json b/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC2.json
new file mode 100644
index 0000000..43fb111
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC2.json
@@ -0,0 +1,17 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ },
+ {
+ "vm": {
+ "crosvm": {
+ "enable_sandbox": true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC3.json b/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC3.json
new file mode 100644
index 0000000..5fd26f9
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/enable_sandbox/TC3.json
@@ -0,0 +1,19 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {
+ "enable_sandbox": true
+ }
+ }
+ },
+ {
+ "vm": {
+ "crosvm": {
+ "enable_sandbox": true
+ }
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/mvp_features/vm/memory_mb/TC1.json b/host/cvd_test_configs/mvp_features/vm/memory_mb/TC1.json
new file mode 100644
index 0000000..4b79b75
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/memory_mb/TC1.json
@@ -0,0 +1,13 @@
+{
+ "instances":
+ [
+ {
+ "vm": {}
+ },
+ {
+ "vm": {
+ "memory_mb": 4096
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/memory_mb/TC2.json b/host/cvd_test_configs/mvp_features/vm/memory_mb/TC2.json
new file mode 100644
index 0000000..622f6fd
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/memory_mb/TC2.json
@@ -0,0 +1,15 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "memory_mb": 4096
+ }
+ },
+ {
+ "vm": {
+ "memory_mb": 8192
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC1.json b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC1.json
new file mode 100644
index 0000000..488a7b5
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC1.json
@@ -0,0 +1,11 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {},
+ "setupwizard_mode": "ENABLED"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC2.json b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC2.json
new file mode 100644
index 0000000..c821d0f
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC2.json
@@ -0,0 +1,15 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ },
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC3.json b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC3.json
new file mode 100644
index 0000000..8902611
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC3.json
@@ -0,0 +1,16 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ },
+ {
+ "vm": {
+ "crosvm": {},
+ "setupwizard_mode": "REQUIRED"
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC4.json b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC4.json
new file mode 100644
index 0000000..7c7f434
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/setupwizard_mode/TC4.json
@@ -0,0 +1,17 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {},
+ "setupwizard_mode": "OPTIONAL"
+ }
+ },
+ {
+ "vm": {
+ "crosvm": {},
+ "setupwizard_mode": "REQUIRED"
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/mvp_features/vm/vm_manager/TC1.json b/host/cvd_test_configs/mvp_features/vm/vm_manager/TC1.json
new file mode 100644
index 0000000..3225bb1
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/vm_manager/TC1.json
@@ -0,0 +1,9 @@
+{
+ "instances":
+ [
+ {
+ "vm": {}
+ },
+ {}
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/vm_manager/TC2.json b/host/cvd_test_configs/mvp_features/vm/vm_manager/TC2.json
new file mode 100644
index 0000000..467a222
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/vm_manager/TC2.json
@@ -0,0 +1,15 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "qemu": {}
+ }
+ },
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/mvp_features/vm/vm_manager/TC3.json b/host/cvd_test_configs/mvp_features/vm/vm_manager/TC3.json
new file mode 100644
index 0000000..5dcebe4
--- /dev/null
+++ b/host/cvd_test_configs/mvp_features/vm/vm_manager/TC3.json
@@ -0,0 +1,15 @@
+{
+ "instances":
+ [
+ {
+ "vm": {
+ "crosvm": {}
+ }
+ },
+ {
+ "vm": {
+ "gem5": {}
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/host/cvd_test_configs/templates_inheritance/custom/TC1.json b/host/cvd_test_configs/templates_inheritance/custom/TC1.json
new file mode 100644
index 0000000..4f9dffc
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/custom/TC1.json
@@ -0,0 +1,11 @@
+{
+ "instances":
+ [
+ {
+ "@import": "phone",
+ "vm": {
+ "memory_mb": 4096
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/custom/TC2.json b/host/cvd_test_configs/templates_inheritance/custom/TC2.json
new file mode 100644
index 0000000..4a689ff
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/custom/TC2.json
@@ -0,0 +1,18 @@
+{
+ "instances":
+ [
+ {
+ "@import": "phone",
+ "vm": {
+ "memory_mb": 4096
+ }
+ },
+ {
+ "@import": "tablet",
+ "vm": {
+ "memory_mb": 8192,
+ "cpus": 4
+ }
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/multi/TC1.json b/host/cvd_test_configs/templates_inheritance/multi/TC1.json
new file mode 100644
index 0000000..a500c4a
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/multi/TC1.json
@@ -0,0 +1,26 @@
+{
+ "instances":
+ [
+ {
+ "@import": "auto"
+ },
+ {
+ "@import": "go"
+ },
+ {
+ "@import": "phone"
+ },
+ {
+ "@import": "slim"
+ },
+ {
+ "@import": "tablet"
+ },
+ {
+ "@import": "tv"
+ },
+ {
+ "@import": "wearable"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/multi/TC2.json b/host/cvd_test_configs/templates_inheritance/multi/TC2.json
new file mode 100644
index 0000000..79cf60e
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/multi/TC2.json
@@ -0,0 +1,29 @@
+{
+ "instances":
+ [
+ {
+ "@import": "auto"
+ },
+ {
+ "@import": "foldable"
+ },
+ {
+ "@import": "go"
+ },
+ {
+ "@import": "phone"
+ },
+ {
+ "@import": "slim"
+ },
+ {
+ "@import": "tablet"
+ },
+ {
+ "@import": "tv"
+ },
+ {
+ "@import": "wearable"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_auto.json b/host/cvd_test_configs/templates_inheritance/single/TC_auto.json
new file mode 100644
index 0000000..ec1b23b
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_auto.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "auto"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_foldable.json b/host/cvd_test_configs/templates_inheritance/single/TC_foldable.json
new file mode 100644
index 0000000..8d4614c
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_foldable.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "foldable"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_go.json b/host/cvd_test_configs/templates_inheritance/single/TC_go.json
new file mode 100644
index 0000000..e5aa719
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_go.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "go"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_phone.json b/host/cvd_test_configs/templates_inheritance/single/TC_phone.json
new file mode 100644
index 0000000..bc59f38
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_phone.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "phone"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_slim.json b/host/cvd_test_configs/templates_inheritance/single/TC_slim.json
new file mode 100644
index 0000000..1598986
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_slim.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "slim"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_tablet.json b/host/cvd_test_configs/templates_inheritance/single/TC_tablet.json
new file mode 100644
index 0000000..df3c6bb
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_tablet.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "tablet"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_tv.json b/host/cvd_test_configs/templates_inheritance/single/TC_tv.json
new file mode 100644
index 0000000..452120d
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_tv.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "tv"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/templates_inheritance/single/TC_wear.json b/host/cvd_test_configs/templates_inheritance/single/TC_wear.json
new file mode 100644
index 0000000..ff2a1e1
--- /dev/null
+++ b/host/cvd_test_configs/templates_inheritance/single/TC_wear.json
@@ -0,0 +1,8 @@
+{
+ "instances":
+ [
+ {
+ "@import": "wearable"
+ }
+ ]
+}
diff --git a/host/cvd_test_configs/tm_phone-tm_watch-main_host_pkg.json b/host/cvd_test_configs/tm_phone-tm_watch-main_host_pkg.json
new file mode 100644
index 0000000..34304db
--- /dev/null
+++ b/host/cvd_test_configs/tm_phone-tm_watch-main_host_pkg.json
@@ -0,0 +1,28 @@
+{
+ "instances": [
+ {
+ "@import": "phone",
+ "vm": {
+ "memory_mb": 8192,
+ "setupwizard_mode": "OPTIONAL",
+ "cpus": 4
+ },
+ "disk": {
+ "default_build": "@ab/git_tm-qpr-dev/cf_x86_64_phone-userdebug",
+ "host_package": "@ab/aosp-main/aosp_cf_x86_64_phone-trunk_staging-userdebug"
+ }
+ },
+ {
+ "@import": "wearable",
+ "vm": {
+ "memory_mb": 8192,
+ "setupwizard_mode": "REQUIRED",
+ "cpus": 4
+ },
+ "disk": {
+ "default_build": "@ab/git_tm-wear-dev/cf_gwear_x86-userdebug",
+ "host_package": "@ab/aosp-main/aosp_cf_x86_64_phone-trunk_staging-userdebug"
+ }
+ }
+ ]
+}
diff --git a/host/frontend/webrtc/libcommon/Android.bp b/host/frontend/webrtc/libcommon/Android.bp
index f6fe47d..9afc36b 100644
--- a/host/frontend/webrtc/libcommon/Android.bp
+++ b/host/frontend/webrtc/libcommon/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_webrtc_common",
srcs: [
"audio_device.cpp",
@@ -38,11 +38,18 @@
"libwebrtc_absl_headers",
],
static_libs: [
+ "libevent",
+ "libopus",
+ "libsrtp2",
+ "libvpx",
"libwebrtc",
+ "libyuv",
],
shared_libs: [
"libbase",
+ "libcrypto",
"libjsoncpp",
+ "libssl",
],
defaults: ["cuttlefish_buildhost_only"],
}
diff --git a/host/frontend/webrtc/libdevice/Android.bp b/host/frontend/webrtc/libdevice/Android.bp
index b4277c2..57756e5 100644
--- a/host/frontend/webrtc/libdevice/Android.bp
+++ b/host/frontend/webrtc/libdevice/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_webrtc_device",
srcs: [
"audio_track_source_impl.cpp",
@@ -25,6 +25,7 @@
"client_handler.cpp",
"data_channels.cpp",
"keyboard.cpp",
+ "lights_observer.cpp",
"local_recorder.cpp",
"streamer.cpp",
"video_track_source_impl.cpp",
@@ -49,6 +50,7 @@
"libcuttlefish_webrtc_common",
"libgflags",
"libdrm",
+ "libevent",
"libffi",
"libwayland_crosvm_gpu_display_extension_server_protocols",
"libwayland_extension_server_protocols",
@@ -59,10 +61,14 @@
"libwebrtc",
"libcvd_gnss_grpc_proxy",
"liblocation",
+ "libopus",
+ "libvpx",
+ "libyuv",
],
shared_libs: [
"libbase",
"libcn-cbor",
+ "libcrypto",
"libcuttlefish_fs",
"libfruit",
"libjsoncpp",
diff --git a/host/frontend/webrtc/libdevice/lights_observer.cpp b/host/frontend/webrtc/libdevice/lights_observer.cpp
new file mode 100644
index 0000000..f616b6e
--- /dev/null
+++ b/host/frontend/webrtc/libdevice/lights_observer.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "lights_observer.h"
+
+#include <android-base/logging.h>
+#include <chrono>
+#include "common/libs/utils/vsock_connection.h"
+
+namespace cuttlefish {
+namespace webrtc_streaming {
+
+LightsObserver::LightsObserver(unsigned int port, unsigned int cid)
+ : cid_(cid), port_(port), is_running_(false), session_active_(false) {}
+
+LightsObserver::~LightsObserver() { Stop(); }
+
+bool LightsObserver::Start() {
+ if (connection_thread_.joinable()) {
+ LOG(ERROR) << "Connection thread is already running.";
+ return false;
+ }
+
+ is_running_ = true;
+
+ connection_thread_ = std::thread([this] {
+ while (is_running_) {
+ while (cvd_connection_.IsConnected()) {
+ ReadServerMessages();
+ }
+
+ // Try to start a new connection. If this fails, delay retrying a bit.
+ if (is_running_ && !cvd_connection_.Connect(port_, cid_)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ continue;
+ }
+ }
+
+ LOG(INFO) << "Exiting connection thread";
+ });
+
+ LOG(INFO) << "Connection thread running";
+ return true;
+}
+
+void LightsObserver::Stop() {
+ is_running_ = false;
+ cvd_connection_.Disconnect();
+
+ // The connection_thread_ should finish at any point now. Let's join it.
+ if (connection_thread_.joinable()) {
+ connection_thread_.join();
+ }
+}
+
+void LightsObserver::ReadServerMessages() {
+ // TODO: Expand this with the rest of the protocol. Cache lights states.
+}
+
+} // namespace webrtc_streaming
+} // namespace cuttlefish
diff --git a/host/frontend/webrtc/libdevice/lights_observer.h b/host/frontend/webrtc/libdevice/lights_observer.h
new file mode 100644
index 0000000..6a55dd5
--- /dev/null
+++ b/host/frontend/webrtc/libdevice/lights_observer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include "common/libs/utils/vsock_connection.h"
+
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+namespace cuttlefish {
+namespace webrtc_streaming {
+
+class LightsObserver {
+ public:
+ LightsObserver(unsigned int port, unsigned int cid);
+ ~LightsObserver();
+
+ LightsObserver(const LightsObserver& other) = delete;
+ LightsObserver& operator=(const LightsObserver& other) = delete;
+
+ bool Start();
+
+ private:
+ void Stop();
+ void ReadServerMessages();
+ // TODO(b/295543722): Move to a virtio_console transport instead.
+ VsockClientConnection cvd_connection_;
+ unsigned int cid_;
+ unsigned int port_;
+ std::thread connection_thread_;
+ std::atomic<bool> is_running_;
+ std::atomic<bool> session_active_;
+};
+
+} // namespace webrtc_streaming
+} // namespace cuttlefish
diff --git a/host/libs/audio_connector/Android.bp b/host/libs/audio_connector/Android.bp
index c26fecb..7da54ad 100644
--- a/host/libs/audio_connector/Android.bp
+++ b/host/libs/audio_connector/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_audio_connector",
srcs: [
"buffers.cpp",
diff --git a/host/libs/avb/Android.bp b/host/libs/avb/Android.bp
index 49d16e1..62b6ad7 100644
--- a/host/libs/avb/Android.bp
+++ b/host/libs/avb/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_avb",
srcs: [
"avb.cpp"
@@ -25,8 +25,8 @@
shared_libs: [
"libcuttlefish_utils",
"libfruit",
- // need to access host/libs/config/cuttlefish_config.h
- "libjsoncpp",
+ "libjsoncpp", // need to access host/libs/config/cuttlefish_config.h
+ "liblog",
],
static_libs: [
"libbase",
diff --git a/host/libs/command_util/Android.bp b/host/libs/command_util/Android.bp
index 0564fa2..92f2308 100644
--- a/host/libs/command_util/Android.bp
+++ b/host/libs/command_util/Android.bp
@@ -17,13 +17,14 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_command_util",
srcs: [
"launcher_message.cc",
"util.cc",
],
shared_libs: [
+ "liblog",
"libcuttlefish_fs",
"libcuttlefish_utils",
"libjsoncpp",
diff --git a/host/libs/command_util/launcher_message.cc b/host/libs/command_util/launcher_message.cc
index 4cd9a4a..5ef35b2 100644
--- a/host/libs/command_util/launcher_message.cc
+++ b/host/libs/command_util/launcher_message.cc
@@ -56,13 +56,6 @@
}
}
LauncherActionMessage new_message(action, type, std::move(serialized_data));
- /* To avoid -Wunused-private-field compilation error
- *
- * will be moved above when type_ is actually used.
- */
- CF_EXPECTF(IsSupportedType(new_message.type_),
- "ExtendedActionType {} is not supported.",
- static_cast<std::uint32_t>(new_message.type_));
return new_message;
}
@@ -83,17 +76,6 @@
return Contains(supported_actions, action);
}
-bool LauncherActionMessage::IsSupportedType(const ExtendedActionType type) {
- std::set<ExtendedActionType> supported_action_types{
- ExtendedActionType::kUnused,
- ExtendedActionType::kSuspend,
- ExtendedActionType::kResume,
- ExtendedActionType::kStartScreenRecording,
- ExtendedActionType::kStopScreenRecording,
- };
- return Contains(supported_action_types, type);
-}
-
static Result<void> WriteBuffer(const SharedFD& fd, const std::string& buf,
const std::string& description) {
CF_EXPECT(fd->IsOpen(), "The file descriptor to write is not open.");
diff --git a/host/libs/command_util/launcher_message.h b/host/libs/command_util/launcher_message.h
index c5a7ef9..9e35260 100644
--- a/host/libs/command_util/launcher_message.h
+++ b/host/libs/command_util/launcher_message.h
@@ -53,7 +53,6 @@
std::string serialized_data);
// returns true if the action does not need extended field
static bool IsShortAction(const LauncherAction action);
- static bool IsSupportedType(const ExtendedActionType type);
const LauncherAction action_;
const ExtendedActionType type_;
diff --git a/host/libs/config/Android.bp b/host/libs/config/Android.bp
index 113dbaa..74ff5ea 100644
--- a/host/libs/config/Android.bp
+++ b/host/libs/config/Android.bp
@@ -17,10 +17,9 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_host_config",
srcs: [
- "bootconfig_args.cpp",
"display.cpp",
"config_flag.cpp",
"custom_actions.cpp",
diff --git a/host/libs/config/adb/Android.bp b/host/libs/config/adb/Android.bp
index 587de68..7ebc01f 100644
--- a/host/libs/config/adb/Android.bp
+++ b/host/libs/config/adb/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_host_config_adb",
srcs: [
"config.cpp",
@@ -27,9 +27,10 @@
"strings.cpp",
],
shared_libs: [
- "libcuttlefish_fs",
- "libcuttlefish_utils",
"libbase",
+ "libcuttlefish_fs",
+ "libcuttlefish_host_config",
+ "libcuttlefish_utils",
"libfruit",
"libgflags",
"libjsoncpp",
diff --git a/host/libs/config/adb/flags.cpp b/host/libs/config/adb/flags.cpp
index 6606d34..0440f61 100644
--- a/host/libs/config/adb/flags.cpp
+++ b/host/libs/config/adb/flags.cpp
@@ -36,13 +36,14 @@
}
return modes.str().substr(1); // First comma
});
- mode_flag_.Setter([this](const FlagMatch& match) {
+ mode_flag_.Setter([this](const FlagMatch& match) -> Result<void> {
// TODO(schuffelen): Error on unknown types?
std::set<AdbMode> modes;
for (auto& mode : android::base::Split(match.value, ",")) {
modes.insert(StringToAdbMode(mode));
}
- return config_.SetModes(modes);
+ CF_EXPECT(config_.SetModes(modes));
+ return {};
});
}
diff --git a/host/libs/config/adb/launch.cpp b/host/libs/config/adb/launch.cpp
index a3f7170..896ac82 100644
--- a/host/libs/config/adb/launch.cpp
+++ b/host/libs/config/adb/launch.cpp
@@ -21,6 +21,7 @@
#include <vector>
#include <fruit/fruit.h>
+#include <gflags/gflags.h>
#include "common/libs/utils/result.h"
#include "host/commands/kernel_log_monitor/utils.h"
@@ -129,8 +130,30 @@
// CommandSource
Result<std::vector<MonitorCommand>> Commands() override {
std::vector<MonitorCommand> commands;
- if (helper_.VsockTunnelEnabled()) {
- Command adb_tunnel(SocketVsockProxyBinary());
+ const auto vsock_tunnel_enabled = helper_.VsockTunnelEnabled();
+ const auto vsock_half_tunnel_enabled = helper_.VsockHalfTunnelEnabled();
+ CF_EXPECT(!vsock_half_tunnel_enabled || !vsock_tunnel_enabled,
+ "Up to one of vsock_tunnel or vsock_half_tunnel is allowed.");
+ if (!vsock_half_tunnel_enabled && !vsock_tunnel_enabled) {
+ return commands;
+ }
+
+ Command adb_tunnel(SocketVsockProxyBinary());
+ adb_tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
+ adb_tunnel.AddParameter("--start_event_id=", monitor::Event::AdbdStarted);
+ adb_tunnel.AddParameter("--stop_event_id=",
+ monitor::Event::FastbootStarted);
+ /* fmayle@ found out that when cuttlefish starts from the saved snapshot
+ * that was saved after ADBD start event, the socket_vsock_proxy must not
+ * wait for the AdbdStarted event.
+ */
+ if (!instance_.sock_vsock_proxy_wait_adbd_start()) {
+ adb_tunnel.AddParameter("--start_immediately=true");
+ }
+ adb_tunnel.AddParameter("--server_type=tcp");
+ adb_tunnel.AddParameter("--server_tcp_port=", instance_.adb_host_port());
+
+ if (vsock_tunnel_enabled) {
/**
* This socket_vsock_proxy (a.k.a. sv proxy) runs on the host. It assumes
* that another sv proxy runs inside the guest. see:
@@ -145,17 +168,9 @@
* instance.adb_host_port()
*
*/
- adb_tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
- adb_tunnel.AddParameter("--start_event_id=", monitor::Event::AdbdStarted);
- adb_tunnel.AddParameter("--server_type=tcp");
- adb_tunnel.AddParameter("--server_fd=", tcp_server_);
adb_tunnel.AddParameter("--client_type=vsock");
adb_tunnel.AddParameter("--client_vsock_port=6520");
- adb_tunnel.AddParameter("--client_vsock_id=", instance_.vsock_guest_cid());
- commands.emplace_back(std::move(adb_tunnel));
- }
- if (helper_.VsockHalfTunnelEnabled()) {
- Command adb_tunnel(SocketVsockProxyBinary());
+ } else {
/*
* This socket_vsock_proxy (a.k.a. sv proxy) runs on the host, and
* cooperates with the adbd inside the guest. See this file:
@@ -166,16 +181,13 @@
* should be therefore tcp, and the port should differ from instance to
* instance and be equal to instance.adb_host_port()
*/
- adb_tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
- adb_tunnel.AddParameter("--start_event_id=", monitor::Event::AdbdStarted);
- adb_tunnel.AddParameter("--server_type=tcp");
- adb_tunnel.AddParameter("--server_fd=", tcp_server_);
adb_tunnel.AddParameter("--client_type=vsock");
adb_tunnel.AddParameter("--client_vsock_port=", 5555);
- adb_tunnel.AddParameter("--client_vsock_id=", instance_.vsock_guest_cid());
- adb_tunnel.AddParameter("--label=", "adb");
- commands.emplace_back(std::move(adb_tunnel));
}
+
+ adb_tunnel.AddParameter("--client_vsock_id=", instance_.vsock_guest_cid());
+ adb_tunnel.AddParameter("--label=", "adb");
+ commands.emplace_back(std::move(adb_tunnel));
return commands;
}
@@ -189,11 +201,8 @@
std::unordered_set<SetupFeature*> Dependencies() const override {
return {static_cast<SetupFeature*>(&log_pipe_provider_)};
}
+
Result<void> ResultSetup() override {
- tcp_server_ =
- SharedFD::SocketLocalServer(instance_.adb_host_port(), SOCK_STREAM);
- CF_EXPECT(tcp_server_->IsOpen(),
- "Unable to create socket_vsock_proxy server socket: ");
kernel_log_pipe_ = log_pipe_provider_.KernelLogPipe();
return {};
}
@@ -202,7 +211,6 @@
const CuttlefishConfig::InstanceSpecific& instance_;
KernelLogPipeProvider& log_pipe_provider_;
SharedFD kernel_log_pipe_;
- SharedFD tcp_server_;
};
} // namespace
diff --git a/host/libs/config/config_flag.cpp b/host/libs/config/config_flag.cpp
index 457d60d..fd5bfce 100644
--- a/host/libs/config/config_flag.cpp
+++ b/host/libs/config/config_flag.cpp
@@ -123,7 +123,10 @@
"device/google/cuttlefish/shared/config/config_*.json for possible "
"values.";
auto getter = [this]() { return config_; };
- auto setter = [this](const FlagMatch& m) { return ChooseConfig(m.value); };
+ auto setter = [this](const FlagMatch& m) -> Result<void> {
+ CF_EXPECT(ChooseConfig(m.value));
+ return {};
+ };
flag_ = GflagsCompatFlag("config").Help(help).Getter(getter).Setter(setter);
}
@@ -163,15 +166,13 @@
}
private:
- bool ChooseConfig(const std::string& name) {
- if (!config_reader_.HasConfig(name)) {
- LOG(ERROR) << "Invalid --config option '" << name << "'. Valid options: "
- << android::base::Join(config_reader_.AvailableConfigs(), ",");
- return false;
- }
+ Result<void> ChooseConfig(const std::string& name) {
+ CF_EXPECTF(config_reader_.HasConfig(name),
+ "Invalid --config option '{}'. Valid options: [{}]", name,
+ fmt::join(config_reader_.AvailableConfigs(), ","));
config_ = name;
is_default_ = false;
- return true;
+ return {};
}
std::optional<std::string> FindAndroidInfoConfig() const {
auto info_path = system_image_dir_flag_.Path() + "/android-info.txt";
diff --git a/host/libs/config/custom_actions.cpp b/host/libs/config/custom_actions.cpp
index e98c46c..87aa948 100644
--- a/host/libs/config/custom_actions.cpp
+++ b/host/libs/config/custom_actions.cpp
@@ -213,19 +213,19 @@
"empty then the custom action config will be empty as well.");
custom_action_config_flag_.Getter(
[this]() { return custom_action_config_[0]; });
- custom_action_config_flag_.Setter([this](const FlagMatch& match) {
- if (!match.value.empty() &&
- (match.value == "unset" || match.value == "\"unset\"")) {
- custom_action_config_.push_back(DefaultCustomActionConfig());
- } else if (!match.value.empty() && !FileExists(match.value)) {
- LOG(ERROR) << "custom_action_config file \"" << match.value << "\" "
- << "does not exist.";
- return false;
- } else {
- custom_action_config_.push_back(match.value);
- }
- return true;
- });
+ custom_action_config_flag_.Setter(
+ [this](const FlagMatch& match) -> Result<void> {
+ if (!match.value.empty() &&
+ (match.value == "unset" || match.value == "\"unset\"")) {
+ custom_action_config_.push_back(DefaultCustomActionConfig());
+ } else if (!match.value.empty() && !FileExists(match.value)) {
+ return CF_ERRF("custom_action_config file \"{}\" does not exist.",
+ match.value);
+ } else {
+ custom_action_config_.push_back(match.value);
+ }
+ return {};
+ });
// TODO(schuffelen): Access ConfigFlag directly for these values.
custom_actions_flag_ = GflagsCompatFlag("custom_actions");
custom_actions_flag_.Help(
@@ -234,23 +234,16 @@
"preset config files; prefer --custom_action_config to specify a "
"custom config file on the command line. Actions in this flag are "
"combined with actions in --custom_action_config.");
- custom_actions_flag_.Setter([this](const FlagMatch& match) {
+ custom_actions_flag_.Setter([this](const FlagMatch& match) -> Result<void> {
// Load the custom action from the --config preset file.
if (match.value == "unset" || match.value == "\"unset\"") {
AddEmptyJsonCustomActionConfigs();
- return true;
+ return {};
}
- Json::CharReaderBuilder builder;
- std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
- std::string errorMessage;
- Json::Value custom_action_array(Json::arrayValue);
- if (!reader->parse(&*match.value.begin(), &*match.value.end(),
- &custom_action_array, &errorMessage)) {
- LOG(ERROR) << "Could not read custom actions config flag: "
- << errorMessage;
- return false;
- }
- return AddJsonCustomActionConfigs(custom_action_array);
+ auto custom_action_array = CF_EXPECT(
+ ParseJson(match.value), "Could not read custom actions config flag");
+ CF_EXPECT(AddJsonCustomActionConfigs(custom_action_array));
+ return {};
});
}
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index c9fb6c5..6e34dbd 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -331,6 +331,22 @@
(*dictionary_)[kNetsimInstanceNum] = netsim_instance_num;
}
+static constexpr char kNetsimArgs[] = "netsim_args";
+void CuttlefishConfig::set_netsim_args(const std::string& netsim_args) {
+ Json::Value args_json_obj(Json::arrayValue);
+ for (const auto& arg : android::base::Tokenize(netsim_args, " ")) {
+ args_json_obj.append(arg);
+ }
+ (*dictionary_)[kNetsimArgs] = args_json_obj;
+}
+std::vector<std::string> CuttlefishConfig::netsim_args() const {
+ std::vector<std::string> netsim_args;
+ for (const Json::Value& arg : (*dictionary_)[kNetsimArgs]) {
+ netsim_args.push_back(arg.asString());
+ }
+ return netsim_args;
+}
+
static constexpr char kEnableMetrics[] = "enable_metrics";
void CuttlefishConfig::set_enable_metrics(std::string enable_metrics) {
(*dictionary_)[kEnableMetrics] = kUnknown;
@@ -490,6 +506,14 @@
(*dictionary_)[kRootcanalTestPort] = rootcanal_test_port;
}
+static constexpr char kSnapshotPath[] = "snapshot_path";
+std::string CuttlefishConfig::snapshot_path() const {
+ return (*dictionary_)[kSnapshotPath].asString();
+}
+void CuttlefishConfig::set_snapshot_path(const std::string& snapshot_path) {
+ (*dictionary_)[kSnapshotPath] = snapshot_path;
+}
+
/*static*/ CuttlefishConfig* CuttlefishConfig::BuildConfigImpl(
const std::string& path) {
auto ret = new CuttlefishConfig();
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index fb83e7e..08d0f72 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -37,38 +37,42 @@
}
namespace cuttlefish {
-constexpr char kLogcatSerialMode[] = "serial";
-constexpr char kLogcatVsockMode[] = "vsock";
-constexpr char kDefaultUuidPrefix[] = "699acfc4-c8c4-11e7-882b-5065f31dc1";
-constexpr char kCuttlefishConfigEnvVarName[] = "CUTTLEFISH_CONFIG_FILE";
-constexpr char kCuttlefishInstanceEnvVarName[] = "CUTTLEFISH_INSTANCE";
-constexpr char kVsocUserPrefix[] = "vsoc-";
-constexpr char kCvdNamePrefix[] = "cvd-";
-constexpr char kBootStartedMessage[] ="VIRTUAL_DEVICE_BOOT_STARTED";
-constexpr char kBootCompletedMessage[] = "VIRTUAL_DEVICE_BOOT_COMPLETED";
-constexpr char kBootFailedMessage[] = "VIRTUAL_DEVICE_BOOT_FAILED";
-constexpr char kMobileNetworkConnectedMessage[] =
+inline constexpr char kLogcatSerialMode[] = "serial";
+inline constexpr char kLogcatVsockMode[] = "vsock";
+
+inline constexpr char kDefaultUuidPrefix[] =
+ "699acfc4-c8c4-11e7-882b-5065f31dc1";
+inline constexpr char kCuttlefishConfigEnvVarName[] = "CUTTLEFISH_CONFIG_FILE";
+inline constexpr char kCuttlefishInstanceEnvVarName[] = "CUTTLEFISH_INSTANCE";
+inline constexpr char kVsocUserPrefix[] = "vsoc-";
+inline constexpr char kCvdNamePrefix[] = "cvd-";
+inline constexpr char kBootStartedMessage[] = "VIRTUAL_DEVICE_BOOT_STARTED";
+inline constexpr char kBootCompletedMessage[] = "VIRTUAL_DEVICE_BOOT_COMPLETED";
+inline constexpr char kBootFailedMessage[] = "VIRTUAL_DEVICE_BOOT_FAILED";
+inline constexpr char kMobileNetworkConnectedMessage[] =
"VIRTUAL_DEVICE_NETWORK_MOBILE_CONNECTED";
-constexpr char kWifiConnectedMessage[] =
+inline constexpr char kWifiConnectedMessage[] =
"VIRTUAL_DEVICE_NETWORK_WIFI_CONNECTED";
-constexpr char kEthernetConnectedMessage[] =
+inline constexpr char kEthernetConnectedMessage[] =
"VIRTUAL_DEVICE_NETWORK_ETHERNET_CONNECTED";
// TODO(b/131864854): Replace this with a string less likely to change
-constexpr char kAdbdStartedMessage[] =
+inline constexpr char kAdbdStartedMessage[] =
"init: starting service 'adbd'...";
-constexpr char kFastbootdStartedMessage[] =
+inline constexpr char kFastbootdStartedMessage[] =
"init: starting service 'fastbootd'...";
-constexpr char kScreenChangedMessage[] = "VIRTUAL_DEVICE_SCREEN_CHANGED";
-constexpr char kDisplayPowerModeChangedMessage[] =
+inline constexpr char kFastbootStartedMessage[] =
+ "Listening for fastboot command on tcp";
+inline constexpr char kScreenChangedMessage[] = "VIRTUAL_DEVICE_SCREEN_CHANGED";
+inline constexpr char kDisplayPowerModeChangedMessage[] =
"VIRTUAL_DEVICE_DISPLAY_POWER_MODE_CHANGED";
-constexpr char kInternalDirName[] = "internal";
-constexpr char kGrpcSocketDirName[] = "grpc_socket";
-constexpr char kSharedDirName[] = "shared";
-constexpr char kLogDirName[] = "logs";
-constexpr char kCrosvmVarEmptyDir[] = "/var/empty";
-constexpr char kKernelLoadedMessage[] = "] Linux version";
-constexpr char kBootloaderLoadedMessage[] = "U-Boot 20";
+inline constexpr char kInternalDirName[] = "internal";
+inline constexpr char kGrpcSocketDirName[] = "grpc_socket";
+inline constexpr char kSharedDirName[] = "shared";
+inline constexpr char kLogDirName[] = "logs";
+inline constexpr char kCrosvmVarEmptyDir[] = "/var/empty";
+inline constexpr char kKernelLoadedMessage[] = "] Linux version";
+inline constexpr char kBootloaderLoadedMessage[] = "U-Boot 20";
enum class SecureHal {
Unknown,
@@ -164,6 +168,8 @@
bool netsim_radio_enabled(NetsimRadio flag) const;
void set_netsim_instance_num(int netsim_instance_num);
int netsim_instance_num() const;
+ void set_netsim_args(const std::string& netsim_args);
+ std::vector<std::string> netsim_args() const;
enum Answer {
kUnknown = 0,
@@ -254,6 +260,10 @@
std::string ap_image_dev_path() const;
void set_ap_image_dev_path(const std::string& dev_path);
+ // path to the saved snapshot file(s)
+ std::string snapshot_path() const;
+ void set_snapshot_path(const std::string& snapshot_path);
+
class InstanceSpecific;
class MutableInstanceSpecific;
@@ -306,6 +316,8 @@
std::string adb_ip_and_port() const;
// Port number to connect to the camera hal on the guest
int camera_server_port() const;
+ // Port number to connect to the lights hal on the guest
+ int lights_server_port() const;
std::string adb_device_name() const;
std::string gnss_file_path() const;
@@ -465,6 +477,14 @@
bool crosvm_use_balloon() const;
bool crosvm_use_rng() const;
bool use_pmem() const;
+ /* fmayle@ found out that when cuttlefish starts from the saved snapshot
+ * that was saved after ADBD start event, the socket_vsock_proxy must not
+ * wait for the AdbdStarted event.
+ *
+ * This instance-specific configuration tells the host sock_vsock_proxy
+ * not to wait for the adbd start event.
+ */
+ bool sock_vsock_proxy_wait_adbd_start() const;
// Wifi MAC address inside the guest
int wifi_mac_prefix() const;
@@ -560,6 +580,9 @@
std::string gpu_angle_feature_overrides_disabled() const;
std::string gpu_capture_binary() const;
bool enable_gpu_udmabuf() const;
+ bool enable_gpu_vhost_user() const;
+ bool enable_gpu_external_blob() const;
+ bool enable_gpu_system_blob() const;
std::string hwcomposer() const;
@@ -633,6 +656,7 @@
void set_keymaster_vsock_port(int keymaster_vsock_port);
void set_vehicle_hal_server_port(int vehicle_server_port);
void set_audiocontrol_server_port(int audiocontrol_server_port);
+ void set_lights_server_port(int lights_server_port);
void set_adb_host_port(int adb_host_port);
void set_modem_simulator_host_id(int modem_simulator_id);
void set_adb_ip_and_port(const std::string& ip_port);
@@ -668,6 +692,7 @@
void set_crosvm_use_balloon(const bool use_balloon);
void set_crosvm_use_rng(const bool use_rng);
void set_use_pmem(const bool use_pmem);
+ void set_sock_vsock_proxy_wait_adbd_start(const bool);
// Wifi MAC address inside the guest
void set_wifi_mac_prefix(const int wifi_mac_prefix);
// Gnss grpc proxy server port inside the host
@@ -740,6 +765,9 @@
void set_gpu_angle_feature_overrides_disabled(const std::string& overrides);
void set_gpu_capture_binary(const std::string&);
void set_enable_gpu_udmabuf(const bool enable_gpu_udmabuf);
+ void set_enable_gpu_vhost_user(const bool enable_gpu_vhost_user);
+ void set_enable_gpu_external_blob(const bool enable_gpu_external_blob);
+ void set_enable_gpu_system_blob(const bool enable_gpu_system_blob);
void set_hwcomposer(const std::string&);
diff --git a/host/libs/config/cuttlefish_config_instance.cpp b/host/libs/config/cuttlefish_config_instance.cpp
index deb7ab8..b8e73f1 100644
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ b/host/libs/config/cuttlefish_config_instance.cpp
@@ -712,6 +712,33 @@
return (*Dictionary())[kEnableGpuUdmabuf].asBool();
}
+static constexpr char kEnableGpuVhostUser[] = "enable_gpu_vhost_user";
+void CuttlefishConfig::MutableInstanceSpecific::set_enable_gpu_vhost_user(
+ const bool enable_gpu_vhost_user) {
+ (*Dictionary())[kEnableGpuVhostUser] = enable_gpu_vhost_user;
+}
+bool CuttlefishConfig::InstanceSpecific::enable_gpu_vhost_user() const {
+ return (*Dictionary())[kEnableGpuVhostUser].asBool();
+}
+
+static constexpr char kEnableGpuExternalBlob[] = "enable_gpu_external_blob";
+void CuttlefishConfig::MutableInstanceSpecific::set_enable_gpu_external_blob(
+ const bool enable_gpu_external_blob) {
+ (*Dictionary())[kEnableGpuExternalBlob] = enable_gpu_external_blob;
+}
+bool CuttlefishConfig::InstanceSpecific::enable_gpu_external_blob() const {
+ return (*Dictionary())[kEnableGpuExternalBlob].asBool();
+}
+
+static constexpr char kEnableGpuSystemBlob[] = "enable_gpu_system_blob";
+void CuttlefishConfig::MutableInstanceSpecific::set_enable_gpu_system_blob(
+ const bool enable_gpu_system_blob) {
+ (*Dictionary())[kEnableGpuSystemBlob] = enable_gpu_system_blob;
+}
+bool CuttlefishConfig::InstanceSpecific::enable_gpu_system_blob() const {
+ return (*Dictionary())[kEnableGpuSystemBlob].asBool();
+}
+
static constexpr char kEnableAudio[] = "enable_audio";
void CuttlefishConfig::MutableInstanceSpecific::set_enable_audio(bool enable) {
(*Dictionary())[kEnableAudio] = enable;
@@ -1358,6 +1385,14 @@
(*Dictionary())[kConfigServerPort] = config_server_port;
}
+static constexpr char kLightsServerPort[] = "lights_server_port";
+int CuttlefishConfig::InstanceSpecific::lights_server_port() const {
+ return (*Dictionary())[kLightsServerPort].asInt();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_lights_server_port(int lights_server_port) {
+ (*Dictionary())[kLightsServerPort] = lights_server_port;
+}
+
static constexpr char kCameraServerPort[] = "camera_server_port";
int CuttlefishConfig::InstanceSpecific::camera_server_port() const {
return (*Dictionary())[kCameraServerPort].asInt();
@@ -1471,6 +1506,17 @@
return (*Dictionary())[kCrosvmUsePmem].asBool();
}
+static constexpr char kSockVsockWaitAdbdStart[] =
+ "sock_vsock_proxy_wait_adbd_start";
+void CuttlefishConfig::MutableInstanceSpecific::
+ set_sock_vsock_proxy_wait_adbd_start(const bool wait_adbd_start) {
+ (*Dictionary())[kSockVsockWaitAdbdStart] = wait_adbd_start;
+}
+bool CuttlefishConfig::InstanceSpecific::sock_vsock_proxy_wait_adbd_start()
+ const {
+ return (*Dictionary())[kSockVsockWaitAdbdStart].asBool();
+}
+
std::string CuttlefishConfig::InstanceSpecific::touch_socket_path(
int screen_idx) const {
return PerInstanceInternalUdsPath(
diff --git a/host/libs/config/data_image.cpp b/host/libs/config/data_image.cpp
index 7769672..9b2ea7e 100644
--- a/host/libs/config/data_image.cpp
+++ b/host/libs/config/data_image.cpp
@@ -22,7 +22,6 @@
#include "common/libs/fs/shared_buf.h"
#include "common/libs/utils/files.h"
-#include "common/libs/utils/network.h"
#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
#include "host/libs/config/esp.h"
@@ -33,10 +32,10 @@
namespace cuttlefish {
namespace {
-const std::string kDataPolicyUseExisting = "use_existing";
-const std::string kDataPolicyCreateIfMissing = "create_if_missing";
-const std::string kDataPolicyAlwaysCreate = "always_create";
-const std::string kDataPolicyResizeUpTo= "resize_up_to";
+
+static constexpr std::string_view kDataPolicyUseExisting = "use_existing";
+static constexpr std::string_view kDataPolicyAlwaysCreate = "always_create";
+static constexpr std::string_view kDataPolicyResizeUpTo = "resize_up_to";
const int FSCK_ERROR_CORRECTED = 1;
const int FSCK_ERROR_CORRECTED_REQUIRES_REBOOT = 2;
@@ -142,8 +141,8 @@
MasterBootRecord mbr = {
.partitions = {{
.partition_type = 0xC,
- .first_lba = (std::uint32_t) offset_size_bytes / SECTOR_SIZE,
- .num_sectors = (std::uint32_t) image_size_bytes / SECTOR_SIZE,
+ .first_lba = (std::uint32_t)offset_size_bytes / kSectorSize,
+ .num_sectors = (std::uint32_t)image_size_bytes / kSectorSize,
}},
.boot_signature = {0x55, 0xAA},
};
diff --git a/host/libs/config/display.cpp b/host/libs/config/display.cpp
index 0e5a111..6c6540d 100644
--- a/host/libs/config/display.cpp
+++ b/host/libs/config/display.cpp
@@ -111,9 +111,9 @@
.Help(kDisplayHelp),
GflagsCompatFlag(kDisplayFlag)
.Help(kDisplayHelp)
- .Setter([&](const FlagMatch& match) {
+ .Setter([&](const FlagMatch& match) -> Result<void> {
repeated_display_flag_values.push_back(match.value);
- return true;
+ return {};
}),
};
@@ -148,4 +148,4 @@
return displays_configs;
}
-} // namespace cuttlefish
\ No newline at end of file
+} // namespace cuttlefish
diff --git a/host/libs/config/esp.cpp b/host/libs/config/esp.cpp
index c0b6bdd..f16a52d 100644
--- a/host/libs/config/esp.cpp
+++ b/host/libs/config/esp.cpp
@@ -13,7 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <algorithm>
+#include <array>
#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
#include "host/libs/config/esp.h"
#include "common/libs/fs/shared_buf.h"
@@ -23,6 +28,60 @@
namespace cuttlefish {
+// For licensing and build reproducibility reasons, pick up the bootloaders
+// from the host Linux distribution (if present) and pack them into the
+// automatically generated ESP. If the user wants their own bootloaders,
+// they can use -esp_image=/path/to/esp.img to override, so we don't need
+// to accommodate customizations of this packing process.
+
+// Currently we only support Debian based distributions, and GRUB is built
+// for those distros to always load grub.cfg from EFI/debian/grub.cfg, and
+// nowhere else. If you want to add support for other distros, make the
+// extra directories below and copy the initial grub.cfg there as well
+//
+// Currently the Cuttlefish bootloaders are built only for x86 (32-bit),
+// ARM (QEMU only, 32-bit) and AArch64 (64-bit), and U-Boot will hard-code
+// these search paths. Install all bootloaders to one of these paths.
+// NOTE: For now, just ignore the 32-bit ARM version, as Debian doesn't
+// build an EFI monolith for this architecture.
+// These are the paths Debian installs the monoliths to. If another distro
+// uses an alternative monolith path, add it to this table
+static constexpr char kBootSrcPathIA32[] =
+ "/usr/lib/grub/i386-efi/monolithic/grubia32.efi";
+static constexpr char kBootDestPathIA32[] = "/EFI/BOOT/BOOTIA32.EFI";
+
+static constexpr char kBootSrcPathAA64[] =
+ "/usr/lib/grub/arm64-efi/monolithic/grubaa64.efi";
+static constexpr char kBootDestPathAA64[] = "/EFI/BOOT/BOOTAA64.EFI";
+
+static constexpr char kMultibootModuleSrcPathIA32[] =
+ "/usr/lib/grub/i386-efi/multiboot.mod";
+static constexpr char kMultibootModuleDestPathIA32[] =
+ "/EFI/modules/multiboot.mod";
+
+static constexpr char kMultibootModuleSrcPathAA64[] =
+ "/usr/lib/grub/arm64-efi/multiboot.mod";
+static constexpr char kMultibootModuleDestPathAA64[] =
+ "/EFI/modules/multiboot.mod";
+
+static constexpr char kKernelDestPath[] = "/vmlinuz";
+static constexpr char kInitrdDestPath[] = "/initrd";
+static constexpr char kZedbootDestPath[] = "/zedboot.zbi";
+static constexpr char kMultibootBinDestPath[] = "/multiboot.bin";
+
+// TODO(b/260338443, b/260337906) remove ubuntu and debian variations
+// after migrating to grub-mkimage or adding grub binaries as a prebuilt
+static constexpr char kGrubDebianConfigDestPath[] = "/EFI/debian/grub.cfg";
+static constexpr char kGrubUbuntuConfigDestPath[] = "/EFI/ubuntu/grub.cfg";
+static constexpr char kGrubConfigDestDirectoryPath[] = "/boot/grub";
+static constexpr char kGrubConfigDestPath[] = "/boot/grub/grub.cfg";
+
+static constexpr std::array kGrubModulesX86{
+ "normal", "configfile", "linux", "linuxefi", "multiboot", "ls",
+ "cat", "help", "fat", "part_msdos", "part_gpt"};
+static constexpr char kGrubModulesPath[] = "/usr/lib/grub/";
+static constexpr char kGrubModulesX86Name[] = "i386-efi";
+
bool NewfsMsdos(const std::string& data_image, int data_image_mb,
int offset_num_mb) {
off_t image_size_bytes = static_cast<off_t>(data_image_mb) << 20;
@@ -65,10 +124,9 @@
case Arch::X86:
case Arch::X86_64: {
const auto x86_modules = std::string(kGrubModulesPath) + std::string(kGrubModulesX86Name);
- const auto modules_presented = all_of(kGrubModulesX86.begin(), kGrubModulesX86.end(),
- [&](const std::string& m) {
- return FileExists(x86_modules + m);
- });
+ const auto modules_presented = std::all_of(
+ kGrubModulesX86.begin(), kGrubModulesX86.end(),
+ [&](const std::string& m) { return FileExists(x86_modules + m); });
if (modules_presented) return true;
const auto monolith_presented = FileExists(kBootSrcPathIA32);
@@ -79,8 +137,8 @@
return false;
}
-bool MsdosMakeDirectories(const std::string& image_path,
- const std::vector<std::string>& directories) {
+static bool MsdosMakeDirectories(const std::string& image_path,
+ const std::vector<std::string>& directories) {
auto mmd = HostBinaryPath("mmd");
std::vector<std::string> command {mmd, "-i", image_path};
command.insert(command.end(), directories.begin(), directories.end());
@@ -92,8 +150,8 @@
return true;
}
-bool CopyToMsdos(const std::string& image, const std::string& path,
- const std::string& destination) {
+static bool CopyToMsdos(const std::string& image, const std::string& path,
+ const std::string& destination) {
const auto mcopy = HostBinaryPath("mcopy");
const auto success =
Execute({mcopy, "-o", "-i", image, "-s", path, destination});
@@ -103,9 +161,10 @@
return true;
}
-bool GrubMakeImage(const std::string& prefix, const std::string& format,
- const std::string& directory, const std::string& output,
- std::vector<std::string> modules) {
+template <typename T>
+static bool GrubMakeImage(const std::string& prefix, const std::string& format,
+ const std::string& directory,
+ const std::string& output, const T& modules) {
std::vector<std::string> command = {"grub-mkimage", "--prefix", prefix,
"--format", format, "--directory", directory,
"--output", output};
diff --git a/host/libs/config/esp.h b/host/libs/config/esp.h
index 8cb782b..f6850f3 100644
--- a/host/libs/config/esp.h
+++ b/host/libs/config/esp.h
@@ -15,65 +15,15 @@
#pragma once
-#include <utility>
#include <optional>
#include <string>
+#include <utility>
#include <vector>
-#include "host/libs/config/cuttlefish_config.h"
#include "common/libs/utils/environment.h"
namespace cuttlefish {
-// For licensing and build reproducibility reasons, pick up the bootloaders
-// from the host Linux distribution (if present) and pack them into the
-// automatically generated ESP. If the user wants their own bootloaders,
-// they can use -esp_image=/path/to/esp.img to override, so we don't need
-// to accommodate customizations of this packing process.
-
-// Currently we only support Debian based distributions, and GRUB is built
-// for those distros to always load grub.cfg from EFI/debian/grub.cfg, and
-// nowhere else. If you want to add support for other distros, make the
-// extra directories below and copy the initial grub.cfg there as well
-//
-// Currently the Cuttlefish bootloaders are built only for x86 (32-bit),
-// ARM (QEMU only, 32-bit) and AArch64 (64-bit), and U-Boot will hard-code
-// these search paths. Install all bootloaders to one of these paths.
-// NOTE: For now, just ignore the 32-bit ARM version, as Debian doesn't
-// build an EFI monolith for this architecture.
-// These are the paths Debian installs the monoliths to. If another distro
-// uses an alternative monolith path, add it to this table
-static constexpr char kBootSrcPathIA32[] = "/usr/lib/grub/i386-efi/monolithic/grubia32.efi";
-static constexpr char kBootDestPathIA32[] = "/EFI/BOOT/BOOTIA32.EFI";
-
-static constexpr char kBootSrcPathAA64[] = "/usr/lib/grub/arm64-efi/monolithic/grubaa64.efi";
-static constexpr char kBootDestPathAA64[] = "/EFI/BOOT/BOOTAA64.EFI";
-
-static constexpr char kMultibootModuleSrcPathIA32[] = "/usr/lib/grub/i386-efi/multiboot.mod";
-static constexpr char kMultibootModuleDestPathIA32[] = "/EFI/modules/multiboot.mod";
-
-static constexpr char kMultibootModuleSrcPathAA64[] = "/usr/lib/grub/arm64-efi/multiboot.mod";
-static constexpr char kMultibootModuleDestPathAA64[] = "/EFI/modules/multiboot.mod";
-
-static constexpr char kKernelDestPath[] = "/vmlinuz";
-static constexpr char kInitrdDestPath[] = "/initrd";
-static constexpr char kZedbootDestPath[] = "/zedboot.zbi";
-static constexpr char kMultibootBinDestPath[] = "/multiboot.bin";
-
-// TODO(b/260338443, b/260337906) remove ubuntu and debian variations
-// after migrating to grub-mkimage or adding grub binaries as a prebuilt
-static constexpr char kGrubDebianConfigDestPath[] = "/EFI/debian/grub.cfg";
-static constexpr char kGrubUbuntuConfigDestPath[] = "/EFI/ubuntu/grub.cfg";
-static constexpr char kGrubConfigDestDirectoryPath[] = "/boot/grub";
-static constexpr char kGrubConfigDestPath[] = "/boot/grub/grub.cfg";
-
-const std::vector<std::string> kGrubModulesX86 =
- {"normal", "configfile", "linux", "linuxefi", "multiboot",
- "ls", "cat", "help", "fat", "part_msdos", "part_gpt"};
-static constexpr char kGrubModulesPath[] = "/usr/lib/grub/";
-static constexpr char kGrubModulesX86Name[] = "i386-efi";
-static constexpr char kGrubModulesArm64Name[] = "arm64-efi";
-
class LinuxEspBuilder final {
public:
LinuxEspBuilder() = delete;
diff --git a/host/libs/config/fastboot/Android.bp b/host/libs/config/fastboot/Android.bp
index 978c4e4..c2fb041 100644
--- a/host/libs/config/fastboot/Android.bp
+++ b/host/libs/config/fastboot/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_host_config_fastboot",
srcs: [
"config.cpp",
@@ -27,6 +27,9 @@
],
shared_libs: [
"libbase",
+ "libcuttlefish_fs",
+ "libcuttlefish_host_config",
+ "libcuttlefish_utils",
"libfruit",
"libjsoncpp",
],
diff --git a/host/libs/config/fastboot/fastboot.h b/host/libs/config/fastboot/fastboot.h
index ddccf1d..607a78b 100644
--- a/host/libs/config/fastboot/fastboot.h
+++ b/host/libs/config/fastboot/fastboot.h
@@ -42,7 +42,8 @@
FastbootConfigFlagComponent();
fruit::Component<fruit::Required<FastbootConfig>, FastbootConfigFragment>
FastbootConfigFragmentComponent();
-fruit::Component<fruit::Required<const CuttlefishConfig::InstanceSpecific,
+fruit::Component<fruit::Required<KernelLogPipeProvider,
+ const CuttlefishConfig::InstanceSpecific,
const FastbootConfig>>
LaunchFastbootComponent();
diff --git a/host/libs/config/fastboot/launch.cpp b/host/libs/config/fastboot/launch.cpp
index adf6e5e..3686378 100644
--- a/host/libs/config/fastboot/launch.cpp
+++ b/host/libs/config/fastboot/launch.cpp
@@ -27,18 +27,23 @@
namespace cuttlefish {
namespace {
-class FastbootProxy : public CommandSource {
+class FastbootProxy : public CommandSource, public KernelLogPipeConsumer {
public:
INJECT(FastbootProxy(const CuttlefishConfig::InstanceSpecific& instance,
- const FastbootConfig& fastboot_config))
+ const FastbootConfig& fastboot_config,
+ KernelLogPipeProvider& log_pipe_provider))
: instance_(instance),
- fastboot_config_(fastboot_config) {}
+ fastboot_config_(fastboot_config),
+ log_pipe_provider_(log_pipe_provider) {}
Result<std::vector<MonitorCommand>> Commands() override {
const std::string ethernet_host = instance_.ethernet_ipv6() + "%" +
instance_.ethernet_bridge_name();
Command tunnel(SocketVsockProxyBinary());
+ tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
+ tunnel.AddParameter("--start_event_id=", monitor::Event::FastbootStarted);
+ tunnel.AddParameter("--stop_event_id=", monitor::Event::AdbdStarted);
tunnel.AddParameter("--server_type=", "tcp");
tunnel.AddParameter("--server_tcp_port=", instance_.fastboot_host_port());
tunnel.AddParameter("--client_type=", "tcp");
@@ -59,22 +64,29 @@
private:
std::unordered_set<SetupFeature*> Dependencies() const override {
+ return {static_cast<SetupFeature*>(&log_pipe_provider_)};
+ }
+
+ Result<void> ResultSetup() override {
+ kernel_log_pipe_ = log_pipe_provider_.KernelLogPipe();
return {};
}
- Result<void> ResultSetup() override { return {}; }
-
const CuttlefishConfig::InstanceSpecific& instance_;
const FastbootConfig& fastboot_config_;
+ KernelLogPipeProvider& log_pipe_provider_;
+ SharedFD kernel_log_pipe_;
};
} // namespace
-fruit::Component<fruit::Required<const CuttlefishConfig::InstanceSpecific,
+fruit::Component<fruit::Required<KernelLogPipeProvider,
+ const CuttlefishConfig::InstanceSpecific,
const FastbootConfig>>
LaunchFastbootComponent() {
return fruit::createComponent()
.addMultibinding<CommandSource, FastbootProxy>()
+ .addMultibinding<KernelLogPipeConsumer, FastbootProxy>()
.addMultibinding<SetupFeature, FastbootProxy>();
}
diff --git a/host/libs/config/mbr.h b/host/libs/config/mbr.h
index 3388237..33f4db7 100644
--- a/host/libs/config/mbr.h
+++ b/host/libs/config/mbr.h
@@ -15,8 +15,10 @@
*/
#pragma once
-constexpr int SECTOR_SIZE_SHIFT = 9;
-constexpr int SECTOR_SIZE = 1 << SECTOR_SIZE_SHIFT;
+#include <cstdint>
+
+inline constexpr int kSectorSizeShift = 9;
+inline constexpr int kSectorSize = 1 << kSectorSizeShift;
struct __attribute__((packed)) MbrPartitionEntry {
std::uint8_t status;
@@ -33,4 +35,4 @@
std::uint8_t boot_signature[2];
};
-static_assert(sizeof(MasterBootRecord) == SECTOR_SIZE);
+static_assert(sizeof(MasterBootRecord) == kSectorSize);
diff --git a/host/libs/confui/Android.bp b/host/libs/confui/Android.bp
index be4b22a..450bda7 100644
--- a/host/libs/confui/Android.bp
+++ b/host/libs/confui/Android.bp
@@ -29,7 +29,7 @@
],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_confui_host",
srcs: [
"cbor.cc",
diff --git a/host/libs/control_env/Android.bp b/host/libs/control_env/Android.bp
index 8512584..144258a 100644
--- a/host/libs/control_env/Android.bp
+++ b/host/libs/control_env/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_control_env",
srcs: [
"grpc_service_handler.cc",
@@ -25,15 +25,23 @@
shared_libs: [
"libbase",
"libcuttlefish_utils",
+ "libprotobuf-cpp-full",
"libgrpc++",
+ "libjsoncpp",
],
static_libs: [
"grpc_cli_libs",
"libc++fs",
+ "libgflags",
],
cflags: [
"-Wno-unused-parameter",
],
cpp_std: "c++17",
defaults: ["cuttlefish_buildhost_only"],
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
}
diff --git a/host/libs/control_env/grpc_service_handler.cc b/host/libs/control_env/grpc_service_handler.cc
index 7ef3900..68a674d 100644
--- a/host/libs/control_env/grpc_service_handler.cc
+++ b/host/libs/control_env/grpc_service_handler.cc
@@ -18,12 +18,16 @@
#include <unordered_map>
#include <android-base/strings.h>
+#include <json/json.h>
#include <test/cpp/util/grpc_tool.h>
#include <test/cpp/util/test_config.h>
#include "common/libs/utils/contains.h"
#include "common/libs/utils/result.h"
+using android::base::EndsWith;
+using android::base::Split;
+using android::base::Trim;
using grpc::InsecureChannelCredentials;
namespace cuttlefish {
@@ -32,6 +36,12 @@
constexpr char kDefaultOptionL[] = "-l=false";
constexpr char kDefaultOptionJsonInput[] = "--json_input=true";
constexpr char kDefaultOptionJsonOutput[] = "--json_output=true";
+constexpr char kServiceServerReflection[] =
+ "grpc.reflection.v1alpha.ServerReflection";
+constexpr char kServiceHealth[] = "grpc.health.v1.Health";
+constexpr char kServiceControlEnvProxy[] = "ControlEnvProxyService";
+constexpr char kServiceControlEnvProxyFull[] =
+ "controlenvproxyserver.ControlEnvProxyService";
bool PrintStream(std::stringstream* ss, const grpc::string& output) {
(*ss) << output;
@@ -91,6 +101,11 @@
return output_stream.str();
}
+Result<std::string> RunGrpcCommand(const std::vector<std::string>& arguments) {
+ std::vector<std::string> options;
+ return RunGrpcCommand(arguments, options);
+}
+
Result<std::vector<std::string>> GetServiceList(
const std::string& server_address) {
std::vector<std::string> service_list;
@@ -102,7 +117,8 @@
std::string service_name;
while (std::getline(output_stream, service_name)) {
- if (service_name.compare("grpc.reflection.v1alpha.ServerReflection") == 0) {
+ if (service_name.compare(kServiceServerReflection) == 0 ||
+ service_name.compare(kServiceHealth) == 0) {
continue;
}
service_list.emplace_back(service_name);
@@ -118,7 +134,7 @@
for (const auto& server_address : server_address_list) {
auto service_names = CF_EXPECT(GetServiceList(server_address));
for (auto& full_service_name : service_names) {
- if (android::base::EndsWith(full_service_name, service_name)) {
+ if (EndsWith(full_service_name, service_name)) {
candidates.emplace_back(server_address);
break;
}
@@ -136,7 +152,7 @@
std::vector<std::string> candidates;
auto service_names = CF_EXPECT(GetServiceList(server_address));
for (auto& full_service_name : service_names) {
- if (android::base::EndsWith(full_service_name, service_name)) {
+ if (EndsWith(full_service_name, service_name)) {
candidates.emplace_back(full_service_name);
}
}
@@ -155,107 +171,114 @@
return full_service_name + "/" + method_name;
}
-Result<std::string> GetFullTypeName(const std::string& server_address,
- const std::string& service_name,
- const std::string& method_name,
- const std::string& type_name) {
- // Run grpc_cli ls -l for given method to extract full type name.
- // Example output:
- // rpc OpenwrtIpaddr(google.protobuf.Empty) returns
- // (openwrtcontrolserver.OpenwrtIpaddrReply) {}
- const auto& full_method_name =
- CF_EXPECT(GetFullMethodName(server_address, service_name, method_name));
- std::vector<std::string> arguments{"grpc_cli", "ls", server_address,
- full_method_name};
- std::vector<std::string> options{"-l"};
- auto grpc_result = CF_EXPECT(RunGrpcCommand(arguments, options));
-
- std::vector<std::string> candidates;
- for (auto& full_type_name : android::base::Split(grpc_result, "()")) {
- if (android::base::EndsWith(full_type_name, type_name)) {
- candidates.emplace_back(full_type_name);
- }
- }
-
- CF_EXPECT(candidates.size() > 0, service_name + " is not found.");
- CF_EXPECT(candidates.size() < 2, service_name + " is ambiguous.");
-
- return candidates[0];
-}
-
Result<std::string> HandleLsCmd(
const std::vector<std::string>& server_address_list,
- const std::vector<std::string>& args,
- const std::vector<std::string>& options) {
- CF_EXPECT(args.size() < 3, "too many arguments");
- std::string command_output;
+ const std::vector<std::string>& args) {
+ switch (args.size()) {
+ case 0: {
+ // ls subcommand with no arguments
+ std::string command_output;
+ for (const auto& server_address : server_address_list) {
+ std::vector<std::string> grpc_arguments{"grpc_cli", "ls",
+ server_address};
+ command_output += CF_EXPECT(RunGrpcCommand(grpc_arguments));
+ }
- if (args.size() > 0) {
- std::vector<std::string> grpc_arguments{"grpc_cli", "ls"};
+ Json::Value json;
+ json["services"] = Json::Value(Json::arrayValue);
+ for (auto& full_service_name : Split(Trim(command_output), "\n")) {
+ if (full_service_name.compare(kServiceServerReflection) == 0 ||
+ full_service_name.compare(kServiceHealth) == 0 ||
+ full_service_name.compare(kServiceControlEnvProxyFull) == 0) {
+ continue;
+ }
+ json["services"].append(Split(full_service_name, ".").back());
+ }
+ Json::StreamWriterBuilder builder;
+ return Json::writeString(builder, json) + "\n";
+ }
+ case 1: {
+ // ls subcommand with 1 argument; service_name
+ const auto& service_name = args[0];
+ CF_EXPECT(service_name.compare(kServiceControlEnvProxy) != 0,
+ "Prohibited service name");
+ const auto& server_address =
+ CF_EXPECT(GetServerAddress(server_address_list, service_name));
+ const auto& full_service_name =
+ CF_EXPECT(GetFullServiceName(server_address, service_name));
+ std::vector<std::string> grpc_arguments{"grpc_cli", "ls", server_address,
+ full_service_name};
+ std::string command_output = CF_EXPECT(RunGrpcCommand(grpc_arguments));
- const auto& service_name = args[0];
- const auto& server_address =
- CF_EXPECT(GetServerAddress(server_address_list, service_name));
- grpc_arguments.push_back(server_address);
- if (args.size() > 1) {
+ Json::Value json;
+ json["methods"] = Json::Value(Json::arrayValue);
+ for (auto& method_name : Split(Trim(command_output), "\n")) {
+ json["methods"].append(method_name);
+ }
+ Json::StreamWriterBuilder builder;
+ return Json::writeString(builder, json) + "\n";
+ }
+ case 2: {
// ls subcommand with 2 arguments; service_name and method_name
+ const auto& service_name = args[0];
+ CF_EXPECT(service_name.compare(kServiceControlEnvProxy) != 0,
+ "Prohibited service name");
+ const auto& server_address =
+ CF_EXPECT(GetServerAddress(server_address_list, service_name));
const auto& method_name = args[1];
const auto& full_method_name = CF_EXPECT(
GetFullMethodName(server_address, service_name, method_name));
- grpc_arguments.push_back(full_method_name);
- } else {
- // ls subcommand with 1 argument; service_name
- const auto& full_service_name =
- CF_EXPECT(GetFullServiceName(server_address, service_name));
- grpc_arguments.push_back(full_service_name);
- }
- command_output += CF_EXPECT(RunGrpcCommand(grpc_arguments, options));
- } else {
- // ls subcommand with no arguments
- for (const auto& server_address : server_address_list) {
- std::vector<std::string> grpc_arguments{"grpc_cli", "ls", server_address};
- command_output += CF_EXPECT(RunGrpcCommand(grpc_arguments, options));
- }
- }
+ std::vector<std::string> grpc_arguments{"grpc_cli", "ls", server_address,
+ full_method_name};
+ std::vector<std::string> options{"-l"};
+ std::string command_output =
+ CF_EXPECT(RunGrpcCommand(grpc_arguments, options));
- return command_output;
+ // Example command_output:
+ // rpc SetTxpower(wmediumdserver.SetTxpowerRequest) returns
+ // (google.protobuf.Empty) {}
+ std::vector<std::string> parsed_output =
+ Split(Trim(command_output), "()");
+ CF_EXPECT(parsed_output.size() == 5, "Unexpected parsing result");
+ Json::Value json;
+ json["request_type"] = parsed_output[1];
+ json["response_type"] = parsed_output[3];
+ Json::StreamWriterBuilder builder;
+ return Json::writeString(builder, json) + "\n";
+ }
+ default:
+ return CF_ERR("too many arguments");
+ }
}
Result<std::string> HandleTypeCmd(
const std::vector<std::string>& server_address_list,
- const std::vector<std::string>& args,
- const std::vector<std::string>& options) {
- CF_EXPECT(args.size() > 2,
- "need to specify a service name, a method name, and type_name");
- CF_EXPECT(args.size() < 4, "too many arguments");
- std::string command_output;
+ const std::vector<std::string>& args) {
+ CF_EXPECT(args.size() > 1,
+ "need to specify the service name and the type_name");
+ CF_EXPECT(args.size() < 3, "too many arguments");
std::vector<std::string> grpc_arguments{"grpc_cli", "type"};
const auto& service_name = args[0];
- const auto& method_name = args[1];
- const auto& type_name = args[2];
+ CF_EXPECT(service_name.compare(kServiceControlEnvProxy) != 0,
+ "Prohibited service name");
+ const auto& type_name = args[1];
const auto& server_address =
CF_EXPECT(GetServerAddress(server_address_list, service_name));
grpc_arguments.push_back(server_address);
- const auto& full_type_name = CF_EXPECT(
- GetFullTypeName(server_address, service_name, method_name, type_name));
- grpc_arguments.push_back(full_type_name);
+ grpc_arguments.push_back(type_name);
- command_output += CF_EXPECT(RunGrpcCommand(grpc_arguments, options));
-
- return command_output;
+ return RunGrpcCommand(grpc_arguments);
}
Result<std::string> HandleCallCmd(
const std::vector<std::string>& server_address_list,
- const std::vector<std::string>& args,
- const std::vector<std::string>& options) {
+ const std::vector<std::string>& args) {
CF_EXPECT(args.size() > 2,
- "need to specify a service name, a method name, and json-formatted "
- "proto");
+ "need to specify the service name, the method name, and the "
+ "json-formatted proto");
CF_EXPECT(args.size() < 4, "too many arguments");
- std::string command_output;
std::vector<std::string> grpc_arguments{"grpc_cli", "call"};
// TODO(b/265384449): support calling streaming method.
@@ -271,17 +294,14 @@
grpc_arguments.push_back(full_method_name);
grpc_arguments.push_back(json_format_proto);
- command_output += CF_EXPECT(RunGrpcCommand(grpc_arguments, options));
-
- return command_output;
+ return RunGrpcCommand(grpc_arguments);
}
} // namespace
Result<std::string> HandleCmds(const std::string& grpc_socket_path,
const std::string& cmd,
- const std::vector<std::string>& args,
- const std::vector<std::string>& options) {
+ const std::vector<std::string>& args) {
std::vector<std::string> server_address_list;
for (const auto& entry :
std::filesystem::directory_iterator(grpc_socket_path)) {
@@ -292,7 +312,6 @@
auto command_map =
std::unordered_map<std::string, std::function<Result<std::string>(
const std::vector<std::string>&,
- const std::vector<std::string>&,
const std::vector<std::string>&)>>{{
{"call", HandleCallCmd},
{"ls", HandleLsCmd},
@@ -300,8 +319,7 @@
}};
CF_EXPECT(Contains(command_map, cmd), cmd << " isn't supported");
- auto command_output =
- CF_EXPECT(command_map[cmd](server_address_list, args, options));
+ auto command_output = CF_EXPECT(command_map[cmd](server_address_list, args));
return command_output;
}
diff --git a/host/libs/control_env/grpc_service_handler.h b/host/libs/control_env/grpc_service_handler.h
index f743745..2978165 100644
--- a/host/libs/control_env/grpc_service_handler.h
+++ b/host/libs/control_env/grpc_service_handler.h
@@ -18,7 +18,6 @@
Result<std::string> HandleCmds(const std::string& grpc_socket_path,
const std::string& cmd,
- const std::vector<std::string>& args,
- const std::vector<std::string>& options);
+ const std::vector<std::string>& args);
} // namespace cuttlefish
diff --git a/host/libs/graphics_detector/Android.bp b/host/libs/graphics_detector/Android.bp
index 278bdeb..986e9a7 100644
--- a/host/libs/graphics_detector/Android.bp
+++ b/host/libs/graphics_detector/Android.bp
@@ -29,13 +29,15 @@
defaults: ["cuttlefish_host"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_graphics_configuration",
srcs: [
"graphics_configuration.cpp",
],
shared_libs: [
"libbase",
+ "libcuttlefish_fs",
+ "libcuttlefish_utils",
"libjsoncpp",
"liblog",
],
@@ -45,7 +47,7 @@
defaults: ["cuttlefish_host"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_graphics_detector",
srcs: [
"egl.cpp",
diff --git a/host/libs/graphics_detector/graphics_configuration.cpp b/host/libs/graphics_detector/graphics_configuration.cpp
index cd9592c..adb8f0f 100644
--- a/host/libs/graphics_detector/graphics_configuration.cpp
+++ b/host/libs/graphics_detector/graphics_configuration.cpp
@@ -127,4 +127,33 @@
};
}
+Result<VhostUserGpuHostRendererFeatures>
+GetNeededVhostUserGpuHostRendererFeatures(
+ RenderingMode mode, const GraphicsAvailability& availability) {
+ VhostUserGpuHostRendererFeatures features = {};
+ if (mode == RenderingMode::kGfxstream ||
+ mode == RenderingMode::kGfxstreamGuestAngle) {
+ features.external_blob = true;
+
+ const bool has_external_memory_host =
+ availability.discrete_gpu_device_extensions.find(
+ "VK_EXT_external_memory_host") != std::string::npos;
+
+ if (!has_external_memory_host &&
+ mode == RenderingMode::kGfxstreamGuestAngle) {
+ return CF_ERR(
+ "VK_EXT_external_memory_host is required for running with "
+ "--gpu_mode=gfxstream_guest_angle and --enable_gpu_vhost_user=true");
+ }
+
+ features.system_blob = has_external_memory_host;
+
+ } else {
+ return CF_ERR(
+ "vhost-user-gpu is only currently supported with --gpu_mode=gfxstream "
+ "and --gpu_mode=gfxstream_guest_angle");
+ }
+ return features;
+}
+
} // namespace cuttlefish
\ No newline at end of file
diff --git a/host/libs/graphics_detector/graphics_configuration.h b/host/libs/graphics_detector/graphics_configuration.h
index 7d8ce5d..2b5eb00 100644
--- a/host/libs/graphics_detector/graphics_configuration.h
+++ b/host/libs/graphics_detector/graphics_configuration.h
@@ -39,4 +39,24 @@
Result<AngleFeatureOverrides> GetNeededAngleFeatures(
RenderingMode mode, const GraphicsAvailability& availability);
+struct VhostUserGpuHostRendererFeatures {
+ // If true, host Virtio GPU blob resources will be allocated with
+ // external memory and exported file descriptors will be shared
+ // with the VMM for mapping resources into the guest address space.
+ bool external_blob = false;
+
+ // If true, host Virtio GPU blob resources will be allocated with
+ // shmem and exported file descriptors will be shared with the VMM
+ // for mapping resources into the guest address space.
+ //
+ // This is an extension of the above external_blob that allows the
+ // VMM to map resources without graphics API support but requires
+ // additional features (VK_EXT_external_memory_host) from the GPU
+ // driver and is potentially less performant.
+ bool system_blob = false;
+};
+Result<VhostUserGpuHostRendererFeatures>
+GetNeededVhostUserGpuHostRendererFeatures(
+ RenderingMode mode, const GraphicsAvailability& availability);
+
} // namespace cuttlefish
\ No newline at end of file
diff --git a/host/libs/image_aggregator/Android.bp b/host/libs/image_aggregator/Android.bp
index fe68208..11ba0c1 100644
--- a/host/libs/image_aggregator/Android.bp
+++ b/host/libs/image_aggregator/Android.bp
@@ -37,7 +37,7 @@
},
}
-cc_library_static {
+cc_library {
name: "libimage_aggregator",
srcs: [
"image_aggregator.cc",
diff --git a/host/libs/image_aggregator/image_aggregator.cc b/host/libs/image_aggregator/image_aggregator.cc
index e2e7e66..632bc56 100644
--- a/host/libs/image_aggregator/image_aggregator.cc
+++ b/host/libs/image_aggregator/image_aggregator.cc
@@ -62,12 +62,12 @@
*/
MasterBootRecord ProtectiveMbr(std::uint64_t size) {
MasterBootRecord mbr = {
- .partitions = {{
- .partition_type = 0xEE,
- .first_lba = 1,
- .num_sectors = (std::uint32_t) size / SECTOR_SIZE,
- }},
- .boot_signature = { 0x55, 0xAA },
+ .partitions = {{
+ .partition_type = 0xEE,
+ .first_lba = 1,
+ .num_sectors = (std::uint32_t)size / kSectorSize,
+ }},
+ .boot_signature = {0x55, 0xAA},
};
return mbr;
}
@@ -105,7 +105,7 @@
struct __attribute__((packed)) GptBeginning {
MasterBootRecord protective_mbr;
GptHeader header;
- std::uint8_t header_padding[SECTOR_SIZE - sizeof(GptHeader)];
+ std::uint8_t header_padding[kSectorSize - sizeof(GptHeader)];
GptPartitionEntry entries[GPT_NUM_PARTITIONS];
std::uint8_t partition_alignment[3072];
};
@@ -116,10 +116,10 @@
struct __attribute__((packed)) GptEnd {
GptPartitionEntry entries[GPT_NUM_PARTITIONS];
GptHeader footer;
- std::uint8_t footer_padding[SECTOR_SIZE - sizeof(GptHeader)];
+ std::uint8_t footer_padding[kSectorSize - sizeof(GptHeader)];
};
-static_assert(sizeof(GptEnd) % SECTOR_SIZE == 0);
+static_assert(sizeof(GptEnd) % kSectorSize == 0);
struct PartitionInfo {
MultipleImagePartition source;
@@ -362,9 +362,9 @@
.revision = {0, 0, 1, 0},
.header_size = sizeof(GptHeader),
.current_lba = 1,
- .backup_lba = (DiskSize() / SECTOR_SIZE) - 1,
- .first_usable_lba = sizeof(GptBeginning) / SECTOR_SIZE,
- .last_usable_lba = (next_disk_offset_ / SECTOR_SIZE) - 1,
+ .backup_lba = (DiskSize() / kSectorSize) - 1,
+ .first_usable_lba = sizeof(GptBeginning) / kSectorSize,
+ .last_usable_lba = (next_disk_offset_ / kSectorSize) - 1,
.partition_entries_lba = 2,
.num_partition_entries = GPT_NUM_PARTITIONS,
.partition_entry_size = sizeof(GptPartitionEntry),
@@ -374,9 +374,9 @@
for (std::size_t i = 0; i < partitions_.size(); i++) {
const auto& partition = partitions_[i];
gpt.entries[i] = GptPartitionEntry{
- .first_lba = partition.offset / SECTOR_SIZE,
+ .first_lba = partition.offset / kSectorSize,
.last_lba =
- (partition.offset + partition.AlignedSize()) / SECTOR_SIZE - 1,
+ (partition.offset + partition.AlignedSize()) / kSectorSize - 1,
};
uuid_generate(gpt.entries[i].unique_partition_guid);
if (uuid_parse(GetPartitionGUID(partition.source),
@@ -405,7 +405,7 @@
std::memcpy((void*)gpt.entries, (void*)head.entries, sizeof(gpt.entries));
gpt.footer = head.header;
gpt.footer.partition_entries_lba =
- (DiskSize() - sizeof(gpt.entries)) / SECTOR_SIZE - 1;
+ (DiskSize() - sizeof(gpt.entries)) / kSectorSize - 1;
std::swap(gpt.footer.current_lba, gpt.footer.backup_lba);
gpt.footer.header_crc32 = 0;
gpt.footer.header_crc32 =
@@ -424,8 +424,8 @@
}
bool WriteEnd(SharedFD out, const GptEnd& end) {
- auto disk_size = (end.footer.current_lba + 1) * SECTOR_SIZE;
- auto footer_start = (end.footer.last_usable_lba + 1) * SECTOR_SIZE;
+ auto disk_size = (end.footer.current_lba + 1) * kSectorSize;
+ auto footer_start = (end.footer.last_usable_lba + 1) * kSectorSize;
auto padding = disk_size - footer_start - sizeof(GptEnd);
std::string padding_str(padding, '\0');
if (WriteAll(out, padding_str) != padding_str.size()) {
diff --git a/host/libs/input_connector/Android.bp b/host/libs/input_connector/Android.bp
index 95a48bc..29a70e6 100644
--- a/host/libs/input_connector/Android.bp
+++ b/host/libs/input_connector/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_input_connector",
srcs: [
"socket_input_connector.cpp",
diff --git a/host/libs/location/Android.bp b/host/libs/location/Android.bp
index 0f0bb7c..96e58b0 100644
--- a/host/libs/location/Android.bp
+++ b/host/libs/location/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "liblocation",
srcs: [
"StringParse.cpp",
@@ -31,6 +31,7 @@
"libcuttlefish_fs",
"libcuttlefish_utils",
"libjsoncpp",
+ "liblog",
"libprotobuf-cpp-full",
"libgrpc++_unsecure",
"libxml2",
@@ -51,4 +52,9 @@
"external/grpc-grpc/include",
"external/protobuf/src",
],
-}
\ No newline at end of file
+ target: {
+ darwin: {
+ enabled: true,
+ },
+ },
+}
diff --git a/host/libs/metrics/Android.bp b/host/libs/metrics/Android.bp
index fd33dc5..9a8196d 100644
--- a/host/libs/metrics/Android.bp
+++ b/host/libs/metrics/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_metrics",
srcs: [
"metrics_receiver.cc",
diff --git a/host/libs/msg_queue/Android.bp b/host/libs/msg_queue/Android.bp
index 741db1b..41ae7a3 100644
--- a/host/libs/msg_queue/Android.bp
+++ b/host/libs/msg_queue/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_msg_queue",
srcs: [
"msg_queue.cc",
diff --git a/host/libs/process_monitor/Android.bp b/host/libs/process_monitor/Android.bp
index 97ab93d..632feed 100644
--- a/host/libs/process_monitor/Android.bp
+++ b/host/libs/process_monitor/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_process_monitor",
srcs: [
"process_monitor.cc",
diff --git a/host/libs/process_monitor/process_monitor.cc b/host/libs/process_monitor/process_monitor.cc
index 1d54fa4..e4c6538 100644
--- a/host/libs/process_monitor/process_monitor.cc
+++ b/host/libs/process_monitor/process_monitor.cc
@@ -31,12 +31,12 @@
#include <algorithm>
#include <atomic>
#include <cstdint>
-#include <functional>
#include <future>
#include <memory>
#include <string>
#include <thread>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include "common/libs/fs/shared_buf.h"
@@ -92,6 +92,7 @@
}
Result<void> MonitorLoop(const std::atomic_bool& running,
+ std::mutex& properties_mutex,
const bool restart_subprocesses,
std::vector<MonitorEntry>& monitored) {
while (running.load()) {
@@ -108,6 +109,7 @@
break;
}
auto matches = [pid](const auto& it) { return it.proc->pid() == pid; };
+ std::unique_lock lock(properties_mutex);
auto it = std::find_if(monitored.begin(), monitored.end(), matches);
if (it == monitored.end()) {
LogSubprocessExit("(unknown)", pid, wstatus);
@@ -115,6 +117,7 @@
LogSubprocessExit(it->cmd->GetShortName(), it->proc->pid(), wstatus);
if (restart_subprocesses) {
auto options = SubprocessOptions().InGroup(true);
+ // in the future, cmd->Start might not run exec()
it->proc.reset(new Subprocess(it->cmd->Start(options)));
} else {
bool is_critical = it->is_critical;
@@ -159,23 +162,89 @@
} // namespace
-Result<void> ProcessMonitor::ReadMonitorSocketLoopForStop(
- std::atomic_bool& running) {
+Result<void> ProcessMonitor::ReadMonitorSocketLoop(std::atomic_bool& running) {
LOG(DEBUG) << "Waiting for a `stop` message from the parent";
while (running.load()) {
using process_monitor_impl::ParentToChildMessage;
- auto message = CF_EXPECT(ParentToChildMessage::Read(monitor_socket_));
+ auto message = CF_EXPECT(ParentToChildMessage::Read(child_monitor_socket_));
if (message.Stop()) {
running.store(false);
// Wake up the wait() loop by giving it an exited child process
if (fork() == 0) {
std::exit(0);
}
+ // will break the for-loop as running is now false
+ continue;
+ }
+ using process_monitor_impl::ParentToChildMessageType;
+ if (message.Type() == ParentToChildMessageType::kHostSuspend) {
+ CF_EXPECT(SuspendHostProcessesImpl());
+ continue;
+ }
+ if (message.Type() == ParentToChildMessageType::kHostResume) {
+ CF_EXPECT(ResumeHostProcessesImpl());
+ continue;
}
}
return {};
}
+Result<void> ProcessMonitor::SuspendHostProcessesImpl() {
+ std::lock_guard lock(properties_mutex_);
+ auto& monitor_entries = properties_.entries_;
+ for (const auto& entry : monitor_entries) {
+ if (!entry.cmd) {
+ LOG(ERROR) << "Monitor Entry has a nullptr for cmd.";
+ continue;
+ }
+ if (!entry.proc) {
+ LOG(ERROR) << "Monitor Entry has a nullptr for proc.";
+ continue;
+ }
+ auto prog_name = android::base::Basename(entry.cmd->Executable());
+ auto process_restart_bin =
+ android::base::Basename(ProcessRestarterBinary());
+ if (process_restart_bin == prog_name) {
+ CF_EXPECT(entry.proc->SendSignal(SIGTSTP));
+ } else {
+ CF_EXPECT(entry.proc->SendSignalToGroup(SIGTSTP));
+ }
+ }
+ using process_monitor_impl::ChildToParentResponse;
+ using process_monitor_impl::ChildToParentResponseType;
+ ChildToParentResponse response(ChildToParentResponseType::kSuccess);
+ CF_EXPECT(response.Write(child_monitor_socket_));
+ return {};
+}
+
+Result<void> ProcessMonitor::ResumeHostProcessesImpl() {
+ std::lock_guard lock(properties_mutex_);
+ auto& monitor_entries = properties_.entries_;
+ for (const auto& entry : monitor_entries) {
+ if (!entry.cmd) {
+ LOG(ERROR) << "Monitor Entry has a nullptr for cmd.";
+ continue;
+ }
+ if (!entry.proc) {
+ LOG(ERROR) << "Monitor Entry has a nullptr for proc.";
+ continue;
+ }
+ auto prog_name = android::base::Basename(entry.cmd->Executable());
+ auto process_restart_bin =
+ android::base::Basename(ProcessRestarterBinary());
+ if (process_restart_bin == prog_name) {
+ CF_EXPECT(entry.proc->SendSignal(SIGCONT));
+ } else {
+ CF_EXPECT(entry.proc->SendSignalToGroup(SIGCONT));
+ }
+ }
+ using process_monitor_impl::ChildToParentResponse;
+ using process_monitor_impl::ChildToParentResponseType;
+ ChildToParentResponse response(ChildToParentResponseType::kSuccess);
+ CF_EXPECT(response.Write(child_monitor_socket_));
+ return {};
+}
+
ProcessMonitor::Properties& ProcessMonitor::Properties::RestartSubprocesses(
bool r) & {
restart_subprocesses_ = r;
@@ -203,15 +272,16 @@
Result<void> ProcessMonitor::StopMonitoredProcesses() {
CF_EXPECT(monitor_ != -1, "The monitor process has already exited.");
- CF_EXPECT(monitor_socket_->IsOpen(), "The monitor socket is already closed");
+ CF_EXPECT(parent_monitor_socket_->IsOpen(),
+ "The monitor socket is already closed");
using process_monitor_impl::ParentToChildMessage;
using process_monitor_impl::ParentToChildMessageType;
ParentToChildMessage message(ParentToChildMessageType::kStop);
- CF_EXPECT(message.Write(monitor_socket_));
+ CF_EXPECT(message.Write(parent_monitor_socket_));
pid_t last_monitor = monitor_;
monitor_ = -1;
- monitor_socket_->Close();
+ parent_monitor_socket_->Close();
int wstatus;
CF_EXPECT(waitpid(last_monitor, &wstatus, 0) == last_monitor,
"Failed to wait for monitor process");
@@ -222,17 +292,49 @@
return {};
}
+Result<void> ProcessMonitor::SuspendMonitoredProcesses() {
+ CF_EXPECT(monitor_ != -1, "The monitor process has already exited.");
+ CF_EXPECT(parent_monitor_socket_->IsOpen(),
+ "The monitor socket is already closed");
+ using process_monitor_impl::ParentToChildMessage;
+ using process_monitor_impl::ParentToChildMessageType;
+ ParentToChildMessage message(ParentToChildMessageType::kHostSuspend);
+ CF_EXPECT(message.Write(parent_monitor_socket_));
+ using process_monitor_impl::ChildToParentResponse;
+ auto response =
+ CF_EXPECT(ChildToParentResponse::Read(parent_monitor_socket_));
+ CF_EXPECT(response.Success(),
+ "On kHostSuspend, the child run_cvd returned kFailure.");
+ return {};
+}
+
+Result<void> ProcessMonitor::ResumeMonitoredProcesses() {
+ CF_EXPECT(monitor_ != -1, "The monitor process has already exited.");
+ CF_EXPECT(parent_monitor_socket_->IsOpen(),
+ "The monitor socket is already closed");
+ using process_monitor_impl::ParentToChildMessage;
+ using process_monitor_impl::ParentToChildMessageType;
+ ParentToChildMessage message(ParentToChildMessageType::kHostResume);
+ CF_EXPECT(message.Write(parent_monitor_socket_));
+ using process_monitor_impl::ChildToParentResponse;
+ auto response =
+ CF_EXPECT(ChildToParentResponse::Read(parent_monitor_socket_));
+ CF_EXPECT(response.Success(),
+ "On kHostResume, the child run_cvd returned kFailure.");
+ return {};
+}
+
Result<void> ProcessMonitor::StartAndMonitorProcesses() {
CF_EXPECT(monitor_ == -1, "The monitor process was already started");
- CF_EXPECT(!monitor_socket_->IsOpen(), "Monitor socket was already opened");
-
- SharedFD client_pipe, host_pipe;
- CF_EXPECT(SharedFD::Pipe(&client_pipe, &host_pipe),
- "Could not create the monitor socket.");
+ CF_EXPECT(!parent_monitor_socket_->IsOpen(),
+ "Parent monitor socket was already opened");
+ SharedFD parent_sock;
+ SharedFD child_sock;
+ SharedFD::SocketPair(AF_UNIX, SOCK_STREAM, 0, &parent_sock, &child_sock);
monitor_ = fork();
if (monitor_ == 0) {
- monitor_socket_ = client_pipe;
- host_pipe->Close();
+ child_monitor_socket_ = std::move(child_sock);
+ parent_sock->Close();
auto monitor_result = MonitorRoutine();
if (!monitor_result.ok()) {
LOG(ERROR) << "Monitoring processes failed:\n"
@@ -242,8 +344,8 @@
}
std::exit(monitor_result.ok() ? 0 : 1);
} else {
- client_pipe->Close();
- monitor_socket_ = host_pipe;
+ parent_monitor_socket_ = std::move(parent_sock);
+ child_sock->Close();
return {};
}
}
@@ -260,15 +362,17 @@
StartSubprocesses(properties_.entries_);
std::atomic_bool running(true);
+
auto read_monitor_socket_loop =
[this](std::atomic_bool& running) -> Result<void> {
- CF_EXPECT(this->ReadMonitorSocketLoopForStop(running));
+ CF_EXPECT(this->ReadMonitorSocketLoop(running));
return {};
};
auto parent_comms = std::async(std::launch::async, read_monitor_socket_loop,
std::ref(running));
- MonitorLoop(running, properties_.restart_subprocesses_, properties_.entries_);
+ MonitorLoop(running, properties_mutex_, properties_.restart_subprocesses_,
+ properties_.entries_);
CF_EXPECT(parent_comms.get(), "Should have exited if monitoring stopped");
StopSubprocesses(properties_.entries_);
diff --git a/host/libs/process_monitor/process_monitor.h b/host/libs/process_monitor/process_monitor.h
index ca95160..45a531a 100644
--- a/host/libs/process_monitor/process_monitor.h
+++ b/host/libs/process_monitor/process_monitor.h
@@ -74,14 +74,34 @@
Result<void> StartAndMonitorProcesses();
// Stops all monitored subprocesses.
Result<void> StopMonitoredProcesses();
+ // Suspend all host subprocesses
+ Result<void> SuspendMonitoredProcesses();
+ // Resume all host subprocesses
+ Result<void> ResumeMonitoredProcesses();
private:
Result<void> MonitorRoutine();
- Result<void> ReadMonitorSocketLoopForStop(std::atomic_bool&);
+ Result<void> ReadMonitorSocketLoop(std::atomic_bool&);
+ /*
+ * The child run_cvd process suspends the host processes
+ */
+ Result<void> SuspendHostProcessesImpl();
+ /*
+ * The child run_cvd process resumes the host processes
+ */
+ Result<void> ResumeHostProcessesImpl();
Properties properties_;
pid_t monitor_;
- SharedFD monitor_socket_;
+ SharedFD parent_monitor_socket_;
+ SharedFD child_monitor_socket_;
+
+ /*
+ * The lock that should be acquired when multiple threads
+ * access to properties_. Currently, used by the child
+ * run_cvd process that runs MonitorRoutine()
+ */
+ std::mutex properties_mutex_;
};
} // namespace cuttlefish
diff --git a/host/libs/screen_connector/Android.bp b/host/libs/screen_connector/Android.bp
index d0bf438..c5e6a14 100644
--- a/host/libs/screen_connector/Android.bp
+++ b/host/libs/screen_connector/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_screen_connector",
srcs: [
"wayland_screen_connector.cpp",
@@ -38,9 +38,14 @@
"libcuttlefish_confui",
"libcuttlefish_wayland_server",
"libcuttlefish_confui_host",
+ "libffi",
"libft2.nodep",
"libteeui",
"libteeui_localization",
+ "libwayland_crosvm_gpu_display_extension_server_protocols",
+ "libwayland_extension_server_protocols",
+ "libwayland_server",
+
],
defaults: ["cuttlefish_buildhost_only"],
}
diff --git a/host/libs/vm_manager/Android.bp b/host/libs/vm_manager/Android.bp
index 1a6bfcf..7ea06ca 100644
--- a/host/libs/vm_manager/Android.bp
+++ b/host/libs/vm_manager/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_vm_manager",
srcs: [
"crosvm_builder.cpp",
@@ -42,10 +42,7 @@
static_libs: [
"libcuttlefish_host_config",
],
- defaults: [
- "cuttlefish_host",
- "cuttlefish_libicuuc"
- ],
+ defaults: ["cuttlefish_host"],
target: {
darwin: {
enabled: true,
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index 4d61fe8..a6b2de9 100644
--- a/host/libs/vm_manager/crosvm_manager.cpp
+++ b/host/libs/vm_manager/crosvm_manager.cpp
@@ -29,6 +29,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
+#include <json/json.h>
#include <vulkan/vulkan.h>
#include "common/libs/utils/environment.h"
@@ -135,13 +136,22 @@
}
Result<std::unordered_map<std::string, std::string>>
-CrosvmManager::ConfigureBootDevices(int num_disks, bool have_gpu) {
+CrosvmManager::ConfigureBootDevices(
+ const CuttlefishConfig::InstanceSpecific& instance) {
+ const int num_disks = instance.virtual_disk_paths().size();
+ const bool has_gpu = instance.hwcomposer() != kHwComposerNone;
// TODO There is no way to control this assignment with crosvm (yet)
if (HostArch() == Arch::X86_64) {
- // crosvm has an additional PCI device for an ISA bridge
+ int num_gpu_pcis = has_gpu ? 1 : 0;
+ if (instance.gpu_mode() != kGpuModeNone &&
+ !instance.enable_gpu_vhost_user()) {
+ // crosvm has an additional PCI device for an ISA bridge when running
+ // with a gpu and without vhost user gpu.
+ num_gpu_pcis += 1;
+ }
// virtio_gpu and virtio_wl precedes the first console or disk
- return ConfigureMultipleBootDevices("pci0000:00/0000:00:",
- 1 + (have_gpu ? 2 : 0), num_disks);
+ return ConfigureMultipleBootDevices("pci0000:00/0000:00:", 1 + num_gpu_pcis,
+ num_disks);
} else {
// On ARM64 crosvm, block devices are on their own bridge, so we don't
// need to calculate it, and the path is always the same
@@ -149,15 +159,245 @@
}
}
+std::string ToSingleLineString(const Json::Value& value) {
+ Json::StreamWriterBuilder builder;
+ builder["indentation"] = "";
+ return Json::writeString(builder, value);
+}
+
constexpr auto crosvm_socket = "crosvm_control.sock";
+void MaybeConfigureVulkanIcd(const CuttlefishConfig& config, Command* command) {
+ const auto& gpu_mode = config.ForDefaultInstance().gpu_mode();
+ if (gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader) {
+ // See https://github.com/KhronosGroup/Vulkan-Loader.
+ const std::string swiftshader_icd_json =
+ HostUsrSharePath("vulkan/icd.d/vk_swiftshader_icd.json");
+ command->AddEnvironmentVariable("VK_DRIVER_FILES", swiftshader_icd_json);
+ command->AddEnvironmentVariable("VK_ICD_FILENAMES", swiftshader_icd_json);
+ }
+}
+
+Result<std::string> CrosvmPathForVhostUserGpu(const CuttlefishConfig& config) {
+ const auto& instance = config.ForDefaultInstance();
+ switch (HostArch()) {
+ case Arch::Arm64:
+ return HostBinaryPath("aarch64-linux-gnu/crosvm");
+ case Arch::X86:
+ case Arch::X86_64:
+ return instance.crosvm_binary();
+ default:
+ break;
+ }
+ return CF_ERR("Unhandled host arch " << HostArchStr()
+ << " for vhost user gpu crosvm");
+}
+
+struct VhostUserDeviceCommands {
+ Command device_cmd;
+ Command device_logs_cmd;
+};
+Result<VhostUserDeviceCommands> BuildVhostUserGpu(
+ const CuttlefishConfig& config, Command* main_crosvm_cmd) {
+ const auto& instance = config.ForDefaultInstance();
+ if (!instance.enable_gpu_vhost_user()) {
+ return CF_ERR("Attempting to build vhost user gpu when not enabled?");
+ }
+
+ auto gpu_device_socket_path =
+ instance.PerInstanceInternalUdsPath("vhost-user-gpu-socket");
+ auto gpu_device_socket = SharedFD::SocketLocalServer(
+ gpu_device_socket_path.c_str(), false, SOCK_STREAM, 0777);
+ CF_EXPECT(gpu_device_socket->IsOpen(),
+ "Failed to create socket for crosvm vhost user gpu's control"
+ << gpu_device_socket->StrError());
+
+ auto gpu_device_logs_path =
+ instance.PerInstanceInternalPath("crosvm_vhost_user_gpu.fifo");
+ auto gpu_device_logs = SharedFD::Fifo(gpu_device_logs_path, 0666);
+ CF_EXPECT(
+ gpu_device_logs->IsOpen(),
+ "Failed to create log fifo for crosvm vhost user gpu's stdout/stderr: "
+ << gpu_device_logs->StrError());
+
+ Command gpu_device_logs_cmd(HostBinaryPath("log_tee"));
+ gpu_device_logs_cmd.AddParameter("--process_name=crosvm_gpu");
+ gpu_device_logs_cmd.AddParameter("--log_fd_in=", gpu_device_logs);
+ gpu_device_logs_cmd.SetStopper([](Subprocess* proc) {
+ // Ask nicely so that log_tee gets a chance to process all the logs.
+ int rval = kill(proc->pid(), SIGINT);
+ if (rval != 0) {
+ LOG(ERROR) << "Failed to stop log_tee nicely, attempting to KILL";
+ return KillSubprocess(proc) == StopperResult::kStopSuccess
+ ? StopperResult::kStopCrash
+ : StopperResult::kStopFailure;
+ }
+ return StopperResult::kStopSuccess;
+ });
+
+ const std::string crosvm_path = CF_EXPECT(CrosvmPathForVhostUserGpu(config));
+
+ Command gpu_device_cmd(crosvm_path);
+ gpu_device_cmd.AddParameter("device");
+ gpu_device_cmd.AddParameter("gpu");
+
+ const auto& gpu_mode = instance.gpu_mode();
+ CF_EXPECT(
+ gpu_mode == kGpuModeGfxstream ||
+ gpu_mode == kGpuModeGfxstreamGuestAngle ||
+ gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader,
+ "GPU mode " << gpu_mode << " not yet supported with vhost user gpu.");
+
+ // Why does this need JSON instead of just following the normal flags style...
+ Json::Value gpu_params_json;
+ if (gpu_mode == kGpuModeGfxstream) {
+ gpu_params_json["context-types"] = "gfxstream-gles:gfxstream-vulkan";
+ gpu_params_json["egl"] = true;
+ gpu_params_json["gles"] = true;
+ } else if (gpu_mode == kGpuModeGfxstreamGuestAngle ||
+ gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader) {
+ gpu_params_json["context-types"] = "gfxstream-vulkan";
+ gpu_params_json["egl"] = false;
+ gpu_params_json["gles"] = false;
+ }
+ gpu_params_json["glx"] = false;
+ gpu_params_json["surfaceless"] = true;
+ gpu_params_json["external-blob"] = instance.enable_gpu_external_blob();
+ gpu_params_json["system-blob"] = instance.enable_gpu_system_blob();
+
+ if (instance.hwcomposer() != kHwComposerNone) {
+ // "displays": [
+ // {
+ // "mode": {
+ // "windowed": [
+ // 720,
+ // 1280
+ // ]
+ // },
+ // "dpi": [
+ // 320,
+ // 320
+ // ],
+ // "refresh-rate": 60
+ // }
+ // ]
+ Json::Value displays(Json::arrayValue);
+ for (const auto& display_config : instance.display_configs()) {
+ Json::Value display_mode_windowed(Json::arrayValue);
+ display_mode_windowed[0] = display_config.width;
+ display_mode_windowed[1] = display_config.height;
+
+ Json::Value display_mode;
+ display_mode["windowed"] = display_mode_windowed;
+
+ Json::Value display_dpi(Json::arrayValue);
+ display_dpi[0] = display_config.dpi;
+ display_dpi[1] = display_config.dpi;
+
+ Json::Value display;
+ display["mode"] = display_mode;
+ display["dpi"] = display_dpi;
+ display["refresh-rate"] = display_config.refresh_rate_hz;
+
+ displays.append(display);
+ }
+ gpu_params_json["displays"] = displays;
+
+ gpu_device_cmd.AddParameter("--wayland-sock=",
+ instance.frames_socket_path());
+ }
+
+ // Connect device to main crosvm:
+ gpu_device_cmd.AddParameter("--socket=", gpu_device_socket_path);
+ main_crosvm_cmd->AddParameter("--vhost-user-gpu=", gpu_device_socket_path);
+
+ gpu_device_cmd.AddParameter("--params");
+ gpu_device_cmd.AddParameter(ToSingleLineString(gpu_params_json));
+
+ MaybeConfigureVulkanIcd(config, &gpu_device_cmd);
+
+ gpu_device_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut,
+ gpu_device_logs);
+ gpu_device_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdErr,
+ gpu_device_logs);
+
+ return VhostUserDeviceCommands{
+ .device_cmd = std::move(gpu_device_cmd),
+ .device_logs_cmd = std::move(gpu_device_logs_cmd),
+ };
+}
+
+Result<void> ConfigureGpu(const CuttlefishConfig& config, Command* crosvm_cmd) {
+ const auto& instance = config.ForDefaultInstance();
+ const auto& gpu_mode = instance.gpu_mode();
+
+ const std::string gles_string =
+ gpu_mode == kGpuModeGfxstreamGuestAngle ||
+ gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader
+ ? ",gles=false"
+ : ",gles=true";
+
+ // 256MB so it is small enough for a 32-bit kernel.
+ const bool target_is_32bit = instance.target_arch() == Arch::Arm ||
+ instance.target_arch() == Arch::X86;
+ const std::string gpu_pci_bar_size =
+ target_is_32bit ? ",pci-bar-size=268435456" : "";
+
+ const std::string gpu_udmabuf_string =
+ instance.enable_gpu_udmabuf() ? ",udmabuf=true" : "";
+
+ const std::string gpu_common_string = gpu_udmabuf_string + gpu_pci_bar_size;
+ const std::string gpu_common_3d_string =
+ gpu_common_string + ",egl=true,surfaceless=true,glx=false" + gles_string;
+
+ if (gpu_mode == kGpuModeGuestSwiftshader) {
+ crosvm_cmd->AddParameter("--gpu=backend=2D", gpu_common_string);
+ } else if (gpu_mode == kGpuModeDrmVirgl) {
+ crosvm_cmd->AddParameter("--gpu=backend=virglrenderer",
+ gpu_common_3d_string);
+ } else if (gpu_mode == kGpuModeGfxstream) {
+ crosvm_cmd->AddParameter(
+ "--gpu=context-types=gfxstream-gles:gfxstream-vulkan:gfxstream-"
+ "composer",
+ gpu_common_3d_string);
+ } else if (gpu_mode == kGpuModeGfxstreamGuestAngle ||
+ gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader) {
+ crosvm_cmd->AddParameter(
+ "--gpu=context-types=gfxstream-vulkan:gfxstream-composer",
+ gpu_common_3d_string);
+ }
+
+ MaybeConfigureVulkanIcd(config, crosvm_cmd);
+
+ if (instance.hwcomposer() != kHwComposerNone) {
+ for (const auto& display_config : instance.display_configs()) {
+ const auto display_w = std::to_string(display_config.width);
+ const auto display_h = std::to_string(display_config.height);
+ const auto display_dpi = std::to_string(display_config.dpi);
+ const auto display_rr = std::to_string(display_config.refresh_rate_hz);
+ const auto display_params = android::base::Join(
+ std::vector<std::string>{
+ "mode=windowed[" + display_w + "," + display_h + "]",
+ "dpi=[" + display_dpi + "," + display_dpi + "]",
+ "refresh-rate=" + display_rr,
+ },
+ ",");
+
+ crosvm_cmd->AddParameter("--gpu-display=", display_params);
+ }
+
+ crosvm_cmd->AddParameter("--wayland-sock=", instance.frames_socket_path());
+ }
+
+ return {};
+}
+
Result<std::vector<MonitorCommand>> CrosvmManager::StartCommands(
const CuttlefishConfig& config,
std::vector<VmmDependencyCommand*>& dependencyCommands) {
auto instance = config.ForDefaultInstance();
CrosvmBuilder crosvm_cmd;
-
crosvm_cmd.Cmd().AddPrerequisite([&dependencyCommands]() -> Result<void> {
for (auto dependencyCommand : dependencyCommands) {
CF_EXPECT(dependencyCommand->WaitForAvailability());
@@ -209,51 +449,12 @@
crosvm_cmd.Cmd().AddParameter("--gdb=", instance.gdb_port());
}
- const auto gpu_capture_enabled = !instance.gpu_capture_binary().empty();
- const auto gpu_mode = instance.gpu_mode();
-
- const std::string gles_string =
- gpu_mode == kGpuModeGfxstreamGuestAngle ||
- gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader
- ? ",gles=false"
- : ",gles=true";
- // 256MB so it is small enough for a 32-bit kernel.
- const bool target_is_32bit = instance.target_arch() == Arch::Arm ||
- instance.target_arch() == Arch::X86;
- const std::string gpu_pci_bar_size =
- target_is_32bit ? ",pci-bar-size=268435456" : "";
- const std::string gpu_udmabuf_string =
- instance.enable_gpu_udmabuf() ? ",udmabuf=true" : "";
-
- const std::string gpu_common_string = gpu_udmabuf_string + gpu_pci_bar_size;
- const std::string gpu_common_3d_string =
- gpu_common_string + ",egl=true,surfaceless=true,glx=false" + gles_string;
-
- if (gpu_mode == kGpuModeGuestSwiftshader) {
- crosvm_cmd.Cmd().AddParameter("--gpu=backend=2D", gpu_common_string);
- } else if (gpu_mode == kGpuModeDrmVirgl) {
- crosvm_cmd.Cmd().AddParameter("--gpu=backend=virglrenderer",
- gpu_common_3d_string);
- } else if (gpu_mode == kGpuModeGfxstream) {
- crosvm_cmd.Cmd().AddParameter(
- "--gpu=context-types=gfxstream-gles:gfxstream-vulkan:gfxstream-"
- "composer",
- gpu_common_3d_string);
- } else if (gpu_mode == kGpuModeGfxstreamGuestAngle ||
- gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader) {
- crosvm_cmd.Cmd().AddParameter(
- "--gpu=context-types=gfxstream-vulkan:gfxstream-composer",
- gpu_common_3d_string);
-
- if (gpu_mode == kGpuModeGfxstreamGuestAngleHostSwiftShader) {
- // See https://github.com/KhronosGroup/Vulkan-Loader.
- const std::string swiftshader_icd_json =
- HostUsrSharePath("vulkan/icd.d/vk_swiftshader_icd.json");
- crosvm_cmd.Cmd().AddEnvironmentVariable("VK_DRIVER_FILES",
- swiftshader_icd_json);
- crosvm_cmd.Cmd().AddEnvironmentVariable("VK_ICD_FILENAMES",
- swiftshader_icd_json);
- }
+ std::optional<VhostUserDeviceCommands> vhost_user_gpu;
+ if (instance.enable_gpu_vhost_user()) {
+ vhost_user_gpu.emplace(
+ CF_EXPECT(BuildVhostUserGpu(config, &crosvm_cmd.Cmd())));
+ } else {
+ CF_EXPECT(ConfigureGpu(config, &crosvm_cmd.Cmd()));
}
if (instance.hwcomposer() != kHwComposerNone) {
@@ -262,26 +463,10 @@
crosvm_cmd.Cmd().AddParameter("--rw-pmem-device=",
instance.hwcomposer_pmem_path());
}
-
- for (const auto& display_config : instance.display_configs()) {
- const auto display_w = std::to_string(display_config.width);
- const auto display_h = std::to_string(display_config.height);
- const auto display_dpi = std::to_string(display_config.dpi);
- const auto display_rr = std::to_string(display_config.refresh_rate_hz);
- const auto display_params = android::base::Join(
- std::vector<std::string>{
- "mode=windowed[" + display_w + "," + display_h + "]",
- "dpi=[" + display_dpi + "," + display_dpi + "]",
- "refresh-rate=" + display_rr,
- },
- ",");
- crosvm_cmd.Cmd().AddParameter("--gpu-display=", display_params);
- }
-
- crosvm_cmd.Cmd().AddParameter("--wayland-sock=",
- instance.frames_socket_path());
}
+ const auto gpu_capture_enabled = !instance.gpu_capture_binary().empty();
+
// crosvm_cmd.Cmd().AddParameter("--null-audio");
crosvm_cmd.Cmd().AddParameter("--mem=", instance.memory_mb());
crosvm_cmd.Cmd().AddParameter("--cpus=", instance.cpus());
@@ -327,13 +512,13 @@
// GPU capture can only support named files and not file descriptors due to
// having to pass arguments to crosvm via a wrapper script.
#ifdef __linux__
- if (!gpu_capture_enabled && config.enable_wifi()) {
+ if (!gpu_capture_enabled) {
// The ordering of tap devices is important. Make sure any change here
// is reflected in ethprime u-boot variable
crosvm_cmd.AddTap(instance.mobile_tap_name(), instance.mobile_mac());
crosvm_cmd.AddTap(instance.ethernet_tap_name(), instance.ethernet_mac());
- if (!config.virtio_mac80211_hwsim()) {
+ if (!config.virtio_mac80211_hwsim() && config.enable_wifi()) {
wifi_tap = crosvm_cmd.AddTap(instance.wifi_tap_name());
}
}
@@ -586,6 +771,11 @@
commands.emplace_back(std::move(crosvm_cmd.Cmd()), true);
}
+ if (vhost_user_gpu) {
+ commands.emplace_back(std::move(vhost_user_gpu->device_cmd));
+ commands.emplace_back(std::move(vhost_user_gpu->device_logs_cmd));
+ }
+
return commands;
}
diff --git a/host/libs/vm_manager/crosvm_manager.h b/host/libs/vm_manager/crosvm_manager.h
index 822ec55..a1433d2 100644
--- a/host/libs/vm_manager/crosvm_manager.h
+++ b/host/libs/vm_manager/crosvm_manager.h
@@ -40,7 +40,7 @@
const CuttlefishConfig::InstanceSpecific& instance) override;
Result<std::unordered_map<std::string, std::string>> ConfigureBootDevices(
- int num_disks, bool have_gpu) override;
+ const CuttlefishConfig::InstanceSpecific& instance) override;
Result<std::vector<MonitorCommand>> StartCommands(
const CuttlefishConfig& config,
diff --git a/host/libs/vm_manager/gem5_manager.cpp b/host/libs/vm_manager/gem5_manager.cpp
index 0d2cbf6..df62785 100644
--- a/host/libs/vm_manager/gem5_manager.cpp
+++ b/host/libs/vm_manager/gem5_manager.cpp
@@ -16,7 +16,6 @@
#include "host/libs/vm_manager/gem5_manager.h"
-#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -24,11 +23,8 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <cstdlib>
#include <fstream>
-#include <sstream>
#include <string>
-#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -37,14 +33,10 @@
#include <android-base/logging.h>
#include <vulkan/vulkan.h>
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/utils/files.h"
#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
-#include "common/libs/utils/users.h"
#include "host/libs/config/command_source.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
using cuttlefish::StringFromEnv;
@@ -52,10 +44,100 @@
namespace vm_manager {
namespace {
-void LogAndSetEnv(const char* key, const std::string& value) {
- setenv(key, value.c_str(), 1);
- LOG(INFO) << key << "=" << value;
-}
+static constexpr char kFsHeader[] = R"CPP_STR_END(import argparse
+import devices
+import os
+import shutil
+import m5
+from m5.util import addToPath
+from m5.objects import *
+from m5.options import *
+from m5.objects.Ethernet import NSGigE, IGbE_igb, IGbE_e1000, EtherTap
+from common import SysPaths
+from common import ObjectList
+from common import MemConfig
+from common.cores.arm import HPI
+m5.util.addToPath('../..')
+)CPP_STR_END";
+
+static constexpr char kFsMemPci[] = R"CPP_STR_END(
+ MemConfig.config_mem(args, root.system)
+
+ pci_devices = []
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=0))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=1, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=2))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=3, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=4, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=5, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=6, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=7, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=8, outfile="none"))))
+ pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=9, outfile="none"))))
+
+ for each_item in args.disk_image:
+ disk_image = CowDiskImage()
+ disk_image.child.image_file = SysPaths.disk(each_item)
+ pci_devices.append(PciVirtIO(vio=VirtIOBlock(image=disk_image)))
+
+ nic = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0, InterruptLine=1, InterruptPin=1)
+ pci_devices.append(nic)
+ root.system.pci_devices = pci_devices
+ for pci_device in root.system.pci_devices:
+ root.system.attach_pci(pci_device)
+
+ root.tap = EtherTap(tun_clone_device='/dev/net/tun', tap_device_name='cvd-mtap-01')
+ root.tap.tap = nic.interface
+ root.system.connect()
+)CPP_STR_END";
+
+static constexpr char kFsKernelCmd[] = R"CPP_STR_END(
+ kernel_cmd = [
+ "lpj=19988480",
+ "norandmaps",
+ "mem=%s" % args.mem_size,
+ "console=hvc0",
+ "panic=-1",
+ "earlycon=pl011,mmio32,0x1c090000",
+ "audit=1",
+ "printk.devkmsg=on",
+ "firmware_class.path=/vendor/etc/",
+ "kfence.sample_interval=500",
+ "loop.max_part=7",
+ "bootconfig",
+ "androidboot.force_normal_boot=1",
+ ]
+ root.system.workload.command_line = " ".join(kernel_cmd)
+ if args.restore is not None:
+ m5.instantiate(args.restore)
+ else:
+ m5.instantiate()
+
+ while True:
+ event = m5.simulate()
+ msg = event.getCause()
+ cur_tick = m5.curTick()
+ if msg == "checkpoint":
+ backup_path = backup_path = os.path.join(root_dir, "gem5_checkpoint")
+ if not os.path.isdir(backup_path):
+ os.mkdir(backup_path)
+
+ print("Checkpoint @", cur_tick)
+ src_dir = os.path.join(m5.options.outdir, "cpt.%d" % cur_tick)
+ backup_path = os.path.join(backup_path, "cpt.%d" % cur_tick)
+ m5.checkpoint(src_dir)
+ shutil.copytree(src_dir, backup_path)
+ print("Checkpoint done.")
+ else:
+ print("Exit msg: " + msg + " @", cur_tick)
+ break
+ sys.exit(event.getCode())
+)CPP_STR_END";
+
+static constexpr char kFsExeMain[] = R"CPP_STR_END(
+if __name__ == "__m5_main__":
+ main()
+)CPP_STR_END";
void GenerateGem5File(const CuttlefishConfig& config,
const CuttlefishConfig::InstanceSpecific& instance) {
@@ -76,7 +158,7 @@
std::string fs_path = instance.gem5_binary_dir() +
"/configs/example/arm/starter_fs.py";
std::ofstream starter_fs_ofstream(fs_path.c_str());
- starter_fs_ofstream << fs_header << "\n";
+ starter_fs_ofstream << kFsHeader << "\n";
// global vars in python
starter_fs_ofstream << "default_disk = 'linaro-minimal-aarch64.img'\n";
@@ -101,7 +183,7 @@
starter_fs_ofstream << " root.system = devices.SimpleSystem(has_caches, args.mem_size, mem_mode=mem_mode, workload=ArmFsLinux(object_file=SysPaths.binary(\"" << config.assembly_dir() << "/kernel\")))\n";
// mem config and pci instantiate
- starter_fs_ofstream << fs_mem_pci;
+ starter_fs_ofstream << kFsMemPci;
// system settings
starter_fs_ofstream << " root.system.cpu_cluster = [devices.CpuCluster(root.system, " << num_cores << ", \"" << cpu_freq << "\", \"1.0V\", " << cpu_class << ", " << l1_icache_class << ", " << l1_dcache_class << ", " << walk_cache_class << ", " << l2_Cache_class << ")]\n";
@@ -113,10 +195,10 @@
starter_fs_ofstream << " root_dir = \"" << StringFromEnv("HOME", ".") << "\"\n";
//kernel cmd
- starter_fs_ofstream << fs_kernel_cmd << "\n";
+ starter_fs_ofstream << kFsKernelCmd << "\n";
// execute main
- starter_fs_ofstream << fs_exe_main << "\n";
+ starter_fs_ofstream << kFsExeMain << "\n";
}
} // namespace
@@ -182,7 +264,8 @@
}
Result<std::unordered_map<std::string, std::string>>
-Gem5Manager::ConfigureBootDevices(int /*num_disks*/, bool /*have_gpu*/) {
+Gem5Manager::ConfigureBootDevices(
+ const CuttlefishConfig::InstanceSpecific& /*instance*/) {
switch (arch_) {
case Arch::Arm:
case Arch::Arm64:
@@ -248,7 +331,7 @@
gem5_cmd.AddParameter("--disk-image=", disk);
}
- LogAndSetEnv("M5_PATH", config.assembly_dir());
+ gem5_cmd.AddEnvironmentVariable("M5_PATH", config.assembly_dir());
std::vector<MonitorCommand> commands;
commands.emplace_back(std::move(gem5_cmd), true);
diff --git a/host/libs/vm_manager/gem5_manager.h b/host/libs/vm_manager/gem5_manager.h
index cb639aa..4c4bbdb 100644
--- a/host/libs/vm_manager/gem5_manager.h
+++ b/host/libs/vm_manager/gem5_manager.h
@@ -42,7 +42,7 @@
const CuttlefishConfig::InstanceSpecific& instance) override;
Result<std::unordered_map<std::string, std::string>> ConfigureBootDevices(
- int num_disks, bool have_gpu) override;
+ const CuttlefishConfig::InstanceSpecific& instance) override;
Result<std::vector<MonitorCommand>> StartCommands(
const CuttlefishConfig& config,
@@ -52,100 +52,5 @@
Arch arch_;
};
-const std::string fs_header = R"CPP_STR_END(import argparse
-import devices
-import os
-import shutil
-import m5
-from m5.util import addToPath
-from m5.objects import *
-from m5.options import *
-from m5.objects.Ethernet import NSGigE, IGbE_igb, IGbE_e1000, EtherTap
-from common import SysPaths
-from common import ObjectList
-from common import MemConfig
-from common.cores.arm import HPI
-m5.util.addToPath('../..')
-)CPP_STR_END";
-
-const std::string fs_mem_pci = R"CPP_STR_END(
- MemConfig.config_mem(args, root.system)
-
- pci_devices = []
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=0))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=1, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=2))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=3, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=4, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=5, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=6, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=7, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=8, outfile="none"))))
- pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=9, outfile="none"))))
-
- for each_item in args.disk_image:
- disk_image = CowDiskImage()
- disk_image.child.image_file = SysPaths.disk(each_item)
- pci_devices.append(PciVirtIO(vio=VirtIOBlock(image=disk_image)))
-
- nic = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0, InterruptLine=1, InterruptPin=1)
- pci_devices.append(nic)
- root.system.pci_devices = pci_devices
- for pci_device in root.system.pci_devices:
- root.system.attach_pci(pci_device)
-
- root.tap = EtherTap(tun_clone_device='/dev/net/tun', tap_device_name='cvd-mtap-01')
- root.tap.tap = nic.interface
- root.system.connect()
-)CPP_STR_END";
-
-const std::string fs_kernel_cmd = R"CPP_STR_END(
- kernel_cmd = [
- "lpj=19988480",
- "norandmaps",
- "mem=%s" % args.mem_size,
- "console=hvc0",
- "panic=-1",
- "earlycon=pl011,mmio32,0x1c090000",
- "audit=1",
- "printk.devkmsg=on",
- "firmware_class.path=/vendor/etc/",
- "kfence.sample_interval=500",
- "loop.max_part=7",
- "bootconfig",
- "androidboot.force_normal_boot=1",
- ]
- root.system.workload.command_line = " ".join(kernel_cmd)
- if args.restore is not None:
- m5.instantiate(args.restore)
- else:
- m5.instantiate()
-
- while True:
- event = m5.simulate()
- msg = event.getCause()
- cur_tick = m5.curTick()
- if msg == "checkpoint":
- backup_path = backup_path = os.path.join(root_dir, "gem5_checkpoint")
- if not os.path.isdir(backup_path):
- os.mkdir(backup_path)
-
- print("Checkpoint @", cur_tick)
- src_dir = os.path.join(m5.options.outdir, "cpt.%d" % cur_tick)
- backup_path = os.path.join(backup_path, "cpt.%d" % cur_tick)
- m5.checkpoint(src_dir)
- shutil.copytree(src_dir, backup_path)
- print("Checkpoint done.")
- else:
- print("Exit msg: " + msg + " @", cur_tick)
- break
- sys.exit(event.getCode())
-)CPP_STR_END";
-
-const std::string fs_exe_main = R"CPP_STR_END(
-if __name__ == "__m5_main__":
- main()
-)CPP_STR_END";
-
} // namespace vm_manager
} // namespace cuttlefish
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index aa25938..0253b98 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -25,9 +25,7 @@
#include <unistd.h>
#include <cstdlib>
-#include <sstream>
#include <string>
-#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -37,15 +35,11 @@
#include <vulkan/vulkan.h>
#include "common/libs/device_config/device_config.h"
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/utils/contains.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
-#include "common/libs/utils/users.h"
#include "host/libs/config/command_source.h"
#include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/config/known_paths.h"
namespace cuttlefish {
namespace vm_manager {
@@ -56,11 +50,6 @@
"qemu_monitor.sock");
}
-void LogAndSetEnv(const char* key, const std::string& value) {
- setenv(key, value.c_str(), 1);
- LOG(INFO) << key << "=" << value;
-}
-
bool Stop() {
auto config = CuttlefishConfig::Get();
auto monitor_path = GetMonitorPath(*config);
@@ -199,7 +188,10 @@
}
Result<std::unordered_map<std::string, std::string>>
-QemuManager::ConfigureBootDevices(int num_disks, bool have_gpu) {
+QemuManager::ConfigureBootDevices(
+ const CuttlefishConfig::InstanceSpecific& instance) {
+ const int num_disks = instance.virtual_disk_paths().size();
+ const int num_gpu = instance.hwcomposer() != kHwComposerNone;
switch (arch_) {
case Arch::Arm:
return {{{"androidboot.boot_devices", "3f000000.pcie"}}};
@@ -215,8 +207,8 @@
case Arch::X86_64: {
// QEMU has additional PCI devices for an ISA bridge and PIIX4
// virtio_gpu precedes the first console or disk
- return ConfigureMultipleBootDevices("pci0000:00/0000:00:",
- 2 + (have_gpu ? 1 : 0), num_disks);
+ return ConfigureMultipleBootDevices("pci0000:00/0000:00:", 2 + num_gpu,
+ num_disks);
}
}
}
@@ -788,7 +780,7 @@
qemu_cmd.AddParameter("tcp::", instance.gdb_port());
}
- LogAndSetEnv("QEMU_AUDIO_DRV", "none");
+ qemu_cmd.AddEnvironmentVariable("QEMU_AUDIO_DRV", "none");
std::vector<MonitorCommand> commands;
commands.emplace_back(std::move(qemu_cmd), true);
diff --git a/host/libs/vm_manager/qemu_manager.h b/host/libs/vm_manager/qemu_manager.h
index 65f30ea..c0e4624 100644
--- a/host/libs/vm_manager/qemu_manager.h
+++ b/host/libs/vm_manager/qemu_manager.h
@@ -42,7 +42,7 @@
const CuttlefishConfig::InstanceSpecific& instance) override;
Result<std::unordered_map<std::string, std::string>> ConfigureBootDevices(
- int num_disks, bool have_gpu) override;
+ const CuttlefishConfig::InstanceSpecific& instance) override;
Result<std::vector<MonitorCommand>> StartCommands(
const CuttlefishConfig& config,
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index 9483354..d52fc15 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -84,7 +84,7 @@
ConfigureGraphics(const CuttlefishConfig::InstanceSpecific& instance) = 0;
virtual Result<std::unordered_map<std::string, std::string>>
- ConfigureBootDevices(int num_disks, bool have_gpu) = 0;
+ ConfigureBootDevices(const CuttlefishConfig::InstanceSpecific& instance) = 0;
// Starts the VMM. It will usually build a command and pass it to the
// command_starter function, although it may start more than one. The
diff --git a/host/libs/wayland/Android.bp b/host/libs/wayland/Android.bp
index 12700f3..2aefda3 100644
--- a/host/libs/wayland/Android.bp
+++ b/host/libs/wayland/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "libcuttlefish_wayland_server",
srcs: [
"wayland_compositor.cpp",
diff --git a/host/libs/web/credential_source.cc b/host/libs/web/credential_source.cc
index 33b878d..da77d29 100644
--- a/host/libs/web/credential_source.cc
+++ b/host/libs/web/credential_source.cc
@@ -13,7 +13,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "credential_source.h"
+#include "host/libs/web/credential_source.h"
+
+#include <chrono>
#include <android-base/logging.h>
#include <android-base/strings.h>
@@ -23,16 +25,11 @@
#include <openssl/pem.h>
#include "common/libs/utils/base64.h"
+#include "common/libs/utils/result.h"
namespace cuttlefish {
-namespace {
-std::chrono::steady_clock::duration REFRESH_WINDOW =
- std::chrono::minutes(2);
-std::string REFRESH_URL = "http://metadata.google.internal/computeMetadata/"
- "v1/instance/service-accounts/default/token";
-
-} // namespace
+static constexpr auto kRefreshWindow = std::chrono::minutes(2);
GceMetadataCredentialSource::GceMetadataCredentialSource(
HttpClient& http_client)
@@ -42,15 +39,18 @@
}
Result<std::string> GceMetadataCredentialSource::Credential() {
- if (expiration - std::chrono::steady_clock::now() < REFRESH_WINDOW) {
+ if (expiration - std::chrono::steady_clock::now() < kRefreshWindow) {
CF_EXPECT(RefreshCredential());
}
return latest_credential;
}
Result<void> GceMetadataCredentialSource::RefreshCredential() {
+ static constexpr char kRefreshUrl[] =
+ "http://metadata.google.internal/computeMetadata/v1/instance/"
+ "service-accounts/default/token";
auto response = CF_EXPECT(
- http_client.DownloadToJson(REFRESH_URL, {"Metadata-Flavor: Google"}));
+ http_client.DownloadToJson(kRefreshUrl, {"Metadata-Flavor: Google"}));
const auto& json = response.data;
CF_EXPECT(response.HttpSuccess(),
"Error fetching credentials. The server response was \""
@@ -132,7 +132,7 @@
refresh_token_(refresh_token) {}
Result<std::string> RefreshCredentialSource::Credential() {
- if (expiration_ - std::chrono::steady_clock::now() < REFRESH_WINDOW) {
+ if (expiration_ - std::chrono::steady_clock::now() < kRefreshWindow) {
CF_EXPECT(UpdateLatestCredential());
}
return latest_credential_;
@@ -294,10 +294,10 @@
}
Result<std::string> ServiceAccountOauthCredentialSource::Credential() {
- if (expiration_ - std::chrono::steady_clock::now() < REFRESH_WINDOW) {
+ if (expiration_ - std::chrono::steady_clock::now() < kRefreshWindow) {
CF_EXPECT(RefreshCredential());
}
return latest_credential_;
}
-} // namespace cuttlefish
+} // namespace cuttlefish
diff --git a/host/libs/websocket/Android.bp b/host/libs/websocket/Android.bp
index 327224b..640e37d 100644
--- a/host/libs/websocket/Android.bp
+++ b/host/libs/websocket/Android.bp
@@ -17,7 +17,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_host_static {
+cc_library {
name: "libcuttlefish_host_websocket",
srcs: [
"websocket_handler.cpp",
diff --git a/recovery/Android.bp b/recovery/Android.bp
index 0923d17..4392c4e 100644
--- a/recovery/Android.bp
+++ b/recovery/Android.bp
@@ -18,7 +18,7 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_static {
+cc_library {
name: "librecovery_ui_cuttlefish",
owner: "google",
cflags: [
diff --git a/shared/BoardConfig.mk b/shared/BoardConfig.mk
index 5277d99..2eee523 100644
--- a/shared/BoardConfig.mk
+++ b/shared/BoardConfig.mk
@@ -57,6 +57,17 @@
# GKI >5.10 will have and require virtio_pci_modern_dev.ko
BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard $(KERNEL_MODULES_PATH)/virtio_pci_modern_dev.ko)
+# TODO(b/176860479) once virt_wifi is deprecated we can stop loading mac80211 in
+# first stage init. To minimize scope of modules options to first stage init,
+# mac80211_hwsim.radios=0 has to be specified in the modules options file (which we
+# only read in first stage) and mac80211_hwsim has to be loaded in first stage consequently..
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard $(SYSTEM_DLKM_SRC)/libarc4.ko)
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard $(SYSTEM_DLKM_SRC)/rfkill.ko)
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard $(KERNEL_MODULES_PATH)/cfg80211.ko)
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard $(KERNEL_MODULES_PATH)/mac80211.ko)
+BOARD_VENDOR_RAMDISK_KERNEL_MODULES += $(wildcard $(KERNEL_MODULES_PATH)/mac80211_hwsim.ko)
+BOARD_DO_NOT_STRIP_VENDOR_RAMDISK_MODULES := true
+
ALL_KERNEL_MODULES := $(wildcard $(KERNEL_MODULES_PATH)/*.ko)
BOARD_VENDOR_KERNEL_MODULES := \
$(filter-out $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),\
@@ -279,7 +290,7 @@
TARGET_RELEASETOOLS_EXTENSIONS := device/google/cuttlefish/shared
# Generate a partial ota update package for partitions in vbmeta_system
-BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST := product system system_ext vbmeta_system
+BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST := product system system_ext vbmeta_system init_boot
BOARD_BOOTLOADER_IN_UPDATE_PACKAGE := true
BOARD_RAMDISK_USE_LZ4 := true
diff --git a/shared/auto/device_vendor.mk b/shared/auto/device_vendor.mk
index fb7510e..4cc46dc 100644
--- a/shared/auto/device_vendor.mk
+++ b/shared/auto/device_vendor.mk
@@ -29,7 +29,6 @@
$(call inherit-product, device/google/cuttlefish/shared/swiftshader/device_vendor.mk)
$(call inherit-product, device/google/cuttlefish/shared/telephony/device_vendor.mk)
$(call inherit-product, device/google/cuttlefish/shared/sensors/device_vendor.mk)
-$(call inherit-product, device/google/cuttlefish/shared/virgl/device_vendor.mk)
$(call inherit-product, device/google/cuttlefish/shared/device.mk)
# Extend cuttlefish common sepolicy with auto-specific functionality
diff --git a/shared/config/manifest.xml b/shared/config/manifest.xml
index f121c95..eab12db 100644
--- a/shared/config/manifest.xml
+++ b/shared/config/manifest.xml
@@ -17,15 +17,6 @@
*/
-->
<manifest version="1.0" type="device" target-level="9">
- <hal format="hidl">
- <name>android.hardware.authsecret</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IAuthSecret</name>
- <instance>default</instance>
- </interface>
- </hal>
<!-- DO NOT ADD MORE - use vintf_fragments -->
diff --git a/shared/config/previous_manifest.xml b/shared/config/previous_manifest.xml
new file mode 100644
index 0000000..40b9e1b
--- /dev/null
+++ b/shared/config/previous_manifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2023, The Android Open Source Project.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<manifest version="1.0" type="device" target-level="8">
+
+ <!-- DO NOT ADD MORE - use vintf_fragments -->
+
+</manifest>
diff --git a/shared/device.mk b/shared/device.mk
index 24af8e0..08f1a7a 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -37,7 +37,6 @@
PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for audio and wifi
-PRODUCT_SHIPPING_API_LEVEL := 35
PRODUCT_USE_DYNAMIC_PARTITIONS := true
DISABLE_RILD_OEM_HOOK := true
@@ -182,7 +181,13 @@
#
# Common manifest for all targets
#
+ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
+PRODUCT_SHIPPING_API_LEVEL := 35
LOCAL_DEVICE_FCM_MANIFEST_FILE ?= device/google/cuttlefish/shared/config/manifest.xml
+else
+PRODUCT_SHIPPING_API_LEVEL := 34
+LOCAL_DEVICE_FCM_MANIFEST_FILE ?= device/google/cuttlefish/shared/config/previous_manifest.xml
+endif
DEVICE_MANIFEST_FILE += $(LOCAL_DEVICE_FCM_MANIFEST_FILE)
#
@@ -255,18 +260,11 @@
PRODUCT_PACKAGES += \
android.hardware.weaver-service.example
-
-#
-# Authsecret HAL
-#
-PRODUCT_PACKAGES += \
- android.hardware.authsecret@1.0-service
-
#
# Authsecret AIDL HAL
#
PRODUCT_PACKAGES += \
- android.hardware.authsecret-service.example
+ com.android.hardware.authsecret
#
# Audio HAL
@@ -408,7 +406,7 @@
# KeyMint HAL
#
ifeq ($(LOCAL_KEYMINT_PRODUCT_PACKAGE),)
- LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := com.google.cf.keymint.rust
endif
PRODUCT_PACKAGES += \
@@ -553,11 +551,8 @@
endif
# UWB HAL
-PRODUCT_PACKAGES += \
- android.hardware.uwb-service
-PRODUCT_COPY_FILES += \
- device/google/cuttlefish/guest/hals/uwb/uwb-service.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/uwb-service.rc
-
+PRODUCT_PACKAGES += com.android.hardware.uwb
+PRODUCT_VENDOR_PROPERTIES += ro.vendor.uwb.dev=/dev/hvc9
# Host packages to install
PRODUCT_HOST_PACKAGES += socket_vsock_proxy
@@ -598,4 +593,4 @@
android.hardware.threadnetwork-service.sim \
ot-cli-ftd
PRODUCT_COPY_FILES += \
- frameworks/native/data/etc/android.hardware.threadnetwork.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.threadnetwork.xml
+ frameworks/native/data/etc/android.hardware.thread_network.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.thread_network.xml
diff --git a/shared/phone/device_vendor.mk b/shared/phone/device_vendor.mk
index 4091c3f..5982a60 100644
--- a/shared/phone/device_vendor.mk
+++ b/shared/phone/device_vendor.mk
@@ -53,6 +53,8 @@
endif
+DEVICE_PACKAGE_OVERLAYS += device/google/cuttlefish/shared/phone/overlay
+
# Runtime Resource Overlays
ifeq ($(LOCAL_PREFER_VENDOR_APEX),true)
PRODUCT_PACKAGES += com.google.aosp_cf_phone.rros
diff --git a/shared/phone/overlay/frameworks/base/libs/WindowManager/Shell/res/values/dimen.xml b/shared/phone/overlay/frameworks/base/libs/WindowManager/Shell/res/values/dimen.xml
new file mode 100644
index 0000000..c500636
--- /dev/null
+++ b/shared/phone/overlay/frameworks/base/libs/WindowManager/Shell/res/values/dimen.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2023, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <dimen name="dismiss_circle_size">60dp</dimen>
+</resources>
diff --git a/shared/sepolicy/vendor/bug_map b/shared/sepolicy/vendor/bug_map
index b6d528f..6417191 100644
--- a/shared/sepolicy/vendor/bug_map
+++ b/shared/sepolicy/vendor/bug_map
@@ -1,3 +1,4 @@
init system_lib_file dir b/133444385
init system_lib_file file b/133444385
priv_app radio_vendor_data_file dir b/188833462
+rs privapp_data_file file b/291029681
diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts
index 619dc93..a9b1422 100644
--- a/shared/sepolicy/vendor/file_contexts
+++ b/shared/sepolicy/vendor/file_contexts
@@ -72,7 +72,7 @@
/vendor/bin/hw/android\.hardware\.gatekeeper@1\.0-service\.software u:object_r:hal_gatekeeper_default_exec:s0
/vendor/bin/hw/android\.hardware\.health-service\.cuttlefish u:object_r:hal_health_default_exec:s0
/vendor/bin/hw/android\.hardware\.health\.storage-service\.cuttlefish u:object_r:hal_health_storage_default_exec:s0
-/vendor/bin/hw/android\.hardware\.lights-service\.cuttlefish u:object_r:hal_light_default_exec:s0
+/vendor/bin/hw/android\.hardware\.lights-service\.cuttlefish u:object_r:hal_light_cuttlefish_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks-shim-service-sample u:object_r:hal_neuralnetworks_sample_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks-service-sample-.* u:object_r:hal_neuralnetworks_sample_exec:s0
/vendor/bin/hw/android\.hardware\.nfc-service\.cuttlefish u:object_r:hal_nfc_default_exec:s0
diff --git a/shared/sepolicy/vendor/hal_light_cuttlefish.te b/shared/sepolicy/vendor/hal_light_cuttlefish.te
new file mode 100644
index 0000000..e02f8e0
--- /dev/null
+++ b/shared/sepolicy/vendor/hal_light_cuttlefish.te
@@ -0,0 +1,7 @@
+type hal_light_cuttlefish, domain;
+hal_server_domain(hal_light_cuttlefish, hal_light)
+
+type hal_light_cuttlefish_exec, exec_type, vendor_file_type, file_type;
+init_daemon_domain(hal_light_cuttlefish)
+
+allow hal_light_cuttlefish self:{ socket vsock_socket } { create_socket_perms_no_ioctl listen accept };
diff --git a/shared/sepolicy/vendor/property.te b/shared/sepolicy/vendor/property.te
index 371ce92..6f3dca1 100644
--- a/shared/sepolicy/vendor/property.te
+++ b/shared/sepolicy/vendor/property.te
@@ -4,3 +4,4 @@
vendor_internal_prop(vendor_hwcomposer_prop)
vendor_restricted_prop(vendor_wlan_versions_prop)
vendor_internal_prop(vendor_device_prop)
+vendor_internal_prop(vendor_uwb_prop)
\ No newline at end of file
diff --git a/shared/sepolicy/vendor/property_contexts b/shared/sepolicy/vendor/property_contexts
index d4235ff..9acb483 100644
--- a/shared/sepolicy/vendor/property_contexts
+++ b/shared/sepolicy/vendor/property_contexts
@@ -13,6 +13,7 @@
ro.vendor.hwcomposer.display_finder_mode u:object_r:vendor_hwcomposer_prop:s0 exact string
ro.vendor.hwcomposer.mode u:object_r:vendor_hwcomposer_prop:s0 exact string
ro.vendor.hwcomposer.pmem u:object_r:vendor_hwcomposer_prop:s0 exact string
+ro.vendor.uwb.dev u:object_r:vendor_uwb_prop:s0 exact string
vendor.wlan.firmware.version u:object_r:vendor_wlan_versions_prop:s0 exact string
vendor.wlan.driver.version u:object_r:vendor_wlan_versions_prop:s0 exact string
vendor.dlkm.modules.ready u:object_r:vendor_device_prop:s0 exact bool
diff --git a/shared/sepolicy/vendor/vendor_init.te b/shared/sepolicy/vendor/vendor_init.te
index 613a78f..b36ae67 100644
--- a/shared/sepolicy/vendor/vendor_init.te
+++ b/shared/sepolicy/vendor/vendor_init.te
@@ -10,5 +10,6 @@
vendor_internal_prop(vendor_wifi_impl)
set_prop(vendor_init, vendor_wifi_impl)
+set_prop(vendor_init, vendor_uwb_prop)
set_prop(vendor_init, vendor_boot_security_patch_level_prop)
diff --git a/host/commands/cvd_load_tester/Android.bp b/tests/fastboot/Android.bp
similarity index 61%
rename from host/commands/cvd_load_tester/Android.bp
rename to tests/fastboot/Android.bp
index b51cea3..813abdd 100644
--- a/host/commands/cvd_load_tester/Android.bp
+++ b/tests/fastboot/Android.bp
@@ -1,4 +1,3 @@
-//
// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,25 +16,15 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_binary {
- name: "test_cvd_load_parser",
- shared_libs: [
- "libbase",
- "libcuttlefish_fs",
- "libcuttlefish_utils",
- "libjsoncpp",
- "libgrpc++_unsecure",
- "libxml2",
- ],
- static_libs: [
- "libprotobuf-cpp-full",
- "libcuttlefish_launch_cvd_proto",
- "libcvd_parser",
- "libcuttlefish_host_config",
- "libgflags",
- ],
+java_test_host {
+ name: "FastbootRebootTest",
srcs: [
- "main.cc",
+ "src/com/android/cuttlefish/tests/FastbootRebootTest.java",
],
- defaults: ["cvd_load_defaults"],
-}
\ No newline at end of file
+ test_suites: [
+ "device-tests",
+ ],
+ libs: [
+ "tradefed",
+ ],
+}
diff --git a/tests/fastboot/src/com/android/cuttlefish/tests/FastbootRebootTest.java b/tests/fastboot/src/com/android/cuttlefish/tests/FastbootRebootTest.java
new file mode 100644
index 0000000..d883cc4
--- /dev/null
+++ b/tests/fastboot/src/com/android/cuttlefish/tests/FastbootRebootTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cuttlefish.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tradefed.device.TestDeviceState;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class FastbootRebootTest extends BaseHostJUnit4Test {
+
+ @Before
+ public void rebootToBootloader() throws Exception {
+ getDevice().rebootIntoBootloader();
+ }
+
+ @AfterClassWithInfo
+ public static void rebootToAndroid(TestInformation information) throws Exception {
+ information.getDevice().reboot();
+ }
+
+ @Test
+ public void testReboot() throws Exception {
+ getDevice().rebootUserspace();
+ assertEquals(TestDeviceState.ONLINE, getDevice().getDeviceState());
+ }
+
+ @Test
+ public void testRebootRecovery() throws Exception {
+ getDevice().rebootIntoRecovery();
+ assertEquals(TestDeviceState.RECOVERY, getDevice().getDeviceState());
+ }
+
+ @Test
+ public void testRebootBootloader() throws Exception {
+ getDevice().rebootIntoBootloader();
+ assertEquals(TestDeviceState.FASTBOOT, getDevice().getDeviceState());
+ }
+
+ @Test
+ @Ignore("b/296629925")
+ public void testRebootFastboot() throws Exception {
+ getDevice().rebootIntoFastbootd();
+ assertEquals(TestDeviceState.FASTBOOTD, getDevice().getDeviceState());
+ }
+}
diff --git a/tests/hal/Android.bp b/tests/hal/Android.bp
index 1a63d6e..acf49bf 100644
--- a/tests/hal/Android.bp
+++ b/tests/hal/Android.bp
@@ -32,6 +32,11 @@
"libutils",
"packagemanager_aidl-cpp",
],
+ product_variables: {
+ release_aidl_use_unfrozen: {
+ cflags: ["-DAIDL_USE_UNFROZEN"],
+ },
+ },
cflags: [
"-Wall",
"-Werror",
diff --git a/tests/hal/hal_implementation_test.cpp b/tests/hal/hal_implementation_test.cpp
index 0c8abe4..3429fb1 100644
--- a/tests/hal/hal_implementation_test.cpp
+++ b/tests/hal/hal_implementation_test.cpp
@@ -33,6 +33,12 @@
#include <string>
#include <vector>
+#ifdef AIDL_USE_UNFROZEN
+constexpr bool kAidlUseUnfrozen = true;
+#else
+constexpr bool kAidlUseUnfrozen = false;
+#endif
+
using namespace android;
// clang-format off
@@ -59,6 +65,7 @@
"android.hardware.audio.effect@4.0",
"android.hardware.audio.effect@5.0",
"android.hardware.audio.effect@6.0",
+ "android.hardware.authsecret@1.0", // converted to AIDL, see b/182976659
"android.hardware.automotive.audiocontrol@1.0",
"android.hardware.automotive.audiocontrol@2.0",
"android.hardware.automotive.evs@1.1",
@@ -453,6 +460,7 @@
}
TEST(Hal, AllHidlInterfacesAreInAosp) {
+ if (!kAidlUseUnfrozen) GTEST_SKIP() << "Not valid in 'next' configuration";
for (const FQName& name : allHidlManifestInterfaces()) {
EXPECT_TRUE(isAospHidlInterface(name))
<< "This device should only have AOSP interfaces, not: "
@@ -461,6 +469,7 @@
}
TEST(Hal, HidlInterfacesImplemented) {
+ if (!kAidlUseUnfrozen) GTEST_SKIP() << "Not valid in 'next' configuration";
// instances -> major version -> minor versions
std::map<std::string, std::map<size_t, std::set<size_t>>> unimplemented;
@@ -516,6 +525,7 @@
}
TEST(Hal, AllAidlInterfacesAreInAosp) {
+ if (!kAidlUseUnfrozen) GTEST_SKIP() << "Not valid in 'next' configuration";
for (const auto& package : allAidlManifestInterfaces()) {
EXPECT_TRUE(isAospAidlInterface(package.name))
<< "This device should only have AOSP interfaces, not: "
@@ -529,6 +539,7 @@
};
TEST(Hal, AidlInterfacesImplemented) {
+ if (!kAidlUseUnfrozen) GTEST_SKIP() << "Not valid in 'next' configuration";
std::vector<VersionedAidlPackage> manifest = allAidlManifestInterfaces();
std::vector<VersionedAidlPackage> thoughtMissing = kKnownMissingAidl;
diff --git a/tools/create_base_image_arm.sh b/tools/create_base_image_arm.sh
index a5fe3ad..20fb758 100755
--- a/tools/create_base_image_arm.sh
+++ b/tools/create_base_image_arm.sh
@@ -118,7 +118,7 @@
fastboot_raw_partition_raw1=0x0 0x2000000
EOF
echo "Sha=`${script_dir}/gen_sha.sh --uboot ${UBOOT_DIST} --kernel ${KERNEL_DIST}`" >> ${bootenv_src}
-${ANDROID_BUILD_TOP}/device/google/cuttlefish_prebuilts/uboot_tools/mkenvimage -s 32768 -o ${bootenv} - < ${bootenv_src}
+mkenvimage -s 32768 -o ${bootenv} - < ${bootenv_src}
rm -f ${bootenv_src}
IMAGE=`mktemp`
diff --git a/tools/launch_cvd_arm64_server.sh b/tools/launch_cvd_arm64_server.sh
index c8740ff..cbb5f33 100755
--- a/tools/launch_cvd_arm64_server.sh
+++ b/tools/launch_cvd_arm64_server.sh
@@ -35,7 +35,11 @@
# copy and compress the artifacts to the temp directory
ssh $server -t "mkdir -p ~/.cvd_artifact; mkdir -p ~/cvd_home"
-rsync -aSvch --recursive $ANDROID_PRODUCT_OUT --files-from=$ANDROID_PRODUCT_OUT/required_images $server:~/cvd_home --info=progress2
+if [ -f $ANDROID_PRODUCT_OUT/required_images ]; then
+ rsync -aSvch --recursive $ANDROID_PRODUCT_OUT --files-from=$ANDROID_PRODUCT_OUT/required_images $server:~/cvd_home --info=progress2
+else
+ rsync -aSvch --recursive $ANDROID_PRODUCT_OUT/bootloader $ANDROID_PRODUCT_OUT/*.img $server:~/cvd_home --info=progress2
+fi
# copy the cvd host package
cvd_host_tool_dir=$ANDROID_HOST_OUT/../linux_musl-arm64
@@ -56,7 +60,6 @@
web_ui_port=$((8443+$base_instance_num-1))
adb_port=$((6520+$base_instance_num-1))
-fastboot_port=$((7520+$base_instance_num-1))
instance_id=$(uuidgen)
# sets up SSH port forwarding to the remote server for various ports and launch cvd instance
# port forward rule as base_instance_num=1 in local
@@ -64,5 +67,5 @@
-L 15550:127.0.0.1:15550 -L 15551:127.0.0.1:15551 -L 15552:127.0.0.1:15552 \
-L 15553:127.0.0.1:15553 -L 15554:127.0.0.1:15554 -L 15555:127.0.0.1:15555 \
-L 15556:127.0.0.1:15556 -L 15557:127.0.0.1:15557 -L 15558:127.0.0.1:15558 \
- -L 6520:127.0.0.1:$adb_port -L 7520:127.0.0.1:$fastboot_port \
+ -L 6520:127.0.0.1:$adb_port \
-t "cd cvd_home && HOME=~/cvd_home bin/launch_cvd --base_instance_num=$base_instance_num"
diff --git a/tools/raw2iso.sh b/tools/raw2iso.sh
index 25fdd41..103bfa3 100755
--- a/tools/raw2iso.sh
+++ b/tools/raw2iso.sh
@@ -125,27 +125,21 @@
dd if="\${SCRIPT_DIR}"/esp.img of=\${1}\${partition}1 bs=16M
mkfs.ext4 -L ROOT -U \$(cat \${SCRIPT_DIR}/rootfs_uuid) \${1}\${partition}2
mount \${1}\${partition}2 /media
-tar -C /media -Spxf \${SCRIPT_DIR}/rootfs.tar.lz4
+tar -C /media -Spxf \${SCRIPT_DIR}/rootfs.tar.xz
umount /media
EOF
chmod a+x "${workdir}"/install.sh
-cat >"${workdir}"/installer.service <<EOF
-[Unit]
-Description=Installer script starter
-After=getty.target
-Conflicts=serial-getty@ttyAMA0.service
-
+cat >"${workdir}"/override-getty.conf <<EOF
[Service]
-Type=oneshot
-RemainAfterExit=yes
-ExecStart=/bin/bash
-StandardInput=tty-force
-StandardOutput=inherit
-StandardError=inherit
+ExecStart=
+ExecStart=-/sbin/agetty -a root --noclear tty1 \$TERM
+EOF
-[Install]
-WantedBy=graphical.target
+cat >"${workdir}"/override-serial-getty.conf <<EOF
+[Service]
+ExecStart=
+ExecStart=-/sbin/agetty -a root --keep-baud 115200,57600,38400,9600 ttyAMA0 \$TERM
EOF
# Back up the GPT so we can restore it when installing
@@ -194,13 +188,13 @@
sudo mount -o loop,offset=${root_partition_offset} "${input}" "${mount}"
trap unmount EXIT
sudo rm -f "${mount}"/root/esp.img "${mount}"/root/gpt.img
-sudo rm -f "${mount}"/root/rootfs.tar.lz4
+sudo rm -f "${mount}"/root/rootfs.tar.xz
sudo rm -f "${mount}"/root/rootfs_uuid
sudo rm -f "${mount}"/boot/grub/eltorito.img
sudo rm -f "${mount}"/boot/grub/${grub_arch}/grub.cfg
sudo rm -rf "${mount}"/tmp/*
sudo rm -rf "${mount}"/var/tmp/*
-( cd "${mount}" && sudo tar -Szcpf "${workdir}"/rootfs.tar.lz4 * )
+( cd "${mount}" && sudo tar -SJcpf "${workdir}"/rootfs.tar.xz * )
# Prepare a new ESP for the ISO's El Torito image
mkdir -p "${workdir}/EFI/Boot"
@@ -214,22 +208,34 @@
# Build ISO from rootfs
sudo cp "${workdir}"/esp.img "${workdir}"/gpt.img "${mount}"/root
-sudo cp "${workdir}"/rootfs.tar.lz4 "${workdir}"/install.sh "${mount}"/root
+sudo cp "${workdir}"/rootfs.tar.xz "${workdir}"/install.sh "${mount}"/root
echo -n "${rootfs_uuid}" | sudo tee "${mount}"/root/rootfs_uuid >/dev/null
sudo cp "${workdir}"/eltorito.img "${mount}"/boot/grub
sudo cp "${workdir}"/grub.cfg "${mount}"/boot/grub/${grub_arch}/grub.cfg
-sudo cp "${workdir}"/installer.service "${mount}"/usr/lib/systemd/system/installer.service
-sudo ln -f -r -s "${mount}"/usr/lib/systemd/system/installer.service "${mount}"/usr/lib/systemd/system/getty.target.wants/installer.service
+sudo mkdir -p "${mount}"/etc/systemd/system/getty@tty1.service.d
+sudo cp "${workdir}"/override-getty.conf "${mount}"/etc/systemd/system/getty@tty1.service.d/override.conf
+sudo mkdir -p "${mount}"/etc/systemd/system/serial-getty@ttyAMA0.service.d
+sudo cp "${workdir}"/override-serial-getty.conf "${mount}"/etc/systemd/system/serial-getty@ttyAMA0.service.d/override.conf
sudo chown root:root \
"${mount}"/root/esp.img "${mount}"/root/gpt.img \
"${mount}"/boot/grub/eltorito.img \
"${mount}"/boot/grub/${grub_arch}/grub.cfg
+sudo mv "${mount}"/usr "${mount}"/usr_o
+sudo mkzftree "${mount}"/usr_o "${mount}"/usr
+sudo rm -rf "${mount}"/usr_o
+sudo mv "${mount}"/root "${mount}"/root_o
+sudo mkzftree "${mount}"/root_o "${mount}"/root
+sudo rm -rf "${mount}"/root_o
+sudo mv "${mount}"/var "${mount}"/var_o
+sudo mkzftree "${mount}"/var_o "${mount}"/var
+sudo rm -rf "${mount}"/var_o
rm -f "${output}"
touch "${output}"
sudo xorriso \
-as mkisofs -r -checksum_algorithm_iso sha256,sha512 -V install "${mount}" \
-o "${output}" -e boot/grub/eltorito.img -no-emul-boot \
-append_partition 2 0xef "${workdir}"/eltorito.img \
+ -z \
-partition_cyl_align all
echo "Output ISO generated at '${output}'."
diff --git a/vsoc_arm64/BoardConfig.mk b/vsoc_arm64/BoardConfig.mk
index ae9e686..eed5fb3 100644
--- a/vsoc_arm64/BoardConfig.mk
+++ b/vsoc_arm64/BoardConfig.mk
@@ -44,4 +44,7 @@
-include device/google/cuttlefish/shared/sensors/BoardConfig.mk
-include device/google/cuttlefish/shared/swiftshader/BoardConfig.mk
-include device/google/cuttlefish/shared/telephony/BoardConfig.mk
+
+ifneq ($(BOARD_IS_AUTOMOTIVE), true)
-include device/google/cuttlefish/shared/virgl/BoardConfig.mk
+endif
diff --git a/vsoc_arm64_only/BoardConfig.mk b/vsoc_arm64_only/BoardConfig.mk
index 740eaf1..8b8dfeb 100644
--- a/vsoc_arm64_only/BoardConfig.mk
+++ b/vsoc_arm64_only/BoardConfig.mk
@@ -40,4 +40,7 @@
-include device/google/cuttlefish/shared/sensors/BoardConfig.mk
-include device/google/cuttlefish/shared/swiftshader/BoardConfig.mk
-include device/google/cuttlefish/shared/telephony/BoardConfig.mk
+
+ifneq ($(BOARD_IS_AUTOMOTIVE), true)
-include device/google/cuttlefish/shared/virgl/BoardConfig.mk
+endif
diff --git a/vsoc_arm64_only/phone/aosp_cf_pgagnostic.mk b/vsoc_arm64_only/phone/aosp_cf_pgagnostic.mk
new file mode 100644
index 0000000..0498cc2
--- /dev/null
+++ b/vsoc_arm64_only/phone/aosp_cf_pgagnostic.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+$(call inherit-product, device/google/cuttlefish/vsoc_arm64_only/phone/aosp_cf.mk)
+
+PRODUCT_NAME := aosp_cf_arm64_phone_pgagnostic
+PRODUCT_PAGE_SIZE_AGNOSTIC := true
+PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 65536
diff --git a/vsoc_riscv64/phone/aosp_cf.mk b/vsoc_riscv64/phone/aosp_cf.mk
index c5a19a3..bc2af1f 100644
--- a/vsoc_riscv64/phone/aosp_cf.mk
+++ b/vsoc_riscv64/phone/aosp_cf.mk
@@ -39,6 +39,8 @@
LOCAL_PREFER_VENDOR_APEX := true
$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
+PRODUCT_ENFORCE_MAC80211_HWSIM := false
+
# TODO: Nested virtualization support
# $(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
diff --git a/vsoc_riscv64/slim/aosp_cf.mk b/vsoc_riscv64/slim/aosp_cf.mk
index ab79b49..b85b738 100644
--- a/vsoc_riscv64/slim/aosp_cf.mk
+++ b/vsoc_riscv64/slim/aosp_cf.mk
@@ -40,8 +40,7 @@
LOCAL_PREFER_VENDOR_APEX := true
$(call inherit-product, device/google/cuttlefish/shared/slim/device_vendor.mk)
-# TODO(b/205788876) remove this when openwrt has an image for riscv64
-#PRODUCT_ENFORCE_MAC80211_HWSIM := false
+PRODUCT_ENFORCE_MAC80211_HWSIM := false
#
# Special settings for the target
diff --git a/vsoc_riscv64/wear/aosp_cf.mk b/vsoc_riscv64/wear/aosp_cf.mk
index 215ede6..aa44c7f 100644
--- a/vsoc_riscv64/wear/aosp_cf.mk
+++ b/vsoc_riscv64/wear/aosp_cf.mk
@@ -37,6 +37,8 @@
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.software.app_widgets.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.app_widgets.xml \
+PRODUCT_ENFORCE_MAC80211_HWSIM := false
+
#
# All components inherited here go to system_ext image
#
diff --git a/vsoc_riscv64_minidroid/aosp_cf.mk b/vsoc_riscv64_minidroid/aosp_cf.mk
index a49ec77..8436a7b 100644
--- a/vsoc_riscv64_minidroid/aosp_cf.mk
+++ b/vsoc_riscv64_minidroid/aosp_cf.mk
@@ -24,6 +24,8 @@
PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish riscv64 minidroid
+PRODUCT_ENFORCE_MAC80211_HWSIM := false
+
PRODUCT_VENDOR_PROPERTIES += \
ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
ro.soc.model=$(PRODUCT_DEVICE)
diff --git a/vsoc_x86_64/BoardConfig.mk b/vsoc_x86_64/BoardConfig.mk
index d0ff0b3..cda2a45 100644
--- a/vsoc_x86_64/BoardConfig.mk
+++ b/vsoc_x86_64/BoardConfig.mk
@@ -47,4 +47,7 @@
-include device/google/cuttlefish/shared/sensors/BoardConfig.mk
-include device/google/cuttlefish/shared/swiftshader/BoardConfig.mk
-include device/google/cuttlefish/shared/telephony/BoardConfig.mk
+
+ifneq ($(BOARD_IS_AUTOMOTIVE), true)
-include device/google/cuttlefish/shared/virgl/BoardConfig.mk
+endif
diff --git a/vsoc_x86_64/phone/aosp_cf.mk b/vsoc_x86_64/phone/aosp_cf.mk
index e5c8b47..f9e8d62 100644
--- a/vsoc_x86_64/phone/aosp_cf.mk
+++ b/vsoc_x86_64/phone/aosp_cf.mk
@@ -60,11 +60,8 @@
PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86_64 phone
-# Window sidecar and extensions to enhance activity embedding, multi-display,
-# tablet, and foldable support.
-PRODUCT_PACKAGES += \
- androidx.window.extensions \
- androidx.window.sidecar \
+# Window Extensions
+$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
PRODUCT_VENDOR_PROPERTIES += \
ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
diff --git a/vsoc_x86_64_only/BoardConfig.mk b/vsoc_x86_64_only/BoardConfig.mk
index 3afdbf0..d36821b 100644
--- a/vsoc_x86_64_only/BoardConfig.mk
+++ b/vsoc_x86_64_only/BoardConfig.mk
@@ -40,4 +40,7 @@
-include device/google/cuttlefish/shared/sensors/BoardConfig.mk
-include device/google/cuttlefish/shared/swiftshader/BoardConfig.mk
-include device/google/cuttlefish/shared/telephony/BoardConfig.mk
+
+ifneq ($(BOARD_IS_AUTOMOTIVE), true)
-include device/google/cuttlefish/shared/virgl/BoardConfig.mk
+endif
diff --git a/vsoc_x86_64_only/phone/aosp_cf.mk b/vsoc_x86_64_only/phone/aosp_cf.mk
index 45fed56..d843574 100644
--- a/vsoc_x86_64_only/phone/aosp_cf.mk
+++ b/vsoc_x86_64_only/phone/aosp_cf.mk
@@ -55,6 +55,9 @@
PRODUCT_MANUFACTURER := Google
PRODUCT_MODEL := Cuttlefish x86_64 phone 64-bit only
+# Window Extensions
+$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
+
PRODUCT_VENDOR_PROPERTIES += \
ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
ro.soc.model=$(PRODUCT_DEVICE)