aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-04-25 18:02:51 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-04-25 18:02:51 +0000
commitf868842436a3bb534ffbc2cbe9159064a80df710 (patch)
treee35d46772a21dff5a171cca6ec039b0fc9f77afb
parent2ea70bc57ef228f9975250839d1eb2a603725bd8 (diff)
parenteef6290c3da817cc9b8b72bbcfb1bfc6d4e975b6 (diff)
downloadcuttlefish-emu-35-1-release.tar.gz
Snap for 11762816 from eef6290c3da817cc9b8b72bbcfb1bfc6d4e975b6 to emu-35-1-releaseemu-35-1-release
Change-Id: Ia9996f1eab145ded9cfcaf25ab6333ce95e8cfad
-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--common/libs/utils/subprocess.cpp17
-rw-r--r--common/libs/utils/subprocess.h4
-rw-r--r--host/commands/assemble_cvd/assemble_cvd.cc3
-rw-r--r--host/commands/assemble_cvd/boot_config.cc28
-rw-r--r--host/commands/assemble_cvd/boot_image_utils.cc55
-rw-r--r--host/commands/assemble_cvd/boot_image_utils.h4
-rw-r--r--host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp27
-rw-r--r--host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp51
-rw-r--r--host/commands/assemble_cvd/disk_flags.cc36
-rw-r--r--host/commands/assemble_cvd/flags.cc56
-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.cc257
-rw-r--r--host/commands/assemble_cvd/misc_info.h19
-rw-r--r--host/commands/assemble_cvd/super_image_mixer.cc332
-rw-r--r--host/commands/assemble_cvd/vendor_dlkm_utils.cc40
-rw-r--r--host/commands/run_cvd/boot_state_machine.cc2
-rw-r--r--host/commands/run_cvd/launch/modem.cpp27
-rw-r--r--host/commands/run_cvd/launch/streamer.cpp8
-rw-r--r--host/commands/start/main.cc1
-rw-r--r--host/libs/avb/Android.bp1
-rw-r--r--host/libs/avb/avb.cpp163
-rw-r--r--host/libs/avb/avb.h42
-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.h14
-rw-r--r--host/libs/config/cuttlefish_config_instance.cpp44
-rw-r--r--host/libs/config/known_paths.cpp2
-rw-r--r--host/libs/config/known_paths.h1
-rw-r--r--host/libs/screen_connector/screen_connector.h4
-rw-r--r--host/libs/vm_manager/crosvm_builder.cpp14
-rw-r--r--host/libs/vm_manager/crosvm_manager.cpp66
-rw-r--r--host/libs/vm_manager/gem5_manager.cpp7
-rw-r--r--host/libs/vm_manager/qemu_manager.cpp25
-rw-r--r--shared/chd/chd_debug.prop3
-rw-r--r--system_image/Android.bp96
-rw-r--r--tests/snapshot/OWNERS3
-rw-r--r--tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java2
-rw-r--r--tests/wmediumd_control/Android.bp1
-rwxr-xr-xtools/launch_cvd_arm64_server_docker.sh13
45 files changed, 1018 insertions, 599 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/common/libs/utils/subprocess.cpp b/common/libs/utils/subprocess.cpp
index 6595cd5ed..40b13c3cf 100644
--- a/common/libs/utils/subprocess.cpp
+++ b/common/libs/utils/subprocess.cpp
@@ -293,6 +293,23 @@ StopperResult KillSubprocess(Subprocess* subprocess) {
return StopperResult::kStopSuccess;
}
+SubprocessStopper KillSubprocessFallback(std::function<StopperResult()> nice) {
+ return KillSubprocessFallback([nice](Subprocess*) { return nice(); });
+}
+
+SubprocessStopper KillSubprocessFallback(SubprocessStopper nice_stopper) {
+ return [nice_stopper](Subprocess* proccess) {
+ auto nice_result = nice_stopper(proccess);
+ if (nice_result == StopperResult::kStopFailure) {
+ auto harsh_result = KillSubprocess(proccess);
+ return harsh_result == StopperResult::kStopSuccess
+ ? StopperResult::kStopCrash
+ : harsh_result;
+ }
+ return nice_result;
+ };
+}
+
Command::Command(std::string executable, SubprocessStopper stopper)
: subprocess_stopper_(stopper) {
for (char** env = environ; *env; env++) {
diff --git a/common/libs/utils/subprocess.h b/common/libs/utils/subprocess.h
index 2f695304d..4fadd757e 100644
--- a/common/libs/utils/subprocess.h
+++ b/common/libs/utils/subprocess.h
@@ -56,6 +56,10 @@ class Subprocess;
using SubprocessStopper = std::function<StopperResult(Subprocess*)>;
// Kills a process by sending it the SIGKILL signal.
StopperResult KillSubprocess(Subprocess* subprocess);
+/* Creates a `SubprocessStopper` that first tries `nice_stopper` then falls back
+ * to `KillSubprocess` if that fails. */
+SubprocessStopper KillSubprocessFallback(std::function<StopperResult()>);
+SubprocessStopper KillSubprocessFallback(SubprocessStopper nice_stopper);
// Keeps track of a running (sub)process. Allows to wait for its completion.
// It's an error to wait twice for the same subprocess.
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index 5ad253b71..37d931af0 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -223,6 +223,7 @@ Result<std::set<std::string>> PreservingOnResume(
preserving.insert("os_composite_gpt_header.img");
preserving.insert("os_composite_gpt_footer.img");
preserving.insert("os_composite.img");
+ preserving.insert("os_vbmeta.img");
preserving.insert("sdcard.img");
preserving.insert("sdcard_overlay.img");
preserving.insert("boot_repacked.img");
@@ -245,7 +246,7 @@ Result<std::set<std::string>> PreservingOnResume(
preserving.insert("factory_reset_protected.img");
preserving.insert("misc.img");
preserving.insert("metadata.img");
- preserving.insert("vbmeta.img");
+ preserving.insert("persistent_vbmeta.img");
preserving.insert("oemlock_secure");
preserving.insert("oemlock_insecure");
// Preserve logs if restoring from a snapshot.
diff --git a/host/commands/assemble_cvd/boot_config.cc b/host/commands/assemble_cvd/boot_config.cc
index 35ccfbb9b..e24f074ac 100644
--- a/host/commands/assemble_cvd/boot_config.cc
+++ b/host/commands/assemble_cvd/boot_config.cc
@@ -32,9 +32,9 @@
#include "common/libs/utils/size_utils.h"
#include "common/libs/utils/subprocess.h"
#include "host/commands/assemble_cvd/bootconfig_args.h"
+#include "host/libs/avb/avb.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/kernel_args.h"
-#include "host/libs/config/known_paths.h"
#include "host/libs/vm_manager/crosvm_manager.h"
#include "host/libs/vm_manager/vm_manager.h"
@@ -42,9 +42,6 @@ using cuttlefish::vm_manager::CrosvmManager;
DECLARE_string(vm_manager);
-// Taken from external/avb/avbtool.py; this define is not in the headers
-#define MAX_AVB_METADATA_SIZE 69632ul
-
namespace cuttlefish {
namespace {
@@ -200,24 +197,11 @@ Result<void> PrepareBootEnvImage(
"Unable to run mkenvimage_slim. Exited with status {}", success);
const off_t boot_env_size_bytes =
- AlignToPowerOf2(MAX_AVB_METADATA_SIZE + 4096, PARTITION_SIZE_SHIFT);
-
- auto avbtool_path = HostBinaryPath("avbtool");
- Command boot_env_hash_footer_cmd(avbtool_path);
- boot_env_hash_footer_cmd.AddParameter("add_hash_footer");
- boot_env_hash_footer_cmd.AddParameter("--image");
- boot_env_hash_footer_cmd.AddParameter(tmp_boot_env_image_path);
- boot_env_hash_footer_cmd.AddParameter("--partition_size");
- boot_env_hash_footer_cmd.AddParameter(boot_env_size_bytes);
- boot_env_hash_footer_cmd.AddParameter("--partition_name");
- boot_env_hash_footer_cmd.AddParameter("uboot_env");
- boot_env_hash_footer_cmd.AddParameter("--key");
- boot_env_hash_footer_cmd.AddParameter(TestKeyRsa4096());
- boot_env_hash_footer_cmd.AddParameter("--algorithm");
- boot_env_hash_footer_cmd.AddParameter("SHA256_RSA4096");
- success = boot_env_hash_footer_cmd.Start().Wait();
- CF_EXPECTF(success == 0,
- "Unable to append hash footer. Exited with status {}", success);
+ AlignToPowerOf2(kMaxAvbMetadataSize + 4096, PARTITION_SIZE_SHIFT);
+
+ std::unique_ptr<Avb> avbtool = GetDefaultAvb();
+ CF_EXPECT(avbtool->AddHashFooter(tmp_boot_env_image_path, "uboot_env",
+ boot_env_size_bytes));
if (!FileExists(image_path) ||
ReadFile(image_path) != ReadFile(tmp_boot_env_image_path)) {
diff --git a/host/commands/assemble_cvd/boot_image_utils.cc b/host/commands/assemble_cvd/boot_image_utils.cc
index a601e5e93..1fbeef543 100644
--- a/host/commands/assemble_cvd/boot_image_utils.cc
+++ b/host/commands/assemble_cvd/boot_image_utils.cc
@@ -15,22 +15,26 @@
*/
#include "host/commands/assemble_cvd/boot_image_utils.h"
-#include "common/libs/fs/shared_fd.h"
-#include "host/libs/config/cuttlefish_config.h"
#include <string.h>
#include <unistd.h>
#include <fstream>
+#include <memory>
#include <regex>
#include <sstream>
+#include <string>
#include <android-base/logging.h>
#include <android-base/strings.h>
+#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
+#include "host/libs/avb/avb.cpp"
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/config/known_paths.h"
const char TMP_EXTENSION[] = ".tmp";
const char CPIO_EXT[] = ".cpio";
@@ -158,26 +162,13 @@ void UnpackRamdisk(const std::string& original_ramdisk_path,
<< success;
}
-bool GetAvbMetadatFromBootImage(const std::string& boot_image_path,
- const std::string& unpack_dir) {
- auto avbtool_path = HostBinaryPath("avbtool");
- Command avb_cmd(avbtool_path);
- avb_cmd.AddParameter("info_image");
- avb_cmd.AddParameter("--image");
- avb_cmd.AddParameter(boot_image_path);
-
- auto output_file = SharedFD::Creat(unpack_dir + "/boot_params", 0666);
- if (!output_file->IsOpen()) {
- LOG(ERROR) << "Unable to create intermediate boot params file: "
- << output_file->StrError();
- return false;
- }
- avb_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, output_file);
-
- int success = avb_cmd.Start().Wait();
-
- if (success != 0) {
- LOG(ERROR) << "Unable to run avb command. Exited with status " << success;
+bool GetAvbMetadataFromBootImage(const std::string& boot_image_path,
+ const std::string& unpack_dir) {
+ std::unique_ptr<Avb> avbtool = GetDefaultAvb();
+ Result<void> result =
+ avbtool->WriteInfoImage(boot_image_path, unpack_dir + "/boot_params");
+ if (!result.ok()) {
+ LOG(ERROR) << result.error().Trace();
return false;
}
return true;
@@ -355,18 +346,12 @@ bool RepackVendorBootImage(const std::string& new_ramdisk,
return false;
}
- auto avbtool_path = HostBinaryPath("avbtool");
- Command avb_cmd(avbtool_path);
- avb_cmd.AddParameter("add_hash_footer");
- avb_cmd.AddParameter("--image");
- avb_cmd.AddParameter(tmp_vendor_boot_image_path);
- avb_cmd.AddParameter("--partition_size");
- avb_cmd.AddParameter(FileSize(vendor_boot_image_path));
- avb_cmd.AddParameter("--partition_name");
- avb_cmd.AddParameter("vendor_boot");
- success = avb_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to run avbtool. Exited with status " << success;
+ auto avbtool = Avb(AvbToolBinary());
+ Result<void> result =
+ avbtool.AddHashFooter(tmp_vendor_boot_image_path, "vendor_boot",
+ FileSize(vendor_boot_image_path));
+ if (!result.ok()) {
+ LOG(ERROR) << result.error().Trace();
return false;
}
@@ -468,7 +453,7 @@ Result<std::string> ReadAndroidVersionFromBootImage(
if (!unpack_dir) {
return CF_ERR("boot image unpack dir could not be created");
}
- bool unpack_status = GetAvbMetadatFromBootImage(boot_image_path, unpack_dir);
+ bool unpack_status = GetAvbMetadataFromBootImage(boot_image_path, unpack_dir);
if (!unpack_status) {
RecursivelyRemoveDirectory(unpack_dir);
return CF_ERR("\"" + boot_image_path + "\" boot image unpack into \"" +
diff --git a/host/commands/assemble_cvd/boot_image_utils.h b/host/commands/assemble_cvd/boot_image_utils.h
index 657e6f75d..26a3dc38c 100644
--- a/host/commands/assemble_cvd/boot_image_utils.h
+++ b/host/commands/assemble_cvd/boot_image_utils.h
@@ -23,10 +23,6 @@
namespace cuttlefish {
-// Taken from external/avb/libavb/avb_slot_verify.c; this define is not in the
-// headers
-static constexpr size_t VBMETA_MAX_SIZE = 65536ul;
-
Result<void> RepackBootImage(const Avb& avb,
const std::string& new_kernel_path,
const std::string& boot_image_path,
diff --git a/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp b/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp
index 616d86f30..7960b631b 100644
--- a/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp
+++ b/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp
@@ -16,6 +16,7 @@
#include "host/commands/assemble_cvd/disk/disk.h"
+#include <memory>
#include <string>
#include <unordered_set>
@@ -27,15 +28,13 @@
#include "common/libs/utils/result.h"
#include "common/libs/utils/size_utils.h"
#include "host/commands/assemble_cvd/bootconfig_args.h"
+#include "host/libs/avb/avb.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/data_image.h"
#include "host/libs/config/feature.h"
#include "host/libs/config/known_paths.h"
#include "host/libs/vm_manager/gem5_manager.h"
-// Taken from external/avb/avbtool.py; this define is not in the headers
-#define MAX_AVB_METADATA_SIZE 69632ul
-
namespace cuttlefish {
Result<void> GeneratePersistentBootconfig(
@@ -87,25 +86,11 @@ Result<void> GeneratePersistentBootconfig(
} else {
bootconfig_fd->Close();
const off_t bootconfig_size_bytes = AlignToPowerOf2(
- MAX_AVB_METADATA_SIZE + bootconfig.size(), PARTITION_SIZE_SHIFT);
+ kMaxAvbMetadataSize + bootconfig.size(), PARTITION_SIZE_SHIFT);
- auto avbtool_path = HostBinaryPath("avbtool");
- Command bootconfig_hash_footer_cmd(avbtool_path);
- bootconfig_hash_footer_cmd.AddParameter("add_hash_footer");
- bootconfig_hash_footer_cmd.AddParameter("--image");
- bootconfig_hash_footer_cmd.AddParameter(bootconfig_path);
- bootconfig_hash_footer_cmd.AddParameter("--partition_size");
- bootconfig_hash_footer_cmd.AddParameter(bootconfig_size_bytes);
- bootconfig_hash_footer_cmd.AddParameter("--partition_name");
- bootconfig_hash_footer_cmd.AddParameter("bootconfig");
- bootconfig_hash_footer_cmd.AddParameter("--key");
- bootconfig_hash_footer_cmd.AddParameter(TestKeyRsa4096());
- bootconfig_hash_footer_cmd.AddParameter("--algorithm");
- bootconfig_hash_footer_cmd.AddParameter("SHA256_RSA4096");
- int success = bootconfig_hash_footer_cmd.Start().Wait();
- CF_EXPECT(
- success == 0,
- "Unable to run append hash footer. Exited with status " << success);
+ std::unique_ptr<Avb> avbtool = GetDefaultAvb();
+ CF_EXPECT(avbtool->AddHashFooter(bootconfig_path, "bootconfig",
+ bootconfig_size_bytes));
}
return {};
}
diff --git a/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp b/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp
index 4d91d7472..add41dc07 100644
--- a/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp
+++ b/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp
@@ -31,46 +31,25 @@ namespace cuttlefish {
using APBootFlow = CuttlefishConfig::InstanceSpecific::APBootFlow;
static bool PrepareVBMetaImage(const std::string& path, bool has_boot_config) {
- auto avbtool_path = HostBinaryPath("avbtool");
- Command vbmeta_cmd(avbtool_path);
- vbmeta_cmd.AddParameter("make_vbmeta_image");
- vbmeta_cmd.AddParameter("--output");
- vbmeta_cmd.AddParameter(path);
- vbmeta_cmd.AddParameter("--algorithm");
- vbmeta_cmd.AddParameter("SHA256_RSA4096");
- vbmeta_cmd.AddParameter("--key");
- vbmeta_cmd.AddParameter(TestKeyRsa4096());
-
- vbmeta_cmd.AddParameter("--chain_partition");
- vbmeta_cmd.AddParameter("uboot_env:1:" + TestPubKeyRsa4096());
-
+ std::unique_ptr<Avb> avbtool = GetDefaultAvb();
+ std::vector<ChainPartition> chained_partitions = {ChainPartition{
+ .name = "uboot_env",
+ .rollback_index = "1",
+ .key_path = TestPubKeyRsa4096(),
+ }};
if (has_boot_config) {
- vbmeta_cmd.AddParameter("--chain_partition");
- vbmeta_cmd.AddParameter("bootconfig:2:" + TestPubKeyRsa4096());
+ chained_partitions.emplace_back(ChainPartition{
+ .name = "bootconfig",
+ .rollback_index = "2",
+ .key_path = TestPubKeyRsa4096(),
+ });
}
-
- bool success = vbmeta_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to create persistent vbmeta. Exited with status "
- << success;
+ Result<void> result =
+ avbtool->MakeVbMetaImage(path, chained_partitions, {}, {});
+ if (!result.ok()) {
+ LOG(ERROR) << result.error().Trace();
return false;
}
-
- const auto vbmeta_size = FileSize(path);
- if (vbmeta_size > VBMETA_MAX_SIZE) {
- LOG(ERROR) << "Generated vbmeta - " << path
- << " is larger than the expected " << VBMETA_MAX_SIZE
- << ". Stopping.";
- return false;
- }
- if (vbmeta_size != VBMETA_MAX_SIZE) {
- auto fd = SharedFD::Open(path, O_RDWR);
- if (!fd->IsOpen() || fd->Truncate(VBMETA_MAX_SIZE) != 0) {
- LOG(ERROR) << "`truncate --size=" << VBMETA_MAX_SIZE << " " << path
- << "` failed: " << fd->StrError();
- return false;
- }
- }
return true;
}
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
index 7bc0c436e..6f23e0323 100644
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ b/host/commands/assemble_cvd/disk_flags.cc
@@ -16,15 +16,18 @@
#include "host/commands/assemble_cvd/disk_flags.h"
+#include <sys/statvfs.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
#include <android-base/logging.h>
#include <android-base/parsebool.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <fruit/fruit.h>
#include <gflags/gflags.h>
-#include <sys/statvfs.h>
-
-#include <fstream>
#include "common/libs/fs/shared_buf.h"
#include "common/libs/utils/files.h"
@@ -40,6 +43,7 @@
#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/avb/avb.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/data_image.h"
#include "host/libs/config/inject.h"
@@ -356,14 +360,18 @@ std::vector<ImagePartition> android_composite_disk_config(
.image_file_path = AbsolutePath(instance.new_vendor_boot_image()),
.read_only = FLAGS_use_overlay,
});
+ auto vbmeta_image = instance.new_vbmeta_image();
+ if (!FileExists(vbmeta_image)) {
+ vbmeta_image = instance.vbmeta_image();
+ }
partitions.push_back(ImagePartition{
.label = "vbmeta_a",
- .image_file_path = AbsolutePath(instance.vbmeta_image()),
+ .image_file_path = AbsolutePath(vbmeta_image),
.read_only = FLAGS_use_overlay,
});
partitions.push_back(ImagePartition{
.label = "vbmeta_b",
- .image_file_path = AbsolutePath(instance.vbmeta_image()),
+ .image_file_path = AbsolutePath(vbmeta_image),
.read_only = FLAGS_use_overlay,
});
partitions.push_back(ImagePartition{
@@ -630,20 +638,13 @@ Result<void> VbmetaEnforceMinimumSize(
// libavb expects to be able to read the maximum vbmeta size, so we must
// provide a partition which matches this or the read will fail
for (const auto& vbmeta_image :
- {instance.vbmeta_image(), instance.vbmeta_system_image(),
- instance.vbmeta_vendor_dlkm_image(),
+ {instance.vbmeta_image(), instance.new_vbmeta_image(),
+ instance.vbmeta_system_image(), instance.vbmeta_vendor_dlkm_image(),
instance.vbmeta_system_dlkm_image()}) {
// In some configurations of cuttlefish, the vendor dlkm vbmeta image does
// not exist
- if (FileExists(vbmeta_image) && FileSize(vbmeta_image) != VBMETA_MAX_SIZE) {
- auto fd = SharedFD::Open(vbmeta_image, O_RDWR);
- CF_EXPECTF(fd->IsOpen(), "Could not open \"{}\": {}", vbmeta_image,
- fd->StrError());
- CF_EXPECTF(fd->Truncate(VBMETA_MAX_SIZE) == 0,
- "`truncate --size={} {}` failed: {}", VBMETA_MAX_SIZE,
- vbmeta_image, fd->StrError());
- CF_EXPECTF(fd->Fsync() == 0, "fsync on `{}` failed: {}", vbmeta_image,
- fd->StrError());
+ if (FileExists(vbmeta_image)) {
+ CF_EXPECT(EnforceVbMetaSize(vbmeta_image));
}
}
return {};
@@ -971,6 +972,9 @@ Result<void> DiskImageFlagsVectorization(CuttlefishConfig& config, const Fetcher
const std::string new_super_image_path =
const_instance.PerInstancePath("super.img");
instance.set_new_super_image(new_super_image_path);
+ const std::string new_vbmeta_image_path =
+ const_instance.PerInstancePath("os_vbmeta.img");
+ instance.set_new_vbmeta_image(new_vbmeta_image_path);
}
instance.set_new_vbmeta_vendor_dlkm_image(
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index c1e8b8767..4a74ac5e7 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));
@@ -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..834cf7389 100644
--- a/host/commands/assemble_cvd/misc_info.cc
+++ b/host/commands/assemble_cvd/misc_info.cc
@@ -15,15 +15,101 @@
#include "misc_info.h"
-#include <algorithm>
+#include <array>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_set>
+#include <vector>
#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
+#include <android-base/parseint.h>
#include <android-base/strings.h>
+#include <fmt/format.h>
+
+#include "common/libs/fs/shared_buf.h"
+#include "common/libs/fs/shared_fd.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 kRollbackIndexSuffix[] = "_rollback_index_location";
+constexpr char kSuperBlockDevices[] = "super_block_devices";
+constexpr char kSuperPartitionGroups[] = "super_partition_groups";
+constexpr char kUseDynamicPartitions[] = "use_dynamic_partitions";
+constexpr std::array kNonPartitionKeysToMerge = {
+ "ab_update", "default_system_dev_certificate"};
+
+Result<std::string> GetExpected(const MiscInfo& misc_info,
+ const std::string& key) {
+ auto lookup = misc_info.find(key);
+ CF_EXPECTF(lookup != misc_info.end(),
+ "Unable to retrieve expected value from key: {}", key);
+ return lookup->second;
+}
+
+std::string GetOrDefault(const MiscInfo& misc_info, const std::string& key,
+ const std::string& default_value) {
+ auto result = GetExpected(misc_info, key);
+ return result.ok() ? *result : default_value;
+}
+
+std::string MergePartitionLists(const std::string& vendor,
+ const std::string& system) {
+ const std::string full_string = fmt::format("{} {}", vendor, system);
+ auto full_list = android::base::Tokenize(full_string, " ");
+ // std::set removes duplicates and orders the elements, which we want
+ std::set<std::string> full_set(full_list.begin(), full_list.end());
+ return android::base::Join(full_set, " ");
+}
+
+std::string GetPartitionList(const MiscInfo& vendor_info,
+ const MiscInfo& system_info,
+ const std::string& key) {
+ std::string vendor_list = GetOrDefault(vendor_info, key, "");
+ std::string system_list = GetOrDefault(system_info, key, "");
+ return MergePartitionLists(vendor_list, system_list);
+}
+
+std::vector<std::string> GeneratePartitionKeys(const std::string& name) {
+ std::vector<std::string> result;
+ result.emplace_back("avb_" + name);
+ result.emplace_back("avb_" + name + "_algorithm");
+ result.emplace_back("avb_" + name + "_key_path");
+ result.emplace_back("avb_" + name + kRollbackIndexSuffix);
+ result.emplace_back("avb_" + name + "_hashtree_enable");
+ result.emplace_back("avb_" + name + "_add_hashtree_footer_args");
+ result.emplace_back(name + "_disable_sparse");
+ result.emplace_back("building_" + name + "_image");
+ auto fs_type_key = name + "_fs_type";
+ if (name == "system") {
+ fs_type_key = "fs_type";
+ }
+ result.emplace_back(fs_type_key);
+ return result;
+}
+
+Result<int> ResolveRollbackIndexConflicts(
+ const std::string& index_string,
+ const std::unordered_set<int> used_indices) {
+ int index;
+ CF_EXPECTF(android::base::ParseInt(index_string, &index),
+ "Unable to parse value {} to string. Maybe a wrong or bad value "
+ "read for the rollback index?",
+ index_string);
+ while (Contains(used_indices, index)) {
+ ++index;
+ }
+ return index;
+}
+
+} // 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,91 +123,124 @@ 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;
}
-std::string WriteMiscInfo(const MiscInfo& misc_info) {
- std::stringstream out;
+Result<void> WriteMiscInfo(const MiscInfo& misc_info,
+ const std::string& output_path) {
+ std::stringstream file_content;
for (const auto& entry : misc_info) {
- out << entry.first << "=" << entry.second << "\n";
+ file_content << entry.first << "=" << entry.second << "\n";
}
- return out.str();
-}
-static const std::string kDynamicPartitions = "dynamic_partition_list";
+ SharedFD output_file = SharedFD::Creat(output_path.c_str(), 0644);
+ CF_EXPECT(output_file->IsOpen(),
+ "Failed to open output misc file: " << output_file->StrError());
-std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) {
- auto value_it = info.find(kDynamicPartitions);
- if (value_it == info.end()) {
- return {};
+ CF_EXPECT(
+ WriteAll(output_file, file_content.str()) >= 0,
+ "Failed to write output misc file contents: " << output_file->StrError());
+ return {};
+}
+
+// based on build/make/tools/releasetools/merge/merge_target_files.py
+Result<MiscInfo> GetCombinedDynamicPartitions(const MiscInfo& vendor_info,
+ const MiscInfo& system_info) {
+ CF_EXPECTF(CF_EXPECT(GetExpected(vendor_info, kDynamicPartitions)) == "true",
+ "Vendor build must have {}=true", kUseDynamicPartitions);
+ CF_EXPECTF(CF_EXPECT(GetExpected(system_info, kDynamicPartitions)) == "true",
+ "System build must have {}=true", kUseDynamicPartitions);
+ MiscInfo result;
+ // copy where both files are equal
+ for (const auto& key_val : vendor_info) {
+ const auto value_result = GetExpected(system_info, key_val.first);
+ if (value_result.ok() && *value_result == key_val.second) {
+ result[key_val.first] = key_val.second;
+ }
}
- auto components = android::base::Split(value_it->second, " ");
- for (auto& component : components) {
- component = android::base::Trim(component);
+
+ result[kDynamicPartitions] =
+ GetPartitionList(vendor_info, system_info, kDynamicPartitions);
+
+ const auto block_devices_result =
+ GetExpected(vendor_info, kSuperBlockDevices);
+ if (block_devices_result.ok()) {
+ result[kSuperBlockDevices] = *block_devices_result;
+ for (const auto& block_device :
+ android::base::Tokenize(result[kSuperBlockDevices], " ")) {
+ const auto key = "super_" + block_device + "_device_size";
+ result[key] = CF_EXPECT(GetExpected(vendor_info, key));
+ }
}
- components.erase(std::remove(components.begin(), components.end(), ""),
- components.end());
- return components;
-}
-static constexpr const char* kGoogleDynamicPartitions =
- "google_dynamic_partitions";
-static constexpr const char* kSuperPartitionGroups = "super_partition_groups";
+ result[kSuperPartitionGroups] =
+ CF_EXPECT(GetExpected(vendor_info, kSuperPartitionGroups));
+ for (const auto& group :
+ android::base::Tokenize(result[kSuperPartitionGroups], " ")) {
+ const auto group_size_key = "super_" + group + "_group_size";
+ result[group_size_key] =
+ CF_EXPECT(GetExpected(vendor_info, group_size_key));
-bool SetSuperPartitionComponents(const std::vector<std::string>& components,
- MiscInfo* misc_info) {
- auto super_partition_groups = misc_info->find(kSuperPartitionGroups);
- if (super_partition_groups == misc_info->end()) {
- LOG(ERROR) << "Failed to find super partition groups in misc_info";
- return false;
+ const auto partition_list_key = "super_" + group + "_partition_list";
+ result[partition_list_key] =
+ GetPartitionList(vendor_info, system_info, partition_list_key);
}
- // Remove all existing update groups in misc_info
- auto update_groups =
- android::base::Split(super_partition_groups->second, " ");
- for (const auto& group_name : update_groups) {
- auto partition_list = android::base::StringPrintf("super_%s_partition_list",
- group_name.c_str());
- auto partition_size =
- android::base::StringPrintf("super_%s_group_size", group_name.c_str());
- for (const auto& key : {partition_list, partition_size}) {
- auto it = misc_info->find(key);
- if (it == misc_info->end()) {
- LOG(ERROR) << "Failed to find " << key << " in misc_info";
- return false;
- }
- misc_info->erase(it);
+ // TODO(chadreynolds): add vabc_cow_version logic if we need to support older
+ // builds
+ for (const auto& key :
+ {"virtual_ab", "virtual_ab_retrofit", "lpmake", "super_metadata_device",
+ "super_partition_error_limit", "super_partition_size"}) {
+ const auto value_result = GetExpected(vendor_info, key);
+ if (value_result.ok()) {
+ result[key] = *value_result;
}
}
+ return std::move(result);
+}
- // For merged target-file, put all dynamic partitions under the
- // google_dynamic_partitions update group.
- // TODO(xunchang) use different update groups for system and vendor images.
- (*misc_info)[kDynamicPartitions] = android::base::Join(components, " ");
- (*misc_info)[kSuperPartitionGroups] = kGoogleDynamicPartitions;
- std::string partitions_list_key = android::base::StringPrintf(
- "super_%s_partition_list", kGoogleDynamicPartitions);
- (*misc_info)[partitions_list_key] = android::base::Join(components, " ");
-
- // Use the entire super partition as the group size
- std::string group_size_key = android::base::StringPrintf(
- "super_%s_group_size", kGoogleDynamicPartitions);
- auto super_size_it = misc_info->find("super_partition_size");
- if (super_size_it == misc_info->end()) {
- LOG(ERROR) << "Failed to find super partition size";
- return false;
+Result<MiscInfo> MergeMiscInfos(
+ const MiscInfo& vendor_info, const MiscInfo& system_info,
+ const MiscInfo& combined_dp_info,
+ const std::vector<std::string>& system_partitions) {
+ // the combined misc info uses the vendor values as defaults
+ MiscInfo result = vendor_info;
+ std::unordered_set<int> used_indices;
+ for (const auto& partition : system_partitions) {
+ for (const auto& key : GeneratePartitionKeys(partition)) {
+ if (!Contains(system_info, key)) {
+ continue;
+ }
+ auto system_value = system_info.find(key)->second;
+ // avb_<partition>_rollback_index_location values can conflict across
+ // different builds
+ if (android::base::EndsWith(key, kRollbackIndexSuffix)) {
+ const auto index = CF_EXPECT(
+ ResolveRollbackIndexConflicts(system_value, used_indices));
+ used_indices.insert(index);
+ system_value = std::to_string(index);
+ }
+ result[key] = system_value;
+ }
+ }
+ for (const auto& key : kNonPartitionKeysToMerge) {
+ if (Contains(system_info, key)) {
+ result[key] = system_info.find(key)->second;
+ }
+ }
+ for (const auto& key_val : combined_dp_info) {
+ result[key_val.first] = key_val.second;
}
- (*misc_info)[group_size_key] = super_size_it->second;
- return true;
+ return std::move(result);
}
} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/misc_info.h b/host/commands/assemble_cvd/misc_info.h
index aa130bcc9..9b018bd43 100644
--- a/host/commands/assemble_cvd/misc_info.h
+++ b/host/commands/assemble_cvd/misc_info.h
@@ -19,15 +19,22 @@
#include <string>
#include <vector>
+#include "common/libs/utils/result.h"
+
namespace cuttlefish {
+// TODO(chadreynolds): rename MiscInfo to more generic KeyValueFile since this
+// logic is processing multiple filetypes now
using MiscInfo = std::map<std::string, std::string>;
-MiscInfo ParseMiscInfo(const std::string& file_contents);
-std::string WriteMiscInfo(const MiscInfo& info);
-
-std::vector<std::string> SuperPartitionComponents(const MiscInfo&);
-bool SetSuperPartitionComponents(const std::vector<std::string>& components,
- MiscInfo* misc_info);
+Result<MiscInfo> ParseMiscInfo(const std::string& file_contents);
+Result<void> WriteMiscInfo(const MiscInfo& misc_info,
+ const std::string& output_path);
+Result<MiscInfo> GetCombinedDynamicPartitions(const MiscInfo& vendor_info,
+ const MiscInfo& system_info);
+Result<MiscInfo> MergeMiscInfos(
+ const MiscInfo& vendor_info, const MiscInfo& system_info,
+ const MiscInfo& combined_dp_info,
+ const std::vector<std::string>& system_partitions);
} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc
index f8ebf7f38..0cf46707d 100644
--- a/host/commands/assemble_cvd/super_image_mixer.cc
+++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -20,93 +20,59 @@
#include <algorithm>
#include <array>
#include <memory>
+#include <string>
+#include <unordered_set>
+#include <vector>
#include <android-base/strings.h>
#include <android-base/logging.h>
-#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/result.h"
#include "common/libs/utils/subprocess.h"
#include "host/commands/assemble_cvd/misc_info.h"
+#include "host/libs/config/config_utils.h"
#include "host/libs/config/cuttlefish_config.h"
#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 kDefaultTargetImages = {
+constexpr char kDynamicPartitionsPath[] = "META/dynamic_partitions_info.txt";
+constexpr std::array kVendorTargetImages = {
"IMAGES/boot.img",
+ "IMAGES/dtbo.img",
+ "IMAGES/init_boot.img",
"IMAGES/odm.img",
"IMAGES/odm_dlkm.img",
"IMAGES/recovery.img",
+ "IMAGES/system_dlkm.img",
"IMAGES/userdata.img",
"IMAGES/vbmeta.img",
+ "IMAGES/vbmeta_system_dlkm.img",
+ "IMAGES/vbmeta_vendor.img",
+ "IMAGES/vbmeta_vendor_dlkm.img",
"IMAGES/vendor.img",
"IMAGES/vendor_dlkm.img",
- "IMAGES/vbmeta_vendor_dlkm.img",
- "IMAGES/system_dlkm.img",
+ "IMAGES/vendor_kernel_boot.img",
};
-constexpr std::array kDefaultTargetBuildProp = {
+constexpr std::array kVendorTargetBuildProps = {
"ODM/build.prop",
"ODM/etc/build.prop",
"VENDOR/build.prop",
"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");
@@ -118,119 +84,139 @@ 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.");
-
- 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()) {
- system_super_partitions.push_back(partition);
- }
- }
- CF_EXPECT(SetSuperPartitionComponents(system_super_partitions, &output_misc),
- "Failed to update super partitions components for misc_info");
+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");
+}
- auto misc_output_path = output_path + "/" + kMiscInfoPath;
- 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());
+std::string GetPartitionNameFromPath(const std::string& path) {
+ // "IMAGES/<name>.img" -> "<name>"
+ return path.substr(7, path.length() - 11);
+}
- CF_EXPECT(WriteAll(misc_output_file, WriteMiscInfo(output_misc)) >= 0,
- "Failed to write output misc file contents: "
- << misc_output_file->StrError());
+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;
+}
- for (const auto& name : default_target_contents) {
- if (!android::base::StartsWith(name, "IMAGES/")) {
- continue;
- } else if (!android::base::EndsWith(name, ".img")) {
+Result<MiscInfo> CombineDynamicPartitionsInfo(TargetFiles& target_files) {
+ CF_EXPECTF(Contains(target_files.vendor_contents, kDynamicPartitionsPath),
+ "Vendor target files zip does not contain {}",
+ kDynamicPartitionsPath);
+ CF_EXPECTF(Contains(target_files.system_contents, kDynamicPartitionsPath),
+ "System target files zip does not contain {}",
+ kDynamicPartitionsPath);
+
+ const MiscInfo vendor_dp_info = CF_EXPECT(ParseMiscInfo(
+ target_files.vendor_zip.ExtractToMemory(kDynamicPartitionsPath)));
+ const MiscInfo system_dp_info = CF_EXPECT(ParseMiscInfo(
+ target_files.system_zip.ExtractToMemory(kDynamicPartitionsPath)));
+
+ return CF_EXPECT(
+ GetCombinedDynamicPartitions(vendor_dp_info, system_dp_info));
+}
+
+Result<void> CombineMiscInfo(
+ TargetFiles& target_files, const std::string& misc_output_path,
+ const std::vector<std::string>& system_partitions) {
+ CF_EXPECTF(Contains(target_files.vendor_contents, kMiscInfoPath),
+ "Vendor 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 vendor_misc = CF_EXPECT(
+ ParseMiscInfo(target_files.vendor_zip.ExtractToMemory(kMiscInfoPath)));
+ const MiscInfo system_misc = CF_EXPECT(
+ ParseMiscInfo(target_files.system_zip.ExtractToMemory(kMiscInfoPath)));
+
+ const auto combined_dp_info =
+ CF_EXPECT(CombineDynamicPartitionsInfo(target_files));
+ const auto output_misc = CF_EXPECT(MergeMiscInfos(
+ vendor_misc, system_misc, combined_dp_info, system_partitions));
+
+ CF_EXPECT(WriteMiscInfo(output_misc, misc_output_path));
+ return {};
+}
+
+Result<std::vector<std::string>> 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(kDefaultTargetImages, name)) {
+ } 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(kDefaultTargetBuildProp, name)) {
+ } 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")) {
+ std::vector<std::string> system_partitions;
+ for (const auto& name : target_files.system_contents) {
+ if (!IsTargetFilesImage(name)) {
continue;
- } else if (Contains(kDefaultTargetImages, name)) {
+ } 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");
+ system_partitions.emplace_back(GetPartitionNameFromPath(name));
}
- 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(kDefaultTargetBuildProp, name)) {
+ } 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 std::move(system_partitions);
+}
+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));
+ const auto system_partitions =
+ CF_EXPECT(ExtractTargetFiles(target_files, output_path));
+ const auto misc_output_path = output_path + "/" + kMiscInfoPath;
+ CF_EXPECT(CombineMiscInfo(target_files, misc_output_path, system_partitions));
return {};
}
@@ -250,6 +236,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) {
@@ -311,6 +313,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>
@@ -320,4 +354,4 @@ SuperImageRebuilderComponent() {
.addMultibinding<SetupFeature, SuperImageRebuilder>();
}
-} // namespace cuttlefish
+} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/vendor_dlkm_utils.cc b/host/commands/assemble_cvd/vendor_dlkm_utils.cc
index ded0baaee..57890e4a7 100644
--- a/host/commands/assemble_cvd/vendor_dlkm_utils.cc
+++ b/host/commands/assemble_cvd/vendor_dlkm_utils.cc
@@ -291,7 +291,8 @@ bool GenerateFileContexts(const char* output_path,
bool AddVbmetaFooter(const std::string& output_image,
const std::string& partition_name) {
- auto avbtool_path = HostBinaryPath("avbtool");
+ // TODO(b/335742241): update to use Avb
+ auto avbtool_path = AvbToolBinary();
Command avb_cmd(avbtool_path);
// Add host binary path to PATH, so that avbtool can locate host util
// binaries such as 'fec'
@@ -408,41 +409,14 @@ bool BuildVbmetaImage(const std::string& image_path,
const std::string& vbmeta_path) {
CHECK(!image_path.empty());
CHECK(FileExists(image_path));
- auto avbtool_path = HostBinaryPath("avbtool");
- Command vbmeta_cmd(avbtool_path);
- vbmeta_cmd.AddParameter("make_vbmeta_image");
- vbmeta_cmd.AddParameter("--output");
- vbmeta_cmd.AddParameter(vbmeta_path);
- vbmeta_cmd.AddParameter("--algorithm");
- vbmeta_cmd.AddParameter("SHA256_RSA4096");
- vbmeta_cmd.AddParameter("--key");
- vbmeta_cmd.AddParameter(TestKeyRsa4096());
- vbmeta_cmd.AddParameter("--include_descriptors_from_image");
- vbmeta_cmd.AddParameter(image_path);
- vbmeta_cmd.AddParameter("--padding_size");
- vbmeta_cmd.AddParameter("4096");
-
- bool success = vbmeta_cmd.Start().Wait();
- if (success != 0) {
- LOG(ERROR) << "Unable to create vbmeta. Exited with status " << success;
- return false;
- }
- const auto vbmeta_size = FileSize(vbmeta_path);
- if (vbmeta_size > VBMETA_MAX_SIZE) {
- LOG(ERROR) << "Generated vbmeta - " << vbmeta_path
- << " is larger than the expected " << VBMETA_MAX_SIZE
- << ". Stopping.";
+ std::unique_ptr<Avb> avbtool = GetDefaultAvb();
+ Result<void> result = avbtool->MakeVbMetaImage(vbmeta_path, {}, {image_path},
+ {"--padding_size", "4096"});
+ if (!result.ok()) {
+ LOG(ERROR) << result.error().Trace();
return false;
}
- if (vbmeta_size != VBMETA_MAX_SIZE) {
- auto fd = SharedFD::Open(vbmeta_path, O_RDWR | O_CLOEXEC);
- if (!fd->IsOpen() || fd->Truncate(VBMETA_MAX_SIZE) != 0) {
- LOG(ERROR) << "`truncate --size=" << VBMETA_MAX_SIZE << " " << vbmeta_path
- << "` failed: " << fd->StrError();
- return false;
- }
- }
return true;
}
diff --git a/host/commands/run_cvd/boot_state_machine.cc b/host/commands/run_cvd/boot_state_machine.cc
index cc9f09441..67060e07a 100644
--- a/host/commands/run_cvd/boot_state_machine.cc
+++ b/host/commands/run_cvd/boot_state_machine.cc
@@ -51,7 +51,7 @@ namespace {
// 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 child assumes the restore was
+// instance's "restore_pipe" and then the parent assumes the restore was
// successful.
//
// We should consider unifying these two types of pipes.
diff --git a/host/commands/run_cvd/launch/modem.cpp b/host/commands/run_cvd/launch/modem.cpp
index 2502d86a2..af6c0dc57 100644
--- a/host/commands/run_cvd/launch/modem.cpp
+++ b/host/commands/run_cvd/launch/modem.cpp
@@ -31,33 +31,33 @@
namespace cuttlefish {
-static bool StopModemSimulator(int id) {
+static StopperResult StopModemSimulator(int id) {
std::string socket_name = "modem_simulator" + std::to_string(id);
auto monitor_sock =
SharedFD::SocketLocalClient(socket_name, true, SOCK_STREAM);
if (!monitor_sock->IsOpen()) {
LOG(ERROR) << "The connection to modem simulator is closed";
- return false;
+ return StopperResult::kStopFailure;
}
std::string msg("STOP");
if (monitor_sock->Write(msg.data(), msg.size()) < 0) {
monitor_sock->Close();
LOG(ERROR) << "Failed to send 'STOP' to modem simulator";
- return false;
+ return StopperResult::kStopFailure;
}
char buf[64] = {0};
if (monitor_sock->Read(buf, sizeof(buf)) <= 0) {
monitor_sock->Close();
LOG(ERROR) << "Failed to read message from modem simulator";
- return false;
+ return StopperResult::kStopFailure;
}
if (strcmp(buf, "OK")) {
monitor_sock->Close();
LOG(ERROR) << "Read '" << buf << "' instead of 'OK' from modem simulator";
- return false;
+ return StopperResult::kStopFailure;
}
- return true;
+ return StopperResult::kStopSuccess;
}
Result<std::optional<MonitorCommand>> ModemSimulator(
@@ -89,18 +89,9 @@ Result<std::optional<MonitorCommand>> ModemSimulator(
sockets.emplace_back(std::move(modem_sim_socket));
}
- auto host_id = instance.modem_simulator_host_id();
- Command cmd(ModemSimulatorBinary(), [host_id](Subprocess* proc) {
- auto stopped = StopModemSimulator(host_id);
- if (stopped) {
- return StopperResult::kStopSuccess;
- }
- LOG(WARNING) << "Failed to stop modem simulator nicely, "
- << "attempting to KILL";
- return KillSubprocess(proc) == StopperResult::kStopSuccess
- ? StopperResult::kStopCrash
- : StopperResult::kStopFailure;
- });
+ auto id = instance.modem_simulator_host_id();
+ auto nice_stop = [id]() { return StopModemSimulator(id); };
+ Command cmd(ModemSimulatorBinary(), KillSubprocessFallback(nice_stop));
auto sim_type = instance.modem_simulator_sim_type();
cmd.AddParameter(std::string{"-sim_type="} + std::to_string(sim_type));
diff --git a/host/commands/run_cvd/launch/streamer.cpp b/host/commands/run_cvd/launch/streamer.cpp
index 4ed0d5c2e..3334efdf1 100644
--- a/host/commands/run_cvd/launch/streamer.cpp
+++ b/host/commands/run_cvd/launch/streamer.cpp
@@ -250,14 +250,12 @@ class WebRtcServer : public virtual CommandSource,
commands.emplace_back(std::move(sig_proxy));
}
- auto stopper = [webrtc_recorder = webrtc_recorder_](Subprocess* proc) {
+ auto stopper = [webrtc_recorder = webrtc_recorder_]() {
webrtc_recorder.SendStopRecordingCommand();
- return KillSubprocess(proc) == StopperResult::kStopSuccess
- ? StopperResult::kStopCrash
- : StopperResult::kStopFailure;
+ return StopperResult::kStopFailure;
};
- Command webrtc(WebRtcBinary(), stopper);
+ Command webrtc(WebRtcBinary(), KillSubprocessFallback(stopper));
webrtc.AddParameter("-group_id=", instance_.group_id());
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/avb/Android.bp b/host/libs/avb/Android.bp
index 62b6ad74e..3c198acef 100644
--- a/host/libs/avb/Android.bp
+++ b/host/libs/avb/Android.bp
@@ -23,6 +23,7 @@ cc_library {
"avb.cpp"
],
shared_libs: [
+ "libcuttlefish_fs",
"libcuttlefish_utils",
"libfruit",
"libjsoncpp", // need to access host/libs/config/cuttlefish_config.h
diff --git a/host/libs/avb/avb.cpp b/host/libs/avb/avb.cpp
index 3b6732bd5..6ffa0aba6 100644
--- a/host/libs/avb/avb.cpp
+++ b/host/libs/avb/avb.cpp
@@ -17,45 +17,164 @@
#include "host/libs/avb/avb.h"
+#include <fcntl.h>
+
+#include <memory>
+#include <string>
+
+#include <fruit/fruit.h>
+
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/files.h"
+#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/known_paths.h"
namespace cuttlefish {
+namespace {
+
+constexpr char kAddHashFooter[] = "add_hash_footer";
+constexpr char kDefaultAlgorithm[] = "SHA256_RSA4096";
+constexpr char kInfoImage[] = "info_image";
+constexpr char kMakeVbmetaImage[] = "make_vbmeta_image";
+// Taken from external/avb/libavb/avb_slot_verify.c; this define is not in the
+// headers
+constexpr size_t kVbMetaMaxSize = 65536ul;
+
+} // namespace
+
+Avb::Avb(std::string avbtool_path) : avbtool_path_(std::move(avbtool_path)) {}
Avb::Avb(std::string avbtool_path, std::string algorithm, std::string key)
: avbtool_path_(std::move(avbtool_path)),
algorithm_(std::move(algorithm)),
key_(std::move(key)) {}
+Command Avb::GenerateAddHashFooter(const std::string& image_path,
+ const std::string& partition_name,
+ const off_t partition_size_bytes) const {
+ Command command(avbtool_path_);
+ command.AddParameter(kAddHashFooter);
+ if (!algorithm_.empty()) {
+ command.AddParameter("--algorithm");
+ command.AddParameter(algorithm_);
+ }
+ if (!key_.empty()) {
+ command.AddParameter("--key");
+ command.AddParameter(key_);
+ }
+ command.AddParameter("--image");
+ command.AddParameter(image_path);
+ command.AddParameter("--partition_name");
+ command.AddParameter(partition_name);
+ command.AddParameter("--partition_size");
+ command.AddParameter(partition_size_bytes);
+ return std::move(command);
+}
+
Result<void> Avb::AddHashFooter(const std::string& image_path,
const std::string& partition_name,
- off_t partition_size_bytes) const {
- int res;
-
- Command avb_cmd(avbtool_path_);
- avb_cmd.AddParameter("add_hash_footer");
- avb_cmd.AddParameter("--image");
- avb_cmd.AddParameter(image_path);
- avb_cmd.AddParameter("--partition_size");
- avb_cmd.AddParameter(partition_size_bytes);
- avb_cmd.AddParameter("--partition_name");
- avb_cmd.AddParameter(partition_name);
- avb_cmd.AddParameter("--key");
- avb_cmd.AddParameter(key_);
- avb_cmd.AddParameter("--algorithm");
- avb_cmd.AddParameter(algorithm_);
- res = avb_cmd.Start().Wait();
-
- CF_EXPECT(res == 0, "Unable to run avbtool. Exited with status " << res);
+ const off_t partition_size_bytes) const {
+ auto command =
+ GenerateAddHashFooter(image_path, partition_name, partition_size_bytes);
+ int exit_code = command.Start().Wait();
+ CF_EXPECTF(exit_code == 0, "Failure running {} {}. Exited with status {}",
+ command.Executable(), kAddHashFooter, exit_code);
+ return {};
+}
+
+Command Avb::GenerateInfoImage(const std::string& image_path,
+ const SharedFD& output_file) const {
+ Command command(avbtool_path_);
+ command.AddParameter(kInfoImage);
+ command.AddParameter("--image");
+ command.AddParameter(image_path);
+ command.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, output_file);
+ return command;
+}
+
+Result<void> Avb::WriteInfoImage(const std::string& image_path,
+ const std::string& output_path) const {
+ auto output_file = SharedFD::Creat(output_path, 0666);
+ CF_EXPECTF(output_file->IsOpen(), "Unable to create {} with error - {}",
+ output_path, output_file->StrError());
+ auto command = GenerateInfoImage(image_path, output_file);
+ int exit_code = command.Start().Wait();
+ CF_EXPECTF(exit_code == 0, "Failure running {} {}. Exited with status {}",
+ command.Executable(), kInfoImage, exit_code);
+ return {};
+}
+
+Command Avb::GenerateMakeVbMetaImage(
+ const std::string& output_path,
+ const std::vector<ChainPartition>& chained_partitions,
+ const std::vector<std::string>& included_partitions,
+ const std::vector<std::string>& extra_arguments) {
+ Command command(avbtool_path_);
+ command.AddParameter(kMakeVbmetaImage);
+ command.AddParameter("--algorithm");
+ command.AddParameter(algorithm_);
+ command.AddParameter("--key");
+ command.AddParameter(key_);
+ command.AddParameter("--output");
+ command.AddParameter(output_path);
+
+ for (const auto& partition : chained_partitions) {
+ const std::string argument = partition.name + ":" +
+ partition.rollback_index + ":" +
+ partition.key_path;
+ command.AddParameter("--chain_partition");
+ command.AddParameter(argument);
+ }
+ for (const auto& partition : included_partitions) {
+ command.AddParameter("--include_descriptors_from_image");
+ command.AddParameter(partition);
+ }
+ for (const auto& extra_arg : extra_arguments) {
+ command.AddParameter(extra_arg);
+ }
+ return command;
+}
+
+Result<void> Avb::MakeVbMetaImage(
+ const std::string& output_path,
+ const std::vector<ChainPartition>& chained_partitions,
+ const std::vector<std::string>& included_partitions,
+ const std::vector<std::string>& extra_arguments) {
+ auto command = GenerateMakeVbMetaImage(output_path, chained_partitions,
+ included_partitions, extra_arguments);
+ int exit_code = command.Start().Wait();
+ CF_EXPECTF(exit_code == 0, "Failure running {} {}. Exited with status {}",
+ command.Executable(), kMakeVbmetaImage, exit_code);
+ CF_EXPECT(EnforceVbMetaSize(output_path));
+ return {};
+}
+
+Result<void> EnforceVbMetaSize(const std::string& path) {
+ const auto vbmeta_size = FileSize(path);
+ CF_EXPECT_LE(vbmeta_size, kVbMetaMaxSize);
+ if (vbmeta_size != kVbMetaMaxSize) {
+ auto vbmeta_fd = SharedFD::Open(path, O_RDWR);
+ CF_EXPECTF(vbmeta_fd->IsOpen(), "Unable to open {} with error {}", path,
+ vbmeta_fd->StrError());
+ CF_EXPECTF(vbmeta_fd->Truncate(kVbMetaMaxSize) == 0,
+ "Truncating {} failed with error {}", path,
+ vbmeta_fd->StrError());
+ CF_EXPECTF(vbmeta_fd->Fsync() == 0, "fsync on {} failed with error {}",
+ path, vbmeta_fd->StrError());
+ }
return {};
}
+std::unique_ptr<Avb> GetDefaultAvb() {
+ return std::unique_ptr<Avb>(
+ new Avb(AvbToolBinary(), kDefaultAlgorithm, TestKeyRsa4096()));
+}
+
fruit::Component<Avb> CuttlefishKeyAvbComponent() {
- return fruit::createComponent().registerProvider([]() -> Avb* {
- return new Avb(HostBinaryPath("avbtool"), "SHA256_RSA4096",
- TestKeyRsa4096());
- });
+ return fruit::createComponent().registerProvider(
+ []() -> Avb* { return GetDefaultAvb().release(); });
}
} // namespace cuttlefish \ No newline at end of file
diff --git a/host/libs/avb/avb.h b/host/libs/avb/avb.h
index cc488c166..ac4a61b89 100644
--- a/host/libs/avb/avb.h
+++ b/host/libs/avb/avb.h
@@ -19,12 +19,30 @@
#include <sys/types.h>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
#include <fruit/fruit.h>
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/subprocess.h"
+
namespace cuttlefish {
+// Taken from external/avb/avbtool.py; this define is not in the headers
+inline constexpr uint64_t kMaxAvbMetadataSize = 69632ul;
+
+struct ChainPartition {
+ std::string name;
+ std::string rollback_index;
+ std::string key_path;
+};
+
class Avb {
public:
+ Avb(std::string avbtool_path);
Avb(std::string avbtool_path, std::string algorithm, std::string key);
/**
@@ -37,14 +55,36 @@ class Avb {
*/
Result<void> AddHashFooter(const std::string& image_path,
const std::string& partition_name,
- off_t partition_size_bytes) const;
+ const off_t partition_size_bytes) const;
+ Result<void> WriteInfoImage(const std::string& image_path,
+ const std::string& output_path) const;
+ Result<void> MakeVbMetaImage(
+ const std::string& output_path,
+ const std::vector<ChainPartition>& chained_partitions,
+ const std::vector<std::string>& included_partitions,
+ const std::vector<std::string>& extra_arguments);
private:
+ Command GenerateAddHashFooter(const std::string& image_path,
+ const std::string& partition_name,
+ const off_t partition_size_bytes) const;
+ Command GenerateInfoImage(const std::string& image_path,
+ const SharedFD& output_path) const;
+ Command GenerateMakeVbMetaImage(
+ const std::string& output_path,
+ const std::vector<ChainPartition>& chained_partitions,
+ const std::vector<std::string>& included_partitions,
+ const std::vector<std::string>& extra_arguments);
+
std::string avbtool_path_;
std::string algorithm_;
std::string key_;
};
+Result<void> EnforceVbMetaSize(const std::string& path);
+
+std::unique_ptr<Avb> GetDefaultAvb();
+
fruit::Component<Avb> CuttlefishKeyAvbComponent();
} // namespace cuttlefish
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 e4a924806..8de591aa8 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;
@@ -509,6 +508,7 @@ class CuttlefishConfig {
std::string persistent_bootconfig_path() const;
+ // used for the persistent_composite_disk vbmeta
std::string vbmeta_path() const;
std::string ap_vbmeta_path() const;
@@ -559,6 +559,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;
@@ -601,6 +602,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;
@@ -627,6 +631,7 @@ class CuttlefishConfig {
std::string vendor_boot_image() const;
std::string new_vendor_boot_image() const;
std::string vbmeta_image() const;
+ std::string new_vbmeta_image() const;
std::string vbmeta_system_image() const;
std::string vbmeta_vendor_dlkm_image() const;
std::string new_vbmeta_vendor_dlkm_image() const;
@@ -761,6 +766,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);
@@ -807,6 +813,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);
@@ -828,6 +838,7 @@ class CuttlefishConfig {
void set_vendor_boot_image(const std::string& vendor_boot_image);
void set_new_vendor_boot_image(const std::string& new_vendor_boot_image);
void set_vbmeta_image(const std::string& vbmeta_image);
+ void set_new_vbmeta_image(const std::string& new_vbmeta_image);
void set_vbmeta_system_image(const std::string& vbmeta_system_image);
void set_vbmeta_vendor_dlkm_image(
const std::string& vbmeta_vendor_dlkm_image);
@@ -969,6 +980,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 335c0621a..41c319e5b 100644
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ b/host/libs/config/cuttlefish_config_instance.cpp
@@ -192,6 +192,14 @@ void CuttlefishConfig::MutableInstanceSpecific::set_vbmeta_image(
const std::string& vbmeta_image) {
(*Dictionary())[kVbmetaImage] = vbmeta_image;
}
+static constexpr char kNewVbmetaImage[] = "new_vbmeta_image";
+std::string CuttlefishConfig::InstanceSpecific::new_vbmeta_image() const {
+ return (*Dictionary())[kNewVbmetaImage].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_new_vbmeta_image(
+ const std::string& new_vbmeta_image) {
+ (*Dictionary())[kNewVbmetaImage] = new_vbmeta_image;
+}
static constexpr char kVbmetaSystemImage[] = "vbmeta_system_image";
std::string CuttlefishConfig::InstanceSpecific::vbmeta_system_image() const {
return (*Dictionary())[kVbmetaSystemImage].asString();
@@ -740,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();
@@ -816,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 {
@@ -1247,7 +1281,7 @@ std::string CuttlefishConfig::InstanceSpecific::ap_composite_disk_path()
}
std::string CuttlefishConfig::InstanceSpecific::vbmeta_path() const {
- return AbsolutePath(PerInstancePath("vbmeta.img"));
+ return AbsolutePath(PerInstancePath("persistent_vbmeta.img"));
}
std::string CuttlefishConfig::InstanceSpecific::ap_vbmeta_path() const {
@@ -1713,8 +1747,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/config/known_paths.cpp b/host/libs/config/known_paths.cpp
index f8d3c4930..9303fa805 100644
--- a/host/libs/config/known_paths.cpp
+++ b/host/libs/config/known_paths.cpp
@@ -24,6 +24,8 @@ std::string AdbConnectorBinary() {
return HostBinaryPath("adb_connector");
}
+std::string AvbToolBinary() { return HostBinaryPath("avbtool"); }
+
std::string CasimirControlServerBinary() {
return HostBinaryPath("casimir_control_server");
}
diff --git a/host/libs/config/known_paths.h b/host/libs/config/known_paths.h
index 439197d93..0670b644d 100644
--- a/host/libs/config/known_paths.h
+++ b/host/libs/config/known_paths.h
@@ -20,6 +20,7 @@
namespace cuttlefish {
std::string AdbConnectorBinary();
+std::string AvbToolBinary();
std::string CasimirControlServerBinary();
std::string ConfigServerBinary();
std::string ConsoleForwarderBinary();
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_builder.cpp b/host/libs/vm_manager/crosvm_builder.cpp
index bef5a6eed..cb863db32 100644
--- a/host/libs/vm_manager/crosvm_builder.cpp
+++ b/host/libs/vm_manager/crosvm_builder.cpp
@@ -48,18 +48,14 @@ void CrosvmBuilder::ApplyProcessRestarter(
void CrosvmBuilder::AddControlSocket(const std::string& control_socket,
const std::string& executable_path) {
- command_.SetStopper([executable_path, control_socket](Subprocess* proc) {
+ auto stopper = [executable_path, control_socket]() {
Command stop_cmd(executable_path);
stop_cmd.AddParameter("stop");
stop_cmd.AddParameter(control_socket);
- if (stop_cmd.Start().Wait() == 0) {
- return StopperResult::kStopSuccess;
- }
- LOG(WARNING) << "Failed to stop VMM nicely, attempting to KILL";
- return KillSubprocess(proc) == StopperResult::kStopSuccess
- ? StopperResult::kStopCrash
- : StopperResult::kStopFailure;
- });
+ return stop_cmd.Start().Wait() == 0 ? StopperResult::kStopSuccess
+ : StopperResult::kStopFailure;
+ };
+ command_.SetStopper(KillSubprocessFallback(stopper));
command_.AddParameter("--socket=", control_socket);
}
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index 162219baa..c26da188e 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));
@@ -214,17 +219,12 @@ Result<VhostUserDeviceCommands> BuildVhostUserGpu(
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) {
+ gpu_device_logs_cmd.SetStopper(KillSubprocessFallback([](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;
- });
+ // TODO: b/335934714 - Make sure the process actually exits
+ bool res = kill(proc->pid(), SIGINT) == 0;
+ return res ? StopperResult::kStopSuccess : StopperResult::kStopFailure;
+ }));
const std::string crosvm_path = CF_EXPECT(CrosvmPathForVhostUserGpu(config));
@@ -312,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);
@@ -379,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);
@@ -456,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");
@@ -669,17 +684,12 @@ Result<std::vector<MonitorCommand>> CrosvmManager::StartCommands(
Command crosvm_log_tee_cmd(HostBinaryPath("log_tee"));
crosvm_log_tee_cmd.AddParameter("--process_name=crosvm");
crosvm_log_tee_cmd.AddParameter("--log_fd_in=", crosvm_logs);
- crosvm_log_tee_cmd.SetStopper([](Subprocess* proc) {
+ crosvm_log_tee_cmd.SetStopper(KillSubprocessFallback([](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;
- });
+ bool res = kill(proc->pid(), SIGINT) == 0;
+ // TODO: b/335934714 - Make sure the process actually exits
+ return res ? StopperResult::kStopSuccess : StopperResult::kStopFailure;
+ }));
// /dev/hvc2 = serial logging
// Serial port for logcat, redirected to a pipe
diff --git a/host/libs/vm_manager/gem5_manager.cpp b/host/libs/vm_manager/gem5_manager.cpp
index df62785a2..79a5e4ba7 100644
--- a/host/libs/vm_manager/gem5_manager.cpp
+++ b/host/libs/vm_manager/gem5_manager.cpp
@@ -280,11 +280,6 @@ Result<std::vector<MonitorCommand>> Gem5Manager::StartCommands(
const CuttlefishConfig& config, std::vector<VmmDependencyCommand*>&) {
auto instance = config.ForDefaultInstance();
- auto stop = [](Subprocess* proc) {
- return KillSubprocess(proc) == StopperResult::kStopSuccess
- ? StopperResult::kStopCrash
- : StopperResult::kStopFailure;
- };
std::string gem5_binary = instance.gem5_binary_dir();
switch (arch_) {
case Arch::Arm:
@@ -302,7 +297,7 @@ Result<std::vector<MonitorCommand>> Gem5Manager::StartCommands(
// generate Gem5 starter_fs.py before we execute it
GenerateGem5File(config, instance);
- Command gem5_cmd(gem5_binary, stop);
+ Command gem5_cmd(gem5_binary);
// Always enable listeners, because auto mode will disable once it detects
// gem5 is not run interactively
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index 38fead7b7..0f300d41d 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -51,7 +51,7 @@ std::string GetMonitorPath(const CuttlefishConfig& config) {
"qemu_monitor.sock");
}
-bool Stop() {
+StopperResult Stop() {
auto config = CuttlefishConfig::Get();
auto monitor_path = GetMonitorPath(*config);
auto monitor_sock = SharedFD::SocketLocalClient(
@@ -59,7 +59,7 @@ bool Stop() {
if (!monitor_sock->IsOpen()) {
LOG(ERROR) << "The connection to qemu is closed, is it still running?";
- return false;
+ return StopperResult::kStopFailure;
}
char msg[] = "{\"execute\":\"qmp_capabilities\"}{\"execute\":\"quit\"}";
ssize_t len = sizeof(msg) - 1;
@@ -67,7 +67,7 @@ bool Stop() {
int tmp = monitor_sock->Write(msg, len);
if (tmp < 0) {
LOG(ERROR) << "Error writing to socket: " << monitor_sock->StrError();
- return false;
+ return StopperResult::kStopFailure;
}
len -= tmp;
}
@@ -78,7 +78,7 @@ bool Stop() {
LOG(INFO) << "From qemu monitor: " << buff;
}
- return true;
+ return StopperResult::kStopSuccess;
}
Result<std::pair<int, int>> GetQemuVersion(const std::string& qemu_binary) {
@@ -216,18 +216,6 @@ QemuManager::ConfigureBootDevices(
Result<std::vector<MonitorCommand>> QemuManager::StartCommands(
const CuttlefishConfig& config, std::vector<VmmDependencyCommand*>&) {
auto instance = config.ForDefaultInstance();
-
- auto stop = [](Subprocess* proc) {
- auto stopped = Stop();
- if (stopped) {
- return StopperResult::kStopSuccess;
- }
- LOG(WARNING) << "Failed to stop VMM nicely, "
- << "attempting to KILL";
- return KillSubprocess(proc) == StopperResult::kStopSuccess
- ? StopperResult::kStopCrash
- : StopperResult::kStopFailure;
- };
std::string qemu_binary = instance.qemu_binary_dir();
switch (arch_) {
case Arch::Arm:
@@ -248,7 +236,7 @@ Result<std::vector<MonitorCommand>> QemuManager::StartCommands(
}
auto qemu_version = CF_EXPECT(GetQemuVersion(qemu_binary));
- Command qemu_cmd(qemu_binary, stop);
+ Command qemu_cmd(qemu_binary, KillSubprocessFallback(Stop));
int hvc_num = 0;
int serial_num = 0;
@@ -819,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/shared/chd/chd_debug.prop b/shared/chd/chd_debug.prop
index 163a293b7..9e9de7abc 100644
--- a/shared/chd/chd_debug.prop
+++ b/shared/chd/chd_debug.prop
@@ -21,3 +21,6 @@
# Disable adb authentication to allow test automation for CHD.
ro.adb.secure=0
+
+# Allow 'adb root' on user build CHD
+ro.debuggable=1
diff --git a/system_image/Android.bp b/system_image/Android.bp
index fff8482bf..062ff2068 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",
@@ -187,6 +188,7 @@ android_system_image {
"e2freefrag",
"e2fsck",
"e2fsdroid",
+ "etc_hosts",
"evemu-record",
"extra_free_kbytes",
"fastbootd",
@@ -230,6 +232,7 @@ android_system_image {
"incident-helper-cmd",
"incident",
"incidentd",
+ "init-debug.rc",
"init_first_stage",
"init.boringssl.zygote64_32.rc",
"init.boringssl.zygote64.rc",
@@ -259,12 +262,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",
@@ -288,6 +293,7 @@ android_system_image {
"libaudioutils",
"libaudioutils",
"libbinder_ndk",
+ "libbinder_rpc_unstable",
"libbinder",
"libblas",
"libbootloader_message",
@@ -351,6 +357,8 @@ android_system_image {
"libhidcommand_jni",
"libhidlmemory",
"libhidlmemory",
+ "libhidltransport",
+ "libhwbinder",
"libincident",
"libinput",
"libinputflinger",
@@ -377,6 +385,7 @@ android_system_image {
"libnetd_client",
"libnetlink",
"libnetutils",
+ "libneuralnetworks_packageinfo",
"libnfc_nci_jni",
"libnl",
"libOpenglCodecCommon",
@@ -423,6 +432,7 @@ android_system_image {
"libsync",
"libsysutils",
"libtinyxml2",
+ "libtombstoned_client",
"libtracingproxy",
"libui",
"libuinputcommand_jni",
@@ -450,6 +460,7 @@ android_system_image {
"logcatd",
"logd",
"logpersist.start",
+ "logtagd.rc",
"logwrapper",
"lpdump",
"lpdumpd",
@@ -457,6 +468,7 @@ android_system_image {
"make_f2fs",
"mapper.minigbm",
"mdnsd",
+ "media_profiles_V1_0.dtd",
"mediacodec.policy",
"mediaextractor",
"mediametrics",
@@ -680,7 +692,6 @@ android_system_image {
"ping",
"ping6",
"pintool",
- "plat_sepolicy_and_mapping.sha256",
"platform.xml",
"pm",
"power.default",
@@ -691,6 +702,7 @@ android_system_image {
"preinstalled-packages-platform-handheld-system.xml",
"preinstalled-packages-platform-telephony-product.xml",
"preinstalled-packages-platform.xml",
+ "preinstalled-packages-strict-signature.xml",
"preloads_copy.sh",
"preloads_copy.sh",
"preopt2cachename",
@@ -721,7 +733,6 @@ android_system_image {
"screenrecord",
"sdcard",
"secdiscard",
- "secilc",
"sensorservice",
"server_configurable_flags",
"service",
@@ -731,6 +742,7 @@ android_system_image {
"settaskprofile",
"settings",
"sfdo",
+ "sgdisk",
"sh",
"showmap",
"simpleperf_app_runner",
@@ -803,38 +815,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: {
@@ -850,6 +830,7 @@ android_system_image {
"androidx.camera.extensions.impl",
"androidx.window.extensions",
"androidx.window.sidecar",
+ "aosp_mainline_modules",
"BackupRestoreConfirmation",
"BasicDreams",
"BlockedNumberProvider",
@@ -872,15 +853,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",
@@ -891,6 +866,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",
@@ -915,20 +892,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",
@@ -961,7 +927,9 @@ android_system_image {
"ExternalStorageProvider",
"ExtShared",
"framework-graphics",
+ "framework-location",
"framework-minus-apex-install-dependencies",
+ "framework-nfc",
"framework-res",
"FusedLocation",
"fuseMedia.o",
@@ -982,6 +950,7 @@ android_system_image {
"LiveWallpapersPicker",
"llndk.libraries.txt",
"LocalTransport",
+ "lockagent",
"ManagedProvisioning",
"MediaProviderLegacy",
"messaging",
@@ -998,14 +967,6 @@ android_system_image {
"PacProcessor",
"PartnerBookmarksProvider",
"PhotoTable",
- "plat_file_contexts",
- "plat_hwservice_contexts",
- "plat_keystore2_key_contexts",
- "plat_mapping_file",
- "plat_property_contexts",
- "plat_seapp_contexts",
- "plat_sepolicy.cil",
- "plat_service_contexts",
"PrintRecommendationService",
"PrintSpooler",
"Provision",
@@ -1013,6 +974,7 @@ android_system_image {
"QualifiedNetworksService",
"QuickSearchBox",
"SecureElement",
+ "selinux_policy_system_soong",
"services",
"Settings",
"SettingsIntelligence",
@@ -1035,36 +997,24 @@ android_system_image {
"TeleService",
"timeInState.o",
"Traceur",
- "userdebug_plat_sepolicy.cil",
"UserDictionaryProvider",
"voip-common",
"VpnDialogs",
"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",
],
diff --git a/tests/snapshot/OWNERS b/tests/snapshot/OWNERS
new file mode 100644
index 000000000..671026eed
--- /dev/null
+++ b/tests/snapshot/OWNERS
@@ -0,0 +1,3 @@
+fmayle@google.com
+khei@google.com
+smoreland@google.com
diff --git a/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java b/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java
index 19b36ecda..d1e071c4f 100644
--- a/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java
+++ b/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java
@@ -44,7 +44,7 @@ public class SnapshotTest extends BaseHostJUnit4Test {
@Option(
name = "test-count",
description = "Number of times to restore the device back to snapshot state.")
- private int mTestCount = 1;
+ private int mTestCount = 10;
@Test
public void testSnapshot() throws Exception {
diff --git a/tests/wmediumd_control/Android.bp b/tests/wmediumd_control/Android.bp
index e23cf2921..e62321b32 100644
--- a/tests/wmediumd_control/Android.bp
+++ b/tests/wmediumd_control/Android.bp
@@ -35,5 +35,6 @@ java_test_host {
"cuttlefish_host_test_utils",
"platform-test-annotations",
"WmediumdServerProto_java",
+ "libprotobuf-java-util-full",
],
}
diff --git a/tools/launch_cvd_arm64_server_docker.sh b/tools/launch_cvd_arm64_server_docker.sh
index 7979cddd6..ac1a9392c 100755
--- a/tools/launch_cvd_arm64_server_docker.sh
+++ b/tools/launch_cvd_arm64_server_docker.sh
@@ -140,6 +140,19 @@ ssh $server \
done"
echo -e "Done"
+# extract cvd-host_package.tar.gz with /:extract API if the API exists
+ssh $server \
+ "job_id=\$(curl -s -k -X POST ${host_orchestrator_url}/userartifacts/$user_artifacts_dir/cvd-host_package.tar.gz/:extract | jq -r '.name' 2>/dev/null) && \
+ if [[ \$job_id != \"\" ]]; then \
+ echo Extracting cvd-host_package.tar.gz ... && \
+ job_done=\"false\" && \
+ while [[ \$job_done == \"false\" ]]; do \
+ sleep 1 && \
+ job_done=\$(curl -s -k ${host_orchestrator_url}/operations/\$job_id | jq -r '.done'); \
+ done && \
+ echo Done; \
+ fi"
+
echo -e "Creating image from root docker container"
root_image_id=$(ssh $server -t "docker commit $root_container_id cvd_root_image:$root_container_id")
root_image_id=${root_image_id//$'\r'} # to remove trailing ^M