aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.bp31
-rw-r--r--common/libs/utils/files.cpp52
-rw-r--r--common/libs/utils/files.h2
-rw-r--r--host/commands/assemble_cvd/flags.cc60
-rw-r--r--host/commands/assemble_cvd/flags_defaults.h7
-rw-r--r--host/commands/assemble_cvd/graphics_flags.cc28
-rw-r--r--host/commands/assemble_cvd/graphics_flags.h3
-rw-r--r--host/commands/assemble_cvd/misc_info.cc34
-rw-r--r--host/commands/assemble_cvd/misc_info.h4
-rw-r--r--host/commands/assemble_cvd/super_image_mixer.cc260
-rw-r--r--host/commands/logcat_receiver/main.cpp33
-rw-r--r--host/commands/run_cvd/boot_state_machine.cc192
-rw-r--r--host/commands/run_cvd/boot_state_machine.h1
-rw-r--r--host/commands/run_cvd/server_loop_impl.cpp1
-rw-r--r--host/commands/start/main.cc1
-rw-r--r--host/libs/config/config_utils.cpp20
-rw-r--r--host/libs/config/config_utils.h5
-rw-r--r--host/libs/config/cuttlefish_config.cpp1
-rw-r--r--host/libs/config/cuttlefish_config.h12
-rw-r--r--host/libs/config/cuttlefish_config_instance.cpp38
-rw-r--r--host/libs/screen_connector/screen_connector.h4
-rw-r--r--host/libs/vm_manager/crosvm_manager.cpp63
-rw-r--r--host/libs/vm_manager/crosvm_manager.h2
-rw-r--r--host/libs/vm_manager/qemu_manager.cpp3
-rw-r--r--host/libs/vm_manager/vm_manager.h8
-rw-r--r--shared/auto/sepolicy/evs/hal_evs_default.te4
-rw-r--r--system_image/Android.bp80
27 files changed, 606 insertions, 343 deletions
diff --git a/build/Android.bp b/build/Android.bp
index 33563de5a..1e69ce018 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -45,6 +45,33 @@ soong_config_module_type {
],
}
+// Start of generated qemu_aarch64_linux_gnu_binary
+// Generated by gen_android_bp.py
+qemu_aarch64_linux_gnu_binary = [
+ "aarch64_linux_gnu_libc++.so.1_binary_for_qemu",
+ "aarch64_linux_gnu_libc++abi.so.1_binary_for_qemu",
+ "aarch64_linux_gnu_libepoxy.so.0_binary_for_qemu",
+ "aarch64_linux_gnu_libgbm.so.1_binary_for_qemu",
+ "aarch64_linux_gnu_libgfxstream_backend.so.0_binary_for_qemu",
+ "aarch64_linux_gnu_librutabaga_gfx_ffi.so.0_binary_for_qemu",
+ "aarch64_linux_gnu_libunwind.so.1_binary_for_qemu",
+ "aarch64_linux_gnu_libvirglrenderer.so.1_binary_for_qemu",
+ "aarch64_linux_gnu_libz.so.1_binary_for_qemu",
+ "aarch64_linux_gnu_qemu-system-aarch64_binary_for_qemu",
+ "aarch64_linux_gnu_qemu-system-riscv64_binary_for_qemu",
+ "aarch64_linux_gnu_qemu-system-x86_64_binary_for_qemu",
+]
+// End of generated qemu_aarch64_linux_gnu_binary
+
+// Start of generated qemu_aarch64_linux_gnu_resource
+// Generated by gen_android_bp.py
+qemu_aarch64_linux_gnu_resource = [
+ "aarch64_efi-virtio.rom_resource_for_qemu",
+ "aarch64_en-us_resource_for_qemu",
+ "aarch64_opensbi-riscv64-generic-fw_dynamic.bin_resource_for_qemu",
+]
+// End of generated qemu_aarch64_linux_gnu_resource
+
// Start of generated qemu_x86_64_linux_gnu_binary
// Generated by gen_android_bp.py
qemu_x86_64_linux_gnu_binary = [
@@ -247,7 +274,7 @@ cvd_host_aarch64_crosvm = [
"aarch64_linux_gnu_libwayland_client.so.0_for_crosvm",
]
-cvd_host_aarch64 = cvd_host_aarch64_crosvm + cvd_host_aarch64_graphics_detector
+cvd_host_aarch64 = cvd_host_aarch64_crosvm + cvd_host_aarch64_graphics_detector + qemu_aarch64_linux_gnu_binary
cvd_host_seccomp_policy_x86_64 = [
"9p_device.policy_x86_64",
@@ -428,7 +455,7 @@ cvd_host_package_customization {
deps: cvd_host_aarch64,
multilib: {
common: {
- deps: cvd_host_seccomp_policy_aarch64,
+ deps: cvd_host_seccomp_policy_aarch64 + qemu_aarch64_linux_gnu_resource,
},
},
},
diff --git a/common/libs/utils/files.cpp b/common/libs/utils/files.cpp
index 5fa1e6ecf..0f9f93ec1 100644
--- a/common/libs/utils/files.cpp
+++ b/common/libs/utils/files.cpp
@@ -52,6 +52,7 @@
#include <numeric>
#include <ostream>
#include <ratio>
+#include <regex>
#include <string>
#include <vector>
@@ -663,6 +664,57 @@ Result<void> WaitForUnixSocket(const std::string& path, int timeoutSec) {
return CF_ERR("This shouldn't be executed");
}
+
+Result<void> WaitForUnixSocketListeningWithoutConnect(const std::string& path,
+ int timeoutSec) {
+ const auto targetTime =
+ std::chrono::system_clock::now() + std::chrono::seconds(timeoutSec);
+
+ CF_EXPECT(WaitForFile(path, timeoutSec),
+ "Waiting for socket path creation failed");
+ CF_EXPECT(FileIsSocket(path), "Specified path is not a socket");
+
+ std::regex socket_state_regex("TST=(.*)");
+
+ while (true) {
+ const auto currentTime = std::chrono::system_clock::now();
+
+ if (currentTime >= targetTime) {
+ return CF_ERR("Timed out");
+ }
+
+ Command lsof("lsof");
+ lsof.AddParameter(/*"format"*/ "-F", /*"connection state"*/ "TST");
+ lsof.AddParameter(path);
+ std::string lsof_out;
+ std::string lsof_err;
+ int rval =
+ RunWithManagedStdio(std::move(lsof), nullptr, &lsof_out, &lsof_err);
+ if (rval != 0) {
+ return CF_ERR("Failed to run `lsof`, stderr: " << lsof_err);
+ }
+
+ LOG(DEBUG) << "lsof stdout:" << lsof_out;
+
+ std::smatch socket_state_match;
+ if (!std::regex_search(lsof_out, socket_state_match, socket_state_regex)) {
+ return CF_ERR("Failed to find state in `lsof` stdout: " << lsof_out);
+ }
+ if (socket_state_match.size() != 2) {
+ return CF_ERR(
+ "Unexpected number of matches in `lsof` stdout: " << lsof_out);
+ }
+
+ const std::string& socket_state = socket_state_match[1];
+ if (socket_state == "LISTEN") {
+ return {};
+ }
+
+ sched_yield();
+ }
+
+ return CF_ERR("This shouldn't be executed");
+}
#endif
namespace {
diff --git a/common/libs/utils/files.h b/common/libs/utils/files.h
index cf13dea72..6e423cda4 100644
--- a/common/libs/utils/files.h
+++ b/common/libs/utils/files.h
@@ -84,6 +84,8 @@ Result<void> WalkDirectory(
#ifdef __linux__
Result<void> WaitForFile(const std::string& path, int timeoutSec);
Result<void> WaitForUnixSocket(const std::string& path, int timeoutSec);
+Result<void> WaitForUnixSocketListeningWithoutConnect(const std::string& path,
+ int timeoutSec);
#endif
// parameter to EmulateAbsolutePath
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index c1e8b8767..a65f47fbf 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -134,7 +134,7 @@ DEFINE_vec(use_random_serial, fmt::format("{}", CF_DEFAULTS_USE_RANDOM_SERIAL),
DEFINE_vec(vm_manager, CF_DEFAULTS_VM_MANAGER,
"What virtual machine manager to use, one of {qemu_cli, crosvm}");
DEFINE_vec(gpu_mode, CF_DEFAULTS_GPU_MODE,
- "What gpu configuration to use, one of {auto, drm_virgl, "
+ "What gpu configuration to use, one of {auto, custom, drm_virgl, "
"gfxstream, gfxstream_guest_angle, "
"gfxstream_guest_angle_host_swiftshader, guest_swiftshader}");
DEFINE_vec(gpu_vhost_user_mode,
@@ -155,6 +155,22 @@ DEFINE_vec(
"be a semicolon separated list of \"<feature name>:[enabled|disabled]\""
"pairs.");
+DEFINE_vec(gpu_context_types, CF_DEFAULTS_GPU_CONTEXT_TYPES,
+ "A colon separated list of virtio-gpu context types. Only valid "
+ "with --gpu_mode=custom."
+ " For example \"--gpu_context_types=cross_domain:gfxstream\"");
+
+DEFINE_vec(
+ guest_vulkan_driver, CF_DEFAULTS_GUEST_VULKAN_DRIVER,
+ "Vulkan driver to use with Cuttlefish. Android VMs require specifying "
+ "this at boot time. Only valid with --gpu_mode=custom. "
+ "For example \"--guest_vulkan_driver=ranchu\"");
+
+DEFINE_vec(
+ frames_socket_path, CF_DEFAULTS_FRAME_SOCKET_PATH,
+ "Frame socket path to use when launching a VM "
+ "For example, \"--frames_socket_path=${XDG_RUNTIME_DIR}/wayland-0\"");
+
DEFINE_vec(use_allocd, CF_DEFAULTS_USE_ALLOCD?"true":"false",
"Acquire static resources from the resource allocator daemon.");
DEFINE_vec(
@@ -435,6 +451,9 @@ DEFINE_vec(mte, fmt::format("{}", CF_DEFAULTS_MTE), "Enable MTE");
DEFINE_vec(enable_audio, fmt::format("{}", CF_DEFAULTS_ENABLE_AUDIO),
"Whether to play or capture audio");
+DEFINE_vec(enable_usb, fmt::format("{}", CF_DEFAULTS_ENABLE_USB),
+ "Whether to allow USB passthrough on the device");
+
DEFINE_vec(camera_server_port, std::to_string(CF_DEFAULTS_CAMERA_SERVER_PORT),
"camera vsock port");
@@ -524,7 +543,7 @@ Result<std::string> GetAndroidInfoConfig(
CF_EXPECT(FileExists(android_info_file_path));
std::string android_info_contents = ReadFile(android_info_file_path);
- auto android_info_map = ParseMiscInfo(android_info_contents);
+ auto android_info_map = CF_EXPECT(ParseMiscInfo(android_info_contents));
CF_EXPECT(android_info_map.find(key) != android_info_map.end());
return android_info_map[key];
}
@@ -885,6 +904,14 @@ Result<void> CheckSnapshotCompatible(
"--enable_virtiofs=false");
/*
+ * TODO(khei@): delete this block once usb is supported
+ */
+ CF_EXPECTF(gflags::GetCommandLineFlagInfoOrDie("enable_usb").current_value ==
+ "false",
+ "--enable_usb should be false for snapshot, consider \"{}\"",
+ "--enable_usb=false");
+
+ /*
* TODO(kwstephenkim@): delete this block once 3D gpu mode snapshots are
* supported
*/
@@ -1076,6 +1103,7 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
modem_simulator_sim_type));
std::vector<bool> console_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(console));
std::vector<bool> enable_audio_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_audio));
+ std::vector<bool> enable_usb_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_usb));
std::vector<bool> start_gnss_proxy_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
start_gnss_proxy));
std::vector<bool> enable_bootanimation_vec =
@@ -1124,6 +1152,12 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
CF_EXPECT(GET_FLAG_STR_VALUE(gpu_vhost_user_mode));
std::vector<std::string> gpu_renderer_features_vec =
CF_EXPECT(GET_FLAG_STR_VALUE(gpu_renderer_features));
+ std::vector<std::string> gpu_context_types_vec =
+ CF_EXPECT(GET_FLAG_STR_VALUE(gpu_context_types));
+ std::vector<std::string> guest_vulkan_driver_vec =
+ CF_EXPECT(GET_FLAG_STR_VALUE(guest_vulkan_driver));
+ std::vector<std::string> frames_socket_path_vec =
+ CF_EXPECT(GET_FLAG_STR_VALUE(frames_socket_path));
std::vector<std::string> gpu_capture_binary_vec =
CF_EXPECT(GET_FLAG_STR_VALUE(gpu_capture_binary));
@@ -1192,8 +1226,8 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
if (FLAGS_casimir_instance_num > 0) {
casimir_instance_num = FLAGS_casimir_instance_num - 1;
}
- tmp_config_obj.set_casimir_nci_port(7100 + casimir_instance_num);
- tmp_config_obj.set_casimir_rf_port(8100 + casimir_instance_num);
+ tmp_config_obj.set_casimir_nci_port(7800 + casimir_instance_num);
+ tmp_config_obj.set_casimir_rf_port(7900 + casimir_instance_num);
LOG(DEBUG) << "casimir_instance_num: " << casimir_instance_num;
LOG(DEBUG) << "launch casimir: " << (FLAGS_casimir_instance_num <= 0);
@@ -1301,6 +1335,7 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
guest_configs[instance_index].hctr2_supported ? "hctr2" : "cts");
instance.set_use_allocd(use_allocd_vec[instance_index]);
instance.set_enable_audio(enable_audio_vec[instance_index]);
+ instance.set_enable_usb(enable_usb_vec[instance_index]);
instance.set_enable_gnss_grpc_proxy(start_gnss_proxy_vec[instance_index]);
instance.set_enable_bootanimation(enable_bootanimation_vec[instance_index]);
@@ -1513,8 +1548,8 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
const std::string gpu_mode = CF_EXPECT(ConfigureGpuSettings(
gpu_mode_vec[instance_index], gpu_vhost_user_mode_vec[instance_index],
gpu_renderer_features_vec[instance_index],
- vm_manager_vec[instance_index], guest_configs[instance_index],
- instance));
+ gpu_context_types_vec[instance_index], vm_manager_vec[instance_index],
+ guest_configs[instance_index], instance));
calculated_gpu_mode_vec[instance_index] = gpu_mode_vec[instance_index];
instance.set_restart_subprocesses(restart_subprocesses_vec[instance_index]);
@@ -1550,6 +1585,16 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
instance.set_enable_gpu_udmabuf(enable_gpu_udmabuf_vec[instance_index]);
+ instance.set_gpu_context_types(gpu_context_types_vec[instance_index]);
+ instance.set_guest_vulkan_driver(guest_vulkan_driver_vec[instance_index]);
+
+ if (!frames_socket_path_vec[instance_index].empty()) {
+ instance.set_frames_socket_path(frames_socket_path_vec[instance_index]);
+ } else {
+ instance.set_frames_socket_path(
+ const_instance.PerInstanceInternalUdsPath("frames.sock"));
+ }
+
// 1. Keep original code order SetCommandLineOptionWithMode("enable_sandbox")
// then set_enable_sandbox later.
// 2. SetCommandLineOptionWithMode condition: if gpu_mode or console,
@@ -1775,7 +1820,8 @@ Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
.ForEnvironment(environment_name);
CF_EXPECT(CheckSnapshotCompatible(
FLAGS_snapshot_compatible &&
- (tmp_config_obj.vm_manager() == CrosvmManager::name()),
+ (tmp_config_obj.vm_manager() == CrosvmManager::name()) &&
+ instance_nums.size() == 1,
calculated_gpu_mode_vec),
"The set of flags is incompatible with snapshot");
diff --git a/host/commands/assemble_cvd/flags_defaults.h b/host/commands/assemble_cvd/flags_defaults.h
index 1fd1b168a..34d69b38b 100644
--- a/host/commands/assemble_cvd/flags_defaults.h
+++ b/host/commands/assemble_cvd/flags_defaults.h
@@ -141,6 +141,10 @@
#define CF_DEFAULTS_RECORD_SCREEN false
#define CF_DEFAULTS_GPU_CAPTURE_BINARY CF_DEFAULTS_DYNAMIC_STRING
#define CF_DEFAULTS_GPU_RENDERER_FEATURES ""
+#define CF_DEFAULTS_GPU_CONTEXT_TYPES \
+ "gfxstream-vulkan:cross-domain:gfxstream-composer"
+#define CF_DEFAULTS_GUEST_VULKAN_DRIVER "ranchu"
+#define CF_DEFAULTS_FRAME_SOCKET_PATH ""
#define CF_DEFAULTS_ENABLE_GPU_UDMABUF false
#define CF_DEFAULTS_ENABLE_GPU_VHOST_USER false
#define CF_DEFAULTS_DISPLAY0 CF_DEFAULTS_DYNAMIC_STRING
@@ -196,6 +200,9 @@
// Audio default parameters
#define CF_DEFAULTS_ENABLE_AUDIO true
+// USB Passhtrough default parameters
+#define CF_DEFAULTS_ENABLE_USB false
+
// Streaming default parameters
#define CF_DEFAULTS_START_WEBRTC false
#define CF_DEFAULTS_START_WEBRTC_SIG_SERVER true
diff --git a/host/commands/assemble_cvd/graphics_flags.cc b/host/commands/assemble_cvd/graphics_flags.cc
index 72a4c8eb4..e5e7e4424 100644
--- a/host/commands/assemble_cvd/graphics_flags.cc
+++ b/host/commands/assemble_cvd/graphics_flags.cc
@@ -39,6 +39,7 @@ namespace {
enum class RenderingMode {
kNone,
+ kCustom,
kGuestSwiftShader,
kGfxstream,
kGfxstreamGuestAngle,
@@ -63,6 +64,9 @@ Result<RenderingMode> GetRenderingMode(const std::string& mode) {
if (mode == std::string(kGpuModeGuestSwiftshader)) {
return RenderingMode::kGuestSwiftShader;
}
+ if (mode == std::string(kGpuModeCustom)) {
+ return RenderingMode::kCustom;
+ }
if (mode == std::string(kGpuModeNone)) {
return RenderingMode::kNone;
}
@@ -232,7 +236,7 @@ Result<std::string> SelectGpuMode(
const GuestConfig& guest_config,
const gfxstream::proto::GraphicsAvailability& graphics_availability) {
if (gpu_mode_arg != kGpuModeAuto && gpu_mode_arg != kGpuModeDrmVirgl &&
- gpu_mode_arg != kGpuModeGfxstream &&
+ gpu_mode_arg != kGpuModeCustom && gpu_mode_arg != kGpuModeGfxstream &&
gpu_mode_arg != kGpuModeGfxstreamGuestAngle &&
gpu_mode_arg != kGpuModeGfxstreamGuestAngleHostSwiftShader &&
gpu_mode_arg != kGpuModeGuestSwiftshader &&
@@ -256,8 +260,8 @@ Result<std::string> SelectGpuMode(
LOG(INFO) << "GPU auto mode: detected prerequisites for accelerated "
<< "rendering support.";
- if (vm_manager == vm_manager::QemuManager::name() && !UseQemu8()) {
- LOG(INFO) << "Not using QEMU8: selecting guest swiftshader";
+ if (vm_manager == vm_manager::QemuManager::name() && !UseQemuPrebuilt()) {
+ LOG(INFO) << "Not using QEMU prebuilt (QEMU 8+): selecting guest swiftshader";
return kGpuModeGuestSwiftshader;
} else if (!guest_config.gfxstream_supported) {
LOG(INFO) << "GPU auto mode: guest does not support gfxstream, "
@@ -286,8 +290,8 @@ Result<std::string> SelectGpuMode(
"--gpu_mode=auto or --gpu_mode=guest_swiftshader.";
}
- if (vm_manager == vm_manager::QemuManager::name() && !UseQemu8()) {
- LOG(INFO) << "Not using QEMU8: selecting guest swiftshader";
+ if (vm_manager == vm_manager::QemuManager::name() && !UseQemuPrebuilt()) {
+ LOG(INFO) << "Not using QEMU prebuilt (QEMU 8+): selecting guest swiftshader";
return kGpuModeGuestSwiftshader;
}
}
@@ -480,9 +484,13 @@ Result<void> SetGfxstreamFlags(
} // namespace
+static std::unordered_set<std::string> kSupportedGpuContexts{
+ "gfxstream-vulkan", "gfxstream-composer", "cross-domain", "magma"};
+
Result<std::string> ConfigureGpuSettings(
const std::string& gpu_mode_arg, const std::string& gpu_vhost_user_mode_arg,
- const std::string& gpu_renderer_features_arg, const std::string& vm_manager,
+ const std::string& gpu_renderer_features_arg,
+ std::string& gpu_context_types_arg, const std::string& vm_manager,
const GuestConfig& guest_config,
CuttlefishConfig::MutableInstanceSpecific& instance) {
#ifdef __APPLE__
@@ -525,6 +533,14 @@ Result<std::string> ConfigureGpuSettings(
guest_config, graphics_availability, instance));
}
+ if (gpu_mode == kGpuModeCustom) {
+ auto requested_types = android::base::Split(gpu_context_types_arg, ":");
+ for (const std::string& requested : requested_types) {
+ CF_EXPECT(kSupportedGpuContexts.count(requested) == 1,
+ "unsupported context type: " + requested);
+ }
+ }
+
const auto angle_features = CF_EXPECT(GetNeededAngleFeatures(
CF_EXPECT(GetRenderingMode(gpu_mode)), graphics_availability));
instance.set_gpu_angle_feature_overrides_enabled(
diff --git a/host/commands/assemble_cvd/graphics_flags.h b/host/commands/assemble_cvd/graphics_flags.h
index 04923e974..63a4df13e 100644
--- a/host/commands/assemble_cvd/graphics_flags.h
+++ b/host/commands/assemble_cvd/graphics_flags.h
@@ -26,7 +26,8 @@ namespace cuttlefish {
Result<std::string> ConfigureGpuSettings(
const std::string& gpu_mode_arg, const std::string& gpu_vhost_user_mode_arg,
- const std::string& gpu_renderer_features_arg, const std::string& vm_manager,
+ const std::string& gpu_renderer_features_arg,
+ std::string& gpu_context_types_arg, const std::string& vm_manager,
const GuestConfig& guest_config,
CuttlefishConfig::MutableInstanceSpecific& instance);
diff --git a/host/commands/assemble_cvd/misc_info.cc b/host/commands/assemble_cvd/misc_info.cc
index e96099c4d..292258b96 100644
--- a/host/commands/assemble_cvd/misc_info.cc
+++ b/host/commands/assemble_cvd/misc_info.cc
@@ -16,14 +16,26 @@
#include "misc_info.h"
#include <algorithm>
+#include <string>
+#include <vector>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include "common/libs/utils/contains.h"
+#include "common/libs/utils/result.h"
+
namespace cuttlefish {
+namespace {
+
+constexpr char kDynamicPartitions[] = "dynamic_partition_list";
+constexpr char kGoogleDynamicPartitions[] = "google_dynamic_partitions";
+constexpr char kSuperPartitionGroups[] = "super_partition_groups";
+
+} // namespace
-MiscInfo ParseMiscInfo(const std::string& misc_info_contents) {
+Result<MiscInfo> ParseMiscInfo(const std::string& misc_info_contents) {
auto lines = android::base::Split(misc_info_contents, "\n");
MiscInfo misc_info;
for (auto& line : lines) {
@@ -37,13 +49,13 @@ MiscInfo ParseMiscInfo(const std::string& misc_info_contents) {
continue;
}
// Not using android::base::Split here to only capture the first =
- auto key = android::base::Trim(line.substr(0, eq_pos));
- auto value = android::base::Trim(line.substr(eq_pos + 1));
- if (misc_info.find(key) != misc_info.end() && misc_info[key] != value) {
- LOG(ERROR) << "Duplicate key: \"" << key << "\". First value: \""
- << misc_info[key] << "\", Second value: \"" << value << "\"";
- return {};
- }
+ const auto key = android::base::Trim(line.substr(0, eq_pos));
+ const auto value = android::base::Trim(line.substr(eq_pos + 1));
+ const bool duplicate = Contains(misc_info, key) && misc_info[key] != value;
+ CF_EXPECTF(!duplicate,
+ "Duplicate key with different value. key:\"{}\", previous "
+ "value:\"{}\", this value:\"{}\"",
+ key, misc_info[key], value);
misc_info[key] = value;
}
return misc_info;
@@ -57,8 +69,6 @@ std::string WriteMiscInfo(const MiscInfo& misc_info) {
return out.str();
}
-static const std::string kDynamicPartitions = "dynamic_partition_list";
-
std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) {
auto value_it = info.find(kDynamicPartitions);
if (value_it == info.end()) {
@@ -73,10 +83,6 @@ std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) {
return components;
}
-static constexpr const char* kGoogleDynamicPartitions =
- "google_dynamic_partitions";
-static constexpr const char* kSuperPartitionGroups = "super_partition_groups";
-
bool SetSuperPartitionComponents(const std::vector<std::string>& components,
MiscInfo* misc_info) {
auto super_partition_groups = misc_info->find(kSuperPartitionGroups);
diff --git a/host/commands/assemble_cvd/misc_info.h b/host/commands/assemble_cvd/misc_info.h
index aa130bcc9..f832a4c5f 100644
--- a/host/commands/assemble_cvd/misc_info.h
+++ b/host/commands/assemble_cvd/misc_info.h
@@ -19,11 +19,13 @@
#include <string>
#include <vector>
+#include "common/libs/utils/result.h"
+
namespace cuttlefish {
using MiscInfo = std::map<std::string, std::string>;
-MiscInfo ParseMiscInfo(const std::string& file_contents);
+Result<MiscInfo> ParseMiscInfo(const std::string& file_contents);
std::string WriteMiscInfo(const MiscInfo& info);
std::vector<std::string> SuperPartitionComponents(const MiscInfo&);
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc
index 8f445310a..b59d163fb 100644
--- a/host/commands/assemble_cvd/super_image_mixer.cc
+++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -30,6 +30,7 @@
#include "common/libs/utils/archive.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 "host/commands/assemble_cvd/misc_info.h"
#include "host/libs/config/config_utils.h"
@@ -37,59 +38,8 @@
#include "host/libs/config/fetcher_config.h"
namespace cuttlefish {
-
-Result<bool> SuperImageNeedsRebuilding(const FetcherConfig& fetcher_config,
- const std::string& default_target_zip,
- const std::string& system_target_zip) {
- bool has_default_target_zip = false;
- bool has_system_target_zip = false;
- if (default_target_zip != "" &&
- default_target_zip != "unset") {
- has_default_target_zip = true;
- }
- if (system_target_zip != "" &&
- system_target_zip != "unset") {
- has_system_target_zip = true;
- }
- CF_EXPECT(has_default_target_zip == has_system_target_zip,
- "default_target_zip and system_target_zip "
- "flags must be specified together");
- // at this time, both should be the same, either true or false
- // therefore, I only check one variable
- if (has_default_target_zip) {
- return true;
- }
-
- bool has_default_build = false;
- bool has_system_build = false;
- for (const auto& file_iter : fetcher_config.get_cvd_files()) {
- if (file_iter.second.source == FileSource::DEFAULT_BUILD) {
- has_default_build = true;
- } else if (file_iter.second.source == FileSource::SYSTEM_BUILD) {
- has_system_build = true;
- }
- }
- return has_default_build && has_system_build;
-}
-
namespace {
-std::string TargetFilesZip(const FetcherConfig& fetcher_config,
- FileSource source) {
- for (const auto& file_iter : fetcher_config.get_cvd_files()) {
- const auto& file_path = file_iter.first;
- const auto& file_info = file_iter.second;
- if (file_info.source != source) {
- continue;
- }
- std::string expected_filename = "target_files-" + file_iter.second.build_id;
- if (file_path.find(expected_filename) != std::string::npos) {
- return file_path;
- }
- }
- return "";
-}
-
constexpr char kMiscInfoPath[] = "META/misc_info.txt";
constexpr std::array kVendorTargetImages = {
"IMAGES/boot.img",
@@ -115,6 +65,13 @@ constexpr std::array kVendorTargetBuildProps = {
"VENDOR/etc/build.prop",
};
+struct TargetFiles {
+ Archive vendor_zip;
+ Archive system_zip;
+ std::vector<std::string> vendor_contents;
+ std::vector<std::string> system_contents;
+};
+
void FindImports(Archive* archive, const std::string& build_prop_file) {
auto contents = archive->ExtractToMemory(build_prop_file);
auto lines = android::base::Split(contents, "\n");
@@ -126,119 +83,126 @@ void FindImports(Archive* archive, const std::string& build_prop_file) {
}
}
-Result<void> CombineTargetZipFiles(const std::string& default_target_zip,
- const std::string& system_target_zip,
- const std::string& output_path) {
- Archive default_target_archive(default_target_zip);
- auto default_target_contents = default_target_archive.Contents();
- CF_EXPECT(default_target_contents.size() != 0,
- "Could not open " << default_target_zip);
-
- Archive system_target_archive(system_target_zip);
- auto system_target_contents = system_target_archive.Contents();
- CF_EXPECT(system_target_contents.size() != 0,
- "Could not open " << system_target_zip);
-
- CF_EXPECT(
- mkdir(output_path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) >= 0,
- "Could not create directory " << output_path);
-
- std::string output_meta = output_path + "/META";
- CF_EXPECT(
- mkdir(output_meta.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) >= 0,
- "Could not create directory " << output_meta);
-
- CF_EXPECT(
- std::find(default_target_contents.begin(), default_target_contents.end(),
- kMiscInfoPath) != default_target_contents.end(),
- "Default target files zip does not have " << kMiscInfoPath);
-
- CF_EXPECT(
- std::find(system_target_contents.begin(), system_target_contents.end(),
- kMiscInfoPath) != system_target_contents.end(),
- "System target files zip does not have " << kMiscInfoPath);
-
- const auto default_misc =
- ParseMiscInfo(default_target_archive.ExtractToMemory(kMiscInfoPath));
- CF_EXPECT(default_misc.size() != 0,
- "Could not read the default misc_info.txt file.");
-
- const auto system_misc =
- ParseMiscInfo(system_target_archive.ExtractToMemory(kMiscInfoPath));
- CF_EXPECT(system_misc.size() != 0,
- "Could not read the system misc_info.txt file.");
+bool IsTargetFilesImage(const std::string& filename) {
+ return android::base::StartsWith(filename, "IMAGES/") &&
+ android::base::EndsWith(filename, ".img");
+}
+
+bool IsTargetFilesBuildProp(const std::string& filename) {
+ return android::base::EndsWith(filename, "build.prop");
+}
+
+Result<TargetFiles> GetTargetFiles(const std::string& vendor_zip_path,
+ const std::string& system_zip_path) {
+ auto result = TargetFiles{
+ .vendor_zip = Archive(vendor_zip_path),
+ .system_zip = Archive(system_zip_path),
+ };
+ result.vendor_contents = result.vendor_zip.Contents();
+ result.system_contents = result.system_zip.Contents();
+ CF_EXPECTF(!result.vendor_contents.empty(), "Could not open {}",
+ vendor_zip_path);
+ CF_EXPECTF(!result.system_contents.empty(), "Could not open {}",
+ system_zip_path);
+ return result;
+}
+
+Result<void> CombineMiscInfo(TargetFiles& target_files,
+ const std::string& misc_output_path) {
+ CF_EXPECTF(Contains(target_files.vendor_contents, kMiscInfoPath),
+ "Default target files zip does not contain {}", kMiscInfoPath);
+ CF_EXPECTF(Contains(target_files.system_contents, kMiscInfoPath),
+ "System target files zip does not contain {}", kMiscInfoPath);
+
+ const MiscInfo default_misc = CF_EXPECT(
+ ParseMiscInfo(target_files.vendor_zip.ExtractToMemory(kMiscInfoPath)));
+ const MiscInfo system_misc = CF_EXPECT(
+ ParseMiscInfo(target_files.system_zip.ExtractToMemory(kMiscInfoPath)));
auto output_misc = default_misc;
auto system_super_partitions = SuperPartitionComponents(system_misc);
// Ensure specific skipped partitions end up in the misc_info.txt
for (auto partition :
{"odm", "odm_dlkm", "vendor", "vendor_dlkm", "system_dlkm"}) {
- if (std::find(system_super_partitions.begin(), system_super_partitions.end(),
- partition) == system_super_partitions.end()) {
+ if (!Contains(system_super_partitions, partition)) {
system_super_partitions.push_back(partition);
}
}
CF_EXPECT(SetSuperPartitionComponents(system_super_partitions, &output_misc),
"Failed to update super partitions components for misc_info");
- auto misc_output_path = output_path + "/" + kMiscInfoPath;
- SharedFD misc_output_file =
- SharedFD::Creat(misc_output_path.c_str(), 0644);
+ SharedFD misc_output_file = SharedFD::Creat(misc_output_path.c_str(), 0644);
CF_EXPECT(misc_output_file->IsOpen(), "Failed to open output misc file: "
<< misc_output_file->StrError());
CF_EXPECT(WriteAll(misc_output_file, WriteMiscInfo(output_misc)) >= 0,
"Failed to write output misc file contents: "
<< misc_output_file->StrError());
+ return {};
+}
- for (const auto& name : default_target_contents) {
- if (!android::base::StartsWith(name, "IMAGES/")) {
- continue;
- } else if (!android::base::EndsWith(name, ".img")) {
+Result<void> ExtractTargetFiles(TargetFiles& target_files,
+ const std::string& combined_output_path) {
+ for (const auto& name : target_files.vendor_contents) {
+ if (!IsTargetFilesImage(name)) {
continue;
} else if (!Contains(kVendorTargetImages, name)) {
continue;
}
- LOG(INFO) << "Writing " << name;
- CF_EXPECT(default_target_archive.ExtractFiles({name}, output_path),
- "Failed to extract " << name << " from the default target zip");
+ LOG(INFO) << "Writing " << name << " from vendor target";
+ CF_EXPECT(
+ target_files.vendor_zip.ExtractFiles({name}, combined_output_path),
+ "Failed to extract " << name << " from the vendor target zip");
}
- for (const auto& name : default_target_contents) {
- if (!android::base::EndsWith(name, "build.prop")) {
+ for (const auto& name : target_files.vendor_contents) {
+ if (!IsTargetFilesBuildProp(name)) {
continue;
} else if (!Contains(kVendorTargetBuildProps, name)) {
continue;
}
- FindImports(&default_target_archive, name);
- LOG(INFO) << "Writing " << name;
- CF_EXPECT(default_target_archive.ExtractFiles({name}, output_path),
- "Failed to extract " << name << " from the default target zip");
+ FindImports(&target_files.vendor_zip, name);
+ LOG(INFO) << "Writing " << name << " from vendor target";
+ CF_EXPECT(
+ target_files.vendor_zip.ExtractFiles({name}, combined_output_path),
+ "Failed to extract " << name << " from the vendor target zip");
}
- for (const auto& name : system_target_contents) {
- if (!android::base::StartsWith(name, "IMAGES/")) {
- continue;
- } else if (!android::base::EndsWith(name, ".img")) {
+ for (const auto& name : target_files.system_contents) {
+ if (!IsTargetFilesImage(name)) {
continue;
} else if (Contains(kVendorTargetImages, name)) {
continue;
}
- LOG(INFO) << "Writing " << name;
- CF_EXPECT(system_target_archive.ExtractFiles({name}, output_path),
- "Failed to extract " << name << " from the system target zip");
+ LOG(INFO) << "Writing " << name << " from system target";
+ CF_EXPECT(
+ target_files.system_zip.ExtractFiles({name}, combined_output_path),
+ "Failed to extract " << name << " from the system target zip");
}
- for (const auto& name : system_target_contents) {
- if (!android::base::EndsWith(name, "build.prop")) {
+ for (const auto& name : target_files.system_contents) {
+ if (!IsTargetFilesBuildProp(name)) {
continue;
} else if (Contains(kVendorTargetBuildProps, name)) {
continue;
}
- FindImports(&system_target_archive, name);
- LOG(INFO) << "Writing " << name;
- CF_EXPECT(system_target_archive.ExtractFiles({name}, output_path),
- "Failed to extract " << name << " from the default target zip");
+ FindImports(&target_files.system_zip, name);
+ LOG(INFO) << "Writing " << name << " from system target";
+ CF_EXPECT(
+ target_files.system_zip.ExtractFiles({name}, combined_output_path),
+ "Failed to extract " << name << " from the system target zip");
}
+ return {};
+}
+Result<void> CombineTargetZipFiles(const std::string& vendor_zip_path,
+ const std::string& system_zip_path,
+ const std::string& output_path) {
+ CF_EXPECT(EnsureDirectoryExists(output_path));
+ CF_EXPECT(EnsureDirectoryExists(output_path + "/META"));
+ auto target_files =
+ CF_EXPECT(GetTargetFiles(vendor_zip_path, system_zip_path));
+ CF_EXPECT(ExtractTargetFiles(target_files, output_path));
+ const auto misc_output_path = output_path + "/" + kMiscInfoPath;
+ CF_EXPECT(CombineMiscInfo(target_files, misc_output_path));
return {};
}
@@ -258,6 +222,22 @@ bool BuildSuperImage(const std::string& combined_target_zip,
}) == 0;
}
+std::string TargetFilesZip(const FetcherConfig& fetcher_config,
+ FileSource source) {
+ for (const auto& file_iter : fetcher_config.get_cvd_files()) {
+ const auto& file_path = file_iter.first;
+ const auto& file_info = file_iter.second;
+ if (file_info.source != source) {
+ continue;
+ }
+ std::string expected_filename = "target_files-" + file_iter.second.build_id;
+ if (file_path.find(expected_filename) != std::string::npos) {
+ return file_path;
+ }
+ }
+ return "";
+}
+
Result<void> RebuildSuperImage(const FetcherConfig& fetcher_config,
const CuttlefishConfig& config,
const std::string& output_path) {
@@ -319,6 +299,38 @@ class SuperImageRebuilderImpl : public SuperImageRebuilder {
} // namespace
+Result<bool> SuperImageNeedsRebuilding(const FetcherConfig& fetcher_config,
+ const std::string& default_target_zip,
+ const std::string& system_target_zip) {
+ bool has_default_target_zip = false;
+ bool has_system_target_zip = false;
+ if (default_target_zip != "" && default_target_zip != "unset") {
+ has_default_target_zip = true;
+ }
+ if (system_target_zip != "" && system_target_zip != "unset") {
+ has_system_target_zip = true;
+ }
+ CF_EXPECT(has_default_target_zip == has_system_target_zip,
+ "default_target_zip and system_target_zip "
+ "flags must be specified together");
+ // at this time, both should be the same, either true or false
+ // therefore, I only check one variable
+ if (has_default_target_zip) {
+ return true;
+ }
+
+ bool has_default_build = false;
+ bool has_system_build = false;
+ for (const auto& file_iter : fetcher_config.get_cvd_files()) {
+ if (file_iter.second.source == FileSource::DEFAULT_BUILD) {
+ has_default_build = true;
+ } else if (file_iter.second.source == FileSource::SYSTEM_BUILD) {
+ has_system_build = true;
+ }
+ }
+ return has_default_build && has_system_build;
+}
+
fruit::Component<fruit::Required<const FetcherConfig, const CuttlefishConfig,
const CuttlefishConfig::InstanceSpecific>,
SuperImageRebuilder>
@@ -328,4 +340,4 @@ SuperImageRebuilderComponent() {
.addMultibinding<SetupFeature, SuperImageRebuilder>();
}
-} // namespace cuttlefish
+} // namespace cuttlefish
diff --git a/host/commands/logcat_receiver/main.cpp b/host/commands/logcat_receiver/main.cpp
index d7c9dbc94..3e08f750a 100644
--- a/host/commands/logcat_receiver/main.cpp
+++ b/host/commands/logcat_receiver/main.cpp
@@ -64,7 +64,6 @@ int main(int argc, char** argv) {
auto logcat_file =
cuttlefish::SharedFD::Open(path.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0666);
- bool first_iter = true;
// Server loop
while (true) {
char buff[1024];
@@ -74,35 +73,9 @@ int main(int argc, char** argv) {
break;
}
auto written = cuttlefish::WriteAll(logcat_file, buff, read);
- CHECK(written == read)
- << "Error writing to log file: " << logcat_file->StrError()
- << ". This is unrecoverable.";
- if (first_iter) {
- first_iter = false;
- if (cuttlefish::IsRestoring(*config)) {
- cuttlefish::SharedFD restore_pipe = cuttlefish::SharedFD::Open(
- instance.restore_pipe_name().c_str(), O_WRONLY);
- if (!restore_pipe->IsOpen()) {
- LOG(ERROR) << "Error opening restore pipe: "
- << restore_pipe->StrError();
- return 2;
- }
- cuttlefish::SharedFD restore_adbd_pipe = cuttlefish::SharedFD::Open(
- instance.restore_adbd_pipe_name().c_str(), O_WRONLY);
- if (!restore_adbd_pipe->IsOpen()) {
- LOG(ERROR) << "Error opening restore pipe: "
- << restore_adbd_pipe->StrError();
- return 2;
- }
-
- CHECK(cuttlefish::WriteAll(restore_pipe, "1") == 1)
- << "Error writing to restore pipe: " << restore_pipe->StrError()
- << ". This is unrecoverable.";
- CHECK(cuttlefish::WriteAll(restore_adbd_pipe, "2") == 1)
- << "Error writing to adbd restore pipe: "
- << restore_adbd_pipe->StrError() << ". This is unrecoverable.";
- }
- }
+ CHECK(written == read) << "Error writing to log file: "
+ << logcat_file->StrError()
+ << ". This is unrecoverable.";
}
logcat_file->Close();
diff --git a/host/commands/run_cvd/boot_state_machine.cc b/host/commands/run_cvd/boot_state_machine.cc
index 67060e07a..242c0a5e3 100644
--- a/host/commands/run_cvd/boot_state_machine.cc
+++ b/host/commands/run_cvd/boot_state_machine.cc
@@ -43,72 +43,47 @@ namespace {
// Forks run_cvd into a daemonized child process. The current process continues
// only until the child has signalled that the boot is finished.
//
-// How the child signals when the boot is finished depends on whether we are
-// restoring from a snapshot.
-//
-// * When booting normally, `DaemonizeLauncher` returns the write end of a
-// pipe. The child is expected to write a `RunnerExitCodes` into the pipe
-// when the boot finishes.
-// * When restoring from a snapshot, `DaemonizeLauncher` returns an invalid
-// `SharedFD`. The child is expected to write an arbitrary byte to the
-// instance's "restore_pipe" and then the parent assumes the restore was
-// successful.
-//
-// We should consider unifying these two types of pipes.
+// `DaemonizeLauncher` returns the write end of a pipe. The child is expected
+// to write a `RunnerExitCodes` into the pipe when the boot finishes.
Result<SharedFD> DaemonizeLauncher(const CuttlefishConfig& config) {
auto instance = config.ForDefaultInstance();
- SharedFD read_end, write_end, restore_pipe_read;
- if (IsRestoring(config)) {
- restore_pipe_read =
- CF_EXPECT(SharedFD::Fifo(instance.restore_pipe_name(), 0600),
- "Unable to create restore fifo");
- } else {
- CF_EXPECT(SharedFD::Pipe(&read_end, &write_end), "Unable to create pipe");
- }
+ SharedFD read_end, write_end;
+ CF_EXPECT(SharedFD::Pipe(&read_end, &write_end), "Unable to create pipe");
auto pid = fork();
if (pid) {
// Explicitly close here, otherwise we may end up reading forever if the
// child process dies.
write_end->Close();
RunnerExitCodes exit_code;
- if (IsRestoring(config)) {
- if (!restore_pipe_read->IsOpen()) {
- LOG(ERROR) << "Error opening restore pipe: "
- << restore_pipe_read->StrError();
- std::exit(RunnerExitCodes::kDaemonizationError);
- }
- // Try to read from restore pipe. IF successfully reads, that means logcat
- // has started, and the VM has resumed. Exit the thread.
- char buff[1];
- auto read = restore_pipe_read->Read(buff, 1);
- if (read <= 0) {
- LOG(ERROR) << "Could not read restore pipe: "
- << restore_pipe_read->StrError();
- std::exit(RunnerExitCodes::kDaemonizationError);
- }
- exit_code = RunnerExitCodes::kSuccess;
- LOG(INFO) << "Virtual device restored successfully";
- std::exit(exit_code);
- }
auto bytes_read = read_end->Read(&exit_code, sizeof(exit_code));
if (bytes_read != sizeof(exit_code)) {
LOG(ERROR) << "Failed to read a complete exit code, read " << bytes_read
<< " bytes only instead of the expected " << sizeof(exit_code);
exit_code = RunnerExitCodes::kPipeIOError;
} else if (exit_code == RunnerExitCodes::kSuccess) {
- LOG(INFO) << "Virtual device booted successfully";
+ if (IsRestoring(config)) {
+ LOG(INFO) << "Virtual device restored successfully";
+ } else {
+ LOG(INFO) << "Virtual device booted successfully";
+ }
} else if (exit_code == RunnerExitCodes::kVirtualDeviceBootFailed) {
- LOG(ERROR) << "Virtual device failed to boot";
+ if (IsRestoring(config)) {
+ LOG(ERROR) << "Virtual device failed to restore";
+ } else {
+ LOG(ERROR) << "Virtual device failed to boot";
+ }
if (!instance.fail_fast()) {
LOG(ERROR) << "Device has been left running for debug";
}
} else {
LOG(ERROR) << "Unexpected exit code: " << exit_code;
}
- if (exit_code == RunnerExitCodes::kSuccess) {
- LOG(INFO) << kBootCompletedMessage;
- } else {
- LOG(INFO) << kBootFailedMessage;
+ if (!IsRestoring(config)) {
+ if (exit_code == RunnerExitCodes::kSuccess) {
+ LOG(INFO) << kBootCompletedMessage;
+ } else {
+ LOG(INFO) << kBootFailedMessage;
+ }
}
std::exit(exit_code);
} else {
@@ -145,12 +120,8 @@ Result<SharedFD> DaemonizeLauncher(const CuttlefishConfig& config) {
std::exit(RunnerExitCodes::kDaemonizationError);
}
- if (IsRestoring(config)) {
- return {};
- } else {
- read_end->Close();
- return write_end;
- }
+ read_end->Close();
+ return write_end;
}
}
@@ -183,11 +154,15 @@ Result<SharedFD> ProcessLeader(
class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
public:
INJECT(
- CvdBootStateMachine(AutoSetup<ProcessLeader>::Type& process_leader,
+ CvdBootStateMachine(const CuttlefishConfig& config,
+ AutoSetup<ProcessLeader>::Type& process_leader,
KernelLogPipeProvider& kernel_log_pipe_provider,
+ const vm_manager::VmManager& vm_manager,
const CuttlefishConfig::InstanceSpecific& instance))
- : process_leader_(process_leader),
+ : config_(config),
+ process_leader_(process_leader),
kernel_log_pipe_provider_(kernel_log_pipe_provider),
+ vm_manager_(vm_manager),
instance_(instance),
state_(kBootStarted) {}
@@ -200,6 +175,9 @@ class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
if (boot_event_handler_.joinable()) {
boot_event_handler_.join();
}
+ if (restore_complete_handler_.joinable()) {
+ restore_complete_handler_.join();
+ }
}
// SetupFeature
@@ -228,12 +206,48 @@ class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
SharedFD boot_events_pipe = kernel_log_pipe_provider_.KernelLogPipe();
CF_EXPECTF(boot_events_pipe->IsOpen(), "Could not get boot events pipe: {}",
boot_events_pipe->StrError());
- boot_event_handler_ = std::thread(
- [this, boot_events_pipe]() { ThreadLoop(boot_events_pipe); });
+
+ SharedFD restore_complete_pipe, restore_complete_pipe_write;
+ if (IsRestoring(config_)) {
+ CF_EXPECT(
+ SharedFD::Pipe(&restore_complete_pipe, &restore_complete_pipe_write),
+ "unable to create pipe");
+
+ // Unlike `boot_event_handler_`, this doesn't support graceful shutdown,
+ // it blocks until it finishes its work.
+ restore_complete_handler_ =
+ std::thread([this, restore_complete_pipe_write]() {
+ const auto result = vm_manager_.WaitForRestoreComplete();
+ CHECK(result.ok()) << "Failed to wait for restore complete: "
+ << result.error().FormatForEnv();
+
+ cuttlefish::SharedFD restore_adbd_pipe = cuttlefish::SharedFD::Open(
+ config_.ForDefaultInstance().restore_adbd_pipe_name().c_str(),
+ O_WRONLY);
+ CHECK(restore_adbd_pipe->IsOpen())
+ << "Error opening adbd restore pipe: "
+ << restore_adbd_pipe->StrError();
+ CHECK(cuttlefish::WriteAll(restore_adbd_pipe, "2") == 1)
+ << "Error writing to adbd restore pipe: "
+ << restore_adbd_pipe->StrError() << ". This is unrecoverable.";
+
+ // Done last so that adb is more likely to be ready.
+ CHECK(cuttlefish::WriteAll(restore_complete_pipe_write, "1") == 1)
+ << "Error writing to restore complete pipe: "
+ << restore_complete_pipe_write->StrError()
+ << ". This is unrecoverable.";
+ });
+ }
+
+ boot_event_handler_ =
+ std::thread([this, boot_events_pipe, restore_complete_pipe]() {
+ ThreadLoop(boot_events_pipe, restore_complete_pipe);
+ });
+
return {};
}
- void ThreadLoop(SharedFD boot_events_pipe) {
+ void ThreadLoop(SharedFD boot_events_pipe, SharedFD restore_complete_pipe) {
while (true) {
std::vector<PollSharedFd> poll_shared_fd = {
{
@@ -241,17 +255,26 @@ class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
.events = POLLIN | POLLHUP,
},
{
+ .fd = restore_complete_pipe,
+ .events = restore_complete_pipe->IsOpen()
+ ? (short)(POLLIN | POLLHUP)
+ : (short)0,
+ },
+ {
.fd = interrupt_fd_read_,
.events = POLLIN | POLLHUP,
- }};
+ },
+ };
int result = SharedFD::Poll(poll_shared_fd, -1);
- if (poll_shared_fd[1].revents & POLLIN) {
+ // interrupt_fd_read_
+ if (poll_shared_fd[2].revents & POLLIN) {
return;
}
if (result < 0) {
PLOG(FATAL) << "Failed to call Select";
return;
}
+ // boot_events_pipe
if (poll_shared_fd[0].revents & POLLHUP) {
LOG(ERROR) << "Failed to read a complete kernel log boot event.";
state_ |= kGuestBootFailed;
@@ -259,23 +282,46 @@ class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
break;
}
}
- if (!(poll_shared_fd[0].revents & POLLIN)) {
- continue;
+ if (poll_shared_fd[0].revents & POLLIN) {
+ auto sent_code = OnBootEvtReceived(boot_events_pipe);
+ if (sent_code) {
+ if (!BootCompleted()) {
+ if (!instance_.fail_fast()) {
+ LOG(ERROR) << "Device running, likely in a bad state";
+ break;
+ }
+ auto monitor_res = GetLauncherMonitorFromInstance(instance_, 5);
+ CHECK(monitor_res.ok()) << monitor_res.error().FormatForEnv();
+ auto fail_res = RunLauncherAction(
+ *monitor_res, LauncherAction::kFail, std::optional<int>());
+ CHECK(fail_res.ok()) << fail_res.error().FormatForEnv();
+ }
+ break;
+ }
}
- auto sent_code = OnBootEvtReceived(boot_events_pipe);
- if (sent_code) {
- if (!BootCompleted()) {
- if (!instance_.fail_fast()) {
- LOG(ERROR) << "Device running, likely in a bad state";
+ // restore_complete_pipe
+ if (poll_shared_fd[1].revents & POLLIN) {
+ char buff[1];
+ auto read = restore_complete_pipe->Read(buff, 1);
+ if (read <= 0) {
+ LOG(ERROR) << "Could not read restore pipe: "
+ << restore_complete_pipe->StrError();
+ state_ |= kGuestBootFailed;
+ if (MaybeWriteNotification()) {
break;
}
- auto monitor_res = GetLauncherMonitorFromInstance(instance_, 5);
- CHECK(monitor_res.ok()) << monitor_res.error().FormatForEnv();
- auto fail_res = RunLauncherAction(*monitor_res, LauncherAction::kFail,
- std::optional<int>());
- CHECK(fail_res.ok()) << fail_res.error().FormatForEnv();
}
- break;
+ state_ |= kGuestBootCompleted;
+ if (MaybeWriteNotification()) {
+ break;
+ }
+ }
+ if (poll_shared_fd[1].revents & POLLHUP) {
+ LOG(ERROR) << "restore_complete_pipe closed unexpectedly";
+ state_ |= kGuestBootFailed;
+ if (MaybeWriteNotification()) {
+ break;
+ }
}
}
}
@@ -325,11 +371,14 @@ class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
return BootCompleted() || (state_ & kGuestBootFailed);
}
+ const CuttlefishConfig& config_;
AutoSetup<ProcessLeader>::Type& process_leader_;
KernelLogPipeProvider& kernel_log_pipe_provider_;
+ const vm_manager::VmManager& vm_manager_;
const CuttlefishConfig::InstanceSpecific& instance_;
std::thread boot_event_handler_;
+ std::thread restore_complete_handler_;
SharedFD fg_launcher_pipe_;
SharedFD reboot_notification_;
SharedFD interrupt_fd_read_;
@@ -344,6 +393,7 @@ class CvdBootStateMachine : public SetupFeature, public KernelLogPipeConsumer {
fruit::Component<fruit::Required<const CuttlefishConfig, KernelLogPipeProvider,
const CuttlefishConfig::InstanceSpecific,
+ const vm_manager::VmManager,
AutoSetup<ValidateTapDevices>::Type>>
bootStateMachineComponent() {
return fruit::createComponent()
diff --git a/host/commands/run_cvd/boot_state_machine.h b/host/commands/run_cvd/boot_state_machine.h
index 04de24801..4b742ac4a 100644
--- a/host/commands/run_cvd/boot_state_machine.h
+++ b/host/commands/run_cvd/boot_state_machine.h
@@ -24,6 +24,7 @@ namespace cuttlefish {
fruit::Component<fruit::Required<const CuttlefishConfig, KernelLogPipeProvider,
const CuttlefishConfig::InstanceSpecific,
+ const vm_manager::VmManager,
AutoSetup<ValidateTapDevices>::Type>>
bootStateMachineComponent();
diff --git a/host/commands/run_cvd/server_loop_impl.cpp b/host/commands/run_cvd/server_loop_impl.cpp
index 8506245cf..61f1fa6bb 100644
--- a/host/commands/run_cvd/server_loop_impl.cpp
+++ b/host/commands/run_cvd/server_loop_impl.cpp
@@ -297,7 +297,6 @@ void ServerLoopImpl::DeleteFifos() {
instance_.console_in_pipe_name(),
instance_.console_out_pipe_name(),
instance_.logcat_pipe_name(),
- instance_.restore_pipe_name(),
instance_.PerInstanceInternalPath("keymaster_fifo_vm.in"),
instance_.PerInstanceInternalPath("keymaster_fifo_vm.out"),
instance_.PerInstanceInternalPath("keymint_fifo_vm.in"),
diff --git a/host/commands/start/main.cc b/host/commands/start/main.cc
index 1f5ca8d07..e0c035f9c 100644
--- a/host/commands/start/main.cc
+++ b/host/commands/start/main.cc
@@ -250,6 +250,7 @@ std::unordered_set<std::string> kBoolFlags = {
"console",
"enable_sandbox",
"enable_virtiofs",
+ "enable_usb",
"restart_subprocesses",
"enable_gpu_udmabuf",
"enable_gpu_vhost_user",
diff --git a/host/libs/config/config_utils.cpp b/host/libs/config/config_utils.cpp
index 9197877dc..c4fea49cc 100644
--- a/host/libs/config/config_utils.cpp
+++ b/host/libs/config/config_utils.cpp
@@ -24,8 +24,10 @@
#include <android-base/logging.h>
#include <android-base/strings.h>
+#include "common/libs/utils/contains.h"
#include "common/libs/utils/environment.h"
#include "host/libs/config/config_constants.h"
+#include "host/libs/config/cuttlefish_config.h"
namespace cuttlefish {
@@ -111,19 +113,17 @@ std::string HostBinaryDir() {
return DefaultHostArtifactsPath("bin");
}
-bool UseQemu8() {
+bool UseQemuPrebuilt() {
const std::string target_prod_str = StringFromEnv("TARGET_PRODUCT", "");
- if (HostArch() == Arch::X86_64 &&
- target_prod_str.find("arm") == std::string::npos) {
+ if (!Contains(target_prod_str, "arm")) {
return true;
}
-
return false;
}
std::string DefaultQemuBinaryDir() {
- if (UseQemu8()) {
- return HostBinaryDir();
+ if (UseQemuPrebuilt()) {
+ return HostBinaryDir() + "/" + HostArchStr() + "-linux-gnu/qemu";
}
return "/usr/bin";
}
@@ -140,6 +140,14 @@ std::string HostUsrSharePath(const std::string& binary_name) {
return DefaultHostArtifactsPath("usr/share/" + binary_name);
}
+std::string HostQemuBiosPath() {
+ if (UseQemuPrebuilt()) {
+ return DefaultHostArtifactsPath(
+ "usr/share/qemu/" + HostArchStr() + "-linux-gnu");
+ }
+ return "/usr/share/qemu";
+}
+
std::string DefaultGuestImagePath(const std::string& file_name) {
return (StringFromEnv("ANDROID_PRODUCT_OUT", StringFromEnv("HOME", "."))) +
file_name;
diff --git a/host/libs/config/config_utils.h b/host/libs/config/config_utils.h
index 8107f5e9b..b5058bb18 100644
--- a/host/libs/config/config_utils.h
+++ b/host/libs/config/config_utils.h
@@ -51,6 +51,7 @@ std::string DefaultHostArtifactsPath(const std::string& file);
std::string DefaultQemuBinaryDir();
std::string HostBinaryPath(const std::string& file);
std::string HostUsrSharePath(const std::string& file);
+std::string HostQemuBiosPath();
std::string DefaultGuestImagePath(const std::string& file);
std::string DefaultEnvironmentPath(const char* environment_key,
const char* default_value,
@@ -59,6 +60,6 @@ std::string DefaultEnvironmentPath(const char* environment_key,
// Whether the host supports qemu
bool HostSupportsQemuCli();
-// Whether to use QEMU8
-bool UseQemu8();
+// Whether to use our local QEMU prebuilt
+bool UseQemuPrebuilt();
}
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index ad65c9cbe..6de482552 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -50,6 +50,7 @@ const char* const kVhostUserVsockModeTrue = "true";
const char* const kVhostUserVsockModeFalse = "false";
const char* const kGpuModeAuto = "auto";
+const char* const kGpuModeCustom = "custom";
const char* const kGpuModeDrmVirgl = "drm_virgl";
const char* const kGpuModeGfxstream = "gfxstream";
const char* const kGpuModeGfxstreamGuestAngle = "gfxstream_guest_angle";
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 5881b2c91..71448ea97 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -376,7 +376,6 @@ class CuttlefishConfig {
std::string rotary_socket_path() const;
std::string keyboard_socket_path() const;
std::string switches_socket_path() const;
- std::string frames_socket_path() const;
std::string access_kregistry_path() const;
@@ -399,7 +398,6 @@ class CuttlefishConfig {
std::string gnss_out_pipe_name() const;
std::string logcat_pipe_name() const;
- std::string restore_pipe_name() const;
std::string restore_adbd_pipe_name() const;
std::string launcher_log_path() const;
@@ -560,6 +558,7 @@ class CuttlefishConfig {
bool enable_audio() const;
bool enable_gnss_grpc_proxy() const;
bool enable_bootanimation() const;
+ bool enable_usb() const;
std::vector<std::string> extra_bootconfig_args() const;
bool record_screen() const;
std::string gem5_debug_file() const;
@@ -602,6 +601,9 @@ class CuttlefishConfig {
std::string gpu_capture_binary() const;
std::string gpu_gfxstream_transport() const;
std::string gpu_renderer_features() const;
+ std::string gpu_context_types() const;
+ std::string guest_vulkan_driver() const;
+ std::string frames_socket_path() const;
std::string gpu_vhost_user_mode() const;
@@ -763,6 +765,7 @@ class CuttlefishConfig {
void set_pause_in_bootloader(bool pause_in_bootloader);
void set_run_as_daemon(bool run_as_daemon);
void set_enable_audio(bool enable);
+ void set_enable_usb(bool enable);
void set_enable_gnss_grpc_proxy(const bool enable_gnss_grpc_proxy);
void set_enable_bootanimation(const bool enable_bootanimation);
void set_extra_bootconfig_args(const std::string& extra_bootconfig_args);
@@ -809,6 +812,10 @@ class CuttlefishConfig {
void set_gpu_capture_binary(const std::string&);
void set_gpu_gfxstream_transport(const std::string& transport);
void set_gpu_renderer_features(const std::string& features);
+ void set_gpu_context_types(const std::string& context_types);
+ void set_guest_vulkan_driver(const std::string& driver);
+ void set_frames_socket_path(const std::string& driver);
+
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);
@@ -972,6 +979,7 @@ extern const char* const kVhostUserVsockModeFalse;
// GPU modes
extern const char* const kGpuModeAuto;
+extern const char* const kGpuModeCustom;
extern const char* const kGpuModeDrmVirgl;
extern const char* const kGpuModeGfxstream;
extern const char* const kGpuModeGfxstreamGuestAngle;
diff --git a/host/libs/config/cuttlefish_config_instance.cpp b/host/libs/config/cuttlefish_config_instance.cpp
index 1cc3c1f00..455f53af5 100644
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ b/host/libs/config/cuttlefish_config_instance.cpp
@@ -748,6 +748,24 @@ void CuttlefishConfig::MutableInstanceSpecific::set_gpu_renderer_features(
(*Dictionary())[kGpuRendererFeatures] = transport;
}
+static constexpr char kGpuContextTypes[] = "gpu_context_types";
+std::string CuttlefishConfig::InstanceSpecific::gpu_context_types() const {
+ return (*Dictionary())[kGpuContextTypes].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_gpu_context_types(
+ const std::string& context_types) {
+ (*Dictionary())[kGpuContextTypes] = context_types;
+}
+
+static constexpr char kVulkanDriver[] = "guest_vulkan_driver";
+std::string CuttlefishConfig::InstanceSpecific::guest_vulkan_driver() const {
+ return (*Dictionary())[kVulkanDriver].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_guest_vulkan_driver(
+ const std::string& driver) {
+ (*Dictionary())[kVulkanDriver] = driver;
+}
+
static constexpr char kRestartSubprocesses[] = "restart_subprocesses";
bool CuttlefishConfig::InstanceSpecific::restart_subprocesses() const {
return (*Dictionary())[kRestartSubprocesses].asBool();
@@ -824,6 +842,14 @@ void CuttlefishConfig::MutableInstanceSpecific::set_enable_bootanimation(
(*Dictionary())[kEnableBootAnimation] = enable_bootanimation;
}
+static constexpr char kEnableUsb[] = "enable_usb";
+void CuttlefishConfig::MutableInstanceSpecific::set_enable_usb(bool enable) {
+ (*Dictionary())[kEnableUsb] = enable;
+}
+bool CuttlefishConfig::InstanceSpecific::enable_usb() const {
+ return (*Dictionary())[kEnableUsb].asBool();
+}
+
static constexpr char kExtraBootconfigArgsInstanced[] = "extra_bootconfig_args";
std::vector<std::string>
CuttlefishConfig::InstanceSpecific::extra_bootconfig_args() const {
@@ -1161,10 +1187,6 @@ std::string CuttlefishConfig::InstanceSpecific::logcat_pipe_name() const {
return AbsolutePath(PerInstanceInternalPath("logcat-pipe"));
}
-std::string CuttlefishConfig::InstanceSpecific::restore_pipe_name() const {
- return AbsolutePath(PerInstanceInternalPath("restore-pipe"));
-}
-
std::string CuttlefishConfig::InstanceSpecific::restore_adbd_pipe_name() const {
return AbsolutePath(PerInstanceInternalPath("restore-pipe-adbd"));
}
@@ -1721,8 +1743,14 @@ std::string CuttlefishConfig::InstanceSpecific::switches_socket_path() const {
return PerInstanceInternalUdsPath("switches.sock");
}
+static constexpr char kFrameSockPath[] = "frame_sock_path";
+void CuttlefishConfig::MutableInstanceSpecific::set_frames_socket_path(
+ const std::string& frame_socket_path) {
+ (*Dictionary())[kFrameSockPath] = frame_socket_path;
+}
+
std::string CuttlefishConfig::InstanceSpecific::frames_socket_path() const {
- return PerInstanceInternalUdsPath("frames.sock");
+ return (*Dictionary())[kFrameSockPath].asString();
}
static constexpr char kWifiMacPrefix[] = "wifi_mac_prefix";
diff --git a/host/libs/screen_connector/screen_connector.h b/host/libs/screen_connector/screen_connector.h
index 634c7adf9..bc56cedf6 100644
--- a/host/libs/screen_connector/screen_connector.h
+++ b/host/libs/screen_connector/screen_connector.h
@@ -68,7 +68,9 @@ class ScreenConnector : public ScreenConnectorInfo,
}
auto instance = config->ForDefaultInstance();
std::unordered_set<std::string_view> valid_gpu_modes{
- cuttlefish::kGpuModeDrmVirgl, cuttlefish::kGpuModeGfxstream,
+ cuttlefish::kGpuModeCustom,
+ cuttlefish::kGpuModeDrmVirgl,
+ cuttlefish::kGpuModeGfxstream,
cuttlefish::kGpuModeGfxstreamGuestAngle,
cuttlefish::kGpuModeGfxstreamGuestAngleHostSwiftShader,
cuttlefish::kGpuModeGuestSwiftshader};
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index e190ffe87..899e39653 100644
--- a/host/libs/vm_manager/crosvm_manager.cpp
+++ b/host/libs/vm_manager/crosvm_manager.cpp
@@ -1,4 +1,4 @@
-/*
+/*crosvm
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -114,6 +114,17 @@ CrosvmManager::ConfigureGraphics(
{"androidboot.hardware.gltransport", gfxstream_transport},
{"androidboot.opengles.version", "196609"}, // OpenGL ES 3.1
};
+ } else if (instance.gpu_mode() == kGpuModeCustom) {
+ bootconfig_args = {
+ {"androidboot.cpuvulkan.version", "0"},
+ {"androidboot.hardware.gralloc", "minigbm"},
+ {"androidboot.hardware.hwcomposer", instance.hwcomposer()},
+ {"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.egl", "angle"},
+ {"androidboot.hardware.vulkan", instance.guest_vulkan_driver()},
+ {"androidboot.hardware.gltransport", "virtio-gpu-asg"},
+ {"androidboot.opengles.version", "196609"}, // OpenGL ES 3.1
+ };
} else if (instance.gpu_mode() == kGpuModeNone) {
return {};
} else {
@@ -201,12 +212,6 @@ Result<VhostUserDeviceCommands> BuildVhostUserGpu(
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 = CF_EXPECT(SharedFD::Fifo(gpu_device_logs_path, 0666));
@@ -307,6 +312,15 @@ Result<VhostUserDeviceCommands> BuildVhostUserGpu(
// Connect device to main crosvm:
gpu_device_cmd.Cmd().AddParameter("--socket=", gpu_device_socket_path);
+
+ main_crosvm_cmd->AddPrerequisite([gpu_device_socket_path]() -> Result<void> {
+#ifdef __linux__
+ return WaitForUnixSocketListeningWithoutConnect(gpu_device_socket_path,
+ /*timeoutSec=*/30);
+#else
+ return CF_ERR("Unhandled check if vhost user gpu ready.");
+#endif
+ });
main_crosvm_cmd->AddParameter(
"--vhost-user=gpu,pci-address=", gpu_pci_address,
",socket=", gpu_device_socket_path);
@@ -374,6 +388,10 @@ Result<void> ConfigureGpu(const CuttlefishConfig& config, Command* crosvm_cmd) {
crosvm_cmd->AddParameter(
"--gpu=context-types=gfxstream-vulkan:gfxstream-composer",
gpu_common_3d_string);
+ } else if (gpu_mode == kGpuModeCustom) {
+ const std::string gpu_context_types =
+ "--gpu=context-types=" + instance.gpu_context_types();
+ crosvm_cmd->AddParameter(gpu_context_types, gpu_common_string);
}
MaybeConfigureVulkanIcd(config, crosvm_cmd);
@@ -451,7 +469,9 @@ Result<std::vector<MonitorCommand>> CrosvmManager::StartCommands(
// Disable USB passthrough. It isn't needed for any key use cases and it is
// not compatible with crosvm suspend-resume support yet (b/266622743).
// TODO: Allow it to be turned back on using a flag.
- crosvm_cmd.Cmd().AddParameter("--no-usb");
+ if (!instance.enable_usb()) {
+ crosvm_cmd.Cmd().AddParameter("--no-usb");
+ }
crosvm_cmd.Cmd().AddParameter("--core-scheduling=false");
@@ -860,5 +880,32 @@ Result<std::vector<MonitorCommand>> CrosvmManager::StartCommands(
return commands;
}
+Result<void> CrosvmManager::WaitForRestoreComplete() const {
+ auto instance = CF_EXPECT(CuttlefishConfig::Get())->ForDefaultInstance();
+
+ // Wait for the control socket to exist. It is created early in crosvm's
+ // startup sequence, but the process may not even have been exec'd by CF at
+ // this point.
+ while (!FileExists(instance.CrosvmSocketPath())) {
+ usleep(50000); // 50 ms, arbitrarily chosen
+ }
+
+ // Ask crosvm to resume the VM. crosvm promises to not complete this command
+ // until the vCPUs are started (even if it was never suspended to begin
+ // with).
+ auto infop = CF_EXPECT(Execute(
+ std::vector<std::string>{
+ instance.crosvm_binary(),
+ "resume",
+ instance.CrosvmSocketPath(),
+ "--full",
+ },
+ SubprocessOptions(), WEXITED));
+ CF_EXPECT_EQ(infop.si_code, CLD_EXITED);
+ CF_EXPECTF(infop.si_status == 0, "crosvm resume returns non zero code {}",
+ infop.si_status);
+ return {};
+}
+
} // namespace vm_manager
} // namespace cuttlefish
diff --git a/host/libs/vm_manager/crosvm_manager.h b/host/libs/vm_manager/crosvm_manager.h
index a1433d2a2..cb119fefb 100644
--- a/host/libs/vm_manager/crosvm_manager.h
+++ b/host/libs/vm_manager/crosvm_manager.h
@@ -46,6 +46,8 @@ class CrosvmManager : public VmManager {
const CuttlefishConfig& config,
std::vector<VmmDependencyCommand*>& dependencyCommands) override;
+ Result<void> WaitForRestoreComplete() const override;
+
private:
static constexpr int kCrosvmVmResetExitCode = 32;
};
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index 26ff43628..0f300d41d 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -807,6 +807,9 @@ Result<std::vector<MonitorCommand>> QemuManager::StartCommands(
qemu_cmd.AddParameter("-device");
qemu_cmd.AddParameter("qemu-xhci,id=xhci");
+ qemu_cmd.AddParameter("-L");
+ qemu_cmd.AddParameter(HostQemuBiosPath());
+
if (is_riscv64) {
qemu_cmd.AddParameter("-kernel");
} else {
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index b3fa4be6c..29fb68a8e 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -101,6 +101,14 @@ class VmManager {
virtual Result<std::vector<MonitorCommand>> StartCommands(
const CuttlefishConfig& config,
std::vector<VmmDependencyCommand*>& dependencyCommands) = 0;
+
+ // Block until the restore work is finished and the guest is running. Only
+ // called if a snapshot is being restored.
+ //
+ // Must be thread safe.
+ virtual Result<void> WaitForRestoreComplete() const {
+ return CF_ERR("not implemented");
+ }
};
fruit::Component<fruit::Required<const CuttlefishConfig,
diff --git a/shared/auto/sepolicy/evs/hal_evs_default.te b/shared/auto/sepolicy/evs/hal_evs_default.te
index e60e2a3f2..16950040e 100644
--- a/shared/auto/sepolicy/evs/hal_evs_default.te
+++ b/shared/auto/sepolicy/evs/hal_evs_default.te
@@ -45,3 +45,7 @@ binder_call(hal_evs_default, mediaserver)
# Allow to use OMX service.
hal_client_domain(hal_evs_default, hal_omx)
hal_client_domain(hal_evs_default, hal_codec2)
+
+# Allow to interact with mediametrics
+allow hal_evs_default mediametrics_service:service_manager find;
+binder_call(hal_evs_default, mediametrics)
diff --git a/system_image/Android.bp b/system_image/Android.bp
index c04f00e3e..8df510752 100644
--- a/system_image/Android.bp
+++ b/system_image/Android.bp
@@ -149,6 +149,7 @@ android_system_image {
"bootanimation",
"bootctl",
"bootstat",
+ "boringssl_self_test",
"bpfloader",
"bu",
"bugreport_procdump",
@@ -262,12 +263,14 @@ android_system_image {
"libaaudio",
"libadbd_auth",
"libadbd_fs",
+ "libalarm_jni",
"libamidi",
"libandroid_runtime",
"libandroid_servers",
"libandroid",
"libandroidemu",
"libandroidfw",
+ "libartpalette-system",
"libasyncio",
"libasyncio",
"libaudio_aidl_conversion_common_ndk_cpp",
@@ -291,6 +294,7 @@ android_system_image {
"libaudioutils",
"libaudioutils",
"libbinder_ndk",
+ "libbinder_rpc_unstable",
"libbinder",
"libblas",
"libbootloader_message",
@@ -354,6 +358,8 @@ android_system_image {
"libhidcommand_jni",
"libhidlmemory",
"libhidlmemory",
+ "libhidltransport",
+ "libhwbinder",
"libincident",
"libinput",
"libinputflinger",
@@ -380,6 +386,7 @@ android_system_image {
"libnetd_client",
"libnetlink",
"libnetutils",
+ "libneuralnetworks_packageinfo",
"libnfc_nci_jni",
"libnl",
"libOpenglCodecCommon",
@@ -426,6 +433,7 @@ android_system_image {
"libsync",
"libsysutils",
"libtinyxml2",
+ "libtombstoned_client",
"libtracingproxy",
"libui",
"libuinputcommand_jni",
@@ -461,6 +469,7 @@ android_system_image {
"make_f2fs",
"mapper.minigbm",
"mdnsd",
+ "media_profiles_V1_0.dtd",
"mediacodec.policy",
"mediaextractor",
"mediametrics",
@@ -734,6 +743,7 @@ android_system_image {
"settaskprofile",
"settings",
"sfdo",
+ "sgdisk",
"sh",
"showmap",
"simpleperf_app_runner",
@@ -806,38 +816,6 @@ android_system_image {
"xml2abx",
"xtables.lock",
"ziptool",
- // TODO(b/321000103): uncomment when visibility option for partitions is introduced
- // "boringssl_self_test_vendor",
- // "boringssl_self_test",
- // "init_second_stage",
- // "libaecsw",
- // "libagc1sw",
- // "libagc2sw",
- // "libalarm_jni",
- // "libartpalette-system",
- // "libbassboostsw",
- // "libbinder_rpc_unstable",
- // "libbundleaidl",
- // "libdownmixaidl",
- // "libdynamicsprocessingaidl",
- // "libenvreverbsw",
- // "libequalizersw",
- // "libextensioneffect",
- // "libhapticgeneratoraidl",
- // "libhidltransport",
- // "libhwbinder",
- // "libloudnessenhanceraidl",
- // "libmdnssd",
- // "libmediametrics",
- // "libneuralnetworks_packageinfo",
- // "libnssw",
- // "libpreprocessingaidl",
- // "libpresetreverbsw",
- // "libreverbaidl",
- // "libvirtualizersw",
- // "libvisualizeraidl",
- // "libvolumesw",
- // "sgdisk",
],
multilib: {
common: {
@@ -853,6 +831,7 @@ android_system_image {
"androidx.camera.extensions.impl",
"androidx.window.extensions",
"androidx.window.sidecar",
+ "aosp_mainline_modules",
"BackupRestoreConfirmation",
"BasicDreams",
"BlockedNumberProvider",
@@ -875,15 +854,9 @@ android_system_image {
"CertInstaller",
"CFSatelliteService",
"charger_res_images",
- "com.android.adbd",
- "com.android.adservices",
"com.android.apex.cts.shim.v1_prebuilt",
- "com.android.appsearch",
"com.android.cellbroadcast",
"com.android.compos",
- "com.android.configinfrastructure",
- "com.android.devicelock",
- "com.android.extservices",
"com.android.future.usb.accessory",
"com.android.hardware.authsecret",
"com.android.hardware.biometrics.face.virtual",
@@ -894,6 +867,8 @@ android_system_image {
"com.android.hardware.dumpstate",
"com.android.hardware.gnss",
"com.android.hardware.input.processor",
+ "com.android.hardware.keymint.rust_cf_remote",
+ "com.android.hardware.keymint.rust_nonsecure",
"com.android.hardware.memtrack",
"com.android.hardware.net.nlinterceptor",
"com.android.hardware.neuralnetworks",
@@ -918,20 +893,9 @@ android_system_image {
"com.android.location.provider",
"com.android.media.remotedisplay.xml",
"com.android.media.remotedisplay",
- "com.android.media.swcodec",
- "com.android.media",
"com.android.mediadrm.signer",
- "com.android.mediaprovider",
- "com.android.neuralnetworks",
"com.android.nfc_extras",
- "com.android.os.statsd",
- "com.android.resolv",
- "com.android.rkpd",
"com.android.runtime",
- "com.android.scheduling",
- "com.android.tethering",
- "com.android.tzdata",
- "com.android.virt",
"com.google.cf.bt",
"com.google.cf.confirmationui",
"com.google.cf.health.storage",
@@ -964,7 +928,9 @@ android_system_image {
"ExternalStorageProvider",
"ExtShared",
"framework-graphics",
+ "framework-location",
"framework-minus-apex-install-dependencies",
+ "framework-nfc",
"framework-res",
"FusedLocation",
"fuseMedia.o",
@@ -985,6 +951,7 @@ android_system_image {
"LiveWallpapersPicker",
"llndk.libraries.txt",
"LocalTransport",
+ "lockagent",
"ManagedProvisioning",
"MediaProviderLegacy",
"messaging",
@@ -1037,29 +1004,18 @@ android_system_image {
"WallpaperBackup",
"WallpaperCropper",
"webview",
- // TODO(b/321000103): uncomment when visibility option for partitions is introduced
- // "com.android.art",
- // "com.android.btservices",
- // "com.android.conscrypt",
- // "com.android.healthfitness",
- // "com.android.ondevicepersonalization",
- // "com.android.permission",
- // "com.android.sdkext",
- // "com.android.uwb",
- // "framework-minus-apex",
],
},
lib32: {
deps: [
"android.hardware.audio.service",
- "mediaserver",
"drmserver",
+ "mediaserver",
],
},
lib64: {
deps: [
- // TODO(b/321000103): uncomment when visibility option for partitions is introduced
- // "boringssl_self_test",
+ "boringssl_self_test",
"libgsi",
"servicemanager",
],