Merge "Slightly increase testRilConnets timeout"
diff --git a/common/frontend/socket_vsock_proxy/main.cpp b/common/frontend/socket_vsock_proxy/main.cpp
index 5d08790..783ad06 100644
--- a/common/frontend/socket_vsock_proxy/main.cpp
+++ b/common/frontend/socket_vsock_proxy/main.cpp
@@ -19,6 +19,7 @@
#include <gflags/gflags.h>
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/contains.h"
#include "common/libs/utils/socket2socket_proxy.h"
#include "host/commands/kernel_log_monitor/utils.h"
@@ -112,7 +113,7 @@
bool socketErrorIsRecoverable(int error) {
std::set<int> unrecoverable{EACCES, EAFNOSUPPORT, EINVAL, EPROTONOSUPPORT};
- return unrecoverable.find(error) == unrecoverable.end();
+ return !cuttlefish::Contains(unrecoverable, error);
}
[[noreturn]] static void SleepForever() {
diff --git a/common/libs/confui/protocol_types.cpp b/common/libs/confui/protocol_types.cpp
index 8c293ea..e5b68e2 100644
--- a/common/libs/confui/protocol_types.cpp
+++ b/common/libs/confui/protocol_types.cpp
@@ -21,6 +21,7 @@
#include "common/libs/confui/packet.h"
#include "common/libs/confui/utils.h"
+#include "common/libs/utils/contains.h"
namespace cuttlefish {
namespace confui {
@@ -40,7 +41,7 @@
{ConfUiCmd::kAbort, "kAbort"},
{ConfUiCmd::kUserInputEvent, "kUserInputEvent"},
{ConfUiCmd::kUserInputEvent, "kUserTouchEvent"}};
- if (look_up_tab.find(cmd) != look_up_tab.end()) {
+ if (Contains(look_up_tab, cmd)) {
return look_up_tab[cmd] + suffix;
}
return "kUnknown" + suffix;
@@ -73,7 +74,7 @@
{"kUserInputEvent", ConfUiCmd::kUserInputEvent},
{"kUserTouchEvent", ConfUiCmd::kUserTouchEvent},
};
- if (cmds.find(cmd_str) != cmds.end()) {
+ if (Contains(cmds, cmd_str)) {
return cmds[cmd_str];
}
return ConfUiCmd::kUnknown;
diff --git a/common/libs/utils/contains.h b/common/libs/utils/contains.h
index 9dea1fc..70923f5 100644
--- a/common/libs/utils/contains.h
+++ b/common/libs/utils/contains.h
@@ -25,37 +25,42 @@
*
* The function returns true if container has the key, or false.
*
- * If the container has a find(key) method (e.g. set, unordered_set, etc), the
- * find method is used. Otherwise, the std::find function from algorithm is
- * used, which may result in a linear search.
+ * If the container has a find(key) method (e.g. set, unordered_set, std::map,
+ * etc), the find method is used. Otherwise, the std::find function from
+ * algorithm is used, which may result in a linear search.
+ *
*/
namespace cuttlefish {
namespace contains_internal_impl {
-template <typename Container>
-using ElemType = decltype(*(std::cbegin(std::declval<Container&>())));
+template <typename Container, typename Key>
+using CheckFindMethodType =
+ decltype(void(std::declval<Container&>().find(std::declval<Key&>())));
-template <typename Container>
-using CheckFindMethodType = decltype(void(
- std::declval<Container&>().find(std::declval<ElemType<Container&>>())));
-
-template <typename Container, typename = void>
+template <typename Container, typename T, typename = void>
struct HasFindImpl : std::false_type {};
-template <typename Container>
-struct HasFindImpl<Container, CheckFindMethodType<Container>> : std::true_type {
-};
+template <typename Container, typename T>
+struct HasFindImpl<Container, T, CheckFindMethodType<Container, T>>
+ : std::true_type {};
} // namespace contains_internal_impl
// TODO(kwstephenkim): Replace these when C++20 starts to be used.
-template <typename Container, typename U>
-bool Contains(Container&& container, U&& u) {
- if constexpr (contains_internal_impl::HasFindImpl<Container>::value) {
- // using O(1) or O(lgN) find()
- return container.find(std::forward<U>(u)) != container.end();
- }
- // using std::find, which is likely O(n)
+template <typename Container, typename U,
+ typename = std::enable_if_t<
+ contains_internal_impl::HasFindImpl<Container, U>::value, void>>
+constexpr bool Contains(Container&& container, U&& u) {
+ // using O(1) or O(lgN) find()
+ return container.find(std::forward<U>(u)) != container.end();
+}
+
+template <
+ typename Container, typename U,
+ std::enable_if_t<!contains_internal_impl::HasFindImpl<Container, U>::value,
+ int> = 0>
+constexpr bool Contains(Container&& container, U&& u) {
+ // falls back to a generic, likely linear search
const auto itr =
std::find(std::begin(container), std::end(container), std::forward<U>(u));
return itr != std::end(container);
diff --git a/common/libs/utils/users.cpp b/common/libs/utils/users.cpp
index 0e38f6c..dc434ce 100644
--- a/common/libs/utils/users.cpp
+++ b/common/libs/utils/users.cpp
@@ -33,6 +33,8 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include "common/libs/utils/contains.h"
+
namespace cuttlefish {
namespace {
gid_t GroupIdFromName(const std::string& group_name) {
@@ -91,11 +93,7 @@
}
auto groups = GetSuplementaryGroups();
-
- if (std::find(groups.cbegin(), groups.cend(), gid) != groups.cend()) {
- return true;
- }
- return false;
+ return Contains(groups, gid);
}
Result<std::string> SystemWideUserHome(const uid_t uid) {
diff --git a/guest/hals/keymint/remote/Android.bp b/guest/hals/keymint/remote/Android.bp
index 1f7a16e..748a0ec 100644
--- a/guest/hals/keymint/remote/Android.bp
+++ b/guest/hals/keymint/remote/Android.bp
@@ -32,6 +32,7 @@
"-Wextra",
],
shared_libs: [
+ "android.hardware.security.rkp-V3-ndk",
"android.hardware.security.secureclock-V1-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"lib_android_keymaster_keymint_utils",
diff --git a/guest/hals/keymint/remote/remote_keymaster.cpp b/guest/hals/keymint/remote/remote_keymaster.cpp
index 2387df6..a725c45 100644
--- a/guest/hals/keymint/remote/remote_keymaster.cpp
+++ b/guest/hals/keymint/remote/remote_keymaster.cpp
@@ -111,6 +111,48 @@
}
}
+ // Pass attestation IDs to the remote KM implementation.
+ // Skip IMEI and MEID as those aren't present on emulators.
+ SetAttestationIdsRequest request(message_version());
+
+ static constexpr char brand_prop_name[] = "ro.product.brand";
+ static constexpr char device_prop_name[] = "ro.product.device";
+ static constexpr char product_prop_name[] = "ro.product.name";
+ static constexpr char serial_prop_name[] = "ro.serialno";
+ static constexpr char manufacturer_prop_name[] = "ro.product.manufacturer";
+ static constexpr char model_prop_name[] = "ro.product.model";
+
+ std::string brand_prop_value =
+ android::base::GetProperty(brand_prop_name, "");
+ std::string device_prop_value =
+ android::base::GetProperty(device_prop_name, "");
+ std::string product_prop_value =
+ android::base::GetProperty(product_prop_name, "");
+ std::string serial_prop_value =
+ android::base::GetProperty(serial_prop_name, "");
+ std::string manufacturer_prop_value =
+ android::base::GetProperty(manufacturer_prop_name, "");
+ std::string model_prop_value =
+ android::base::GetProperty(model_prop_name, "");
+
+ request.brand.Reinitialize(brand_prop_value.data(), brand_prop_value.size());
+ request.device.Reinitialize(device_prop_value.data(),
+ device_prop_value.size());
+ request.product.Reinitialize(product_prop_value.data(),
+ product_prop_value.size());
+ request.serial.Reinitialize(serial_prop_value.data(),
+ serial_prop_value.size());
+ request.manufacturer.Reinitialize(manufacturer_prop_value.data(),
+ manufacturer_prop_value.size());
+ request.model.Reinitialize(model_prop_value.data(), model_prop_value.size());
+
+ SetAttestationIdsResponse response = SetAttestationIds(request);
+ if (response.error != KM_ERROR_OK) {
+ LOG(ERROR) << "Failed to configure keymaster attestation IDs: "
+ << response.error;
+ return false;
+ }
+
return true;
}
@@ -332,4 +374,11 @@
return response;
}
+SetAttestationIdsResponse RemoteKeymaster::SetAttestationIds(
+ const SetAttestationIdsRequest& request) {
+ SetAttestationIdsResponse response(message_version());
+ ForwardCommand(SET_ATTESTATION_IDS, request, &response);
+ return response;
+}
+
} // namespace keymaster
diff --git a/guest/hals/keymint/remote/remote_keymaster.h b/guest/hals/keymint/remote/remote_keymaster.h
index 85d38e4..1e24672 100644
--- a/guest/hals/keymint/remote/remote_keymaster.h
+++ b/guest/hals/keymint/remote/remote_keymaster.h
@@ -98,6 +98,8 @@
GenerateTimestampTokenResponse* response);
GetRootOfTrustResponse GetRootOfTrust(const GetRootOfTrustRequest& request);
GetHwInfoResponse GetHwInfo();
+ SetAttestationIdsResponse SetAttestationIds(
+ const SetAttestationIdsRequest& request);
// CF HAL and remote sides are always compiled together, so will never
// disagree about message versions.
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.cpp b/guest/hals/keymint/remote/remote_keymint_operation.cpp
index aa05035..59624a5 100644
--- a/guest/hals/keymint/remote/remote_keymint_operation.cpp
+++ b/guest/hals/keymint/remote/remote_keymint_operation.cpp
@@ -102,7 +102,7 @@
const optional<vector<uint8_t>>& signature, //
const optional<HardwareAuthToken>& authToken,
const optional<TimeStampToken>& /* timestampToken */,
- const optional<vector<uint8_t>>& /* confirmationToken */,
+ const optional<vector<uint8_t>>& confirmationToken,
vector<uint8_t>* output) {
if (!output) {
return ScopedAStatus(AStatus_fromServiceSpecificError(
@@ -120,6 +120,11 @@
request.additional_params.push_back(keymaster::TAG_AUTH_TOKEN,
tokenAsVec.data(), tokenAsVec.size());
}
+ if (confirmationToken) {
+ request.additional_params.push_back(keymaster::TAG_CONFIRMATION_TOKEN,
+ confirmationToken->data(),
+ confirmationToken->size());
+ }
FinishOperationResponse response(impl_.message_version());
impl_.FinishOperation(request, &response);
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index f8b2702..75af31c 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -51,8 +51,6 @@
"will be reset to the state it was initially launched "
"in. This flag is ignored if the underlying partition "
"images have been updated since the first launch.");
-DEFINE_int32(modem_simulator_count, CF_DEFAULTS_MODEM_SIMULATOR_COUNT,
- "Modem simulator count corresponding to maximum sim number");
DECLARE_bool(use_overlay);
@@ -168,10 +166,15 @@
// SaveConfig line below. Don't launch cuttlefish subprocesses between these
// two operations, as those will assume they can read the config object from
// disk.
- auto config = CF_EXPECT(InitializeCuttlefishConfiguration(
- FLAGS_instance_dir, FLAGS_modem_simulator_count,
- kernel_configs, injector, fetcher_config),
- "cuttlefish configuration initialization failed");
+ auto config = CF_EXPECT(
+ InitializeCuttlefishConfiguration(FLAGS_instance_dir, kernel_configs,
+ injector, fetcher_config),
+ "cuttlefish configuration initialization failed");
+
+ // take the max value of modem_simulator_instance_number in each instance
+ // which is used for preserving/deleting iccprofile_for_simX.xml files
+ int modem_simulator_count = 0;
+
std::set<std::string> preserving;
bool creating_os_disk = false;
// if any device needs to rebuild its composite disk,
@@ -179,6 +182,9 @@
for (const auto& instance : config.Instances()) {
auto os_builder = OsCompositeDiskBuilder(config, instance);
creating_os_disk |= CF_EXPECT(os_builder.WillRebuildCompositeDisk());
+ if (instance.modem_simulator_instance_number() > modem_simulator_count) {
+ modem_simulator_count = instance.modem_simulator_instance_number();
+ }
}
// TODO(schuffelen): Add smarter decision for when to delete runtime files.
// Files like NVChip are tightly bound to Android keymint and should be
@@ -214,7 +220,7 @@
preserving.insert("uboot_env.img");
preserving.insert("factory_reset_protected.img");
std::stringstream ss;
- for (int i = 0; i < FLAGS_modem_simulator_count; i++) {
+ for (int i = 0; i < modem_simulator_count; i++) {
ss.clear();
ss << "iccprofile_for_sim" << i << ".xml";
preserving.insert(ss.str());
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index 30e1fe6..56b3ca2 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -126,10 +126,11 @@
DEFINE_string(use_allocd, CF_DEFAULTS_USE_ALLOCD?"true":"false",
"Acquire static resources from the resource allocator daemon.");
-DEFINE_bool(enable_minimal_mode, CF_DEFAULTS_ENABLE_MINIMAL_MODE,
- "Only enable the minimum features to boot a cuttlefish device and "
- "support minimal UI interactions.\nNote: Currently only supports "
- "handheld/phone targets");
+DEFINE_string(
+ enable_minimal_mode, CF_DEFAULTS_ENABLE_MINIMAL_MODE ? "true" : "false",
+ "Only enable the minimum features to boot a cuttlefish device and "
+ "support minimal UI interactions.\nNote: Currently only supports "
+ "handheld/phone targets");
DEFINE_string(
pause_in_bootloader, CF_DEFAULTS_PAUSE_IN_BOOTLOADER?"true":"false",
"Stop the bootflow in u-boot. You can continue the boot by connecting "
@@ -250,7 +251,7 @@
DEFINE_string(uuid, CF_DEFAULTS_UUID,
"UUID to use for the device. Random if not specified");
-DEFINE_bool(daemon, CF_DEFAULTS_DAEMON,
+DEFINE_string(daemon, CF_DEFAULTS_DAEMON?"true":"false",
"Run cuttlefish in background, the launcher exits on boot "
"completed/failed");
@@ -310,11 +311,13 @@
"Local fixed location file path for the gnss proxy");
// by default, this modem-simulator is disabled
-DEFINE_bool(enable_modem_simulator, CF_DEFAULTS_ENABLE_MODEM_SIMULATOR,
- "Enable the modem simulator to process RILD AT commands");
+DEFINE_string(enable_modem_simulator,
+ CF_DEFAULTS_ENABLE_MODEM_SIMULATOR ? "true" : "false",
+ "Enable the modem simulator to process RILD AT commands");
// modem_simulator_sim_type=2 for test CtsCarrierApiTestCases
-DEFINE_int32(modem_simulator_sim_type, CF_DEFAULTS_MODEM_SIMULATOR_SIM_TYPE,
- "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
+DEFINE_string(modem_simulator_sim_type,
+ std::to_string(CF_DEFAULTS_MODEM_SIMULATOR_SIM_TYPE),
+ "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
DEFINE_bool(console, CF_DEFAULTS_CONSOLE, "Enable the serial console");
@@ -390,6 +393,10 @@
"Capture disk writes an overlay. This is a "
"prerequisite for powerwash_cvd or multiple instances.");
+DEFINE_string(modem_simulator_count,
+ std::to_string(CF_DEFAULTS_MODEM_SIMULATOR_COUNT),
+ "Modem simulator count corresponding to maximum sim number");
+
DECLARE_string(assembly_dir);
DECLARE_string(boot_image);
DECLARE_string(system_image_dir);
@@ -587,7 +594,7 @@
} // namespace
Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
- const std::string& root_dir, int modem_simulator_count,
+ const std::string& root_dir,
const std::vector<KernelConfig>& kernel_configs,
fruit::Injector<>& injector, const FetcherConfig& fetcher_config) {
CuttlefishConfig tmp_config_obj;
@@ -605,8 +612,9 @@
std::vector<std::string> vm_manager_vec =
android::base::Split(FLAGS_vm_manager, ",");
for (int i=1; i<vm_manager_vec.size(); i++) {
- CHECK(vm_manager_vec[0]==vm_manager_vec[i])
- << "All instances should have same vm_manager, " << FLAGS_vm_manager;
+ CF_EXPECT(
+ vm_manager_vec[0] == vm_manager_vec[i],
+ "All instances should have same vm_manager, " << FLAGS_vm_manager);
}
// TODO(weihsu), b/250988697: these should move to instance,
@@ -746,16 +754,9 @@
auto udp_range = ParsePortRange(FLAGS_udp_port_range);
tmp_config_obj.set_webrtc_udp_port_range(udp_range);
- tmp_config_obj.set_enable_modem_simulator(FLAGS_enable_modem_simulator &&
- !FLAGS_enable_minimal_mode);
- tmp_config_obj.set_modem_simulator_instance_number(modem_simulator_count);
- tmp_config_obj.set_modem_simulator_sim_type(FLAGS_modem_simulator_sim_type);
-
tmp_config_obj.set_webrtc_enable_adb_websocket(
FLAGS_webrtc_enable_adb_websocket);
- tmp_config_obj.set_run_as_daemon(FLAGS_daemon);
-
tmp_config_obj.set_enable_gnss_grpc_proxy(FLAGS_start_gnss_proxy);
tmp_config_obj.set_enable_vehicle_hal_grpc_server(
@@ -771,8 +772,6 @@
tmp_config_obj.set_ril_dns(FLAGS_ril_dns);
- tmp_config_obj.set_enable_minimal_mode(FLAGS_enable_minimal_mode);
-
tmp_config_obj.set_vhost_net(FLAGS_vhost_net);
tmp_config_obj.set_vhost_user_mac80211_hwsim(FLAGS_vhost_user_mac80211_hwsim);
@@ -850,6 +849,16 @@
android::base::Split(FLAGS_use_sdcard, ",");
std::vector<std::string> pause_in_bootloader_vec =
android::base::Split(FLAGS_pause_in_bootloader, ",");
+ std::vector<std::string> daemon_vec =
+ android::base::Split(FLAGS_daemon, ",");
+ std::vector<std::string> enable_minimal_mode_vec =
+ android::base::Split(FLAGS_enable_minimal_mode, ",");
+ std::vector<std::string> enable_modem_simulator_vec =
+ android::base::Split(FLAGS_enable_modem_simulator, ",");
+ std::vector<std::string> modem_simulator_count_vec =
+ android::base::Split(FLAGS_modem_simulator_count, ",");
+ std::vector<std::string> modem_simulator_sim_type_vec =
+ android::base::Split(FLAGS_modem_simulator_sim_type, ",");
// new instance specific flags (moved from common flags)
std::vector<std::string> gem5_binary_dirs =
@@ -923,15 +932,16 @@
int vsock_guest_cid_int;
if (instance_index < vsock_guest_cid_vec.size()) {
- CHECK(android::base::ParseInt(vsock_guest_cid_vec[instance_index].c_str(),
- &vsock_guest_cid_int))
- << "Failed to parse value \"" << vsock_guest_cid_vec[instance_index]
- << "\" for vsock_guest_cid";
+ CF_EXPECT(
+ android::base::ParseInt(vsock_guest_cid_vec[instance_index].c_str(),
+ &vsock_guest_cid_int),
+ "Failed to parse value \"" << vsock_guest_cid_vec[instance_index]
+ << "\" for vsock_guest_cid");
} else {
- CHECK(android::base::ParseInt(vsock_guest_cid_vec[0].c_str(),
- &vsock_guest_cid_int))
- << "Failed to parse value \"" << vsock_guest_cid_vec[0]
- << "\" for vsock_guest_cid";
+ CF_EXPECT(android::base::ParseInt(vsock_guest_cid_vec[0].c_str(),
+ &vsock_guest_cid_int),
+ "Failed to parse value \"" << vsock_guest_cid_vec[0]
+ << "\" for vsock_guest_cid");
}
// call this before all stuff that has vsock server: e.g. touchpad, keyboard, etc
@@ -945,53 +955,55 @@
int cpus_int;
if (instance_index < cpus_vec.size()) {
- CHECK(android::base::ParseInt(cpus_vec[instance_index].c_str(),&cpus_int))
- << "Failed to parse value \"" << cpus_vec[instance_index]
- << "\" for cpus";
+ CF_EXPECT(
+ android::base::ParseInt(cpus_vec[instance_index].c_str(), &cpus_int),
+ "Failed to parse value \"" << cpus_vec[instance_index]
+ << "\" for cpus");
} else {
- CHECK(android::base::ParseInt(cpus_vec[0].c_str(),&cpus_int))
- << "Failed to parse value \"" << cpus_vec[0]
- << "\" for cpus";
+ CF_EXPECT(android::base::ParseInt(cpus_vec[0].c_str(), &cpus_int),
+ "Failed to parse value \"" << cpus_vec[0] << "\" for cpus");
}
instance.set_cpus(cpus_int);
// TODO(weihsu): before vectorizing smt flag,
// make sure all instances have multiple of 2 then SMT mode
// if any of instance doesn't have multiple of 2 then NOT SMT
- CHECK(!FLAGS_smt || cpus_int % 2 == 0)
- << "CPUs must be a multiple of 2 in SMT mode";
+ CF_EXPECT(!FLAGS_smt || cpus_int % 2 == 0,
+ "CPUs must be a multiple of 2 in SMT mode");
// new instance specific flags (moved from common flags)
- CHECK(instance_index<kernel_configs.size())
- << "instance_index " << instance_index << " out of boundary " << kernel_configs.size();
+ CF_EXPECT(instance_index < kernel_configs.size(),
+ "instance_index " << instance_index << " out of boundary "
+ << kernel_configs.size());
instance.set_target_arch(kernel_configs[instance_index].target_arch);
instance.set_console(FLAGS_console);
instance.set_kgdb(FLAGS_console && FLAGS_kgdb);
int blank_data_image_mb_int;
if (instance_index < blank_data_image_mb_vec.size()) {
- CHECK(android::base::ParseInt(blank_data_image_mb_vec[instance_index].c_str(),
- &blank_data_image_mb_int))
- << "Failed to parse value \"" << blank_data_image_mb_vec[instance_index]
- << "\" for blank_data_image_mb";
+ CF_EXPECT(android::base::ParseInt(
+ blank_data_image_mb_vec[instance_index].c_str(),
+ &blank_data_image_mb_int),
+ "Failed to parse value \""
+ << blank_data_image_mb_vec[instance_index]
+ << "\" for blank_data_image_mb");
} else {
- CHECK(android::base::ParseInt(blank_data_image_mb_vec[0].c_str(),
- &blank_data_image_mb_int))
- << "Failed to parse value \"" << blank_data_image_mb_vec[0]
- << "\" for blank_data_image_mb";
+ CF_EXPECT(android::base::ParseInt(blank_data_image_mb_vec[0].c_str(),
+ &blank_data_image_mb_int),
+ "Failed to parse value \"" << blank_data_image_mb_vec[0]
+ << "\" for blank_data_image_mb");
}
instance.set_blank_data_image_mb(blank_data_image_mb_int);
int gdb_port_int;
if (instance_index < gdb_port_vec.size()) {
- CHECK(android::base::ParseInt(gdb_port_vec[instance_index].c_str(),
- &gdb_port_int))
- << "Failed to parse value \"" << gdb_port_vec[instance_index]
- << "\" for gdb_port";
+ CF_EXPECT(android::base::ParseInt(gdb_port_vec[instance_index].c_str(),
+ &gdb_port_int),
+ "Failed to parse value \"" << gdb_port_vec[instance_index]
+ << "\" for gdb_port");
} else {
- CHECK(android::base::ParseInt(gdb_port_vec[0].c_str(),
- &gdb_port_int))
- << "Failed to parse value \"" << gdb_port_vec[0]
- << "\" for gdb_port";
+ CF_EXPECT(
+ android::base::ParseInt(gdb_port_vec[0].c_str(), &gdb_port_int),
+ "Failed to parse value \"" << gdb_port_vec[0] << "\" for gdb_port");
}
instance.set_gdb_port(gdb_port_int);
@@ -1015,43 +1027,45 @@
int x_res = 0;
if (instance_index < x_res_vec.size()) {
- CHECK(android::base::ParseInt(x_res_vec[instance_index].c_str(), &x_res))
- << "Failed to parse value \"" << x_res_vec[instance_index]
- << "\" for x_res";
+ CF_EXPECT(
+ android::base::ParseInt(x_res_vec[instance_index].c_str(), &x_res),
+ "Failed to parse value \"" << x_res_vec[instance_index]
+ << "\" for x_res");
} else if (x_res_vec.size() == 1) {
- CHECK(android::base::ParseInt(x_res_vec[0].c_str(), &x_res))
- << "Failed to parse value \"" << x_res_vec[0]
- << "\" for x_res";
+ CF_EXPECT(android::base::ParseInt(x_res_vec[0].c_str(), &x_res),
+ "Failed to parse value \"" << x_res_vec[0] << "\" for x_res");
}
int y_res = 0;
if (instance_index < y_res_vec.size()) {
- CHECK(android::base::ParseInt(y_res_vec[instance_index].c_str(), &y_res))
- << "Failed to parse value \"" << y_res_vec[instance_index]
- << "\" for y_res";
+ CF_EXPECT(
+ android::base::ParseInt(y_res_vec[instance_index].c_str(), &y_res),
+ "Failed to parse value \"" << y_res_vec[instance_index]
+ << "\" for y_res");
} else if (y_res_vec.size() == 1) {
- CHECK(android::base::ParseInt(y_res_vec[0].c_str(), &y_res))
- << "Failed to parse value \"" << y_res_vec[0]
- << "\" for y_res";
+ CF_EXPECT(android::base::ParseInt(y_res_vec[0].c_str(), &y_res),
+ "Failed to parse value \"" << y_res_vec[0] << "\" for y_res");
}
int dpi = 0;
if (instance_index < dpi_vec.size()) {
- CHECK(android::base::ParseInt(dpi_vec[instance_index].c_str(), &dpi))
- << "Failed to parse value \"" << dpi_vec[instance_index]
- << "\" for dpi";
+ CF_EXPECT(android::base::ParseInt(dpi_vec[instance_index].c_str(), &dpi),
+ "Failed to parse value \"" << dpi_vec[instance_index]
+ << "\" for dpi");
} else if (dpi_vec.size() == 1) {
- CHECK(android::base::ParseInt(dpi_vec[0].c_str(), &dpi))
- << "Failed to parse value \"" << dpi_vec[0]
- << "\" for dpi";
+ CF_EXPECT(android::base::ParseInt(dpi_vec[0].c_str(), &dpi),
+ "Failed to parse value \"" << dpi_vec[0] << "\" for dpi");
}
int refresh_rate_hz = 0;
if (instance_index < refresh_rate_hz_vec.size()) {
- CHECK(android::base::ParseInt(refresh_rate_hz_vec[instance_index].c_str(), &refresh_rate_hz))
- << "Failed to parse value \"" << refresh_rate_hz_vec[instance_index]
- << "\" for refresh_rate_hz";
+ CF_EXPECT(
+ android::base::ParseInt(refresh_rate_hz_vec[instance_index].c_str(),
+ &refresh_rate_hz),
+ "Failed to parse value \"" << refresh_rate_hz_vec[instance_index]
+ << "\" for refresh_rate_hz");
} else if (refresh_rate_hz_vec.size() == 1) {
- CHECK(android::base::ParseInt(refresh_rate_hz_vec[0].c_str(), &refresh_rate_hz))
- << "Failed to parse value \"" << refresh_rate_hz_vec[0]
- << "\" for refresh_rate_hz";
+ CF_EXPECT(android::base::ParseInt(refresh_rate_hz_vec[0].c_str(),
+ &refresh_rate_hz),
+ "Failed to parse value \"" << refresh_rate_hz_vec[0]
+ << "\" for refresh_rate_hz");
}
if (x_res > 0 && y_res > 0) {
if (display_configs.empty()) {
@@ -1069,13 +1083,14 @@
int memory_mb;
if (instance_index >= memory_mb_vec.size()) {
- CHECK(android::base::ParseInt(memory_mb_vec[0].c_str(), &memory_mb))
- << "Failed to parse value \"" << memory_mb_vec[0]
- << "\" for memory_mb";
+ CF_EXPECT(
+ android::base::ParseInt(memory_mb_vec[0].c_str(), &memory_mb),
+ "Failed to parse value \"" << memory_mb_vec[0] << "\" for memory_mb");
} else {
- CHECK(android::base::ParseInt(memory_mb_vec[instance_index].c_str(), &memory_mb))
- << "Failed to parse value \"" << memory_mb_vec[instance_index]
- << "\" for memory_mb";
+ CF_EXPECT(android::base::ParseInt(memory_mb_vec[instance_index].c_str(),
+ &memory_mb),
+ "Failed to parse value \"" << memory_mb_vec[instance_index]
+ << "\" for memory_mb");
}
instance.set_memory_mb(memory_mb);
instance.set_ddr_mem_mb(memory_mb * 2);
@@ -1097,8 +1112,8 @@
bool guest_enforce_security;
if (instance_index >= guest_enforce_security_vec.size()) {
- guest_enforce_security = CF_EXPECT(ParseBool(guest_enforce_security_vec[0],
- "guest_enforce_security"));
+ guest_enforce_security = CF_EXPECT(
+ ParseBool(guest_enforce_security_vec[0], "guest_enforce_security"));
} else {
guest_enforce_security = CF_EXPECT(ParseBool(
guest_enforce_security_vec[instance_index], "guest_enforce_security"));
@@ -1115,17 +1130,80 @@
}
instance.set_pause_in_bootloader(pause_in_bootloader);
+ bool daemon;
+ if (instance_index >= daemon_vec.size()) {
+ daemon = CF_EXPECT(ParseBool(daemon_vec[0], "daemon"));
+ } else {
+ daemon = CF_EXPECT(ParseBool(daemon_vec[instance_index], "daemon"));
+ }
+ instance.set_run_as_daemon(daemon);
+
+ bool enable_minimal_mode;
+ if (instance_index >= enable_minimal_mode_vec.size()) {
+ enable_minimal_mode = CF_EXPECT(
+ ParseBool(enable_minimal_mode_vec[0], "enable_minimal_mode"));
+ } else {
+ enable_minimal_mode = CF_EXPECT(ParseBool(
+ enable_minimal_mode_vec[instance_index], "enable_minimal_mode"));
+ }
+ bool enable_modem_simulator;
+ if (instance_index >= enable_modem_simulator_vec.size()) {
+ enable_modem_simulator = CF_EXPECT(
+ ParseBool(enable_modem_simulator_vec[0], "enable_modem_simulator"));
+ } else {
+ enable_modem_simulator =
+ CF_EXPECT(ParseBool(enable_modem_simulator_vec[instance_index],
+ "enable_modem_simulator"));
+ }
+ int modem_simulator_count;
+ if (instance_index >= modem_simulator_count_vec.size()) {
+ CF_EXPECT(android::base::ParseInt(modem_simulator_count_vec[0].c_str(),
+ &modem_simulator_count),
+ "Failed to parse value \"" << modem_simulator_count_vec[0]
+ << "\" for modem_simulator_count");
+ } else {
+ CF_EXPECT(android::base::ParseInt(
+ modem_simulator_count_vec[instance_index].c_str(),
+ &modem_simulator_count),
+ "Failed to parse value \""
+ << modem_simulator_count_vec[instance_index]
+ << "\" for modem_simulator_count");
+ }
+ int modem_simulator_sim_type;
+ if (instance_index >= modem_simulator_sim_type_vec.size()) {
+ CF_EXPECT(android::base::ParseInt(modem_simulator_sim_type_vec[0].c_str(),
+ &modem_simulator_sim_type),
+ "Failed to parse value \""
+ << modem_simulator_sim_type_vec[0]
+ << "\" for modem_simulator_sim_type");
+ } else {
+ CF_EXPECT(android::base::ParseInt(
+ modem_simulator_sim_type_vec[instance_index].c_str(),
+ &modem_simulator_sim_type),
+ "Failed to parse value \""
+ << modem_simulator_sim_type_vec[instance_index]
+ << "\" for modem_simulator_sim_type");
+ }
+ instance.set_enable_modem_simulator(enable_modem_simulator &&
+ !enable_minimal_mode);
+ instance.set_modem_simulator_instance_number(modem_simulator_count);
+ instance.set_modem_simulator_sim_type(modem_simulator_sim_type);
+
+ instance.set_enable_minimal_mode(enable_minimal_mode);
+
int camera_server_port;
if (instance_index < camera_server_port_vec.size()) {
- CHECK(android::base::ParseInt(camera_server_port_vec[instance_index].c_str(),
- &camera_server_port))
- << "Failed to parse value \"" << camera_server_port_vec[instance_index]
- << "\" for camera_server_port";
+ CF_EXPECT(android::base::ParseInt(
+ camera_server_port_vec[instance_index].c_str(),
+ &camera_server_port),
+ "Failed to parse value \""
+ << camera_server_port_vec[instance_index]
+ << "\" for camera_server_port");
} else {
- CHECK(android::base::ParseInt(camera_server_port_vec[0].c_str(),
- &camera_server_port))
- << "Failed to parse value \"" << camera_server_port_vec[0]
- << "\" for camera_server_port";
+ CF_EXPECT(android::base::ParseInt(camera_server_port_vec[0].c_str(),
+ &camera_server_port),
+ "Failed to parse value \"" << camera_server_port_vec[0]
+ << "\" for camera_server_port");
}
instance.set_camera_server_port(camera_server_port);
diff --git a/host/commands/assemble_cvd/flags.h b/host/commands/assemble_cvd/flags.h
index 4278f35..34b3c4c 100644
--- a/host/commands/assemble_cvd/flags.h
+++ b/host/commands/assemble_cvd/flags.h
@@ -22,7 +22,7 @@
Result<std::vector<KernelConfig>> GetKernelConfigAndSetDefaults();
// Must be called after ParseCommandLineFlags.
Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
- const std::string& root_dir, int modem_simulator_count,
+ const std::string& root_dir,
const std::vector<KernelConfig>& kernel_configs,
fruit::Injector<>& injector, const FetcherConfig& fetcher_config);
diff --git a/host/commands/console_forwarder/README.md b/host/commands/console_forwarder/README.md
index bc29757..45b662f 100644
--- a/host/commands/console_forwarder/README.md
+++ b/host/commands/console_forwarder/README.md
@@ -1,11 +1,7 @@
-_This page is best viewed on [codesearch]._
-
Console pass-through to the serial console on a device to access a root shell.
If a user invokes `launch_cvd --console` or `cvd start --console`, this
executable runs to forward data from a serial console to a virtual terminal
that can be accessed with `screen` from the host.
-
-
-[codesearch]: https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/console_forwarder/README.md
+[](https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/console_forwarder/doc/linkage.svg)
diff --git a/host/commands/console_forwarder/linkage.dot b/host/commands/console_forwarder/doc/linkage.dot
similarity index 100%
rename from host/commands/console_forwarder/linkage.dot
rename to host/commands/console_forwarder/doc/linkage.dot
diff --git a/host/commands/console_forwarder/doc/linkage.png b/host/commands/console_forwarder/doc/linkage.png
new file mode 100644
index 0000000..ddf7a84
--- /dev/null
+++ b/host/commands/console_forwarder/doc/linkage.png
Binary files differ
diff --git a/host/commands/console_forwarder/linkage.svg b/host/commands/console_forwarder/doc/linkage.svg
similarity index 100%
rename from host/commands/console_forwarder/linkage.svg
rename to host/commands/console_forwarder/doc/linkage.svg
diff --git a/host/commands/cvd/Android.bp b/host/commands/cvd/Android.bp
index 4f0e0d2..2dfa152 100644
--- a/host/commands/cvd/Android.bp
+++ b/host/commands/cvd/Android.bp
@@ -122,9 +122,8 @@
cc_defaults {
name: "cvd_and_fetch_cvd_defaults",
static_libs: [
- "libcvd_instance_db",
- "libcvd_selector_frontend",
"libcvd_parser",
+ "libcvd_selector",
"libcvd_server_client",
"libfetch_cvd",
],
diff --git a/host/commands/cvd/main.cc b/host/commands/cvd/main.cc
index 6c5fb40..1ae9fce 100644
--- a/host/commands/cvd/main.cc
+++ b/host/commands/cvd/main.cc
@@ -86,10 +86,8 @@
return {};
}
- auto separated_args = CF_EXPECT(selector::SeparateArguments(all_args));
- auto [pre, selector_args, post] = std::move(separated_args);
- std::vector<std::string> args = std::move(pre);
- std::move(post.begin(), post.end(), std::back_inserter(args));
+ auto [args, selector_args] =
+ CF_EXPECT(selector::GetCommandAndSelectorArguments(all_args));
std::vector<std::string> env;
for (char** e = envp; *e != 0; e++) {
diff --git a/host/commands/cvd/parser/Android.bp b/host/commands/cvd/parser/Android.bp
index af41e57..d7bade1 100644
--- a/host/commands/cvd/parser/Android.bp
+++ b/host/commands/cvd/parser/Android.bp
@@ -22,6 +22,7 @@
srcs: [
"instance/cf_vm_configs.cpp",
"instance/cf_boot_configs.cpp",
+ "instance/cf_security_configs.cpp",
"cf_configs_common.cpp",
"cf_configs_instances.cpp",
"load_configs_parser.cpp",
diff --git a/host/commands/cvd/parser/cf_configs_instances.cpp b/host/commands/cvd/parser/cf_configs_instances.cpp
index ad19d5f..7b2c2f5 100644
--- a/host/commands/cvd/parser/cf_configs_instances.cpp
+++ b/host/commands/cvd/parser/cf_configs_instances.cpp
@@ -22,6 +22,7 @@
#include "common/libs/utils/flags_validator.h"
#include "host/commands/cvd/parser/cf_configs_common.h"
#include "host/commands/cvd/parser/instance/cf_boot_configs.h"
+#include "host/commands/cvd/parser/instance/cf_security_configs.h"
#include "host/commands/cvd/parser/instance/cf_vm_configs.h"
namespace cuttlefish {
@@ -29,6 +30,7 @@
static std::map<std::string, Json::ValueType> kInstanceKeyMap = {
{"vm", Json::ValueType::objectValue},
{"boot", Json::ValueType::objectValue},
+ {"security", Json::ValueType::objectValue},
{"disk", Json::ValueType::objectValue},
{"graphics", Json::ValueType::objectValue},
{"camera", Json::ValueType::objectValue},
@@ -52,6 +54,10 @@
if (root[i].isMember("boot")) {
CF_EXPECT(ValidateBootConfigs(root[i]["boot"]), "ValidateBootConfigs fail");
}
+ if (root[i].isMember("security")) {
+ CF_EXPECT(ValidateSecurityConfigs(root[i]["security"]),
+ "ValidateSecurityConfigs fail");
+ }
}
CF_EXPECT(ValidateStringConfig(root, "vm", "setupwizard_mode",
ValidateStupWizardMode),
@@ -63,11 +69,13 @@
void InitInstancesConfigs(Json::Value& root) {
InitVmConfigs(root);
InitBootConfigs(root);
+ InitSecurityConfigs(root);
}
std::vector<std::string> GenerateInstancesConfigs(const Json::Value& root) {
std::vector<std::string> result = GenerateVmConfigs(root);
result = MergeResults(result, GenerateBootConfigs(root));
+ result = MergeResults(result, GenerateSecurityFlags(root));
return result;
}
diff --git a/host/commands/cvd/parser/instance/cf_boot_configs.cpp b/host/commands/cvd/parser/instance/cf_boot_configs.cpp
index f507ea1..5796bee 100644
--- a/host/commands/cvd/parser/instance/cf_boot_configs.cpp
+++ b/host/commands/cvd/parser/instance/cf_boot_configs.cpp
@@ -23,25 +23,16 @@
namespace cuttlefish {
-static std::map<std::string, Json::ValueType> securitykeyMap = {
- {"serial_number", Json::ValueType::stringValue}};
-
static std::map<std::string, Json::ValueType> kernelkeyMap = {
{"extra_kernel_cmdline", Json::ValueType::stringValue},
};
static std::map<std::string, Json::ValueType> kBootKeyMap = {
{"extra_bootconfig_args", Json::ValueType::stringValue},
- {"security", Json::ValueType::objectValue},
{"kernel", Json::ValueType::objectValue},
{"enable_bootanimation", Json::ValueType::booleanValue},
};
-Result<void> ValidateSecurityConfigs(const Json::Value& root) {
- CF_EXPECT(ValidateTypo(root, securitykeyMap), "ValidateSecurityConfigs ValidateTypo fail");
- return {};
-}
-
Result<void> ValidateKernelConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kernelkeyMap), "ValidateKernelConfigs ValidateTypo fail");
return {};
@@ -50,10 +41,6 @@
Result<void> ValidateBootConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kBootKeyMap), "ValidateBootConfigs ValidateTypo fail");
- if (root.isMember("security")) {
- CF_EXPECT(ValidateSecurityConfigs(root["security"]), "ValidateSecurityConfigs fail");
- }
-
if (root.isMember("kernel")) {
CF_EXPECT(ValidateKernelConfigs(root["kernel"]), "ValidateKernelConfigs fail");
}
@@ -66,8 +53,6 @@
CF_DEFAULTS_EXTRA_BOOTCONFIG_ARGS);
InitBoolConfig(instances, "boot", "enable_bootanimation",
CF_DEFAULTS_ENABLE_BOOTANIMATION);
- InitStringConfigSubGroup(instances, "boot", "security", "serial_number",
- CF_DEFAULTS_SERIAL_NUMBER);
InitStringConfigSubGroup(instances, "boot", "kernel", "extra_kernel_cmdline",
CF_DEFAULTS_EXTRA_KERNEL_CMDLINE);
}
@@ -78,8 +63,6 @@
"extra_bootconfig_args"));
result.emplace_back(GenerateStrGflag(instances, "enable_bootanimation",
"boot", "enable_bootanimation"));
- result.emplace_back(GenerateStrGflagSubGroup(instances, "serial_number", "boot",
- "security", "serial_number"));
result.emplace_back(GenerateStrGflagSubGroup(instances, "extra_kernel_cmdline",
"boot", "kernel",
"extra_kernel_cmdline"));
diff --git a/host/commands/cvd/parser/instance/cf_security_configs.cpp b/host/commands/cvd/parser/instance/cf_security_configs.cpp
new file mode 100644
index 0000000..3d58085
--- /dev/null
+++ b/host/commands/cvd/parser/instance/cf_security_configs.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "host/commands/cvd/parser/instance/cf_security_configs.h"
+
+#include <android-base/logging.h>
+
+#include "host/commands/assemble_cvd/flags_defaults.h"
+#include "host/commands/cvd/parser/cf_configs_common.h"
+#include "host/libs/config/cuttlefish_config.h"
+
+namespace cuttlefish {
+
+static std::map<std::string, Json::ValueType> kSecurityKeyMap = {
+ {"serial_number", Json::ValueType::stringValue}};
+
+Result<void> ValidateSecurityConfigs(const Json::Value& root) {
+ CF_EXPECT(ValidateTypo(root, kSecurityKeyMap),
+ "ValidateSecurityConfigs ValidateTypo fail");
+ return {};
+}
+
+/*This function is created to cover the initiation use_random_serial flag
+when the json value of serial_number equal "@random"
+*/
+void InitRandomSerialNumber(Json::Value& instances) {
+ int size = instances.size();
+ for (int i = 0; i < size; i++) {
+ std::string serial_number_str =
+ instances[i]["security"]["serial_number"].asString();
+ if (serial_number_str == "@random") {
+ instances[i]["security"]["use_random_serial"] = true;
+ } else {
+ instances[i]["security"]["use_random_serial"] = false;
+ }
+ }
+}
+
+void InitSecurityConfigs(Json::Value& instances) {
+ InitStringConfig(instances, "security", "serial_number",
+ CF_DEFAULTS_SERIAL_NUMBER);
+ // This init should be called after the InitSecurityConfigs call, since it
+ // depends on serial_number flag
+ InitRandomSerialNumber(instances);
+}
+
+std::vector<std::string> GenerateSecurityFlags(const Json::Value& instances) {
+ std::vector<std::string> result;
+ result.emplace_back(GenerateStrGflag(instances, "serial_number", "security",
+ "serial_number"));
+ result.emplace_back(GenerateBoolGflag(instances, "use_random_serial",
+ "security", "use_random_serial"));
+ return result;
+}
+
+} // namespace cuttlefish
diff --git a/host/commands/cvd/parser/instance/cf_security_configs.h b/host/commands/cvd/parser/instance/cf_security_configs.h
new file mode 100644
index 0000000..0d5c3b3
--- /dev/null
+++ b/host/commands/cvd/parser/instance/cf_security_configs.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ std::string * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ std::string * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <string>
+#include <vector>
+
+#include <json/json.h>
+
+#include "common/libs/utils/result.h"
+
+namespace cuttlefish {
+Result<void> ValidateSecurityConfigs(const Json::Value& root);
+void InitSecurityConfigs(Json::Value& root);
+std::vector<std::string> GenerateSecurityFlags(const Json::Value& root);
+}; // namespace cuttlefish
diff --git a/host/commands/cvd/selector/Android.bp b/host/commands/cvd/selector/Android.bp
index 292badc..b08c648 100644
--- a/host/commands/cvd/selector/Android.bp
+++ b/host/commands/cvd/selector/Android.bp
@@ -18,23 +18,17 @@
}
cc_library_host_static {
- name: "libcvd_selector_frontend",
+ name: "libcvd_selector",
srcs: [
- "selector_cmdline_parser.cpp",
- "selector_flags_parser.cpp",
- "selector_option_parser_utils.cpp",
- ],
- defaults: ["cvd_lib_defaults"],
-}
-
-cc_library_host_static {
- name: "libcvd_instance_db",
- srcs: [
+ "creation_analyzer.cpp",
"instance_database.cpp",
"instance_database_impl.cpp",
"instance_database_utils.cpp",
"instance_group_record.cpp",
"instance_record.cpp",
+ "selector_cmdline_parser.cpp",
+ "selector_flags_parser.cpp",
+ "selector_option_parser_utils.cpp",
],
defaults: ["cvd_lib_defaults"],
}
diff --git a/host/commands/cvd/selector/creation_analyzer.cpp b/host/commands/cvd/selector/creation_analyzer.cpp
new file mode 100644
index 0000000..b8ea927
--- /dev/null
+++ b/host/commands/cvd/selector/creation_analyzer.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "host/commands/cvd/selector/creation_analyzer.h"
+
+#include <sys/types.h>
+
+#include <algorithm>
+#include <regex>
+#include <set>
+#include <string>
+
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+
+#include "common/libs/utils/contains.h"
+#include "common/libs/utils/flag_parser.h"
+#include "common/libs/utils/users.h"
+#include "host/commands/cvd/selector/instance_database_utils.h"
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+#include "host/commands/cvd/selector/selector_constants.h"
+#include "host/libs/config/cuttlefish_config.h"
+
+namespace cuttlefish {
+namespace selector {
+
+Result<GroupCreationInfo> CreationAnalyzer::Analyze(
+ const CreationAnalyzerParam& param, const std::optional<ucred>& credential,
+ InstanceLockFileManager& instance_lock_file_manager) {
+ auto selector_options_parser =
+ CF_EXPECT(SelectorFlagsParser::ConductSelectFlagsParser(
+ param.selector_args, param.cmd_args, param.envs));
+ CreationAnalyzer analyzer(param, credential,
+ std::move(selector_options_parser),
+ instance_lock_file_manager);
+ auto result = CF_EXPECT(analyzer.Analyze());
+ return result;
+}
+
+CreationAnalyzer::CreationAnalyzer(
+ const CreationAnalyzerParam& param, const std::optional<ucred>& credential,
+ SelectorFlagsParser&& selector_options_parser,
+ InstanceLockFileManager& instance_file_lock_manager)
+ : cmd_args_(param.cmd_args),
+ envs_(param.envs),
+ selector_args_(param.selector_args),
+ credential_(credential),
+ selector_options_parser_{std::move(selector_options_parser)},
+ instance_file_lock_manager_{instance_file_lock_manager} {}
+
+static void PlaceHolder(InstanceLockFileManager&) {}
+
+Result<std::vector<PerInstanceInfo>>
+CreationAnalyzer::AnalyzeInstanceIdsWithLock() {
+ // TODO(kwstephenkim): implement AnalyzeInstanceIdsWithLock()
+ PlaceHolder(instance_file_lock_manager_);
+ return std::vector<PerInstanceInfo>{};
+}
+
+Result<GroupCreationInfo> CreationAnalyzer::Analyze() {
+ // TODO(kwstephenkim): check if the command is "start"
+ auto instance_info = CF_EXPECT(AnalyzeInstanceIdsWithLock());
+ group_name_ = AnalyzeGroupName(instance_info);
+ home_ = CF_EXPECT(AnalyzeHome());
+ // TODO(kwstephenkim): implement host_artifacts_path_
+ host_artifacts_path_ = "";
+
+ GroupCreationInfo report = {.home = home_,
+ .host_artifacts_path = host_artifacts_path_,
+ .group_name = group_name_,
+ .instances = std::move(instance_info),
+ .args = cmd_args_,
+ .envs = envs_};
+ return report;
+}
+
+std::string CreationAnalyzer::AnalyzeGroupName(
+ const std::vector<PerInstanceInfo>&) const {
+ // TODO(kwstephenkim): implement AnalyzeGroupName()
+ return "";
+}
+
+Result<std::string> CreationAnalyzer::AnalyzeHome() const {
+ // TODO(kwstephenkim): implement AnalyzeHome()
+ return "";
+}
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/selector/creation_analyzer.h b/host/commands/cvd/selector/creation_analyzer.h
new file mode 100644
index 0000000..a5334c4
--- /dev/null
+++ b/host/commands/cvd/selector/creation_analyzer.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <sys/socket.h> // for ucred
+
+#include <memory>
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "common/libs/utils/result.h"
+
+#include "host/commands/cvd/instance_lock.h"
+#include "host/commands/cvd/selector/instance_database.h"
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+#include "host/commands/cvd/selector/unique_resource_allocator.h"
+
+namespace cuttlefish {
+namespace selector {
+
+struct PerInstanceInfo {
+ // for the sake of std::vector::emplace_back
+ PerInstanceInfo(const unsigned id, const std::string& per_instance_name,
+ InstanceLockFile&& instance_file_lock)
+ : instance_id_(id),
+ per_instance_name_(per_instance_name),
+ instance_file_lock_(std::move(instance_file_lock)) {}
+ const unsigned instance_id_;
+ const std::string per_instance_name_;
+ InstanceLockFile instance_file_lock_;
+};
+
+/**
+ * Creation is currently group by group
+ *
+ * If you want one instance, you should create a group with one instance.
+ */
+struct GroupCreationInfo {
+ std::string home;
+ std::string host_artifacts_path; ///< e.g. out/host/linux-x86
+ std::string group_name;
+ std::vector<PerInstanceInfo> instances;
+ std::vector<std::string> args;
+ std::unordered_map<std::string, std::string> envs;
+};
+
+/**
+ * Instance IDs:
+ * Use the InstanceNumCalculator's logic
+ *
+ * HOME directory:
+ * If given in envs and is different from the system-wide home, use it
+ * If not, try kParentOfDefaultHomeDirectories/.${group_name}
+ *
+ * host_artifacts_path:
+ * ANDROID_HOST_OUT must be given.
+ *
+ * Group name:
+ * if --group_name or --device_name is given, find the group name there
+ * if --name is given and when it is a group name (i.e. --name=<one token>
+ * and that one token is an eligible group name, and the operation is for
+ * a group -- e.g. start), use the "name" as a group name
+ * if a group name is not given, automatically generate:
+ * default_prefix + "_" + android::base::Join(instance_ids, "_")
+ *
+ * Per-instance name:
+ * When not given, use std::string(id) as the per instance name of each
+ *
+ * Number of instances:
+ * Controlled by --instance_nums, --num_instances, etc.
+ * Also controlled by --device_name or equivalent options
+ *
+ * p.s.
+ * dependency: (a-->b means b depends on a)
+ * group_name --> HOME
+ * instance ids --> per_instance_name
+ *
+ */
+class CreationAnalyzer {
+ public:
+ struct CreationAnalyzerParam {
+ const std::vector<std::string>& cmd_args;
+ const std::unordered_map<std::string, std::string>& envs;
+ const std::vector<std::string>& selector_args;
+ };
+
+ static Result<GroupCreationInfo> Analyze(
+ const CreationAnalyzerParam& param,
+ const std::optional<ucred>& credential,
+ InstanceLockFileManager& instance_lock_file_manager);
+
+ private:
+ using IdAllocator = UniqueResourceAllocator<unsigned>;
+
+ CreationAnalyzer(const CreationAnalyzerParam& param,
+ const std::optional<ucred>& credential,
+ SelectorFlagsParser&& selector_options_parser_,
+ InstanceLockFileManager& instance_lock_file_manager);
+
+ Result<GroupCreationInfo> Analyze();
+
+ /**
+ * calculate n_instances_ and instance_ids_
+ */
+ Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIdsWithLock();
+
+ /*
+ * When group name is nil, it is auto-generated using instance ids
+ *
+ * if the given ids are {l, m, n}, the auto-generated group name will be
+ * GenDefaultGroupName() + "_l_m_n." If the ids set is equal to {1}, the
+ * auto-generated group name will be just GenDefaultGroupName()
+ *
+ */
+ std::string AnalyzeGroupName(const std::vector<PerInstanceInfo>&) const;
+
+ /**
+ * Figures out the HOME directory
+ *
+ * If given in envs and is different from the system-wide home, use it
+ * If not, try $(SYSTEM_WIDE_HOME)/.cuttlefish_home/group_name
+ *
+ * The issue here is, mostly, HOME is given anyway. How would we tell
+ * if the HOME is given explicitly or not?
+ * e.g. HOME=/any/path cvd start vs. cvd start
+ *
+ */
+ Result<std::string> AnalyzeHome() const;
+
+ // inputs
+ std::vector<std::string> cmd_args_;
+ std::unordered_map<std::string, std::string> envs_;
+ std::vector<std::string> selector_args_;
+ const std::optional<ucred> credential_;
+
+ // information to return later
+ std::string home_;
+ std::string host_artifacts_path_; ///< e.g. out/host/linux-x86
+ std::string group_name_;
+ std::optional<std::vector<std::string>> per_instance_names_;
+
+ // internal, temporary
+ SelectorFlagsParser selector_options_parser_;
+ InstanceLockFileManager& instance_file_lock_manager_;
+};
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/selector/selector_cmdline_parser.cpp b/host/commands/cvd/selector/selector_cmdline_parser.cpp
index cdd2e1f..381495e 100644
--- a/host/commands/cvd/selector/selector_cmdline_parser.cpp
+++ b/host/commands/cvd/selector/selector_cmdline_parser.cpp
@@ -19,12 +19,19 @@
#include <algorithm>
#include <cctype>
#include <deque>
+#include <iterator>
#include <stack>
namespace cuttlefish {
namespace selector {
namespace {
+struct SeparatedArguments {
+ std::vector<std::string> before_selector_opts;
+ std::vector<std::string> selector_specific;
+ std::vector<std::string> after_selector_opts;
+};
+
enum class ParseState {
kInit = 0,
kSelector = 1,
@@ -32,8 +39,6 @@
kParseError = 3
};
-} // namespace
-
/*
* Basically, cmd with the arguments would look this:
* $ cvd [ <selector options> ] <cvd options>
@@ -125,5 +130,16 @@
.after_selector_opts = after_selector_opts}};
}
+} // namespace
+
+Result<CommandAndSelectorArguments> GetCommandAndSelectorArguments(
+ const std::vector<std::string>& args) {
+ auto [pre, selector_specific, post] = CF_EXPECT(SeparateArguments(args));
+ std::vector<std::string> cmd_args{pre};
+ std::copy(post.begin(), post.end(), std::back_inserter(cmd_args));
+ return CommandAndSelectorArguments{.cmd_args = cmd_args,
+ .selector_args = selector_specific};
+}
+
} // namespace selector
} // namespace cuttlefish
diff --git a/host/commands/cvd/selector/selector_cmdline_parser.h b/host/commands/cvd/selector/selector_cmdline_parser.h
index 50f9c6f..a917f96 100644
--- a/host/commands/cvd/selector/selector_cmdline_parser.h
+++ b/host/commands/cvd/selector/selector_cmdline_parser.h
@@ -18,6 +18,7 @@
#include <optional>
#include <string>
+#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -27,16 +28,12 @@
namespace cuttlefish {
namespace selector {
-struct SeparatedArguments {
- std::vector<std::string> before_selector_opts;
- std::vector<std::string> selector_specific;
- std::vector<std::string> after_selector_opts;
+struct CommandAndSelectorArguments {
+ std::vector<std::string> cmd_args;
+ std::vector<std::string> selector_args;
};
-/**
- * takes cmdline arguments, and separate them into 3 pieces above
- */
-Result<SeparatedArguments> SeparateArguments(
+Result<CommandAndSelectorArguments> GetCommandAndSelectorArguments(
const std::vector<std::string>& args);
/**
@@ -53,13 +50,21 @@
class SelectorFlagsParser {
public:
static Result<SelectorFlagsParser> ConductSelectFlagsParser(
- const std::vector<std::string>& args);
+ const std::vector<std::string>& selector_args,
+ const std::vector<std::string>& cmd_args,
+ const std::unordered_map<std::string, std::string>& envs);
std::optional<std::string> GroupName() const;
std::optional<std::vector<std::string>> PerInstanceNames() const;
const auto& SubstringQueries() const { return substring_queries_; }
+ const std::optional<std::unordered_set<unsigned>>& InstanceIds() const {
+ return instance_ids_;
+ }
+ unsigned RequestedNumInstances() const { return requested_num_instances_; }
private:
- SelectorFlagsParser(const std::vector<std::string>& args);
+ SelectorFlagsParser(const std::vector<std::string>& selector_args,
+ const std::vector<std::string>& cmd_args,
+ const std::unordered_map<std::string, std::string>& envs);
/*
* Note: name may or may not be valid. A name could be a
@@ -102,13 +107,86 @@
const std::optional<std::string>& per_instance_names) const;
Result<std::string> HandleGroupName(
const std::optional<std::string>& group_name) const;
+ struct InstanceIdsParams {
+ std::optional<std::string> num_instances;
+ std::optional<std::string> instance_nums;
+ std::optional<std::string> base_instance_num;
+ std::optional<unsigned> cuttlefish_instance_env;
+ std::optional<unsigned> vsoc_suffix;
+ };
+ class ParsedInstanceIdsOpt {
+ friend class SelectorFlagsParser;
+
+ private:
+ ParsedInstanceIdsOpt(const std::unordered_set<unsigned>& instance_ids)
+ : instance_ids_{instance_ids},
+ n_instances_{static_cast<unsigned>(instance_ids.size())} {}
+ ParsedInstanceIdsOpt(const unsigned n_instances)
+ : instance_ids_{std::nullopt}, n_instances_{n_instances} {}
+ auto GetInstanceIds() { return std::move(instance_ids_); }
+ unsigned GetNumOfInstances() const { return n_instances_; }
+ std::optional<std::unordered_set<unsigned>> instance_ids_;
+ const unsigned n_instances_;
+ };
+
+ /*
+ * CF_ERR is meant to be an error:
+ * For example, --num_instances != |--instance_nums|.
+ *
+ * On the contrary, std::nullopt inside Result is not necessary one.
+ * std::nullopt inside Result means that with the given information,
+ * the instance_ids_ cannot be yet figured out, so the task is deferred
+ * to CreationAnaylizer or so, which has more contexts. For example,
+ * if no option at all is given, it is not an error; however, the
+ * SelectorFlagsParser alone cannot figure out the list of instance ids. The
+ * InstanceDatabase, UniqueResourceAllocator, InstanceLockFileManager will be
+ * involved to automatically generate the valid, numeric instance ids.
+ * If that's the case, Result{std::nullopt} could be returned.
+ *
+ */
+ Result<ParsedInstanceIdsOpt> HandleInstanceIds(
+ const InstanceIdsParams& instance_id_params);
+
+ struct InstanceFromEnvParam {
+ std::optional<unsigned> cuttlefish_instance_env;
+ std::optional<unsigned> vsoc_suffix;
+ std::optional<unsigned> num_instances;
+ };
+ std::optional<std::unordered_set<unsigned>> InstanceFromEnvironment(
+ const InstanceFromEnvParam& params);
+
+ struct VerifyNumOfInstancesParam {
+ std::optional<std::string> num_instances_flag;
+ std::optional<std::vector<std::string>> instance_names;
+ std::optional<std::string> instance_nums_flag;
+ };
+ Result<unsigned> VerifyNumOfInstances(
+ const VerifyNumOfInstancesParam& params,
+ const unsigned default_n_instances = 1) const;
std::optional<std::string> group_name_;
std::optional<std::vector<std::string>> instance_names_;
std::unordered_set<std::string> substring_queries_;
+ /**
+ * The following are considered, and left empty if can't be figured out.
+ *
+ * --base_instance_num, --instance_nums, --num_instances,
+ * instance_names_.size(), CUTTLEFISH_INSTANCE, and vsoc-suffix if
+ * it is the user name.
+ *
+ * instance_names_.size() is effectively another --num_instances.
+ * CUTTLEFISH_INSTANCE and the suffix in order are considered as
+ * --base_instance_num if --base_instance_num is not given and
+ * --instance_nums is not given.
+ *
+ */
+ std::optional<std::unordered_set<unsigned>> instance_ids_;
+ unsigned requested_num_instances_;
- // temporarily keeps the leftover of the input args
- std::vector<std::string> args_;
+ // temporarily keeps the leftover of the input cmd_args
+ std::vector<std::string> selector_args_;
+ std::vector<std::string> cmd_args_;
+ std::unordered_map<std::string, std::string> envs_;
};
} // namespace selector
diff --git a/host/commands/cvd/selector/selector_flags_parser.cpp b/host/commands/cvd/selector/selector_flags_parser.cpp
index 1525198..a2b7ca5 100644
--- a/host/commands/cvd/selector/selector_flags_parser.cpp
+++ b/host/commands/cvd/selector/selector_flags_parser.cpp
@@ -16,24 +16,42 @@
#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+#include <sstream>
+#include <string_view>
+
+#include <android-base/parseint.h>
#include <android-base/strings.h>
#include "host/commands/cvd/selector/instance_database_utils.h"
#include "host/commands/cvd/selector/selector_constants.h"
#include "host/commands/cvd/selector/selector_option_parser_utils.h"
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/config/instance_nums.h"
namespace cuttlefish {
namespace selector {
+static Result<unsigned> ParseNaturalNumber(const std::string& token) {
+ std::int32_t value;
+ CF_EXPECT(android::base::ParseInt(token, &value));
+ CF_EXPECT(value > 0);
+ return static_cast<unsigned>(value);
+}
+
Result<SelectorFlagsParser> SelectorFlagsParser::ConductSelectFlagsParser(
- const std::vector<std::string>& args) {
- SelectorFlagsParser parser(args);
+ const std::vector<std::string>& selector_args,
+ const std::vector<std::string>& cmd_args,
+ const std::unordered_map<std::string, std::string>& envs) {
+ SelectorFlagsParser parser(selector_args, cmd_args, envs);
CF_EXPECT(parser.ParseOptions(), "selector option flag parsing failed.");
return {std::move(parser)};
}
-SelectorFlagsParser::SelectorFlagsParser(const std::vector<std::string>& args)
- : args_(args) {}
+SelectorFlagsParser::SelectorFlagsParser(
+ const std::vector<std::string>& selector_args,
+ const std::vector<std::string>& cmd_args,
+ const std::unordered_map<std::string, std::string>& envs)
+ : selector_args_(selector_args), cmd_args_(cmd_args), envs_(envs) {}
std::optional<std::string> SelectorFlagsParser::GroupName() const {
return group_name_;
@@ -170,6 +188,153 @@
.instance_names = std::move(instance_names_output)}};
}
+namespace {
+
+using Envs = std::unordered_map<std::string, std::string>;
+
+std::optional<unsigned> TryFromCuttlefishInstance(const Envs& envs) {
+ if (envs.find(kCuttlefishInstanceEnvVarName) == envs.end()) {
+ return std::nullopt;
+ }
+ const auto cuttlefish_instance = envs.at(kCuttlefishInstanceEnvVarName);
+ if (cuttlefish_instance.empty()) {
+ return std::nullopt;
+ }
+ auto parsed = ParseNaturalNumber(cuttlefish_instance);
+ return parsed.ok() ? std::optional(*parsed) : std::nullopt;
+}
+
+std::optional<unsigned> TryFromUser(const Envs& envs) {
+ if (envs.find("USER") == envs.end()) {
+ return std::nullopt;
+ }
+ std::string_view user{envs.at("USER")};
+ if (user.empty() || !android::base::ConsumePrefix(&user, kVsocUserPrefix)) {
+ return std::nullopt;
+ }
+ const auto& vsoc_num = user;
+ auto vsoc_id = ParseNaturalNumber(vsoc_num.data());
+ return vsoc_id.ok() ? std::optional(*vsoc_id) : std::nullopt;
+}
+
+} // namespace
+
+std::optional<std::unordered_set<unsigned>>
+SelectorFlagsParser::InstanceFromEnvironment(
+ const InstanceFromEnvParam& params) {
+ const auto& cuttlefish_instance_env = params.cuttlefish_instance_env;
+ const auto& vsoc_suffix = params.vsoc_suffix;
+ const auto& num_instances = params.num_instances;
+
+ // see the logic in cuttlefish::InstanceFromEnvironment()
+ // defined in host/libs/config/cuttlefish_config.cpp
+ std::unordered_set<unsigned> nums;
+ std::optional<unsigned> base;
+ if (cuttlefish_instance_env) {
+ base = *cuttlefish_instance_env;
+ }
+ if (!base && vsoc_suffix) {
+ base = *vsoc_suffix;
+ }
+ if (!base) {
+ return std::nullopt;
+ }
+ // this is guaranteed by the caller
+ // assert(num_instances != std::nullopt);
+ for (unsigned i = 0; i != *num_instances; i++) {
+ nums.insert(base.value() + i);
+ }
+ return nums;
+}
+
+Result<unsigned> SelectorFlagsParser::VerifyNumOfInstances(
+ const VerifyNumOfInstancesParam& params,
+ const unsigned default_n_instances) const {
+ const auto& num_instances_flag = params.num_instances_flag;
+ const auto& instance_names = params.instance_names;
+ const auto& instance_nums_flag = params.instance_nums_flag;
+
+ std::optional<unsigned> num_instances;
+ if (num_instances_flag) {
+ num_instances = CF_EXPECT(ParseNaturalNumber(*num_instances_flag));
+ }
+ if (instance_names && !instance_names->empty()) {
+ auto implied_n_instances = instance_names->size();
+ if (num_instances) {
+ CF_EXPECT_EQ(*num_instances, static_cast<unsigned>(implied_n_instances),
+ "The number of instances requested by --num_instances "
+ << " are not the same as what is implied by "
+ << " --name/device_name/instance_name.");
+ }
+ num_instances = implied_n_instances;
+ }
+ if (instance_nums_flag) {
+ std::vector<std::string> tokens =
+ android::base::Split(*instance_nums_flag, ",");
+ for (const auto& t : tokens) {
+ CF_EXPECT(ParseNaturalNumber(t), t << " must be a natural number");
+ }
+ if (!num_instances) {
+ num_instances = tokens.size();
+ }
+ CF_EXPECT_EQ(*num_instances, tokens.size(),
+ "All information for the number of instances must match.");
+ }
+ return num_instances.value_or(default_n_instances);
+}
+
+Result<SelectorFlagsParser::ParsedInstanceIdsOpt>
+SelectorFlagsParser::HandleInstanceIds(
+ const InstanceIdsParams& instance_id_params) {
+ const auto& instance_nums = instance_id_params.instance_nums;
+ const auto& base_instance_num = instance_id_params.base_instance_num;
+ const auto& cuttlefish_instance_env =
+ instance_id_params.cuttlefish_instance_env;
+ const auto& vsoc_suffix = instance_id_params.vsoc_suffix;
+
+ // calculate and/or verify the number of instances
+ unsigned num_instances =
+ CF_EXPECT(VerifyNumOfInstances(VerifyNumOfInstancesParam{
+ .num_instances_flag = instance_id_params.num_instances,
+ .instance_names = instance_names_,
+ .instance_nums_flag = instance_nums}));
+
+ if (!instance_nums && !base_instance_num) {
+ // num_instances is given. if non-std::nullopt is returned,
+ // the base is also figured out. If base can't be figured out,
+ // std::nullopt is returned.
+ auto instance_ids = InstanceFromEnvironment(
+ {.cuttlefish_instance_env = cuttlefish_instance_env,
+ .vsoc_suffix = vsoc_suffix,
+ .num_instances = num_instances});
+ if (instance_ids) {
+ return ParsedInstanceIdsOpt(*instance_ids);
+ }
+ // the return value, n_instances is the "desired/requested" instances
+ // When instance_ids set isn't figured out, n_instances is not meant to
+ // be always zero; it could be any natural number.
+ return ParsedInstanceIdsOpt(num_instances);
+ }
+
+ InstanceNumsCalculator calculator;
+ calculator.NumInstances(static_cast<std::int32_t>(num_instances));
+ if (instance_nums) {
+ calculator.InstanceNums(*instance_nums);
+ }
+ if (base_instance_num) {
+ unsigned base = CF_EXPECT(ParseNaturalNumber(*base_instance_num));
+ calculator.BaseInstanceNum(static_cast<std::int32_t>(base));
+ }
+ auto instance_ids = std::move(CF_EXPECT(calculator.CalculateFromFlags()));
+ CF_EXPECT(!instance_ids.empty(),
+ "CalculateFromFlags() must be called when --num_instances or "
+ << "--base_instance_num is given, and must not return an "
+ << "empty set");
+ auto instance_ids_hash_set =
+ std::unordered_set<unsigned>{instance_ids.begin(), instance_ids.end()};
+ return ParsedInstanceIdsOpt{instance_ids_hash_set};
+}
+
Result<void> SelectorFlagsParser::ParseOptions() {
// Handling name-related options
std::optional<std::string> names;
@@ -188,7 +353,7 @@
for (auto& [flag_name, value] : key_optional_map) {
// value is set to std::nullopt if parsing failed or no flag_name flag is
// given.
- CF_EXPECT(FilterSelectorFlag(args_, flag_name, value));
+ CF_EXPECT(FilterSelectorFlag(selector_args_, flag_name, value));
}
NameFlagsParam name_flags_param{
@@ -200,7 +365,25 @@
group_name_ = parsed_name_flags.group_name;
instance_names_ = parsed_name_flags.instance_names;
- if (args_.empty()) {
+ std::optional<std::string> num_instances;
+ std::optional<std::string> instance_nums;
+ std::optional<std::string> base_instance_num;
+ // set num_instances as std::nullptr or the value of --num_instances
+ FilterSelectorFlag(cmd_args_, "num_instances", num_instances);
+ FilterSelectorFlag(cmd_args_, "instance_nums", instance_nums);
+ FilterSelectorFlag(cmd_args_, "base_instance_num", base_instance_num);
+
+ InstanceIdsParams instance_nums_param{
+ .num_instances = std::move(num_instances),
+ .instance_nums = std::move(instance_nums),
+ .base_instance_num = std::move(base_instance_num),
+ .cuttlefish_instance_env = TryFromCuttlefishInstance(envs_),
+ .vsoc_suffix = TryFromUser(envs_)};
+ auto parsed_ids = CF_EXPECT(HandleInstanceIds(instance_nums_param));
+ requested_num_instances_ = parsed_ids.GetNumOfInstances();
+ instance_ids_ = std::move(parsed_ids.GetInstanceIds());
+
+ if (selector_args_.empty()) {
return {};
}
substring_queries_ = CF_EXPECT(FindSubstringsToMatch());
@@ -214,20 +397,20 @@
Result<std::unordered_set<std::string>>
SelectorFlagsParser::FindSubstringsToMatch() {
std::unordered_set<std::string> substring_queries;
- const auto args_size = args_.size();
- for (int i = 0; i < args_size; i++) {
+ const auto selector_args_size = selector_args_.size();
+ for (int i = 0; i < selector_args_size; i++) {
/*
* Logically, the order does not matter. The reason why we start from
* behind is that pop_back() of a vector is much cheaper than pop_front()
*/
- const auto& substring = args_.back();
+ const auto& substring = selector_args_.back();
auto tokens = android::base::Split(substring, ",");
for (const auto& t : tokens) {
CF_EXPECT(!t.empty(),
"Empty keyword for substring search is not allowed.");
substring_queries_.insert(t);
}
- args_.pop_back();
+ selector_args_.pop_back();
}
return {substring_queries};
}
diff --git a/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc b/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc
index e853774..17bf24d 100644
--- a/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc
+++ b/host/commands/cvd/unittests/parser/instance/boot_configs_test.cc
@@ -222,16 +222,12 @@
"instances" :
[
{
- "boot": {
- "security": {
- }
+ "security": {
}
},
{
- "boot": {
- "security": {
- "serial_number": "CUTTLEFISHCVD101"
- }
+ "security": {
+ "serial_number": "CUTTLEFISHCVD101"
}
}
]
@@ -256,17 +252,13 @@
"instances" :
[
{
- "boot": {
- "security": {
- "serial_number": "CUTTLEFISHCVD101"
- }
+ "security": {
+ "serial_number": "CUTTLEFISHCVD101"
}
},
{
- "boot": {
- "security": {
- "serial_number": "CUTTLEFISHCVD102"
- }
+ "security": {
+ "serial_number": "CUTTLEFISHCVD102"
}
}
]
@@ -285,6 +277,91 @@
<< "serial_number flag is missing or wrongly formatted";
}
+TEST(BootFlagsParserTest, ParseTwoInstancesRandomSerialFlagEmptyJson) {
+ const char* test_string = R""""(
+{
+ "instances" :
+ [
+ {
+ },
+ {
+ }
+ ]
+}
+ )"""";
+
+ Json::Value json_configs;
+ std::string json_text(test_string);
+
+ EXPECT_TRUE(ParseJsonString(json_text, json_configs))
+ << "Invalid Json string";
+ auto serialized_data = ParseCvdConfigs(json_configs);
+ EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
+ EXPECT_TRUE(
+ FindConfig(*serialized_data, R"(--use_random_serial=false,false)"))
+ << "use_random_serial flag is missing or wrongly formatted";
+}
+
+TEST(BootFlagsParserTest, ParseTwoInstancesRandomSerialFlagPartialJson) {
+ const char* test_string = R""""(
+{
+ "instances" :
+ [
+ {
+ "security": {
+ "serial_number": "CUTTLEFISHCVD101"
+ }
+ },
+ {
+ "security": {
+ "serial_number": "@random"
+ }
+ }
+ ]
+}
+ )"""";
+
+ Json::Value json_configs;
+ std::string json_text(test_string);
+
+ EXPECT_TRUE(ParseJsonString(json_text, json_configs))
+ << "Invalid Json string";
+ auto serialized_data = ParseCvdConfigs(json_configs);
+ EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
+ EXPECT_TRUE(FindConfig(*serialized_data, R"(--use_random_serial=false,true)"))
+ << "use_random_serial flag is missing or wrongly formatted";
+}
+
+TEST(BootFlagsParserTest, ParseTwoInstancesRandomSerialFlagFullJson) {
+ const char* test_string = R""""(
+{
+ "instances" :
+ [
+ {
+ "security": {
+ "serial_number": "@random"
+ }
+ },
+ {
+ "security": {
+ "serial_number": "@random"
+ }
+ }
+ ]
+}
+ )"""";
+
+ Json::Value json_configs;
+ std::string json_text(test_string);
+
+ EXPECT_TRUE(ParseJsonString(json_text, json_configs))
+ << "Invalid Json string";
+ auto serialized_data = ParseCvdConfigs(json_configs);
+ EXPECT_TRUE(serialized_data.ok()) << serialized_data.error().Trace();
+ EXPECT_TRUE(FindConfig(*serialized_data, R"(--use_random_serial=true,true)"))
+ << "use_random_serial flag is missing or wrongly formatted";
+}
+
TEST(BootFlagsParserTest, ParseTwoInstancesKernelCmdFlagEmptyJson) {
const char* test_string = R""""(
{
diff --git a/host/commands/cvd/unittests/selector/Android.bp b/host/commands/cvd/unittests/selector/Android.bp
index ad41ae1..ac1b247 100644
--- a/host/commands/cvd/unittests/selector/Android.bp
+++ b/host/commands/cvd/unittests/selector/Android.bp
@@ -20,7 +20,6 @@
cc_test_host {
name: "cvd_db_instance_test",
srcs: [
- "test_group_record.cpp",
"test_instance_record.cpp",
],
test_options: {
@@ -30,10 +29,20 @@
}
cc_test_host {
+ name: "cvd_db_group_test",
+ srcs: [
+ "test_group_record.cpp",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ defaults: ["cvd_and_fetch_cvd_defaults"],
+}
+
+cc_test_host {
name: "cvd_db_test",
srcs: [
"instance_database_test_helper.cpp",
- "test_id_allocator.cpp",
"test_instance_database.cpp",
],
test_options: {
@@ -43,9 +52,25 @@
}
cc_test_host {
+ name: "cvd_id_allocator_test",
+ srcs: [
+ "test_id_allocator.cpp",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ defaults: ["cvd_and_fetch_cvd_defaults"],
+}
+
+cc_test_host {
name: "cvd_selector_parser_test",
srcs: [
- "test_cvd_selector_parser.cpp",
+ "selector_parser_ids_test_helper.cpp",
+ "selector_parser_names_test_helper.cpp",
+ "selector_parser_substring_test_helper.cpp",
+ "test_cvd_selector_parser_ids.cpp",
+ "test_cvd_selector_parser_names.cpp",
+ "test_cvd_selector_parser_substring.cpp",
],
test_options: {
unit_test: true,
diff --git a/host/commands/cvd/unittests/selector/id_allocator_test_helper.h b/host/commands/cvd/unittests/selector/id_allocator_test_helper.h
new file mode 100644
index 0000000..7719897
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/id_allocator_test_helper.h
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+namespace cuttlefish {
+namespace selector {
+
+// Get one unique item at a time
+class OneEachTest : public testing::TestWithParam<std::vector<unsigned>> {};
+
+/*
+ * ClaimAll, StrideBeyond1, Consecutive, Take, TakeAll, TakeRange,
+ * ReclaimAll, ReclaimEmptyPool
+ *
+ */
+class CvdIdAllocatorTest : public testing::Test {};
+
+/*
+ * Reclaim and Take tests
+ */
+class ReclaimTest : public testing::TestWithParam<std::vector<unsigned>> {};
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.cpp b/host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.cpp
new file mode 100644
index 0000000..493b9cb
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.h"
+
+#include <android-base/strings.h>
+
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+#include "host/libs/config/cuttlefish_config.h"
+
+namespace cuttlefish {
+namespace selector {
+
+InstanceIdTest::InstanceIdTest() {
+ auto [input, cuttlefish_instance, ids, num_instances, result] = GetParam();
+ auto args = android::base::Tokenize(input, " ");
+ flag_separation_result_ = GetCommandAndSelectorArguments(args);
+ if (!flag_separation_result_.ok()) {
+ return;
+ }
+ auto [cmd_args, selector_args] = *flag_separation_result_;
+ if (cuttlefish_instance) {
+ envs_[kCuttlefishInstanceEnvVarName] = cuttlefish_instance.value();
+ }
+ auto parse_result = SelectorFlagsParser::ConductSelectFlagsParser(
+ selector_args, cmd_args, envs_);
+ if (parse_result.ok()) {
+ parser_ = std::move(*parse_result);
+ }
+ expected_ids_ = std::move(ids);
+ expected_result_ = result;
+ requested_num_instances_ = num_instances;
+}
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.h b/host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.h
new file mode 100644
index 0000000..a637643
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.h
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+
+namespace cuttlefish {
+namespace selector {
+
+using Envs = std::unordered_map<std::string, std::string>;
+using Args = std::vector<std::string>;
+
+struct InstanceIdTestInput {
+ std::string input_args;
+ std::optional<std::string> cuttlefish_instance;
+ std::optional<std::unordered_set<unsigned>> expected_ids;
+ unsigned requested_num_instances;
+ bool expected_result;
+};
+
+class InstanceIdTest : public testing::TestWithParam<InstanceIdTestInput> {
+ protected:
+ InstanceIdTest();
+
+ bool expected_result_;
+ unsigned requested_num_instances_;
+ std::optional<std::unordered_set<unsigned>> expected_ids_;
+ std::unordered_map<std::string, std::string> envs_;
+ std::optional<SelectorFlagsParser> parser_;
+ Result<CommandAndSelectorArguments> flag_separation_result_;
+};
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/selector_parser_names_test_helper.cpp b/host/commands/cvd/unittests/selector/selector_parser_names_test_helper.cpp
new file mode 100644
index 0000000..29d9c24
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/selector_parser_names_test_helper.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "host/commands/cvd/unittests/selector/selector_parser_names_test_helper.h"
+
+#include <android-base/strings.h>
+#include <gtest/gtest.h>
+
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+#include "host/commands/cvd/selector/selector_option_parser_utils.h"
+
+namespace cuttlefish {
+namespace selector {
+
+ValidNamesTest::ValidNamesTest() { Init(); }
+
+void ValidNamesTest::Init() {
+ auto [input, expected_output] = GetParam();
+ selector_args_ = android::base::Tokenize(input, " ");
+ expected_output_ = std::move(expected_output);
+ auto parse_result = SelectorFlagsParser::ConductSelectFlagsParser(
+ selector_args_, Args{}, Envs{});
+ if (parse_result.ok()) {
+ parser_ = std::move(*parse_result);
+ }
+}
+
+InvalidNamesTest::InvalidNamesTest() {
+ auto input = GetParam();
+ auto selector_args = android::base::Tokenize(input, " ");
+ auto parse_result = SelectorFlagsParser::ConductSelectFlagsParser(
+ selector_args, Args{}, Envs{});
+ if (parse_result.ok()) {
+ parser_ = std::move(*parse_result);
+ }
+}
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/selector_parser_names_test_helper.h b/host/commands/cvd/unittests/selector/selector_parser_names_test_helper.h
new file mode 100644
index 0000000..ea164b9
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/selector_parser_names_test_helper.h
@@ -0,0 +1,63 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+
+namespace cuttlefish {
+namespace selector {
+
+using Envs = std::unordered_map<std::string, std::string>;
+using Args = std::vector<std::string>;
+
+struct ExpectedOutput {
+ std::optional<std::vector<std::string>> names;
+ std::optional<std::string> group_name;
+ std::optional<std::vector<std::string>> per_instance_names;
+};
+
+struct InputOutput {
+ std::string input;
+ ExpectedOutput expected;
+};
+
+class ValidNamesTest : public testing::TestWithParam<InputOutput> {
+ protected:
+ ValidNamesTest();
+ void Init();
+
+ std::vector<std::string> selector_args_;
+ ExpectedOutput expected_output_;
+ std::optional<SelectorFlagsParser> parser_;
+};
+
+class InvalidNamesTest : public testing::TestWithParam<std::string> {
+ protected:
+ InvalidNamesTest();
+
+ std::optional<SelectorFlagsParser> parser_;
+};
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.cpp b/host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.cpp
new file mode 100644
index 0000000..6d25197
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.h"
+
+#include <android-base/strings.h>
+
+namespace cuttlefish {
+namespace selector {
+
+SubstringTest::SubstringTest() {
+ auto [input, expected] = GetParam();
+ auto selector_args = android::base::Tokenize(input, " ");
+ auto parse_result = SelectorFlagsParser::ConductSelectFlagsParser(
+ selector_args, Args{}, Envs{});
+ if (parse_result.ok()) {
+ parser_ = std::move(*parse_result);
+ }
+ expected_result_ = expected;
+}
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.h b/host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.h
new file mode 100644
index 0000000..f1cd32f
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.h
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+
+namespace cuttlefish {
+namespace selector {
+
+using Envs = std::unordered_map<std::string, std::string>;
+using Args = std::vector<std::string>;
+
+struct SubstringTestInput {
+ std::string input_args;
+ bool expected;
+};
+
+class SubstringTest : public testing::TestWithParam<SubstringTestInput> {
+ protected:
+ SubstringTest();
+
+ bool expected_result_;
+ std::optional<SelectorFlagsParser> parser_;
+};
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/test_cvd_selector_parser.cpp b/host/commands/cvd/unittests/selector/test_cvd_selector_parser.cpp
deleted file mode 100644
index c64eb74..0000000
--- a/host/commands/cvd/unittests/selector/test_cvd_selector_parser.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-//
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <optional>
-#include <string>
-#include <vector>
-
-#include <android-base/strings.h>
-#include <gtest/gtest.h>
-
-#include "host/commands/cvd/selector/selector_cmdline_parser.h"
-#include "host/commands/cvd/selector/selector_option_parser_utils.h"
-
-namespace cuttlefish {
-namespace selector {
-namespace {
-
-struct ExpectedOutput {
- std::optional<std::vector<std::string>> names;
- std::optional<std::string> group_name;
- std::optional<std::vector<std::string>> per_instance_names;
-};
-
-struct InputOutput {
- std::string input;
- ExpectedOutput expected;
-};
-
-} // namespace
-
-class CvdSelectorParserNamesTest : public testing::TestWithParam<InputOutput> {
- protected:
- CvdSelectorParserNamesTest() { Init(); }
- void Init() {
- auto [input, expected_output] = GetParam();
- selector_args_ = android::base::Tokenize(input, " ");
- expected_output_ = std::move(expected_output);
- auto parse_result =
- SelectorFlagsParser::ConductSelectFlagsParser(selector_args_);
- if (parse_result.ok()) {
- parser_ = std::move(*parse_result);
- }
- }
-
- std::vector<std::string> selector_args_;
- ExpectedOutput expected_output_;
- std::optional<SelectorFlagsParser> parser_;
-};
-
-TEST_P(CvdSelectorParserNamesTest, ValidInputs) {
- /*
- * if ParseOptions() is successful, parser_ is not nullopt
- */
- ASSERT_TRUE(parser_);
-}
-
-/**
- * Note that invalid inputs must be tested at the InstanceDatabase level
- */
-TEST_P(CvdSelectorParserNamesTest, FieldsNoSubstring) {
- if (!parser_) {
- /*
- * We aren't testing whether or not parsing is working.
- * That's tested in ValidInputs tests. We test fields.
- */
- GTEST_SKIP() << "Parsing failed, which must be tested in ValidInputs Test";
- }
-
- ASSERT_EQ(parser_->GroupName(), expected_output_.group_name);
- ASSERT_EQ(parser_->PerInstanceNames(), expected_output_.per_instance_names);
-}
-
-INSTANTIATE_TEST_SUITE_P(
- CvdParser, CvdSelectorParserNamesTest,
- testing::Values(
- InputOutput{.input = "--name=cf",
- .expected = ExpectedOutput{.group_name = "cf"}},
- InputOutput{.input = "--name=cvd,cf",
- .expected = ExpectedOutput{.per_instance_names =
- std::vector<std::string>{
- "cvd", "cf"}}},
- InputOutput{.input = "--name=cf-09,cf-tv",
- .expected = ExpectedOutput{.group_name = "cf",
- .per_instance_names =
- std::vector<std::string>{
- "09", "tv"}}},
- InputOutput{
- .input = "--device_name cf-09",
- .expected = ExpectedOutput{.group_name = "cf",
- .per_instance_names =
- std::vector<std::string>{"09"}}},
- InputOutput{.input = "--device_name my_cool-phone,my_cool-tv",
- .expected = ExpectedOutput{.group_name = "my_cool",
- .per_instance_names =
- std::vector<std::string>{
- "phone", "tv"}}},
- InputOutput{
- .input = "--group_name=my_cool --instance_name=phone",
- .expected = ExpectedOutput{.group_name = "my_cool",
- .per_instance_names =
- std::vector<std::string>{"phone"}}},
- InputOutput{.input = "--group_name=my_cool --instance_name=phone,tv",
- .expected = ExpectedOutput{.group_name = "my_cool",
- .per_instance_names =
- std::vector<std::string>{
- "phone", "tv"}}},
- InputOutput{
- .input = "--group_name=my_cool",
- .expected =
- ExpectedOutput{
- .group_name = "my_cool",
- }},
- InputOutput{
- .input = "--instance_name=my_cool",
- .expected = ExpectedOutput{
- .per_instance_names = std::vector<std::string>{"my_cool"}}}));
-
-class CvdSelectorParserInvalidNamesTest
- : public testing::TestWithParam<std::string> {
- protected:
- CvdSelectorParserInvalidNamesTest() {
- input_ = GetParam();
- selector_args_ = android::base::Tokenize(input_, " ");
- }
- std::string input_;
- std::vector<std::string> selector_args_;
-};
-
-TEST_P(CvdSelectorParserInvalidNamesTest, InvalidInputs) {
- auto parse_result =
- SelectorFlagsParser::ConductSelectFlagsParser(selector_args_);
-
- ASSERT_FALSE(parse_result.ok()) << "Failed with " << input_;
-}
-
-INSTANTIATE_TEST_SUITE_P(
- CvdParser2, CvdSelectorParserInvalidNamesTest,
- testing::Values("--name", "--name=?34", "--device_name=abcd",
- "--group_name=3ab", "--name=x --device_name=y",
- "--name=x --group_name=cf",
- "--device_name=z --instance_name=p", "--instance_name=*79a",
- "--device_name=abcd-e,xyz-f", "--device_name=xyz-e,xyz-e"));
-
-struct SubstringTestInput {
- std::string input_args;
- bool expected;
-};
-
-class CvdSelectorParserSubstringTest
- : public testing::TestWithParam<SubstringTestInput> {
- protected:
- CvdSelectorParserSubstringTest() {
- auto [input, expected] = GetParam();
- auto selector_args = android::base::Tokenize(input, " ");
- auto parse_result =
- SelectorFlagsParser::ConductSelectFlagsParser(selector_args);
- if (parse_result.ok()) {
- parser_ = std::move(*parse_result);
- }
- expected_result_ = expected;
- }
- bool expected_result_;
- std::optional<SelectorFlagsParser> parser_;
-};
-
-TEST_P(CvdSelectorParserSubstringTest, Substring) {
- ASSERT_EQ(parser_ != std::nullopt, expected_result_);
-}
-
-INSTANTIATE_TEST_SUITE_P(
- CvdParser3, CvdSelectorParserSubstringTest,
- testing::Values(SubstringTestInput{"--name cvd", true},
- SubstringTestInput{"c v --name cvd d", true},
- SubstringTestInput{"--name cvd c", true},
- SubstringTestInput{"--name cvd c v", true},
- SubstringTestInput{"c --name cvd v", true},
- SubstringTestInput{"--name cvd c,v,d", true},
- SubstringTestInput{"--name cvd c v,d", true},
- SubstringTestInput{"--name cvd c,", false},
- SubstringTestInput{"--name cvd c v,,d", false}));
-
-} // namespace selector
-} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/test_cvd_selector_parser_ids.cpp b/host/commands/cvd/unittests/selector/test_cvd_selector_parser_ids.cpp
new file mode 100644
index 0000000..e2f4068
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/test_cvd_selector_parser_ids.cpp
@@ -0,0 +1,135 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <optional>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <android-base/strings.h>
+#include <gtest/gtest.h>
+
+#include "host/commands/cvd/selector/selector_cmdline_parser.h"
+#include "host/commands/cvd/unittests/selector/selector_parser_ids_test_helper.h"
+
+namespace cuttlefish {
+namespace selector {
+
+TEST_P(InstanceIdTest, InstanceIdCalculation) {
+ if (!flag_separation_result_.ok()) {
+ GTEST_SKIP()
+ << "Selector and Command Args separation failed. "
+ << "Developers must make sure that this does not happen. "
+ << "This is not what InstanceIdCalculation test intended to test.";
+ }
+
+ ASSERT_EQ(parser_ != std::nullopt, expected_result_);
+ if (!expected_result_) {
+ return;
+ }
+ ASSERT_EQ(parser_->InstanceIds(), expected_ids_);
+ ASSERT_EQ(parser_->RequestedNumInstances(), requested_num_instances_);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ CvdParser, InstanceIdTest,
+ testing::Values(
+ InstanceIdTestInput{.input_args = "",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::nullopt,
+ .requested_num_instances = 1,
+ .expected_result = true},
+ InstanceIdTestInput{.input_args = "",
+ .cuttlefish_instance = "8",
+ .expected_ids = std::unordered_set<unsigned>{8},
+ .requested_num_instances = 1,
+ .expected_result = true},
+ InstanceIdTestInput{.input_args = "--num_instances=2",
+ .expected_ids = std::nullopt,
+ .requested_num_instances = 2,
+ .expected_result = true},
+ InstanceIdTestInput{.input_args = "--num_instances=2",
+ .cuttlefish_instance = "8",
+ .expected_ids = std::unordered_set<unsigned>{8, 9},
+ .requested_num_instances = 2,
+ .expected_result = true},
+ InstanceIdTestInput{
+ .input_args = "--base_instance_num=10 --num_instances=2",
+ .cuttlefish_instance = "8",
+ .expected_ids = std::unordered_set<unsigned>{10, 11},
+ .requested_num_instances = 2,
+ .expected_result = true},
+ InstanceIdTestInput{.input_args = "--instance_nums 2",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2},
+ .requested_num_instances = 1,
+ .expected_result = true},
+ InstanceIdTestInput{
+ .input_args = "--instance_nums 2,5,6",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = true},
+ InstanceIdTestInput{
+ .input_args = "--instance_nums 2,5,6 --num_instances=3",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = true},
+ InstanceIdTestInput{
+ .input_args = "[--device_name=c-1,c-3,c-5] "
+ "--instance_nums 2,5,6 --num_instances=3",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = true},
+ InstanceIdTestInput{.input_args = "[--device_name=c-1,c-3,c-5]",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::nullopt,
+ .requested_num_instances = 3,
+ .expected_result = true},
+ // CUTTLEFISH_INSTANCE should be ignored
+ InstanceIdTestInput{
+ .input_args = "--instance_nums 2,5,6 --num_instances=3",
+ .cuttlefish_instance = "8",
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = true},
+ // instance_nums and num_instances mismatch
+ InstanceIdTestInput{
+ .input_args = "--instance_nums 2,5,6 --num_instances=7",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = false},
+ // device_name requested 2 instances while instance_nums 3.
+ InstanceIdTestInput{
+ .input_args = "[--device_name=c-1,c-3] --instance_nums 2,5,6 "
+ "--num_instances=3",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = false},
+ // --base_instance_num is not allowed with --instance_nums
+ InstanceIdTestInput{
+ .input_args = "--instance_nums 2,5,6 --base_instance_num=7",
+ .cuttlefish_instance = std::nullopt,
+ .expected_ids = std::unordered_set<unsigned>{2, 5, 6},
+ .requested_num_instances = 3,
+ .expected_result = false}));
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/test_cvd_selector_parser_names.cpp b/host/commands/cvd/unittests/selector/test_cvd_selector_parser_names.cpp
new file mode 100644
index 0000000..2119c33
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/test_cvd_selector_parser_names.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "host/commands/cvd/unittests/selector/selector_parser_names_test_helper.h"
+
+namespace cuttlefish {
+namespace selector {
+
+TEST_P(ValidNamesTest, ValidInputs) { ASSERT_TRUE(parser_); }
+
+/**
+ * Note that invalid inputs must be tested at the InstanceDatabase level
+ */
+TEST_P(ValidNamesTest, FieldsNoSubstring) {
+ if (!parser_) {
+ /*
+ * We aren't testing whether or not parsing is working.
+ * That's tested in ValidInputs tests. We test fields.
+ */
+ GTEST_SKIP() << "Parsing failed, which must be tested in ValidInputs Test";
+ }
+
+ ASSERT_EQ(parser_->GroupName(), expected_output_.group_name);
+ ASSERT_EQ(parser_->PerInstanceNames(), expected_output_.per_instance_names);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ CvdParser, ValidNamesTest,
+ testing::Values(
+ InputOutput{.input = "--name=cf",
+ .expected = ExpectedOutput{.group_name = "cf"}},
+ InputOutput{.input = "--name=cvd,cf",
+ .expected = ExpectedOutput{.per_instance_names =
+ std::vector<std::string>{
+ "cvd", "cf"}}},
+ InputOutput{.input = "--name=cf-09,cf-tv",
+ .expected = ExpectedOutput{.group_name = "cf",
+ .per_instance_names =
+ std::vector<std::string>{
+ "09", "tv"}}},
+ InputOutput{
+ .input = "--device_name cf-09",
+ .expected = ExpectedOutput{.group_name = "cf",
+ .per_instance_names =
+ std::vector<std::string>{"09"}}},
+ InputOutput{.input = "--device_name my_cool-phone,my_cool-tv",
+ .expected = ExpectedOutput{.group_name = "my_cool",
+ .per_instance_names =
+ std::vector<std::string>{
+ "phone", "tv"}}},
+ InputOutput{
+ .input = "--group_name=my_cool --instance_name=phone",
+ .expected = ExpectedOutput{.group_name = "my_cool",
+ .per_instance_names =
+ std::vector<std::string>{"phone"}}},
+ InputOutput{.input = "--group_name=my_cool --instance_name=phone,tv",
+ .expected = ExpectedOutput{.group_name = "my_cool",
+ .per_instance_names =
+ std::vector<std::string>{
+ "phone", "tv"}}},
+ InputOutput{
+ .input = "--group_name=my_cool",
+ .expected =
+ ExpectedOutput{
+ .group_name = "my_cool",
+ }},
+ InputOutput{
+ .input = "--instance_name=my_cool",
+ .expected = ExpectedOutput{
+ .per_instance_names = std::vector<std::string>{"my_cool"}}}));
+
+TEST_P(InvalidNamesTest, InvalidInputs) { ASSERT_FALSE(parser_); }
+
+INSTANTIATE_TEST_SUITE_P(
+ CvdParser, InvalidNamesTest,
+ testing::Values("--name", "--name=?34", "--device_name=abcd",
+ "--group_name=3ab", "--name=x --device_name=y",
+ "--name=x --group_name=cf",
+ "--device_name=z --instance_name=p", "--instance_name=*79a",
+ "--device_name=abcd-e,xyz-f", "--device_name=xyz-e,xyz-e"));
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/test_cvd_selector_parser_substring.cpp b/host/commands/cvd/unittests/selector/test_cvd_selector_parser_substring.cpp
new file mode 100644
index 0000000..6175643
--- /dev/null
+++ b/host/commands/cvd/unittests/selector/test_cvd_selector_parser_substring.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "host/commands/cvd/unittests/selector/selector_parser_substring_test_helper.h"
+
+namespace cuttlefish {
+namespace selector {
+
+TEST_P(SubstringTest, Substring) {
+ ASSERT_EQ((parser_ != std::nullopt), expected_result_);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ CvdParser, SubstringTest,
+ testing::Values(SubstringTestInput{"--name cvd", true},
+ SubstringTestInput{"--name cvd cv", true},
+ SubstringTestInput{"--name cvd c v", true},
+ SubstringTestInput{"--name cvd c,v,d", true},
+ SubstringTestInput{"--name cvd c v,d", true},
+ SubstringTestInput{"--name cvd c", true},
+ SubstringTestInput{"c v --name cvd d", true},
+ SubstringTestInput{"c --name cvd v", true},
+ SubstringTestInput{"--name cvd c,", false},
+ SubstringTestInput{"--name cvd c v,,d", false}));
+
+} // namespace selector
+} // namespace cuttlefish
diff --git a/host/commands/cvd/unittests/selector/test_id_allocator.cpp b/host/commands/cvd/unittests/selector/test_id_allocator.cpp
index e8e6603..ed8beec 100644
--- a/host/commands/cvd/unittests/selector/test_id_allocator.cpp
+++ b/host/commands/cvd/unittests/selector/test_id_allocator.cpp
@@ -13,20 +13,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "host/commands/cvd/unittests/selector/id_allocator_test_helper.h"
+
#include <memory>
#include <unordered_set>
-#include <vector>
-
-#include <gtest/gtest.h>
#include "host/commands/cvd/selector/unique_resource_allocator.h"
namespace cuttlefish::selector {
-class CvdIdAllocatorOneEachTest
- : public testing::TestWithParam<std::vector<unsigned>> {};
-
-TEST_P(CvdIdAllocatorOneEachTest, GetAnyAvailableOne) {
+TEST_P(OneEachTest, GetAnyAvailableOne) {
const auto resources = GetParam();
auto allocator = UniqueResourceAllocator<unsigned>::New(resources);
std::unordered_set<unsigned> expected_ids{resources.cbegin(),
@@ -41,12 +37,10 @@
}
INSTANTIATE_TEST_SUITE_P(
- AllocatorGetterTest, CvdIdAllocatorOneEachTest,
+ CvdIdAllocator, OneEachTest,
testing::Values(std::vector<unsigned>{}, std::vector<unsigned>{1},
std::vector<unsigned>{1, 22, 3, 43, 5}));
-class CvdIdAllocatorTest : public testing::Test {};
-
TEST_F(CvdIdAllocatorTest, ClaimAll) {
std::vector<unsigned> inputs{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto allocator = UniqueResourceAllocator<unsigned>::New(inputs);
@@ -117,26 +111,6 @@
ASSERT_FALSE(allocator.TakeRange(2, 4));
}
-class CvdIdAllocatorReclaimTest
- : public testing::TestWithParam<std::vector<unsigned>> {};
-
-TEST_P(CvdIdAllocatorReclaimTest, Reclaim) {
- const auto inputs{GetParam()};
- auto allocator = UniqueResourceAllocator<unsigned>::New(inputs);
- if (!allocator.TakeAll(inputs)) {
- GTEST_SKIP() << "In set up for Reclaim, TakeAll failed.";
- }
-
- ASSERT_TRUE(allocator.Reclaim(7));
- ASSERT_FALSE(allocator.Reclaim(100));
- ASSERT_TRUE(allocator.Take(7));
-}
-
-INSTANTIATE_TEST_SUITE_P(
- AllocatorReclaimTest, CvdIdAllocatorReclaimTest,
- testing::Values(std::vector<unsigned>{7}, std::vector<unsigned>{7, 3},
- std::vector<unsigned>{1, 22, 3, 43, 7}));
-
TEST_F(CvdIdAllocatorTest, ReclaimAll) {
std::vector<unsigned> inputs{1, 2, 4, 5, 6, 7, 8, 9, 10, 11};
auto allocator = UniqueResourceAllocator<unsigned>::New(inputs);
@@ -163,4 +137,21 @@
ASSERT_TRUE(allocator.ReclaimAll(std::vector<unsigned>{}));
}
+TEST_P(ReclaimTest, Reclaim) {
+ const auto inputs{GetParam()};
+ auto allocator = UniqueResourceAllocator<unsigned>::New(inputs);
+ if (!allocator.TakeAll(inputs)) {
+ GTEST_SKIP() << "In set up for Reclaim, TakeAll failed.";
+ }
+
+ ASSERT_TRUE(allocator.Reclaim(7));
+ ASSERT_FALSE(allocator.Reclaim(100));
+ ASSERT_TRUE(allocator.Take(7));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ CvdIdAllocator, ReclaimTest,
+ testing::Values(std::vector<unsigned>{7}, std::vector<unsigned>{7, 3},
+ std::vector<unsigned>{1, 22, 3, 43, 7}));
+
} // namespace cuttlefish::selector
diff --git a/host/commands/gnss_grpc_proxy/doc/linkage.dot b/host/commands/gnss_grpc_proxy/doc/linkage.dot
index 4c4ba96..ec3acbc 100644
--- a/host/commands/gnss_grpc_proxy/doc/linkage.dot
+++ b/host/commands/gnss_grpc_proxy/doc/linkage.dot
@@ -1,37 +1,45 @@
digraph {
+ browser [label = "Browser"]
+ cli [label = "User CLI"]
cvd_import_locations [URL = "https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/cvd_import_locations/"]
cvd_update_location [URL = "https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/cvd_update_location/"]
gnss_grpc_proxy [label = < <B>gnss_grpc_proxy</B> >]
gnss_grpc_server [label = "TCP gRPC", shape = "rectangle"]
run_cvd [URL = "https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/run_cvd/"]
- host_gnss_console_in [color = "green", label = "internal/gnsshvc_fifo_vm.in", shape = "rectangle"]
- host_gnss_console_out [color = "green", label = "internal/gnsshvc_fifo_vm.out", shape = "rectangle"]
- host_fixed_location_console_in [color = "blue", label = "internal/locationhvc_fifo_vm.in", shape = "rectangle"]
- host_fixed_location_console_out [color = "blue", label = "internal/locationhvc_fifo_vm.out", shape = "rectangle"]
vmm [label = "crosvm / qemu"]
+ webrtc
+ subgraph fifos {
+ rank = same;
+ host_gnss_console_in [color = "green", label = "internal/gnsshvc_fifo_vm.in", shape = "rectangle"]
+ host_gnss_console_out [color = "green", label = "internal/gnsshvc_fifo_vm.out", shape = "rectangle"]
+ host_fixed_location_console_in [color = "blue", label = "internal/locationhvc_fifo_vm.in", shape = "rectangle"]
+ host_fixed_location_console_out [color = "blue", label = "internal/locationhvc_fifo_vm.out", shape = "rectangle"]
+ }
subgraph cluster_android {
label = "Android"
gnss_hal [label = "vendor.gnss-default", URL = "https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/gnss/aidl/default/"]
- fixed_location_console [color = "blue", label = "/dev/hvc6 | /dev/gnss1", shape = "rectangle"]
- gnss_console [color = "green", label = "/dev/hvc5 | /dev/gnss0", shape = "rectangle"]
+ subgraph consoles {
+ rank = same;
+ fixed_location_console [color = "blue", label = "/dev/hvc6 | /dev/gnss1", shape = "rectangle"]
+ gnss_console [color = "green", label = "/dev/hvc5 | /dev/gnss0", shape = "rectangle"]
+ }
}
+ cli -> cvd_import_locations
+ cli -> cvd_update_location
+ browser -> webrtc
+
run_cvd -> gnss_grpc_proxy
- fixed_location_console -> gnss_hal [color = "blue"]
- gnss_hal -> fixed_location_console [color = "blue"]
- gnss_console -> gnss_hal [color = "green"]
- gnss_hal -> gnss_console [color = "green"]
+ fixed_location_console -> gnss_hal [color = "blue", dir = "both"]
+ gnss_console -> gnss_hal [color = "green", dir = "both"]
- cvd_import_locations -> gnss_grpc_server
- gnss_grpc_server -> cvd_import_locations
+ cvd_import_locations -> gnss_grpc_server [dir = "both"]
+ cvd_update_location -> gnss_grpc_server [dir = "both"]
+ webrtc -> gnss_grpc_server [dir = "both"]
- cvd_update_location -> gnss_grpc_server
- gnss_grpc_server -> cvd_update_location
-
- gnss_grpc_server -> gnss_grpc_proxy
- gnss_grpc_proxy -> gnss_grpc_server
+ gnss_grpc_server -> gnss_grpc_proxy [dir = "both"]
gnss_grpc_proxy -> host_gnss_console_in [color = "green"]
host_gnss_console_out -> gnss_grpc_proxy [color = "green"]
@@ -39,15 +47,12 @@
vmm -> host_gnss_console_out [color = "green"]
host_gnss_console_in -> vmm [color = "green"]
- gnss_grpc_proxy -> host_fixed_location_console_in [color = "blue"]
+ host_fixed_location_console_in -> gnss_grpc_proxy [color = "blue", dir = "back"]
host_fixed_location_console_out -> gnss_grpc_proxy [color = "blue"]
- vmm -> host_fixed_location_console_out [color = "blue"]
- host_fixed_location_console_in -> vmm [color = "blue"]
+ host_fixed_location_console_out -> vmm [color = "blue"]
+ host_fixed_location_console_in -> vmm [color = "blue", dir = "back"]
- vmm -> fixed_location_console [color = "blue"]
- fixed_location_console -> vmm [color = "blue"]
-
- gnss_console -> vmm [color = "green"]
- vmm -> gnss_console [color = "green"]
+ vmm -> fixed_location_console [color = "blue", dir = "both"]
+ vmm -> gnss_console [color = "green", dir = "both"]
}
diff --git a/host/commands/gnss_grpc_proxy/doc/linkage.png b/host/commands/gnss_grpc_proxy/doc/linkage.png
index b07d4ae..11f5541 100644
--- a/host/commands/gnss_grpc_proxy/doc/linkage.png
+++ b/host/commands/gnss_grpc_proxy/doc/linkage.png
Binary files differ
diff --git a/host/commands/gnss_grpc_proxy/doc/linkage.svg b/host/commands/gnss_grpc_proxy/doc/linkage.svg
index 748c8cc..3e2466e 100644
--- a/host/commands/gnss_grpc_proxy/doc/linkage.svg
+++ b/host/commands/gnss_grpc_proxy/doc/linkage.svg
@@ -4,245 +4,253 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
-<svg width="986pt" height="407pt"
- viewBox="0.00 0.00 986.34 407.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 403)">
+<svg width="798pt" height="567pt"
+ viewBox="0.00 0.00 797.50 567.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 563)">
<title>%3</title>
-<polygon fill="white" stroke="transparent" points="-4,4 -4,-403 982.34,-403 982.34,4 -4,4"/>
-<g id="clust1" class="cluster">
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-563 793.5,-563 793.5,4 -4,4"/>
+<g id="clust2" class="cluster">
<title>cluster_android</title>
-<polygon fill="none" stroke="black" points="175.84,-136 175.84,-283 485.84,-283 485.84,-136 175.84,-136"/>
-<text text-anchor="middle" x="330.84" y="-267.8" font-family="Times,serif" font-size="14.00">Android</text>
+<polygon fill="none" stroke="black" points="223,-8 223,-155 533,-155 533,-8 223,-8"/>
+<text text-anchor="middle" x="378" y="-139.8" font-family="Times,serif" font-size="14.00">Android</text>
+</g>
+<!-- browser -->
+<g id="node1" class="node">
+<title>browser</title>
+<ellipse fill="none" stroke="black" cx="190" cy="-541" rx="40.09" ry="18"/>
+<text text-anchor="middle" x="190" y="-537.3" font-family="Times,serif" font-size="14.00">Browser</text>
+</g>
+<!-- webrtc -->
+<g id="node9" class="node">
+<title>webrtc</title>
+<ellipse fill="none" stroke="black" cx="190" cy="-469" rx="34.39" ry="18"/>
+<text text-anchor="middle" x="190" y="-465.3" font-family="Times,serif" font-size="14.00">webrtc</text>
+</g>
+<!-- browser->webrtc -->
+<g id="edge3" class="edge">
+<title>browser->webrtc</title>
+<path fill="none" stroke="black" d="M190,-522.7C190,-514.98 190,-505.71 190,-497.11"/>
+<polygon fill="black" stroke="black" points="193.5,-497.1 190,-487.1 186.5,-497.1 193.5,-497.1"/>
+</g>
+<!-- cli -->
+<g id="node2" class="node">
+<title>cli</title>
+<ellipse fill="none" stroke="black" cx="425" cy="-541" rx="44.39" ry="18"/>
+<text text-anchor="middle" x="425" y="-537.3" font-family="Times,serif" font-size="14.00">User CLI</text>
</g>
<!-- cvd_import_locations -->
-<g id="node1" class="node">
+<g id="node3" class="node">
<title>cvd_import_locations</title>
-<g id="a_node1"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/cvd_import_locations/" xlink:title="cvd_import_locations">
-<ellipse fill="none" stroke="black" cx="383.84" cy="-381" rx="87.99" ry="18"/>
-<text text-anchor="middle" x="383.84" y="-377.3" font-family="Times,serif" font-size="14.00">cvd_import_locations</text>
+<g id="a_node3"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/cvd_import_locations/" xlink:title="cvd_import_locations">
+<ellipse fill="none" stroke="black" cx="330" cy="-469" rx="87.99" ry="18"/>
+<text text-anchor="middle" x="330" y="-465.3" font-family="Times,serif" font-size="14.00">cvd_import_locations</text>
</a>
</g>
</g>
-<!-- gnss_grpc_server -->
-<g id="node4" class="node">
-<title>gnss_grpc_server</title>
-<polygon fill="none" stroke="black" points="422.34,-327 345.34,-327 345.34,-291 422.34,-291 422.34,-327"/>
-<text text-anchor="middle" x="383.84" y="-305.3" font-family="Times,serif" font-size="14.00">TCP gRPC</text>
-</g>
-<!-- cvd_import_locations->gnss_grpc_server -->
-<g id="edge6" class="edge">
-<title>cvd_import_locations->gnss_grpc_server</title>
-<path fill="none" stroke="black" d="M377.93,-362.7C377.13,-354.98 376.9,-345.71 377.25,-337.11"/>
-<polygon fill="black" stroke="black" points="380.74,-337.32 377.95,-327.1 373.76,-336.84 380.74,-337.32"/>
+<!-- cli->cvd_import_locations -->
+<g id="edge1" class="edge">
+<title>cli->cvd_import_locations</title>
+<path fill="none" stroke="black" d="M404.39,-524.81C391.61,-515.4 374.97,-503.14 360.67,-492.6"/>
+<polygon fill="black" stroke="black" points="362.69,-489.74 352.57,-486.63 358.54,-495.38 362.69,-489.74"/>
</g>
<!-- cvd_update_location -->
-<g id="node2" class="node">
+<g id="node4" class="node">
<title>cvd_update_location</title>
-<g id="a_node2"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/cvd_update_location/" xlink:title="cvd_update_location">
-<ellipse fill="none" stroke="black" cx="83.84" cy="-234" rx="83.69" ry="18"/>
-<text text-anchor="middle" x="83.84" y="-230.3" font-family="Times,serif" font-size="14.00">cvd_update_location</text>
+<g id="a_node4"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/cvd_update_location/" xlink:title="cvd_update_location">
+<ellipse fill="none" stroke="black" cx="520" cy="-469" rx="83.69" ry="18"/>
+<text text-anchor="middle" x="520" y="-465.3" font-family="Times,serif" font-size="14.00">cvd_update_location</text>
</a>
</g>
</g>
+<!-- cli->cvd_update_location -->
+<g id="edge2" class="edge">
+<title>cli->cvd_update_location</title>
+<path fill="none" stroke="black" d="M445.61,-524.81C458.48,-515.33 475.27,-502.96 489.64,-492.37"/>
+<polygon fill="black" stroke="black" points="491.8,-495.13 497.77,-486.38 487.64,-489.49 491.8,-495.13"/>
+</g>
+<!-- gnss_grpc_server -->
+<g id="node6" class="node">
+<title>gnss_grpc_server</title>
+<polygon fill="none" stroke="black" points="368.5,-415 291.5,-415 291.5,-379 368.5,-379 368.5,-415"/>
+<text text-anchor="middle" x="330" y="-393.3" font-family="Times,serif" font-size="14.00">TCP gRPC</text>
+</g>
+<!-- cvd_import_locations->gnss_grpc_server -->
+<g id="edge7" class="edge">
+<title>cvd_import_locations->gnss_grpc_server</title>
+<path fill="none" stroke="black" d="M330,-440.67C330,-435.69 330,-430.49 330,-425.51"/>
+<polygon fill="black" stroke="black" points="326.5,-440.7 330,-450.7 333.5,-440.7 326.5,-440.7"/>
+<polygon fill="black" stroke="black" points="333.5,-425.1 330,-415.1 326.5,-425.1 333.5,-425.1"/>
+</g>
<!-- cvd_update_location->gnss_grpc_server -->
<g id="edge8" class="edge">
<title>cvd_update_location->gnss_grpc_server</title>
-<path fill="none" stroke="black" d="M114.5,-250.85C133.14,-261.75 157.46,-275.55 180.84,-283 231.95,-299.28 293.03,-305.14 334.85,-307.16"/>
-<polygon fill="black" stroke="black" points="334.91,-310.67 345.05,-307.6 335.21,-303.68 334.91,-310.67"/>
+<path fill="none" stroke="black" d="M470.16,-449.64C441.76,-439.18 406.36,-426.13 378.23,-415.77"/>
+<polygon fill="black" stroke="black" points="469.11,-452.98 479.71,-453.15 471.53,-446.41 469.11,-452.98"/>
+<polygon fill="black" stroke="black" points="379.21,-412.4 368.61,-412.23 376.79,-418.97 379.21,-412.4"/>
</g>
<!-- gnss_grpc_proxy -->
-<g id="node3" class="node">
+<g id="node5" class="node">
<title>gnss_grpc_proxy</title>
-<ellipse fill="none" stroke="black" cx="679.84" cy="-234" rx="79.89" ry="18"/>
-<text text-anchor="start" x="626.34" y="-231.3" font-family="Times,serif" font-size="14.00"> </text>
-<text text-anchor="start" x="630.34" y="-231.3" font-family="Times,serif" font-weight="bold" font-size="14.00">gnss_grpc_proxy</text>
-<text text-anchor="start" x="729.34" y="-231.3" font-family="Times,serif" font-size="14.00"> </text>
-</g>
-<!-- gnss_grpc_proxy->gnss_grpc_server -->
-<g id="edge11" class="edge">
-<title>gnss_grpc_proxy->gnss_grpc_server</title>
-<path fill="none" stroke="black" d="M633.8,-248.78C597.23,-258.5 544.95,-271.74 498.84,-283 477.22,-288.28 453.06,-293.99 432.4,-298.62"/>
-<polygon fill="black" stroke="black" points="431.58,-295.22 422.57,-300.8 433.09,-302.05 431.58,-295.22"/>
+<ellipse fill="none" stroke="black" cx="378" cy="-325" rx="79.89" ry="18"/>
+<text text-anchor="start" x="324.5" y="-322.3" font-family="Times,serif" font-size="14.00"> </text>
+<text text-anchor="start" x="328.5" y="-322.3" font-family="Times,serif" font-weight="bold" font-size="14.00">gnss_grpc_proxy</text>
+<text text-anchor="start" x="427.5" y="-322.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- host_gnss_console_in -->
-<g id="node6" class="node">
+<g id="node10" class="node">
<title>host_gnss_console_in</title>
-<polygon fill="none" stroke="green" points="665.84,-180 495.84,-180 495.84,-144 665.84,-144 665.84,-180"/>
-<text text-anchor="middle" x="580.84" y="-158.3" font-family="Times,serif" font-size="14.00">internal/gnsshvc_fifo_vm.in</text>
+<polygon fill="none" stroke="green" points="170,-271 0,-271 0,-235 170,-235 170,-271"/>
+<text text-anchor="middle" x="85" y="-249.3" font-family="Times,serif" font-size="14.00">internal/gnsshvc_fifo_vm.in</text>
</g>
<!-- gnss_grpc_proxy->host_gnss_console_in -->
-<g id="edge12" class="edge">
+<g id="edge11" class="edge">
<title>gnss_grpc_proxy->host_gnss_console_in</title>
-<path fill="none" stroke="green" d="M656.63,-216.59C643.76,-207.49 627.54,-196.02 613.42,-186.03"/>
-<polygon fill="green" stroke="green" points="615.13,-182.96 604.94,-180.04 611.09,-188.67 615.13,-182.96"/>
-</g>
-<!-- host_fixed_location_console_in -->
-<g id="node8" class="node">
-<title>host_fixed_location_console_in</title>
-<polygon fill="none" stroke="blue" points="873.84,-180 683.84,-180 683.84,-144 873.84,-144 873.84,-180"/>
-<text text-anchor="middle" x="778.84" y="-158.3" font-family="Times,serif" font-size="14.00">internal/locationhvc_fifo_vm.in</text>
-</g>
-<!-- gnss_grpc_proxy->host_fixed_location_console_in -->
-<g id="edge16" class="edge">
-<title>gnss_grpc_proxy->host_fixed_location_console_in</title>
-<path fill="none" stroke="blue" d="M703.05,-216.59C715.93,-207.49 732.14,-196.02 746.27,-186.03"/>
-<polygon fill="blue" stroke="blue" points="748.6,-188.67 754.74,-180.04 744.56,-182.96 748.6,-188.67"/>
-</g>
-<!-- gnss_grpc_server->cvd_import_locations -->
-<g id="edge7" class="edge">
-<title>gnss_grpc_server->cvd_import_locations</title>
-<path fill="none" stroke="black" d="M389.74,-327.1C390.54,-334.79 390.78,-344.05 390.45,-352.67"/>
-<polygon fill="black" stroke="black" points="386.95,-352.48 389.76,-362.7 393.93,-352.96 386.95,-352.48"/>
-</g>
-<!-- gnss_grpc_server->cvd_update_location -->
-<g id="edge9" class="edge">
-<title>gnss_grpc_server->cvd_update_location</title>
-<path fill="none" stroke="black" d="M345.26,-307.97C300.14,-307.09 224.29,-302.57 162.84,-283 144.03,-277.01 124.61,-266.9 109.6,-257.5"/>
-<polygon fill="black" stroke="black" points="111.15,-254.33 100.86,-251.78 107.31,-260.19 111.15,-254.33"/>
+<path fill="none" stroke="green" d="M325.28,-311.4C281.03,-300.83 217.08,-285.55 166.28,-273.42"/>
+<polygon fill="green" stroke="green" points="166.84,-269.95 156.3,-271.03 165.21,-276.76 166.84,-269.95"/>
</g>
<!-- gnss_grpc_server->gnss_grpc_proxy -->
<g id="edge10" class="edge">
<title>gnss_grpc_server->gnss_grpc_proxy</title>
-<path fill="none" stroke="black" d="M422.47,-297.08C440.26,-292.76 461.56,-287.71 480.84,-283 525.44,-272.11 575.82,-259.36 614.8,-249.74"/>
-<polygon fill="black" stroke="black" points="616.09,-253.03 624.97,-247.24 614.42,-246.23 616.09,-253.03"/>
+<path fill="none" stroke="black" d="M347.58,-370.36C351.76,-364.26 356.23,-357.75 360.41,-351.65"/>
+<polygon fill="black" stroke="black" points="344.63,-368.47 341.87,-378.7 350.41,-372.43 344.63,-368.47"/>
+<polygon fill="black" stroke="black" points="363.5,-353.33 366.27,-343.1 357.73,-349.37 363.5,-353.33"/>
</g>
<!-- run_cvd -->
-<g id="node5" class="node">
+<g id="node7" class="node">
<title>run_cvd</title>
-<g id="a_node5"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/run_cvd/" xlink:title="run_cvd">
-<ellipse fill="none" stroke="black" cx="679.84" cy="-309" rx="39.79" ry="18"/>
-<text text-anchor="middle" x="679.84" y="-305.3" font-family="Times,serif" font-size="14.00">run_cvd</text>
+<g id="a_node7"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:device/google/cuttlefish/host/commands/run_cvd/" xlink:title="run_cvd">
+<ellipse fill="none" stroke="black" cx="426" cy="-397" rx="39.79" ry="18"/>
+<text text-anchor="middle" x="426" y="-393.3" font-family="Times,serif" font-size="14.00">run_cvd</text>
</a>
</g>
</g>
<!-- run_cvd->gnss_grpc_proxy -->
-<g id="edge1" class="edge">
+<g id="edge4" class="edge">
<title>run_cvd->gnss_grpc_proxy</title>
-<path fill="none" stroke="black" d="M679.84,-290.7C679.84,-282.25 679.84,-271.87 679.84,-262.37"/>
-<polygon fill="black" stroke="black" points="683.34,-262.18 679.84,-252.18 676.34,-262.18 683.34,-262.18"/>
+<path fill="none" stroke="black" d="M414.62,-379.41C408.91,-371.08 401.86,-360.8 395.48,-351.49"/>
+<polygon fill="black" stroke="black" points="398.17,-349.22 389.63,-342.96 392.4,-353.18 398.17,-349.22"/>
</g>
<!-- vmm -->
-<g id="node10" class="node">
+<g id="node8" class="node">
<title>vmm</title>
-<ellipse fill="none" stroke="black" cx="494.84" cy="-90" rx="64.19" ry="18"/>
-<text text-anchor="middle" x="494.84" y="-86.3" font-family="Times,serif" font-size="14.00">crosvm / qemu</text>
-</g>
-<!-- host_gnss_console_in->vmm -->
-<g id="edge15" class="edge">
-<title>host_gnss_console_in->vmm</title>
-<path fill="none" stroke="green" d="M559.58,-143.7C548.43,-134.62 534.63,-123.38 522.64,-113.62"/>
-<polygon fill="green" stroke="green" points="524.64,-110.74 514.68,-107.14 520.22,-116.17 524.64,-110.74"/>
+<ellipse fill="none" stroke="black" cx="378" cy="-181" rx="64.19" ry="18"/>
+<text text-anchor="middle" x="378" y="-177.3" font-family="Times,serif" font-size="14.00">crosvm / qemu</text>
</g>
<!-- host_gnss_console_out -->
-<g id="node7" class="node">
+<g id="node11" class="node">
<title>host_gnss_console_out</title>
-<polygon fill="none" stroke="green" points="643.34,-36 466.34,-36 466.34,0 643.34,0 643.34,-36"/>
-<text text-anchor="middle" x="554.84" y="-14.3" font-family="Times,serif" font-size="14.00">internal/gnsshvc_fifo_vm.out</text>
-</g>
-<!-- host_gnss_console_out->gnss_grpc_proxy -->
-<g id="edge13" class="edge">
-<title>host_gnss_console_out->gnss_grpc_proxy</title>
-<path fill="none" stroke="green" d="M643.63,-23.63C721.05,-32.93 829.11,-59.78 882.84,-136 894.11,-151.98 894.8,-164.52 882.84,-180 867.24,-200.2 807.87,-214.17 757.34,-222.67"/>
-<polygon fill="green" stroke="green" points="756.67,-219.24 747.37,-224.3 757.8,-226.14 756.67,-219.24"/>
-</g>
-<!-- host_fixed_location_console_in->vmm -->
-<g id="edge19" class="edge">
-<title>host_fixed_location_console_in->vmm</title>
-<path fill="none" stroke="blue" d="M709.73,-143.97C661.09,-131.98 596.79,-116.13 551.24,-104.9"/>
-<polygon fill="blue" stroke="blue" points="552.08,-101.5 541.53,-102.51 550.4,-108.3 552.08,-101.5"/>
-</g>
-<!-- host_fixed_location_console_out -->
-<g id="node9" class="node">
-<title>host_fixed_location_console_out</title>
-<polygon fill="none" stroke="blue" points="978.34,-36 781.34,-36 781.34,0 978.34,0 978.34,-36"/>
-<text text-anchor="middle" x="879.84" y="-14.3" font-family="Times,serif" font-size="14.00">internal/locationhvc_fifo_vm.out</text>
-</g>
-<!-- host_fixed_location_console_out->gnss_grpc_proxy -->
-<g id="edge17" class="edge">
-<title>host_fixed_location_console_out->gnss_grpc_proxy</title>
-<path fill="none" stroke="blue" d="M889.41,-36.19C905.79,-68.19 934.35,-137.5 900.84,-180 883.33,-202.21 816.1,-216.17 760.34,-224.15"/>
-<polygon fill="blue" stroke="blue" points="759.86,-220.68 750.44,-225.52 760.82,-227.62 759.86,-220.68"/>
+<polygon fill="none" stroke="green" points="365.5,-271 188.5,-271 188.5,-235 365.5,-235 365.5,-271"/>
+<text text-anchor="middle" x="277" y="-249.3" font-family="Times,serif" font-size="14.00">internal/gnsshvc_fifo_vm.out</text>
</g>
<!-- vmm->host_gnss_console_out -->
-<g id="edge14" class="edge">
+<g id="edge13" class="edge">
<title>vmm->host_gnss_console_out</title>
-<path fill="none" stroke="green" d="M509.06,-72.41C516.32,-63.95 525.29,-53.47 533.37,-44.05"/>
-<polygon fill="green" stroke="green" points="536.04,-46.32 539.89,-36.45 530.72,-41.76 536.04,-46.32"/>
-</g>
-<!-- vmm->host_fixed_location_console_out -->
-<g id="edge18" class="edge">
-<title>vmm->host_fixed_location_console_out</title>
-<path fill="none" stroke="blue" d="M547.17,-79.49C605.68,-68.85 701.94,-51.35 775.9,-37.9"/>
-<polygon fill="blue" stroke="blue" points="776.97,-41.26 786.18,-36.03 775.72,-34.37 776.97,-41.26"/>
+<path fill="none" stroke="green" d="M354.93,-197.99C341.65,-207.2 324.73,-218.92 310.05,-229.1"/>
+<polygon fill="green" stroke="green" points="307.93,-226.3 301.71,-234.88 311.92,-232.06 307.93,-226.3"/>
</g>
<!-- fixed_location_console -->
-<g id="node12" class="node">
+<g id="node15" class="node">
<title>fixed_location_console</title>
-<polygon fill="none" stroke="blue" points="321.84,-180 183.84,-180 183.84,-144 321.84,-144 321.84,-180"/>
-<text text-anchor="middle" x="252.84" y="-158.3" font-family="Times,serif" font-size="14.00">/dev/hvc6 | /dev/gnss1</text>
+<polygon fill="none" stroke="blue" points="525,-124 387,-124 387,-88 525,-88 525,-124"/>
+<text text-anchor="middle" x="456" y="-102.3" font-family="Times,serif" font-size="14.00">/dev/hvc6 | /dev/gnss1</text>
</g>
<!-- vmm->fixed_location_console -->
-<g id="edge20" class="edge">
+<g id="edge19" class="edge">
<title>vmm->fixed_location_console</title>
-<path fill="none" stroke="blue" d="M453.54,-103.85C422.21,-112.57 378.33,-124.56 339.84,-136 334.65,-137.54 329.27,-139.18 323.85,-140.86"/>
-<polygon fill="blue" stroke="blue" points="322.59,-137.58 314.07,-143.88 324.66,-144.27 322.59,-137.58"/>
+<path fill="none" stroke="blue" d="M403.17,-156.44C411.9,-148.27 421.69,-139.11 430.45,-130.91"/>
+<polygon fill="blue" stroke="blue" points="400.61,-154.05 395.7,-163.44 405.39,-159.16 400.61,-154.05"/>
+<polygon fill="blue" stroke="blue" points="432.92,-133.39 437.83,-124.01 428.14,-128.28 432.92,-133.39"/>
</g>
<!-- gnss_console -->
-<g id="node13" class="node">
+<g id="node16" class="node">
<title>gnss_console</title>
-<polygon fill="none" stroke="green" points="477.84,-180 339.84,-180 339.84,-144 477.84,-144 477.84,-180"/>
-<text text-anchor="middle" x="408.84" y="-158.3" font-family="Times,serif" font-size="14.00">/dev/hvc5 | /dev/gnss0</text>
+<polygon fill="none" stroke="green" points="369,-124 231,-124 231,-88 369,-88 369,-124"/>
+<text text-anchor="middle" x="300" y="-102.3" font-family="Times,serif" font-size="14.00">/dev/hvc5 | /dev/gnss0</text>
</g>
<!-- vmm->gnss_console -->
-<g id="edge23" class="edge">
+<g id="edge20" class="edge">
<title>vmm->gnss_console</title>
-<path fill="none" stroke="green" d="M480.26,-107.62C470.27,-116.55 456.77,-127.69 444.14,-137.49"/>
-<polygon fill="green" stroke="green" points="441.84,-134.84 436.02,-143.7 446.09,-140.41 441.84,-134.84"/>
+<path fill="none" stroke="green" d="M352.83,-156.44C344.1,-148.27 334.31,-139.11 325.55,-130.91"/>
+<polygon fill="green" stroke="green" points="350.61,-159.16 360.3,-163.44 355.39,-154.05 350.61,-159.16"/>
+<polygon fill="green" stroke="green" points="327.86,-128.28 318.17,-124.01 323.08,-133.39 327.86,-128.28"/>
+</g>
+<!-- webrtc->gnss_grpc_server -->
+<g id="edge9" class="edge">
+<title>webrtc->gnss_grpc_server</title>
+<path fill="none" stroke="black" d="M223.3,-451.35C242.27,-441.87 266.25,-429.87 286.67,-419.66"/>
+<polygon fill="black" stroke="black" points="221.45,-448.36 214.07,-455.97 224.58,-454.62 221.45,-448.36"/>
+<polygon fill="black" stroke="black" points="288.4,-422.72 295.77,-415.11 285.26,-416.45 288.4,-422.72"/>
+</g>
+<!-- host_gnss_console_in->vmm -->
+<g id="edge14" class="edge">
+<title>host_gnss_console_in->vmm</title>
+<path fill="none" stroke="green" d="M156.3,-234.97C206.8,-222.9 273.66,-206.93 320.7,-195.69"/>
+<polygon fill="green" stroke="green" points="321.81,-199.02 330.72,-193.3 320.18,-192.21 321.81,-199.02"/>
+</g>
+<!-- host_gnss_console_out->gnss_grpc_proxy -->
+<g id="edge12" class="edge">
+<title>host_gnss_console_out->gnss_grpc_proxy</title>
+<path fill="none" stroke="green" d="M301.71,-271.12C315.05,-280.37 331.68,-291.9 346,-301.82"/>
+<polygon fill="green" stroke="green" points="344.36,-304.94 354.57,-307.76 348.35,-299.19 344.36,-304.94"/>
+</g>
+<!-- host_fixed_location_console_in -->
+<g id="node12" class="node">
+<title>host_fixed_location_console_in</title>
+<polygon fill="none" stroke="blue" points="574,-271 384,-271 384,-235 574,-235 574,-271"/>
+<text text-anchor="middle" x="479" y="-249.3" font-family="Times,serif" font-size="14.00">internal/locationhvc_fifo_vm.in</text>
+</g>
+<!-- host_fixed_location_console_in->gnss_grpc_proxy -->
+<g id="edge15" class="edge">
+<title>host_fixed_location_console_in->gnss_grpc_proxy</title>
+<path fill="none" stroke="blue" d="M446.02,-276.86C431.46,-286.95 414.68,-298.58 401.43,-307.76"/>
+<polygon fill="blue" stroke="blue" points="448.07,-279.7 454.29,-271.12 444.08,-273.94 448.07,-279.7"/>
+</g>
+<!-- host_fixed_location_console_in->vmm -->
+<g id="edge18" class="edge">
+<title>host_fixed_location_console_in->vmm</title>
+<path fill="none" stroke="blue" d="M445.95,-229.1C431.27,-218.92 414.35,-207.2 401.07,-197.99"/>
+<polygon fill="blue" stroke="blue" points="444.08,-232.06 454.29,-234.88 448.07,-226.3 444.08,-232.06"/>
+</g>
+<!-- host_fixed_location_console_out -->
+<g id="node13" class="node">
+<title>host_fixed_location_console_out</title>
+<polygon fill="none" stroke="blue" points="789.5,-271 592.5,-271 592.5,-235 789.5,-235 789.5,-271"/>
+<text text-anchor="middle" x="691" y="-249.3" font-family="Times,serif" font-size="14.00">internal/locationhvc_fifo_vm.out</text>
+</g>
+<!-- host_fixed_location_console_out->gnss_grpc_proxy -->
+<g id="edge16" class="edge">
+<title>host_fixed_location_console_out->gnss_grpc_proxy</title>
+<path fill="none" stroke="blue" d="M614.83,-271.03C562.08,-282.83 492.61,-298.37 442.57,-309.56"/>
+<polygon fill="blue" stroke="blue" points="441.52,-306.21 432.52,-311.81 443.04,-313.04 441.52,-306.21"/>
+</g>
+<!-- host_fixed_location_console_out->vmm -->
+<g id="edge17" class="edge">
+<title>host_fixed_location_console_out->vmm</title>
+<path fill="none" stroke="blue" d="M614.83,-234.97C559.87,-222.67 486.76,-206.32 436.39,-195.06"/>
+<polygon fill="blue" stroke="blue" points="437.15,-191.64 426.63,-192.88 435.62,-198.47 437.15,-191.64"/>
</g>
<!-- gnss_hal -->
-<g id="node11" class="node">
+<g id="node14" class="node">
<title>gnss_hal</title>
-<g id="a_node11"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/gnss/aidl/default/" xlink:title="vendor.gnss-default">
-<ellipse fill="none" stroke="black" cx="331.84" cy="-234" rx="79.89" ry="18"/>
-<text text-anchor="middle" x="331.84" y="-230.3" font-family="Times,serif" font-size="14.00">vendor.gnss-default</text>
+<g id="a_node14"><a xlink:href="https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/gnss/aidl/default/" xlink:title="vendor.gnss-default">
+<ellipse fill="none" stroke="black" cx="378" cy="-34" rx="79.89" ry="18"/>
+<text text-anchor="middle" x="378" y="-30.3" font-family="Times,serif" font-size="14.00">vendor.gnss-default</text>
</a>
</g>
</g>
-<!-- gnss_hal->fixed_location_console -->
-<g id="edge3" class="edge">
-<title>gnss_hal->fixed_location_console</title>
-<path fill="none" stroke="blue" d="M307.72,-216.76C296.86,-208.01 284.25,-197.03 273.79,-187.28"/>
-<polygon fill="blue" stroke="blue" points="275.93,-184.49 266.27,-180.12 271.1,-189.56 275.93,-184.49"/>
-</g>
-<!-- gnss_hal->gnss_console -->
-<g id="edge5" class="edge">
-<title>gnss_hal->gnss_console</title>
-<path fill="none" stroke="green" d="M344.6,-216.05C353.34,-207.26 365.13,-196.38 376.27,-186.76"/>
-<polygon fill="green" stroke="green" points="378.85,-189.17 384.22,-180.03 374.33,-183.82 378.85,-189.17"/>
-</g>
-<!-- fixed_location_console->vmm -->
-<g id="edge21" class="edge">
-<title>fixed_location_console->vmm</title>
-<path fill="none" stroke="blue" d="M296.32,-143.88C304.75,-141.19 313.53,-138.47 321.84,-136 359.58,-124.78 402.49,-113.04 436.23,-104.37"/>
-<polygon fill="blue" stroke="blue" points="437.11,-107.75 445.94,-101.89 435.38,-100.97 437.11,-107.75"/>
-</g>
<!-- fixed_location_console->gnss_hal -->
-<g id="edge2" class="edge">
+<g id="edge5" class="edge">
<title>fixed_location_console->gnss_hal</title>
-<path fill="none" stroke="blue" d="M277.95,-180.03C288.71,-188.75 301.04,-199.51 311.26,-209.05"/>
-<polygon fill="blue" stroke="blue" points="308.95,-211.68 318.6,-216.05 313.78,-206.62 308.95,-211.68"/>
-</g>
-<!-- gnss_console->vmm -->
-<g id="edge22" class="edge">
-<title>gnss_console->vmm</title>
-<path fill="none" stroke="green" d="M424.19,-143.7C434.65,-134.4 448.72,-122.84 461.61,-112.91"/>
-<polygon fill="green" stroke="green" points="463.99,-115.5 469.85,-106.67 459.77,-109.92 463.99,-115.5"/>
+<path fill="none" stroke="blue" d="M429.18,-80.93C421.11,-73.68 412.26,-65.75 404.23,-58.54"/>
+<polygon fill="blue" stroke="blue" points="426.94,-83.62 436.72,-87.7 431.61,-78.41 426.94,-83.62"/>
+<polygon fill="blue" stroke="blue" points="406.3,-55.7 396.52,-51.62 401.63,-60.91 406.3,-55.7"/>
</g>
<!-- gnss_console->gnss_hal -->
-<g id="edge4" class="edge">
+<g id="edge6" class="edge">
<title>gnss_console->gnss_hal</title>
-<path fill="none" stroke="green" d="M395.9,-180.12C386.87,-189.2 374.64,-200.46 363.22,-210.26"/>
-<polygon fill="green" stroke="green" points="360.9,-207.65 355.5,-216.76 365.41,-213 360.9,-207.65"/>
+<path fill="none" stroke="green" d="M326.82,-80.93C334.89,-73.68 343.74,-65.75 351.77,-58.54"/>
+<polygon fill="green" stroke="green" points="324.39,-78.41 319.28,-87.7 329.06,-83.62 324.39,-78.41"/>
+<polygon fill="green" stroke="green" points="354.37,-60.91 359.48,-51.62 349.7,-55.7 354.37,-60.91"/>
</g>
</g>
</svg>
diff --git a/host/commands/log_tee/log_tee.cpp b/host/commands/log_tee/log_tee.cpp
index e147d00..863f983 100644
--- a/host/commands/log_tee/log_tee.cpp
+++ b/host/commands/log_tee/log_tee.cpp
@@ -36,7 +36,7 @@
auto instance = config->ForDefaultInstance();
- if (config->run_as_daemon()) {
+ if (instance.run_as_daemon()) {
android::base::SetLogger(
cuttlefish::LogToFiles({instance.launcher_log_path()}));
} else {
diff --git a/host/commands/metrics/metrics.cc b/host/commands/metrics/metrics.cc
index a2d23f1..70500d9 100644
--- a/host/commands/metrics/metrics.cc
+++ b/host/commands/metrics/metrics.cc
@@ -52,7 +52,7 @@
CHECK(config) << "Could not open cuttlefish config";
auto instance = config->ForDefaultInstance();
auto metrics_log_path = instance.PerInstanceLogPath("metrics.log");
- if (config->run_as_daemon()) {
+ if (instance.run_as_daemon()) {
android::base::SetLogger(
cuttlefish::LogToFiles({metrics_log_path, instance.launcher_log_path()}));
} else {
diff --git a/host/commands/modem_simulator/network_service.cpp b/host/commands/modem_simulator/network_service.cpp
index 4d102fa..2334eb3 100644
--- a/host/commands/modem_simulator/network_service.cpp
+++ b/host/commands/modem_simulator/network_service.cpp
@@ -319,13 +319,13 @@
bool NetworkService::WakeupFromSleep() {
// It has not called once yet
- if (android_last_signal_time_ == 0) {
+ if (android_last_signal_time_.load() == 0) {
return false;
}
// Heuristics: if guest has not asked for signal strength
// for 2 minutes, we assume it is caused by host sleep
time_t now = time(0);
- const bool wakeup_from_sleep = (now > android_last_signal_time_ + 120);
+ const bool wakeup_from_sleep = (now > android_last_signal_time_.load() + 120);
return wakeup_from_sleep;
}
@@ -416,11 +416,10 @@
void NetworkService::HandleSignalStrength(const Client& client) {
std::vector<std::string> responses;
std::stringstream ss;
-
+ bool expected = true;
if (WakeupFromSleep()) {
misc_service_->TimeUpdate();
- } else if (first_signal_strength_request_) {
- first_signal_strength_request_ = false;
+ } else if (first_signal_strength_request_.compare_exchange_strong(expected, false)) {
misc_service_->TimeUpdate();
}
diff --git a/host/commands/modem_simulator/network_service.h b/host/commands/modem_simulator/network_service.h
index 37808fb..171cc11 100644
--- a/host/commands/modem_simulator/network_service.h
+++ b/host/commands/modem_simulator/network_service.h
@@ -15,6 +15,7 @@
#pragma once
+#include <atomic>
#include <ctime>
#include "host/commands/modem_simulator/data_service.h"
@@ -290,8 +291,8 @@
int getModemTechFromPrefer(int preferred_mask);
ModemTechnology getTechFromNetworkType(NetworkRegistrationStatus::AccessTechnoloy act);
- bool first_signal_strength_request_; // For time update
- time_t android_last_signal_time_;
+ std::atomic<bool> first_signal_strength_request_; // For time update
+ std::atomic<time_t> android_last_signal_time_;
class KeepSignalStrengthChangingLoop {
public:
diff --git a/host/commands/run_cvd/boot_state_machine.cc b/host/commands/run_cvd/boot_state_machine.cc
index d0cfe18..27a5591 100644
--- a/host/commands/run_cvd/boot_state_machine.cc
+++ b/host/commands/run_cvd/boot_state_machine.cc
@@ -112,7 +112,9 @@
class ProcessLeader : public SetupFeature {
public:
- INJECT(ProcessLeader(const CuttlefishConfig& config)) : config_(config) {}
+ INJECT(ProcessLeader(const CuttlefishConfig& config,
+ const CuttlefishConfig::InstanceSpecific& instance))
+ : config_(config), instance_(instance) {}
SharedFD ForegroundLauncherPipe() { return foreground_launcher_pipe_; }
@@ -126,7 +128,7 @@
/* These two paths result in pretty different process state, but both
* achieve the same goal of making the current process the leader of a
* process group, and are therefore grouped together. */
- if (config_.run_as_daemon()) {
+ if (instance_.run_as_daemon()) {
foreground_launcher_pipe_ = DaemonizeLauncher(config_);
if (!foreground_launcher_pipe_->IsOpen()) {
return false;
@@ -146,6 +148,7 @@
}
const CuttlefishConfig& config_;
+ const CuttlefishConfig::InstanceSpecific& instance_;
SharedFD foreground_launcher_pipe_;
};
@@ -301,7 +304,8 @@
} // namespace
-fruit::Component<fruit::Required<const CuttlefishConfig, KernelLogPipeProvider>>
+fruit::Component<fruit::Required<const CuttlefishConfig, KernelLogPipeProvider,
+ const CuttlefishConfig::InstanceSpecific>>
bootStateMachineComponent() {
return fruit::createComponent()
.addMultibinding<KernelLogPipeConsumer, CvdBootStateMachine>()
diff --git a/host/commands/run_cvd/boot_state_machine.h b/host/commands/run_cvd/boot_state_machine.h
index 0cb92d5..1a2ebfd 100644
--- a/host/commands/run_cvd/boot_state_machine.h
+++ b/host/commands/run_cvd/boot_state_machine.h
@@ -21,7 +21,8 @@
namespace cuttlefish {
-fruit::Component<fruit::Required<const CuttlefishConfig, KernelLogPipeProvider>>
+fruit::Component<fruit::Required<const CuttlefishConfig, KernelLogPipeProvider,
+ const CuttlefishConfig::InstanceSpecific>>
bootStateMachineComponent();
} // namespace cuttlefish
diff --git a/host/commands/run_cvd/launch/modem.cpp b/host/commands/run_cvd/launch/modem.cpp
index 8aa6adb..b1c5c64 100644
--- a/host/commands/run_cvd/launch/modem.cpp
+++ b/host/commands/run_cvd/launch/modem.cpp
@@ -61,9 +61,8 @@
class ModemSimulator : public CommandSource {
public:
- INJECT(ModemSimulator(const CuttlefishConfig& config,
- const CuttlefishConfig::InstanceSpecific& instance))
- : config_(config), instance_(instance) {}
+ INJECT(ModemSimulator(const CuttlefishConfig::InstanceSpecific& instance))
+ : instance_(instance) {}
// CommandSource
Result<std::vector<Command>> Commands() override {
@@ -79,7 +78,7 @@
: StopperResult::kStopFailure;
});
- auto sim_type = config_.modem_simulator_sim_type();
+ auto sim_type = instance_.modem_simulator_sim_type();
cmd.AddParameter(std::string{"-sim_type="} + std::to_string(sim_type));
cmd.AddParameter("-server_fds=");
bool first_socket = true;
@@ -99,16 +98,16 @@
// SetupFeature
std::string Name() const override { return "ModemSimulator"; }
bool Enabled() const override {
- if (!config_.enable_modem_simulator()) {
+ if (!instance_.enable_modem_simulator()) {
LOG(DEBUG) << "Modem simulator not enabled";
}
- return config_.enable_modem_simulator();
+ return instance_.enable_modem_simulator();
}
private:
std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
Result<void> ResultSetup() override {
- int instance_number = config_.modem_simulator_instance_number();
+ int instance_number = instance_.modem_simulator_instance_number();
CF_EXPECT(instance_number >= 0 && instance_number < 4,
"Modem simulator instance number should range between 0 and 3");
auto ports = instance_.modem_simulator_ports();
@@ -125,7 +124,6 @@
return {};
}
- const CuttlefishConfig& config_;
const CuttlefishConfig::InstanceSpecific& instance_;
std::vector<SharedFD> sockets_;
};
diff --git a/host/commands/secure_env/confui_sign_server.cpp b/host/commands/secure_env/confui_sign_server.cpp
index 082f48c..c6d3227 100644
--- a/host/commands/secure_env/confui_sign_server.cpp
+++ b/host/commands/secure_env/confui_sign_server.cpp
@@ -22,6 +22,14 @@
#include "host/libs/config/cuttlefish_config.h"
#include "tpm_keymaster_context.h"
+namespace {
+
+// Defined in
+// hardware/interfaces/confirmationui/1.0/IConfirmationResultCallback.hal
+constexpr const char kConfirmationTokenMessageTag[] = "confirmation token";
+
+} // namespace
+
namespace cuttlefish {
ConfUiSignServer::ConfUiSignServer(TpmResourceManager& tpm_resource_manager,
SharedFD server_fd)
@@ -63,10 +71,14 @@
continue;
}
- // hmac
+ // hmac over (prefix || data)
+ std::vector<std::uint8_t> data{std::begin(kConfirmationTokenMessageTag),
+ std::end(kConfirmationTokenMessageTag) - 1};
+
+ data.insert(data.end(), request.payload_.data(),
+ request.payload_.data() + request.payload_.size());
auto hmac = TpmHmac(tpm_resource_manager_, signing_key->get(),
- TpmAuth(ESYS_TR_PASSWORD), request.payload_.data(),
- request.payload_.size());
+ TpmAuth(ESYS_TR_PASSWORD), data.data(), data.size());
if (!hmac) {
LOG(ERROR) << "Could not calculate confirmation token hmac";
sign_sender.Send(confui::SignMessageError::kUnknownError, {});
diff --git a/host/commands/secure_env/doc/linkage.dot b/host/commands/secure_env/doc/linkage.dot
index c33d43c..069ff82 100644
--- a/host/commands/secure_env/doc/linkage.dot
+++ b/host/commands/secure_env/doc/linkage.dot
@@ -1,70 +1,52 @@
digraph {
browser [label = "Browser"]
- confirmationui_sign [label = "internal/confui_sign.sock", shape = "rectangle"]
- host_confirmationui_in [color = "red", label = "internal/confui_fifo_vm.in", shape = "rectangle"]
- host_confirmationui_out [color = "red", label = "internal/confui_fifo_vm.out", shape = "rectangle"]
- host_gatekeeper_in [color = "green", label = "internal/gatekeeper_fifo_vm.in", shape = "rectangle"]
- host_gatekeeper_out [color = "green", label = "internal/gatekeeper_fifo_vm.out", shape = "rectangle"]
- host_keymint_in [color = "blue", label = "internal/keymaster_fifo_vm.in", shape = "rectangle"]
- host_keymint_out [color = "blue", label = "internal/keymaster_fifo_vm.out", shape = "rectangle"]
+ confirmationui_sign [color = "red", label = "internal/confui_sign.sock", shape = "rectangle"]
run_cvd
secure_env [label = < <B>secure_env</B> >, penwidth=2]
vmm [label = "crosvm / qemu"]
webRTC
+
+ subgraph fifos {
+ rank = same;
+
+ host_keymint_in [color = "blue", label = "internal/keymaster_fifo_vm.in", shape = "rectangle"]
+ host_keymint_out [color = "blue", label = "internal/keymaster_fifo_vm.out", shape = "rectangle"]
+ host_gatekeeper_in [color = "green", label = "internal/gatekeeper_fifo_vm.in", shape = "rectangle"]
+ host_gatekeeper_out [color = "green", label = "internal/gatekeeper_fifo_vm.out", shape = "rectangle"]
+ host_confirmationui_in [color = "red", label = "internal/confui_fifo_vm.in", shape = "rectangle"]
+ host_confirmationui_out [color = "red", label = "internal/confui_fifo_vm.out", shape = "rectangle"]
+ }
+
subgraph cluster_android {
label = "Android VM"
u_boot [label = "u-boot"]
confirmationui [color = "red", label = "ConfirmationUI HAL"]
- confirmationui_console [color = "red", label = "/dev/hvc8", shape = "rectangle"]
gatekeeper [color = "green", label = "Gatekeeper HAL"]
- gatekeeper_console [color = "green", label = "/dev/hvc4", shape = "rectangle"]
keymint [color = "blue", label = "Keymint HAL"]
- keymint_console [color = "blue", label = "/dev/hvc3", shape = "rectangle"]
+
+ subgraph consoles {
+ rank = same;
+ confirmationui_console [color = "red", label = "/dev/hvc8", shape = "rectangle"]
+ gatekeeper_console [color = "green", label = "/dev/hvc4", shape = "rectangle"]
+ keymint_console [color = "blue", label = "/dev/hvc3", shape = "rectangle"]
+ }
}
browser -> webRTC
run_cvd -> secure_env
- host_confirmationui_out -> webRTC [color = "red"]
- webRTC -> host_confirmationui_in [color = "red"]
- host_gatekeeper_out -> secure_env [color = "green"]
- secure_env -> host_gatekeeper_in [color = "green"]
- host_keymint_out -> secure_env [color = "blue"]
- secure_env -> host_keymint_in [color = "blue"]
- vmm -> host_confirmationui_out [color = "red"]
- host_confirmationui_in -> vmm [color = "red"]
+ webRTC -> host_confirmationui_out -> vmm [dir = "back", color = "red"]
+ webRTC -> host_confirmationui_in -> vmm [color = "red"]
+ vmm -> confirmationui_console -> confirmationui [dir = "both", color = "red"]
+ { rank = same; secure_env -> confirmationui_sign -> webRTC [color = "red", dir = "both"] }
- vmm -> host_gatekeeper_out [color = "green"]
- host_gatekeeper_in -> vmm [color = "green"]
+ secure_env -> host_gatekeeper_out -> vmm [color = "green", dir = "back"]
+ secure_env -> host_gatekeeper_in -> vmm [color = "green"]
+ vmm -> gatekeeper_console -> gatekeeper [color = "green", dir = "both"]
- vmm -> host_keymint_out [color = "blue"]
- host_keymint_in -> vmm [color = "blue"]
+ secure_env -> host_keymint_out -> vmm [color = "blue", dir = "back"]
+ secure_env -> host_keymint_in -> vmm [color = "blue"]
+ vmm -> keymint_console -> keymint [color = "blue", dir = "both"]
+ keymint_console -> u_boot [color = "blue", dir = "both"]
- vmm -> confirmationui_console [color = "red"]
- confirmationui_console -> vmm [color = "red"]
-
- vmm -> gatekeeper_console [color = "green"]
- gatekeeper_console -> vmm [color = "green"]
-
- vmm -> keymint_console [color = "blue"]
- keymint_console -> vmm [color = "blue"]
-
- confirmationui_console -> confirmationui [color = "red"]
- confirmationui -> confirmationui_console [color = "red"]
-
- gatekeeper_console -> gatekeeper [color = "green"]
- gatekeeper -> gatekeeper_console [color = "green"]
-
- keymint -> keymint_console [color = "blue"]
- keymint_console -> keymint [color = "blue"]
-
- u_boot -> keymint_console [color = "blue"]
- keymint_console -> u_boot [color = "blue"]
-
- webRTC -> confirmationui_sign
- confirmationui_sign -> webRTC
-
- secure_env -> confirmationui_sign
- confirmationui_sign -> secure_env
}
-
diff --git a/host/commands/secure_env/doc/linkage.png b/host/commands/secure_env/doc/linkage.png
index 481aa6a..2549569 100644
--- a/host/commands/secure_env/doc/linkage.png
+++ b/host/commands/secure_env/doc/linkage.png
Binary files differ
diff --git a/host/commands/secure_env/doc/linkage.svg b/host/commands/secure_env/doc/linkage.svg
index a464ca3..6bb643f 100644
--- a/host/commands/secure_env/doc/linkage.svg
+++ b/host/commands/secure_env/doc/linkage.svg
@@ -4,323 +4,278 @@
<!-- Generated by graphviz version 2.43.0 (0)
-->
<!-- Title: %3 Pages: 1 -->
-<svg width="1009pt" height="479pt"
- viewBox="0.00 0.00 1008.52 479.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 475)">
+<svg width="1180pt" height="423pt"
+ viewBox="0.00 0.00 1179.50 423.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 419)">
<title>%3</title>
-<polygon fill="white" stroke="transparent" points="-4,4 -4,-475 1004.52,-475 1004.52,4 -4,4"/>
-<g id="clust1" class="cluster">
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-419 1175.5,-419 1175.5,4 -4,4"/>
+<g id="clust2" class="cluster">
<title>cluster_android</title>
-<polygon fill="none" stroke="black" points="538,-64 538,-283 977,-283 977,-64 538,-64"/>
-<text text-anchor="middle" x="757.5" y="-267.8" font-family="Times,serif" font-size="14.00">Android VM</text>
+<polygon fill="none" stroke="black" points="297.5,-8 297.5,-155 879.5,-155 879.5,-8 297.5,-8"/>
+<text text-anchor="middle" x="588.5" y="-139.8" font-family="Times,serif" font-size="14.00">Android VM</text>
</g>
<!-- browser -->
<g id="node1" class="node">
<title>browser</title>
-<ellipse fill="none" stroke="black" cx="346" cy="-453" rx="40.09" ry="18"/>
-<text text-anchor="middle" x="346" y="-449.3" font-family="Times,serif" font-size="14.00">Browser</text>
+<ellipse fill="none" stroke="black" cx="904.5" cy="-397" rx="40.09" ry="18"/>
+<text text-anchor="middle" x="904.5" y="-393.3" font-family="Times,serif" font-size="14.00">Browser</text>
</g>
<!-- webRTC -->
-<g id="node12" class="node">
+<g id="node6" class="node">
<title>webRTC</title>
-<ellipse fill="none" stroke="black" cx="346" cy="-381" rx="42.49" ry="18"/>
-<text text-anchor="middle" x="346" y="-377.3" font-family="Times,serif" font-size="14.00">webRTC</text>
+<ellipse fill="none" stroke="black" cx="904.5" cy="-325" rx="42.49" ry="18"/>
+<text text-anchor="middle" x="904.5" y="-321.3" font-family="Times,serif" font-size="14.00">webRTC</text>
</g>
<!-- browser->webRTC -->
<g id="edge1" class="edge">
<title>browser->webRTC</title>
-<path fill="none" stroke="black" d="M346,-434.7C346,-426.98 346,-417.71 346,-409.11"/>
-<polygon fill="black" stroke="black" points="349.5,-409.1 346,-399.1 342.5,-409.1 349.5,-409.1"/>
+<path fill="none" stroke="black" d="M904.5,-378.7C904.5,-370.98 904.5,-361.71 904.5,-353.11"/>
+<polygon fill="black" stroke="black" points="908,-353.1 904.5,-343.1 901,-353.1 908,-353.1"/>
</g>
<!-- confirmationui_sign -->
<g id="node2" class="node">
<title>confirmationui_sign</title>
-<polygon fill="none" stroke="black" points="287,-327 133,-327 133,-291 287,-291 287,-327"/>
-<text text-anchor="middle" x="210" y="-305.3" font-family="Times,serif" font-size="14.00">internal/confui_sign.sock</text>
-</g>
-<!-- secure_env -->
-<g id="node10" class="node">
-<title>secure_env</title>
-<ellipse fill="none" stroke="black" stroke-width="2" cx="210" cy="-234" rx="57.39" ry="18"/>
-<text text-anchor="start" x="174" y="-231.3" font-family="Times,serif" font-size="14.00"> </text>
-<text text-anchor="start" x="178" y="-231.3" font-family="Times,serif" font-weight="bold" font-size="14.00">secure_env</text>
-<text text-anchor="start" x="242" y="-231.3" font-family="Times,serif" font-size="14.00"> </text>
-</g>
-<!-- confirmationui_sign->secure_env -->
-<g id="edge32" class="edge">
-<title>confirmationui_sign->secure_env</title>
-<path fill="none" stroke="black" d="M204.16,-290.7C203.27,-282.18 203.03,-271.72 203.45,-262.17"/>
-<polygon fill="black" stroke="black" points="206.96,-262.15 204.2,-251.92 199.98,-261.64 206.96,-262.15"/>
+<polygon fill="none" stroke="red" points="788.5,-343 634.5,-343 634.5,-307 788.5,-307 788.5,-343"/>
+<text text-anchor="middle" x="711.5" y="-321.3" font-family="Times,serif" font-size="14.00">internal/confui_sign.sock</text>
</g>
<!-- confirmationui_sign->webRTC -->
-<g id="edge30" class="edge">
-<title>confirmationui_sign->webRTC</title>
-<path fill="none" stroke="black" d="M248.98,-327.03C269.91,-337.25 295.27,-350.27 314.88,-360.85"/>
-<polygon fill="black" stroke="black" points="313.27,-363.95 323.72,-365.67 316.62,-357.81 313.27,-363.95"/>
-</g>
-<!-- host_confirmationui_in -->
-<g id="node3" class="node">
-<title>host_confirmationui_in</title>
-<polygon fill="none" stroke="red" points="586.5,-327 425.5,-327 425.5,-291 586.5,-291 586.5,-327"/>
-<text text-anchor="middle" x="506" y="-305.3" font-family="Times,serif" font-size="14.00">internal/confui_fifo_vm.in</text>
-</g>
-<!-- vmm -->
-<g id="node11" class="node">
-<title>vmm</title>
-<ellipse fill="none" stroke="black" cx="466" cy="-90" rx="64.19" ry="18"/>
-<text text-anchor="middle" x="466" y="-86.3" font-family="Times,serif" font-size="14.00">crosvm / qemu</text>
-</g>
-<!-- host_confirmationui_in->vmm -->
<g id="edge10" class="edge">
-<title>host_confirmationui_in->vmm</title>
-<path fill="none" stroke="red" d="M508.5,-290.73C512.24,-260.25 517.27,-195.32 501,-144 497.88,-134.17 492.37,-124.45 486.63,-116.07"/>
-<polygon fill="red" stroke="red" points="489.38,-113.9 480.66,-107.88 483.72,-118.02 489.38,-113.9"/>
-</g>
-<!-- host_confirmationui_out -->
-<g id="node4" class="node">
-<title>host_confirmationui_out</title>
-<polygon fill="none" stroke="red" points="860,-36 692,-36 692,0 860,0 860,-36"/>
-<text text-anchor="middle" x="776" y="-14.3" font-family="Times,serif" font-size="14.00">internal/confui_fifo_vm.out</text>
-</g>
-<!-- host_confirmationui_out->webRTC -->
-<g id="edge3" class="edge">
-<title>host_confirmationui_out->webRTC</title>
-<path fill="none" stroke="red" d="M860.12,-27.89C909.02,-34.83 964.23,-46.32 981,-64 1011.07,-95.7 997,-117.31 997,-161 997,-235 997,-235 997,-235 997,-257.49 998.19,-268.51 981,-283 893.01,-357.16 534.22,-374.79 398.42,-378.84"/>
-<polygon fill="red" stroke="red" points="398.16,-375.34 388.27,-379.13 398.36,-382.34 398.16,-375.34"/>
-</g>
-<!-- host_gatekeeper_in -->
-<g id="node5" class="node">
-<title>host_gatekeeper_in</title>
-<polygon fill="none" stroke="green" points="492.5,-180 307.5,-180 307.5,-144 492.5,-144 492.5,-180"/>
-<text text-anchor="middle" x="400" y="-158.3" font-family="Times,serif" font-size="14.00">internal/gatekeeper_fifo_vm.in</text>
-</g>
-<!-- host_gatekeeper_in->vmm -->
-<g id="edge12" class="edge">
-<title>host_gatekeeper_in->vmm</title>
-<path fill="none" stroke="green" d="M416.31,-143.7C424.43,-135.09 434.36,-124.55 443.21,-115.17"/>
-<polygon fill="green" stroke="green" points="446.01,-117.3 450.33,-107.62 440.92,-112.5 446.01,-117.3"/>
-</g>
-<!-- host_gatekeeper_out -->
-<g id="node6" class="node">
-<title>host_gatekeeper_out</title>
-<polygon fill="none" stroke="green" points="508,-36 316,-36 316,0 508,0 508,-36"/>
-<text text-anchor="middle" x="412" y="-14.3" font-family="Times,serif" font-size="14.00">internal/gatekeeper_fifo_vm.out</text>
-</g>
-<!-- host_gatekeeper_out->secure_env -->
-<g id="edge5" class="edge">
-<title>host_gatekeeper_out->secure_env</title>
-<path fill="none" stroke="green" d="M315.74,-28.77C242.24,-41.85 145.59,-72.45 97,-144 88.01,-157.24 88.42,-166.5 97,-180 109.71,-199.99 132.17,-212.58 153.73,-220.43"/>
-<polygon fill="green" stroke="green" points="152.62,-223.75 163.22,-223.62 154.85,-217.11 152.62,-223.75"/>
-</g>
-<!-- host_keymint_in -->
-<g id="node7" class="node">
-<title>host_keymint_in</title>
-<polygon fill="none" stroke="blue" points="289.5,-180 106.5,-180 106.5,-144 289.5,-144 289.5,-180"/>
-<text text-anchor="middle" x="198" y="-158.3" font-family="Times,serif" font-size="14.00">internal/keymaster_fifo_vm.in</text>
-</g>
-<!-- host_keymint_in->vmm -->
-<g id="edge14" class="edge">
-<title>host_keymint_in->vmm</title>
-<path fill="none" stroke="blue" d="M263.22,-143.97C308.5,-132.14 368.15,-116.56 411.02,-105.36"/>
-<polygon fill="blue" stroke="blue" points="411.92,-108.74 420.72,-102.83 410.16,-101.97 411.92,-108.74"/>
-</g>
-<!-- host_keymint_out -->
-<g id="node8" class="node">
-<title>host_keymint_out</title>
-<polygon fill="none" stroke="blue" points="190,-36 0,-36 0,0 190,0 190,-36"/>
-<text text-anchor="middle" x="95" y="-14.3" font-family="Times,serif" font-size="14.00">internal/keymaster_fifo_vm.out</text>
-</g>
-<!-- host_keymint_out->secure_env -->
-<g id="edge7" class="edge">
-<title>host_keymint_out->secure_env</title>
-<path fill="none" stroke="blue" d="M79.6,-36.07C73.48,-43.97 67.16,-53.85 64,-64 48.68,-113.23 34.41,-137.78 64,-180 82.49,-206.39 115.53,-219.69 145.51,-226.37"/>
-<polygon fill="blue" stroke="blue" points="145.04,-229.85 155.53,-228.39 146.42,-222.98 145.04,-229.85"/>
+<title>confirmationui_sign->webRTC</title>
+<path fill="none" stroke="red" d="M798.79,-325C816.4,-325 834.02,-325 851.64,-325"/>
+<polygon fill="red" stroke="red" points="798.78,-321.5 788.78,-325 798.78,-328.5 798.78,-321.5"/>
+<polygon fill="red" stroke="red" points="852.01,-328.5 862.01,-325 852.01,-321.5 852.01,-328.5"/>
</g>
<!-- run_cvd -->
-<g id="node9" class="node">
+<g id="node3" class="node">
<title>run_cvd</title>
-<ellipse fill="none" stroke="black" cx="345" cy="-309" rx="39.79" ry="18"/>
-<text text-anchor="middle" x="345" y="-305.3" font-family="Times,serif" font-size="14.00">run_cvd</text>
+<ellipse fill="none" stroke="black" cx="502.5" cy="-397" rx="39.79" ry="18"/>
+<text text-anchor="middle" x="502.5" y="-393.3" font-family="Times,serif" font-size="14.00">run_cvd</text>
+</g>
+<!-- secure_env -->
+<g id="node4" class="node">
+<title>secure_env</title>
+<ellipse fill="none" stroke="black" stroke-width="2" cx="502.5" cy="-325" rx="57.39" ry="18"/>
+<text text-anchor="start" x="466.5" y="-322.3" font-family="Times,serif" font-size="14.00"> </text>
+<text text-anchor="start" x="470.5" y="-322.3" font-family="Times,serif" font-weight="bold" font-size="14.00">secure_env</text>
+<text text-anchor="start" x="534.5" y="-322.3" font-family="Times,serif" font-size="14.00"> </text>
</g>
<!-- run_cvd->secure_env -->
<g id="edge2" class="edge">
<title>run_cvd->secure_env</title>
-<path fill="none" stroke="black" d="M320.55,-294.78C299.89,-283.61 270,-267.44 246.5,-254.74"/>
-<polygon fill="black" stroke="black" points="247.98,-251.56 237.52,-249.88 244.65,-257.72 247.98,-251.56"/>
+<path fill="none" stroke="black" d="M502.5,-378.7C502.5,-370.98 502.5,-361.71 502.5,-353.11"/>
+<polygon fill="black" stroke="black" points="506,-353.1 502.5,-343.1 499,-353.1 506,-353.1"/>
</g>
<!-- secure_env->confirmationui_sign -->
-<g id="edge31" class="edge">
+<g id="edge9" class="edge">
<title>secure_env->confirmationui_sign</title>
-<path fill="none" stroke="black" d="M215.8,-251.92C216.72,-260.47 216.97,-271.06 216.55,-280.72"/>
-<polygon fill="black" stroke="black" points="213.06,-280.48 215.84,-290.7 220.05,-280.98 213.06,-280.48"/>
+<path fill="none" stroke="red" d="M570.21,-325C588.23,-325 606.26,-325 624.28,-325"/>
+<polygon fill="red" stroke="red" points="570.06,-321.5 560.06,-325 570.06,-328.5 570.06,-321.5"/>
+<polygon fill="red" stroke="red" points="624.3,-328.5 634.3,-325 624.3,-321.5 624.3,-328.5"/>
</g>
-<!-- secure_env->host_gatekeeper_in -->
-<g id="edge6" class="edge">
-<title>secure_env->host_gatekeeper_in</title>
-<path fill="none" stroke="green" d="M245.74,-219.83C273.4,-209.64 312.24,-195.33 344.02,-183.62"/>
-<polygon fill="green" stroke="green" points="345.46,-186.82 353.63,-180.08 343.04,-180.25 345.46,-186.82"/>
+<!-- host_keymint_in -->
+<g id="node7" class="node">
+<title>host_keymint_in</title>
+<polygon fill="none" stroke="blue" points="183,-271 0,-271 0,-235 183,-235 183,-271"/>
+<text text-anchor="middle" x="91.5" y="-249.3" font-family="Times,serif" font-size="14.00">internal/keymaster_fifo_vm.in</text>
</g>
<!-- secure_env->host_keymint_in -->
-<g id="edge8" class="edge">
+<g id="edge19" class="edge">
<title>secure_env->host_keymint_in</title>
-<path fill="none" stroke="blue" d="M207.03,-215.7C205.71,-207.98 204.12,-198.71 202.65,-190.11"/>
-<polygon fill="blue" stroke="blue" points="206.07,-189.37 200.93,-180.1 199.17,-190.55 206.07,-189.37"/>
+<path fill="none" stroke="blue" d="M453.33,-315.63C389.35,-304.73 275.95,-285.41 193.11,-271.31"/>
+<polygon fill="blue" stroke="blue" points="193.61,-267.84 183.17,-269.61 192.44,-274.74 193.61,-267.84"/>
</g>
-<!-- vmm->host_confirmationui_out -->
-<g id="edge9" class="edge">
-<title>vmm->host_confirmationui_out</title>
-<path fill="none" stroke="red" d="M500.93,-74.88C511.44,-70.98 523.08,-67 534,-64 582.08,-50.79 636.6,-40.28 681.71,-32.74"/>
-<polygon fill="red" stroke="red" points="682.47,-36.16 691.77,-31.08 681.34,-29.26 682.47,-36.16"/>
+<!-- host_keymint_out -->
+<g id="node8" class="node">
+<title>host_keymint_out</title>
+<polygon fill="none" stroke="blue" points="391.5,-271 201.5,-271 201.5,-235 391.5,-235 391.5,-271"/>
+<text text-anchor="middle" x="296.5" y="-249.3" font-family="Times,serif" font-size="14.00">internal/keymaster_fifo_vm.out</text>
</g>
-<!-- vmm->host_gatekeeper_out -->
-<g id="edge11" class="edge">
-<title>vmm->host_gatekeeper_out</title>
-<path fill="none" stroke="green" d="M452.93,-72.05C446.52,-63.75 438.68,-53.58 431.58,-44.38"/>
-<polygon fill="green" stroke="green" points="434.21,-42.06 425.33,-36.28 428.66,-46.33 434.21,-42.06"/>
+<!-- secure_env->host_keymint_out -->
+<g id="edge17" class="edge">
+<title>secure_env->host_keymint_out</title>
+<path fill="none" stroke="blue" d="M455.48,-308.02C423,-296.99 379.85,-282.32 346.71,-271.06"/>
+<polygon fill="blue" stroke="blue" points="454.6,-311.42 465.19,-311.32 456.85,-304.79 454.6,-311.42"/>
</g>
-<!-- vmm->host_keymint_out -->
+<!-- host_gatekeeper_in -->
+<g id="node9" class="node">
+<title>host_gatekeeper_in</title>
+<polygon fill="none" stroke="green" points="595,-271 410,-271 410,-235 595,-235 595,-271"/>
+<text text-anchor="middle" x="502.5" y="-249.3" font-family="Times,serif" font-size="14.00">internal/gatekeeper_fifo_vm.in</text>
+</g>
+<!-- secure_env->host_gatekeeper_in -->
<g id="edge13" class="edge">
-<title>vmm->host_keymint_out</title>
-<path fill="none" stroke="blue" d="M414.02,-79.19C357.57,-68.54 266.02,-51.27 195.44,-37.95"/>
-<polygon fill="blue" stroke="blue" points="195.66,-34.43 185.19,-36.02 194.36,-41.31 195.66,-34.43"/>
+<title>secure_env->host_gatekeeper_in</title>
+<path fill="none" stroke="green" d="M502.5,-306.7C502.5,-298.98 502.5,-289.71 502.5,-281.11"/>
+<polygon fill="green" stroke="green" points="506,-281.1 502.5,-271.1 499,-281.1 506,-281.1"/>
+</g>
+<!-- host_gatekeeper_out -->
+<g id="node10" class="node">
+<title>host_gatekeeper_out</title>
+<polygon fill="none" stroke="green" points="805.5,-271 613.5,-271 613.5,-235 805.5,-235 805.5,-271"/>
+<text text-anchor="middle" x="709.5" y="-249.3" font-family="Times,serif" font-size="14.00">internal/gatekeeper_fifo_vm.out</text>
+</g>
+<!-- secure_env->host_gatekeeper_out -->
+<g id="edge11" class="edge">
+<title>secure_env->host_gatekeeper_out</title>
+<path fill="none" stroke="green" d="M549.75,-308.02C582.38,-296.99 625.74,-282.32 659.05,-271.06"/>
+<polygon fill="green" stroke="green" points="548.34,-304.8 539.99,-311.32 550.58,-311.44 548.34,-304.8"/>
+</g>
+<!-- vmm -->
+<g id="node5" class="node">
+<title>vmm</title>
+<ellipse fill="none" stroke="black" cx="605.5" cy="-181" rx="64.19" ry="18"/>
+<text text-anchor="middle" x="605.5" y="-177.3" font-family="Times,serif" font-size="14.00">crosvm / qemu</text>
</g>
<!-- confirmationui_console -->
-<g id="node15" class="node">
+<g id="node17" class="node">
<title>confirmationui_console</title>
-<polygon fill="none" stroke="red" points="776,-180 706,-180 706,-144 776,-144 776,-180"/>
-<text text-anchor="middle" x="741" y="-158.3" font-family="Times,serif" font-size="14.00">/dev/hvc8</text>
+<polygon fill="none" stroke="red" points="773.5,-124 703.5,-124 703.5,-88 773.5,-88 773.5,-124"/>
+<text text-anchor="middle" x="738.5" y="-102.3" font-family="Times,serif" font-size="14.00">/dev/hvc8</text>
</g>
<!-- vmm->confirmationui_console -->
-<g id="edge15" class="edge">
+<g id="edge7" class="edge">
<title>vmm->confirmationui_console</title>
-<path fill="none" stroke="red" d="M514.28,-102C565.63,-114.52 646.01,-134.96 696.05,-148.19"/>
-<polygon fill="red" stroke="red" points="695.38,-151.64 705.94,-150.82 697.17,-144.87 695.38,-151.64"/>
+<path fill="none" stroke="red" d="M642.4,-159.74C659.81,-150.19 680.61,-138.77 698.4,-129.01"/>
+<polygon fill="red" stroke="red" points="640.46,-156.82 633.38,-164.7 643.83,-162.95 640.46,-156.82"/>
+<polygon fill="red" stroke="red" points="700.32,-131.95 707.4,-124.07 696.95,-125.81 700.32,-131.95"/>
</g>
<!-- gatekeeper_console -->
-<g id="node17" class="node">
+<g id="node18" class="node">
<title>gatekeeper_console</title>
-<polygon fill="none" stroke="green" points="635,-180 565,-180 565,-144 635,-144 635,-180"/>
-<text text-anchor="middle" x="600" y="-158.3" font-family="Times,serif" font-size="14.00">/dev/hvc4</text>
+<polygon fill="none" stroke="green" points="640.5,-124 570.5,-124 570.5,-88 640.5,-88 640.5,-124"/>
+<text text-anchor="middle" x="605.5" y="-102.3" font-family="Times,serif" font-size="14.00">/dev/hvc4</text>
</g>
<!-- vmm->gatekeeper_console -->
-<g id="edge17" class="edge">
+<g id="edge15" class="edge">
<title>vmm->gatekeeper_console</title>
-<path fill="none" stroke="green" d="M499.52,-105.58C519.26,-115.25 544.14,-128.12 564.25,-139.02"/>
-<polygon fill="green" stroke="green" points="562.66,-142.15 573.12,-143.88 566.02,-136.01 562.66,-142.15"/>
+<path fill="none" stroke="green" d="M605.5,-152.49C605.5,-146.55 605.5,-140.27 605.5,-134.33"/>
+<polygon fill="green" stroke="green" points="602,-152.7 605.5,-162.7 609,-152.7 602,-152.7"/>
+<polygon fill="green" stroke="green" points="609,-134.18 605.5,-124.18 602,-134.18 609,-134.18"/>
</g>
<!-- keymint_console -->
<g id="node19" class="node">
<title>keymint_console</title>
-<polygon fill="none" stroke="blue" points="903,-180 833,-180 833,-144 903,-144 903,-180"/>
-<text text-anchor="middle" x="868" y="-158.3" font-family="Times,serif" font-size="14.00">/dev/hvc3</text>
+<polygon fill="none" stroke="blue" points="488.5,-124 418.5,-124 418.5,-88 488.5,-88 488.5,-124"/>
+<text text-anchor="middle" x="453.5" y="-102.3" font-family="Times,serif" font-size="14.00">/dev/hvc3</text>
</g>
<!-- vmm->keymint_console -->
-<g id="edge19" class="edge">
+<g id="edge21" class="edge">
<title>vmm->keymint_console</title>
-<path fill="none" stroke="blue" d="M514.88,-101.75C524.24,-104 533.92,-106.22 543,-108 653.59,-129.7 682.97,-124.68 794,-144 803.36,-145.63 813.29,-147.52 822.75,-149.43"/>
-<polygon fill="blue" stroke="blue" points="822.29,-152.91 832.79,-151.51 823.71,-146.06 822.29,-152.91"/>
+<path fill="none" stroke="blue" d="M565.23,-160.66C544.45,-150.68 519.06,-138.49 497.74,-128.25"/>
+<polygon fill="blue" stroke="blue" points="563.84,-163.88 574.37,-165.05 566.87,-157.57 563.84,-163.88"/>
+<polygon fill="blue" stroke="blue" points="499.1,-125.02 488.57,-123.84 496.07,-131.33 499.1,-125.02"/>
</g>
-<!-- webRTC->confirmationui_sign -->
-<g id="edge29" class="edge">
-<title>webRTC->confirmationui_sign</title>
-<path fill="none" stroke="black" d="M317.04,-367.81C296.25,-357.89 268.24,-343.65 246.02,-331.79"/>
-<polygon fill="black" stroke="black" points="247.67,-328.7 237.21,-327.03 244.35,-334.86 247.67,-328.7"/>
+<!-- host_confirmationui_in -->
+<g id="node11" class="node">
+<title>host_confirmationui_in</title>
+<polygon fill="none" stroke="red" points="985,-271 824,-271 824,-235 985,-235 985,-271"/>
+<text text-anchor="middle" x="904.5" y="-249.3" font-family="Times,serif" font-size="14.00">internal/confui_fifo_vm.in</text>
</g>
<!-- webRTC->host_confirmationui_in -->
-<g id="edge4" class="edge">
+<g id="edge5" class="edge">
<title>webRTC->host_confirmationui_in</title>
-<path fill="none" stroke="red" d="M374.6,-367.49C397.68,-357.39 430.65,-342.96 457.79,-331.09"/>
-<polygon fill="red" stroke="red" points="459.36,-334.22 467.12,-327.01 456.56,-327.81 459.36,-334.22"/>
+<path fill="none" stroke="red" d="M904.5,-306.7C904.5,-298.98 904.5,-289.71 904.5,-281.11"/>
+<polygon fill="red" stroke="red" points="908,-281.1 904.5,-271.1 901,-281.1 908,-281.1"/>
+</g>
+<!-- host_confirmationui_out -->
+<g id="node12" class="node">
+<title>host_confirmationui_out</title>
+<polygon fill="none" stroke="red" points="1171.5,-271 1003.5,-271 1003.5,-235 1171.5,-235 1171.5,-271"/>
+<text text-anchor="middle" x="1087.5" y="-249.3" font-family="Times,serif" font-size="14.00">internal/confui_fifo_vm.out</text>
+</g>
+<!-- webRTC->host_confirmationui_out -->
+<g id="edge3" class="edge">
+<title>webRTC->host_confirmationui_out</title>
+<path fill="none" stroke="red" d="M944.57,-308.67C973.65,-297.55 1013,-282.5 1043.05,-271"/>
+<polygon fill="red" stroke="red" points="943.22,-305.44 935.13,-312.28 945.72,-311.98 943.22,-305.44"/>
+</g>
+<!-- host_keymint_in->vmm -->
+<g id="edge20" class="edge">
+<title>host_keymint_in->vmm</title>
+<path fill="none" stroke="blue" d="M183.13,-236.42C186.29,-235.93 189.42,-235.46 192.5,-235 313.66,-217.04 455.35,-199.63 537.32,-189.92"/>
+<polygon fill="blue" stroke="blue" points="537.74,-193.4 547.26,-188.75 536.92,-186.44 537.74,-193.4"/>
+</g>
+<!-- host_keymint_out->vmm -->
+<g id="edge18" class="edge">
+<title>host_keymint_out->vmm</title>
+<path fill="none" stroke="blue" d="M381.69,-232.7C438.14,-219.91 510.16,-203.6 557.03,-192.98"/>
+<polygon fill="blue" stroke="blue" points="380.67,-229.34 371.69,-234.97 382.22,-236.17 380.67,-229.34"/>
+</g>
+<!-- host_gatekeeper_in->vmm -->
+<g id="edge14" class="edge">
+<title>host_gatekeeper_in->vmm</title>
+<path fill="none" stroke="green" d="M527.7,-234.88C541.54,-225.47 558.84,-213.71 573.62,-203.67"/>
+<polygon fill="green" stroke="green" points="575.67,-206.5 581.98,-197.99 571.74,-200.71 575.67,-206.5"/>
+</g>
+<!-- host_gatekeeper_out->vmm -->
+<g id="edge12" class="edge">
+<title>host_gatekeeper_out->vmm</title>
+<path fill="none" stroke="green" d="M675.47,-229.1C660.36,-218.92 642.93,-207.2 629.25,-197.99"/>
+<polygon fill="green" stroke="green" points="673.81,-232.2 684.06,-234.88 677.72,-226.39 673.81,-232.2"/>
+</g>
+<!-- host_confirmationui_in->vmm -->
+<g id="edge6" class="edge">
+<title>host_confirmationui_in->vmm</title>
+<path fill="none" stroke="red" d="M831.74,-234.97C779.94,-222.84 711.27,-206.76 663.22,-195.51"/>
+<polygon fill="red" stroke="red" points="663.83,-192.06 653.3,-193.19 662.24,-198.88 663.83,-192.06"/>
+</g>
+<!-- host_confirmationui_out->vmm -->
+<g id="edge4" class="edge">
+<title>host_confirmationui_out->vmm</title>
+<path fill="none" stroke="red" d="M993.38,-234.86C869.99,-215.37 737.36,-198.25 663.29,-189.04"/>
+<polygon fill="red" stroke="red" points="992.95,-238.33 1003.38,-236.45 994.05,-231.42 992.95,-238.33"/>
</g>
<!-- u_boot -->
<g id="node13" class="node">
<title>u_boot</title>
-<ellipse fill="none" stroke="black" cx="935" cy="-234" rx="33.6" ry="18"/>
-<text text-anchor="middle" x="935" y="-230.3" font-family="Times,serif" font-size="14.00">u-boot</text>
-</g>
-<!-- u_boot->keymint_console -->
-<g id="edge27" class="edge">
-<title>u_boot->keymint_console</title>
-<path fill="none" stroke="blue" d="M915.89,-218.83C906.18,-209.92 894.63,-198.17 885.21,-187.75"/>
-<polygon fill="blue" stroke="blue" points="887.72,-185.31 878.48,-180.11 882.46,-189.93 887.72,-185.31"/>
+<ellipse fill="none" stroke="black" cx="339.5" cy="-34" rx="33.6" ry="18"/>
+<text text-anchor="middle" x="339.5" y="-30.3" font-family="Times,serif" font-size="14.00">u-boot</text>
</g>
<!-- confirmationui -->
<g id="node14" class="node">
<title>confirmationui</title>
-<ellipse fill="none" stroke="red" cx="795" cy="-234" rx="88.28" ry="18"/>
-<text text-anchor="middle" x="795" y="-230.3" font-family="Times,serif" font-size="14.00">ConfirmationUI HAL</text>
-</g>
-<!-- confirmationui->confirmationui_console -->
-<g id="edge22" class="edge">
-<title>confirmationui->confirmationui_console</title>
-<path fill="none" stroke="red" d="M776.05,-216.05C768.84,-207.84 760.87,-197.79 754.26,-188.66"/>
-<polygon fill="red" stroke="red" points="757.01,-186.47 748.41,-180.28 751.26,-190.48 757.01,-186.47"/>
-</g>
-<!-- confirmationui_console->vmm -->
-<g id="edge16" class="edge">
-<title>confirmationui_console->vmm</title>
-<path fill="none" stroke="red" d="M705.81,-153.17C658.48,-141.79 574.22,-120.44 519.17,-105.97"/>
-<polygon fill="red" stroke="red" points="519.81,-102.52 509.25,-103.36 518.03,-109.29 519.81,-102.52"/>
-</g>
-<!-- confirmationui_console->confirmationui -->
-<g id="edge21" class="edge">
-<title>confirmationui_console->confirmationui</title>
-<path fill="none" stroke="red" d="M760.24,-180.28C767.47,-188.54 775.43,-198.6 782,-207.71"/>
-<polygon fill="red" stroke="red" points="779.22,-209.84 787.81,-216.05 784.97,-205.85 779.22,-209.84"/>
+<ellipse fill="none" stroke="red" cx="783.5" cy="-34" rx="88.28" ry="18"/>
+<text text-anchor="middle" x="783.5" y="-30.3" font-family="Times,serif" font-size="14.00">ConfirmationUI HAL</text>
</g>
<!-- gatekeeper -->
-<g id="node16" class="node">
+<g id="node15" class="node">
<title>gatekeeper</title>
-<ellipse fill="none" stroke="green" cx="617" cy="-234" rx="71.49" ry="18"/>
-<text text-anchor="middle" x="617" y="-230.3" font-family="Times,serif" font-size="14.00">Gatekeeper HAL</text>
-</g>
-<!-- gatekeeper->gatekeeper_console -->
-<g id="edge24" class="edge">
-<title>gatekeeper->gatekeeper_console</title>
-<path fill="none" stroke="green" d="M607.01,-216.05C604.32,-208.35 601.81,-199.03 600.04,-190.36"/>
-<polygon fill="green" stroke="green" points="603.45,-189.53 598.28,-180.28 596.55,-190.73 603.45,-189.53"/>
-</g>
-<!-- gatekeeper_console->vmm -->
-<g id="edge18" class="edge">
-<title>gatekeeper_console->vmm</title>
-<path fill="none" stroke="green" d="M564.89,-145.64C544.59,-135.66 519.28,-122.52 499.29,-111.64"/>
-<polygon fill="green" stroke="green" points="500.96,-108.56 490.51,-106.81 497.59,-114.7 500.96,-108.56"/>
-</g>
-<!-- gatekeeper_console->gatekeeper -->
-<g id="edge23" class="edge">
-<title>gatekeeper_console->gatekeeper</title>
-<path fill="none" stroke="green" d="M610.05,-180.1C612.72,-187.79 615.21,-197.05 616.97,-205.67"/>
-<polygon fill="green" stroke="green" points="613.55,-206.45 618.71,-215.7 620.44,-205.24 613.55,-206.45"/>
+<ellipse fill="none" stroke="green" cx="605.5" cy="-34" rx="71.49" ry="18"/>
+<text text-anchor="middle" x="605.5" y="-30.3" font-family="Times,serif" font-size="14.00">Gatekeeper HAL</text>
</g>
<!-- keymint -->
-<g id="node18" class="node">
+<g id="node16" class="node">
<title>keymint</title>
-<ellipse fill="none" stroke="blue" cx="868" cy="-90" rx="62.29" ry="18"/>
-<text text-anchor="middle" x="868" y="-86.3" font-family="Times,serif" font-size="14.00">Keymint HAL</text>
+<ellipse fill="none" stroke="blue" cx="453.5" cy="-34" rx="62.29" ry="18"/>
+<text text-anchor="middle" x="453.5" y="-30.3" font-family="Times,serif" font-size="14.00">Keymint HAL</text>
</g>
-<!-- keymint->keymint_console -->
-<g id="edge25" class="edge">
-<title>keymint->keymint_console</title>
-<path fill="none" stroke="blue" d="M873.9,-108.1C874.7,-115.79 874.94,-125.05 874.6,-133.67"/>
-<polygon fill="blue" stroke="blue" points="871.11,-133.48 873.92,-143.7 878.09,-133.96 871.11,-133.48"/>
+<!-- confirmationui_console->confirmationui -->
+<g id="edge8" class="edge">
+<title>confirmationui_console->confirmationui</title>
+<path fill="none" stroke="red" d="M755.16,-79.08C759.05,-73.03 763.19,-66.59 767.07,-60.56"/>
+<polygon fill="red" stroke="red" points="752.09,-77.39 749.62,-87.7 757.98,-81.18 752.09,-77.39"/>
+<polygon fill="red" stroke="red" points="770.04,-62.41 772.5,-52.1 764.15,-58.62 770.04,-62.41"/>
</g>
-<!-- keymint_console->vmm -->
-<g id="edge20" class="edge">
-<title>keymint_console->vmm</title>
-<path fill="none" stroke="blue" d="M832.94,-155C815.62,-151.54 794.69,-147.25 776,-144 664.97,-124.68 635.59,-129.7 525,-108 522.2,-107.45 519.35,-106.86 516.47,-106.24"/>
-<polygon fill="blue" stroke="blue" points="517.23,-102.82 506.7,-104.03 515.68,-109.65 517.23,-102.82"/>
+<!-- gatekeeper_console->gatekeeper -->
+<g id="edge16" class="edge">
+<title>gatekeeper_console->gatekeeper</title>
+<path fill="none" stroke="green" d="M605.5,-77.67C605.5,-72.69 605.5,-67.49 605.5,-62.51"/>
+<polygon fill="green" stroke="green" points="602,-77.7 605.5,-87.7 609,-77.7 602,-77.7"/>
+<polygon fill="green" stroke="green" points="609,-62.1 605.5,-52.1 602,-62.1 609,-62.1"/>
</g>
<!-- keymint_console->u_boot -->
-<g id="edge28" class="edge">
+<g id="edge23" class="edge">
<title>keymint_console->u_boot</title>
-<path fill="none" stroke="blue" d="M890.37,-180.2C899.52,-188.82 909.84,-199.41 918.33,-208.84"/>
-<polygon fill="blue" stroke="blue" points="915.74,-211.2 924.96,-216.41 921,-206.58 915.74,-211.2"/>
+<path fill="none" stroke="blue" d="M416.87,-82.51C401.61,-73.14 384.11,-62.39 369.62,-53.49"/>
+<polygon fill="blue" stroke="blue" points="415.26,-85.63 425.61,-87.88 418.92,-79.66 415.26,-85.63"/>
+<polygon fill="blue" stroke="blue" points="371.38,-50.47 361.03,-48.22 367.72,-56.44 371.38,-50.47"/>
</g>
<!-- keymint_console->keymint -->
-<g id="edge26" class="edge">
+<g id="edge22" class="edge">
<title>keymint_console->keymint</title>
-<path fill="none" stroke="blue" d="M862.08,-143.7C861.29,-135.98 861.06,-126.71 861.4,-118.11"/>
-<polygon fill="blue" stroke="blue" points="864.9,-118.32 862.1,-108.1 857.92,-117.84 864.9,-118.32"/>
+<path fill="none" stroke="blue" d="M453.5,-77.67C453.5,-72.69 453.5,-67.49 453.5,-62.51"/>
+<polygon fill="blue" stroke="blue" points="450,-77.7 453.5,-87.7 457,-77.7 450,-77.7"/>
+<polygon fill="blue" stroke="blue" points="457,-62.1 453.5,-52.1 450,-62.1 457,-62.1"/>
</g>
</g>
</svg>
diff --git a/host/commands/secure_env/keymaster_responder.cpp b/host/commands/secure_env/keymaster_responder.cpp
index 7289d48..2504e4d 100644
--- a/host/commands/secure_env/keymaster_responder.cpp
+++ b/host/commands/secure_env/keymaster_responder.cpp
@@ -91,6 +91,7 @@
HANDLE_MESSAGE_W_RETURN(CONFIGURE_VERIFIED_BOOT_INFO,
ConfigureVerifiedBootInfo)
HANDLE_MESSAGE_W_RETURN(GET_ROOT_OF_TRUST, GetRootOfTrust)
+ HANDLE_MESSAGE_W_RETURN(SET_ATTESTATION_IDS, SetAttestationIds)
#undef HANDLE_MESSAGE_W_RETURN
#define HANDLE_MESSAGE_W_RETURN_NO_ARG(ENUM_NAME, METHOD_NAME) \
case ENUM_NAME: { \
diff --git a/host/commands/secure_env/proxy_keymaster_context.h b/host/commands/secure_env/proxy_keymaster_context.h
index 2be72b0..a296074 100644
--- a/host/commands/secure_env/proxy_keymaster_context.h
+++ b/host/commands/secure_env/proxy_keymaster_context.h
@@ -163,6 +163,11 @@
return wrapped_.GetBootPatchlevel();
}
+ keymaster_error_t SetAttestationIds(
+ const keymaster::SetAttestationIdsRequest& request) override {
+ return wrapped_.SetAttestationIds(request);
+ }
+
private:
KeymasterContext& wrapped_;
};
diff --git a/host/commands/secure_env/tpm_attestation_record.cpp b/host/commands/secure_env/tpm_attestation_record.cpp
index 674570b..70620ae 100644
--- a/host/commands/secure_env/tpm_attestation_record.cpp
+++ b/host/commands/secure_env/tpm_attestation_record.cpp
@@ -54,11 +54,76 @@
return KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
}
+// Return true if entries match, false otherwise.
+bool matchAttestationId(keymaster_blob_t blob, const std::vector<uint8_t>& id) {
+ if (blob.data_length != id.size()) {
+ return false;
+ }
+ if (memcmp(blob.data, id.data(), id.size())) {
+ return false;
+ }
+ return true;
+}
+
keymaster_error_t TpmAttestationRecordContext::VerifyAndCopyDeviceIds(
- const AuthorizationSet& /*attestation_params*/,
- AuthorizationSet* /*attestation*/) const {
- LOG(DEBUG) << "TODO(schuffelen): Implement VerifyAndCopyDeviceIds";
- return KM_ERROR_UNIMPLEMENTED;
+ const AuthorizationSet& attestation_params,
+ AuthorizationSet* attestation) const {
+ const AttestationIds& ids = attestation_ids_;
+ bool found_mismatch = false;
+ for (auto& entry : attestation_params) {
+ switch (entry.tag) {
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.brand);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.device);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.product);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.serial);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.imei);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_MEID:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.meid);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.manufacturer);
+ attestation->push_back(entry);
+ break;
+
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ found_mismatch |= !matchAttestationId(entry.blob, ids.model);
+ attestation->push_back(entry);
+ break;
+
+ default:
+ // Ignore non-ID tags.
+ break;
+ }
+ }
+
+ if (found_mismatch) {
+ attestation->Clear();
+ return KM_ERROR_CANNOT_ATTEST_IDS;
+ }
+
+ return KM_ERROR_OK;
}
keymaster::Buffer TpmAttestationRecordContext::GenerateUniqueId(
@@ -107,4 +172,20 @@
vb_params_.device_locked = bootloader_state == "locked";
}
+keymaster_error_t TpmAttestationRecordContext::SetAttestationIds(
+ const keymaster::SetAttestationIdsRequest& request) {
+ attestation_ids_.brand.assign(request.brand.begin(), request.brand.end());
+ attestation_ids_.device.assign(request.device.begin(), request.device.end());
+ attestation_ids_.product.assign(request.product.begin(),
+ request.product.end());
+ attestation_ids_.serial.assign(request.serial.begin(), request.serial.end());
+ attestation_ids_.imei.assign(request.imei.begin(), request.imei.end());
+ attestation_ids_.meid.assign(request.meid.begin(), request.meid.end());
+ attestation_ids_.manufacturer.assign(request.manufacturer.begin(),
+ request.manufacturer.end());
+ attestation_ids_.model.assign(request.model.begin(), request.model.end());
+
+ return KM_ERROR_OK;
+}
+
} // namespace cuttlefish
diff --git a/host/commands/secure_env/tpm_attestation_record.h b/host/commands/secure_env/tpm_attestation_record.h
index dba0e91..3a48fdd 100644
--- a/host/commands/secure_env/tpm_attestation_record.h
+++ b/host/commands/secure_env/tpm_attestation_record.h
@@ -22,10 +22,22 @@
#include <string_view>
#include <vector>
+#include <keymaster/android_keymaster_messages.h>
#include <keymaster/attestation_context.h>
namespace cuttlefish {
+struct AttestationIds {
+ std::vector<uint8_t> brand;
+ std::vector<uint8_t> device;
+ std::vector<uint8_t> product;
+ std::vector<uint8_t> serial;
+ std::vector<uint8_t> imei;
+ std::vector<uint8_t> meid;
+ std::vector<uint8_t> manufacturer;
+ std::vector<uint8_t> model;
+};
+
class TpmAttestationRecordContext : public keymaster::AttestationContext {
public:
TpmAttestationRecordContext();
@@ -46,11 +58,14 @@
void SetVerifiedBootInfo(std::string_view verified_boot_state,
std::string_view bootloader_state,
const std::vector<uint8_t>& vbmeta_digest);
+ keymaster_error_t SetAttestationIds(
+ const keymaster::SetAttestationIdsRequest& request);
private:
std::vector<uint8_t> vbmeta_digest_;
VerifiedBootParams vb_params_;
std::vector<uint8_t> unique_id_hbk_;
+ AttestationIds attestation_ids_;
};
} // namespace cuttlefish
diff --git a/host/commands/secure_env/tpm_keymaster_context.h b/host/commands/secure_env/tpm_keymaster_context.h
index 2271019..df0a007 100644
--- a/host/commands/secure_env/tpm_keymaster_context.h
+++ b/host/commands/secure_env/tpm_keymaster_context.h
@@ -132,6 +132,11 @@
keymaster_error_t SetBootPatchlevel(uint32_t boot_patchlevel) override;
std::optional<uint32_t> GetVendorPatchlevel() const override;
std::optional<uint32_t> GetBootPatchlevel() const override;
+
+ keymaster_error_t SetAttestationIds(
+ const keymaster::SetAttestationIdsRequest& request) override {
+ return attestation_context_->SetAttestationIds(request);
+ }
};
} // namespace cuttlefish
diff --git a/host/commands/secure_env/tpm_remote_provisioning_context.cpp b/host/commands/secure_env/tpm_remote_provisioning_context.cpp
index 48bb545..b63d713 100644
--- a/host/commands/secure_env/tpm_remote_provisioning_context.cpp
+++ b/host/commands/secure_env/tpm_remote_provisioning_context.cpp
@@ -234,17 +234,18 @@
cppcose::ErrMsgOr<cppbor::Array> TpmRemoteProvisioningContext::BuildCsr(
const std::vector<uint8_t>& challenge, cppbor::Array keysToSign) const {
auto deviceInfo = std::move(*CreateDeviceInfo());
- auto signedDataPayload = cppbor::Array()
- .add(1 /* version */)
- .add("keymint" /* CertificateType */)
- .add(std::move(deviceInfo))
- .add(challenge)
- .add(std::move(keysToSign));
+ auto csrPayload = cppbor::Array()
+ .add(3 /* version */)
+ .add("keymint" /* CertificateType */)
+ .add(std::move(deviceInfo))
+ .add(std::move(keysToSign));
+ auto signedDataPayload =
+ cppbor::Array().add(challenge).add(cppbor::Bstr(csrPayload.encode()));
auto signedData = constructCoseSign1(
devicePrivKey_, signedDataPayload.encode(), {} /* aad */);
return cppbor::Array()
- .add(3 /* version */)
+ .add(1 /* version */)
.add(cppbor::Map() /* UdsCerts */)
.add(std::move(*bcc_.clone()->asArray()) /* DiceCertChain */)
.add(std::move(*signedData) /* SignedData */);
diff --git a/host/commands/start/main.cc b/host/commands/start/main.cc
index 45101a1..0bdd794 100644
--- a/host/commands/start/main.cc
+++ b/host/commands/start/main.cc
@@ -189,7 +189,13 @@
// Used to find bool flag and convert "flag"/"noflag" to "--flag=value"
// This is the solution for vectorize bool flags in gFlags
std::unordered_set<std::string> kBoolFlags = {"guest_enforce_security",
- "use_random_serial", "use_allocd", "use_sdcard", "pause_in_bootloader"};
+ "use_random_serial",
+ "use_allocd",
+ "use_sdcard",
+ "pause_in_bootloader",
+ "daemon",
+ "enable_minimal_mode",
+ "enable_modem_simulator"};
struct BooleanFlag {
bool is_bool_flag;
diff --git a/host/libs/config/Android.bp b/host/libs/config/Android.bp
index 668b745..7d3029a 100644
--- a/host/libs/config/Android.bp
+++ b/host/libs/config/Android.bp
@@ -26,6 +26,7 @@
"cuttlefish_config.cpp",
"cuttlefish_config_instance.cpp",
"data_image.cpp",
+ "esp.cpp",
"feature.cpp",
"fetcher_config.cpp",
"host_tools_version.cpp",
diff --git a/host/libs/config/bootconfig_args.cpp b/host/libs/config/bootconfig_args.cpp
index 5ba0112..a751021 100644
--- a/host/libs/config/bootconfig_args.cpp
+++ b/host/libs/config/bootconfig_args.cpp
@@ -161,7 +161,7 @@
concat("androidboot.vsock_camera_cid=", instance.vsock_guest_cid()));
}
- if (config.enable_modem_simulator() &&
+ if (instance.enable_modem_simulator() &&
instance.modem_simulator_ports() != "") {
bootconfig_args.push_back(concat("androidboot.modem_simulator_ports=",
instance.modem_simulator_ports()));
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 1bda946..d625c29 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -339,14 +339,6 @@
(*dictionary_)[kRestartSubprocesses] = restart_subprocesses;
}
-static constexpr char kRunAsDaemon[] = "run_as_daemon";
-bool CuttlefishConfig::run_as_daemon() const {
- return (*dictionary_)[kRunAsDaemon].asBool();
-}
-void CuttlefishConfig::set_run_as_daemon(bool run_as_daemon) {
- (*dictionary_)[kRunAsDaemon] = run_as_daemon;
-}
-
static constexpr char kBootSlot[] = "boot_slot";
void CuttlefishConfig::set_boot_slot(const std::string& boot_slot) {
(*dictionary_)[kBootSlot] = boot_slot;
@@ -443,32 +435,6 @@
return (*dictionary_)[kSigServerHeadersPath].asString();
}
-static constexpr char kRunModemSimulator[] = "enable_modem_simulator";
-bool CuttlefishConfig::enable_modem_simulator() const {
- return (*dictionary_)[kRunModemSimulator].asBool();
-}
-void CuttlefishConfig::set_enable_modem_simulator(bool enable_modem_simulator) {
- (*dictionary_)[kRunModemSimulator] = enable_modem_simulator;
-}
-
-static constexpr char kModemSimulatorInstanceNumber[] =
- "modem_simulator_instance_number";
-void CuttlefishConfig::set_modem_simulator_instance_number(
- int instance_number) {
- (*dictionary_)[kModemSimulatorInstanceNumber] = instance_number;
-}
-int CuttlefishConfig::modem_simulator_instance_number() const {
- return (*dictionary_)[kModemSimulatorInstanceNumber].asInt();
-}
-
-static constexpr char kModemSimulatorSimType[] = "modem_simulator_sim_type";
-void CuttlefishConfig::set_modem_simulator_sim_type(int sim_type) {
- (*dictionary_)[kModemSimulatorSimType] = sim_type;
-}
-int CuttlefishConfig::modem_simulator_sim_type() const {
- return (*dictionary_)[kModemSimulatorSimType].asInt();
-}
-
static constexpr char kHostToolsVersion[] = "host_tools_version";
void CuttlefishConfig::set_host_tools_version(
const std::map<std::string, uint32_t>& versions) {
@@ -591,14 +557,6 @@
return (*dictionary_)[kRilDns].asString();
}
-static constexpr char kEnableMinimalMode[] = "enable_minimal_mode";
-bool CuttlefishConfig::enable_minimal_mode() const {
- return (*dictionary_)[kEnableMinimalMode].asBool();
-}
-void CuttlefishConfig::set_enable_minimal_mode(bool enable_minimal_mode) {
- (*dictionary_)[kEnableMinimalMode] = enable_minimal_mode;
-}
-
static constexpr char kEnableKernelLog[] = "enable_kernel_log";
void CuttlefishConfig::set_enable_kernel_log(bool enable_kernel_log) {
(*dictionary_)[kEnableKernelLog] = enable_kernel_log;
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 278ad5e..debbb2b 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -169,9 +169,6 @@
void set_enable_gnss_grpc_proxy(const bool enable_gnss_grpc_proxy);
bool enable_gnss_grpc_proxy() const;
- void set_run_as_daemon(bool run_as_daemon);
- bool run_as_daemon() const;
-
void set_boot_slot(const std::string& boot_slot);
std::string boot_slot() const;
@@ -259,19 +256,6 @@
void set_enable_kernel_log(bool enable_kernel_log);
bool enable_kernel_log() const;
- // Configuration flags for a minimal device
- bool enable_minimal_mode() const;
- void set_enable_minimal_mode(bool enable_minimal_mode);
-
- void set_enable_modem_simulator(bool enable_modem_simulator);
- bool enable_modem_simulator() const;
-
- void set_modem_simulator_instance_number(int instance_numbers);
- int modem_simulator_instance_number() const;
-
- void set_modem_simulator_sim_type(int sim_type);
- int modem_simulator_sim_type() const;
-
void set_host_tools_version(const std::map<std::string, uint32_t>&);
std::map<std::string, uint32_t> host_tools_version() const;
@@ -537,6 +521,13 @@
bool guest_enforce_security() const;
bool use_sdcard() const;
bool pause_in_bootloader() const;
+ bool run_as_daemon() const;
+
+ // Configuration flags for a minimal device
+ bool enable_minimal_mode() const;
+ bool enable_modem_simulator() const;
+ int modem_simulator_instance_number() const;
+ int modem_simulator_sim_type() const;
// android artifacts
std::string boot_image() const;
@@ -643,6 +634,13 @@
void set_guest_enforce_security(bool guest_enforce_security);
void set_use_sdcard(bool use_sdcard);
void set_pause_in_bootloader(bool pause_in_bootloader);
+ void set_run_as_daemon(bool run_as_daemon);
+
+ // Configuration flags for a minimal device
+ void set_enable_minimal_mode(bool enable_minimal_mode);
+ void set_enable_modem_simulator(bool enable_modem_simulator);
+ void set_modem_simulator_instance_number(int instance_numbers);
+ void set_modem_simulator_sim_type(int sim_type);
// system image files
void set_boot_image(const std::string& boot_image);
diff --git a/host/libs/config/cuttlefish_config_instance.cpp b/host/libs/config/cuttlefish_config_instance.cpp
index eb2cc3e..c3d7e91 100644
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ b/host/libs/config/cuttlefish_config_instance.cpp
@@ -479,6 +479,52 @@
return (*Dictionary())[kPauseInBootloader].asBool();
}
+static constexpr char kRunAsDaemon[] = "run_as_daemon";
+bool CuttlefishConfig::InstanceSpecific::run_as_daemon() const {
+ return (*Dictionary())[kRunAsDaemon].asBool();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_run_as_daemon(bool run_as_daemon) {
+ (*Dictionary())[kRunAsDaemon] = run_as_daemon;
+}
+
+static constexpr char kEnableMinimalMode[] = "enable_minimal_mode";
+bool CuttlefishConfig::InstanceSpecific::enable_minimal_mode() const {
+ return (*Dictionary())[kEnableMinimalMode].asBool();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_enable_minimal_mode(
+ bool enable_minimal_mode) {
+ (*Dictionary())[kEnableMinimalMode] = enable_minimal_mode;
+}
+
+static constexpr char kRunModemSimulator[] = "enable_modem_simulator";
+bool CuttlefishConfig::InstanceSpecific::enable_modem_simulator() const {
+ return (*Dictionary())[kRunModemSimulator].asBool();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_enable_modem_simulator(
+ bool enable_modem_simulator) {
+ (*Dictionary())[kRunModemSimulator] = enable_modem_simulator;
+}
+
+static constexpr char kModemSimulatorInstanceNumber[] =
+ "modem_simulator_instance_number";
+void CuttlefishConfig::MutableInstanceSpecific::
+ set_modem_simulator_instance_number(int instance_number) {
+ (*Dictionary())[kModemSimulatorInstanceNumber] = instance_number;
+}
+int CuttlefishConfig::InstanceSpecific::modem_simulator_instance_number()
+ const {
+ return (*Dictionary())[kModemSimulatorInstanceNumber].asInt();
+}
+
+static constexpr char kModemSimulatorSimType[] = "modem_simulator_sim_type";
+void CuttlefishConfig::MutableInstanceSpecific::set_modem_simulator_sim_type(
+ int sim_type) {
+ (*Dictionary())[kModemSimulatorSimType] = sim_type;
+}
+int CuttlefishConfig::InstanceSpecific::modem_simulator_sim_type() const {
+ return (*Dictionary())[kModemSimulatorSimType].asInt();
+}
+
static constexpr char kDisplayConfigs[] = "display_configs";
static constexpr char kXRes[] = "x_res";
static constexpr char kYRes[] = "y_res";
diff --git a/host/libs/config/data_image.cpp b/host/libs/config/data_image.cpp
index 86b6362..e0bdb8d 100644
--- a/host/libs/config/data_image.cpp
+++ b/host/libs/config/data_image.cpp
@@ -10,6 +10,7 @@
#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
#include "host/libs/config/mbr.h"
+#include "host/libs/config/esp.h"
#include "host/libs/vm_manager/gem5_manager.h"
namespace cuttlefish {
@@ -28,24 +29,20 @@
// these search paths. Install all bootloaders to one of these paths.
// NOTE: For now, just ignore the 32-bit ARM version, as Debian doesn't
// build an EFI monolith for this architecture.
-const std::string kBootPathIA32 = "EFI/BOOT/BOOTIA32.EFI";
-const std::string kBootPathAA64 = "EFI/BOOT/BOOTAA64.EFI";
-const std::string kModulesPath = "EFI/modules";
-const std::string kMultibootModulePath = kModulesPath + "/multiboot.mod";
-const std::string kM5 = "";
-
// These are the paths Debian installs the monoliths to. If another distro
// uses an alternative monolith path, add it to this table
-const std::pair<std::string, std::string> kGrubBlobTable[] = {
- {"/usr/lib/grub/i386-efi/multiboot.mod", kMultibootModulePath},
- {"/usr/lib/grub/i386-efi/monolithic/grubia32.efi", kBootPathIA32},
- {"/usr/lib/grub/arm64-efi/monolithic/grubaa64.efi", kBootPathAA64},
-};
+const std::string kBootSrcPathIA32 = "/usr/lib/grub/i386-efi/monolithic/grubia32.efi";
+const std::string kBootDestPathIA32 = "EFI/BOOT/BOOTIA32.EFI";
-// M5 checkpoint required binary file
-const std::pair<std::string, std::string> kM5BlobTable[] = {
- {"/tmp/m5", kM5},
-};
+const std::string kBootSrcPathAA64 = "/usr/lib/grub/arm64-efi/monolithic/grubaa64.efi";
+const std::string kBootDestPathAA64 = "EFI/BOOT/BOOTAA64.EFI";
+
+const std::string kModulesDestPath = "EFI/modules";
+const std::string kMultibootModuleSrcPathIA32 = "/usr/lib/grub/i386-efi/multiboot.mod";
+const std::string kMultibootModuleDestPathIA32 = kModulesDestPath + "/multiboot.mod";
+
+const std::string kMultibootModuleSrcPathAA64 = "/usr/lib/grub/arm64-efi/multiboot.mod";
+const std::string kMultibootModuleDestPathAA64 = kModulesDestPath + "/multiboot.mod";
bool ForceFsckImage(const std::string& data_image,
const CuttlefishConfig::InstanceSpecific& instance) {
@@ -64,48 +61,6 @@
return true;
}
-bool NewfsMsdos(const std::string& data_image, int data_image_mb,
- int offset_num_mb) {
- off_t image_size_bytes = static_cast<off_t>(data_image_mb) << 20;
- off_t offset_size_bytes = static_cast<off_t>(offset_num_mb) << 20;
- image_size_bytes -= offset_size_bytes;
- off_t image_size_sectors = image_size_bytes / 512;
- auto newfs_msdos_path = HostBinaryPath("newfs_msdos");
- return execute({newfs_msdos_path,
- "-F",
- "32",
- "-m",
- "0xf8",
- "-o",
- "0",
- "-c",
- "8",
- "-h",
- "255",
- "-u",
- "63",
- "-S",
- "512",
- "-s",
- std::to_string(image_size_sectors),
- "-C",
- std::to_string(data_image_mb) + "M",
- "-@",
- std::to_string(offset_size_bytes),
- data_image}) == 0;
-}
-
-bool CopyToMsdos(const std::string& image, const std::string& path,
- const std::string& destination) {
- const auto mcopy = HostBinaryPath("mcopy");
- const auto success = execute({mcopy, "-o", "-i", image, "-s", path, destination});
- if (success != 0) {
- LOG(ERROR) << "Failed to copy " << path << " to " << image;
- return false;
- }
- return true;
-}
-
bool ResizeImage(const std::string& data_image, int data_image_mb,
const CuttlefishConfig::InstanceSpecific& instance) {
auto file_mb = FileSize(data_image) >> 20;
@@ -395,22 +350,20 @@
std::string Name() const override { return "InitializeEspImageImpl"; }
std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
bool Enabled() const override {
- auto flow = instance_.boot_flow();
- return flow == CuttlefishConfig::InstanceSpecific::BootFlow::Linux ||
- flow == CuttlefishConfig::InstanceSpecific::BootFlow::Fuchsia;
+ const auto flow = instance_.boot_flow();
+ const auto vm = config_.vm_manager();
+ const auto not_gem5 = vm != vm_manager::Gem5Manager::name();
+ const auto boot_flow_required_esp =
+ flow == CuttlefishConfig::InstanceSpecific::BootFlow::Linux ||
+ flow == CuttlefishConfig::InstanceSpecific::BootFlow::Fuchsia;
+
+ return not_gem5 && boot_flow_required_esp;
}
protected:
bool Setup() override {
LOG(DEBUG) << "esp partition image: creating default";
-
- // newfs_msdos won't make a partition smaller than 257 mb
- // this should be enough for anybody..
- auto tmp_esp_image = instance_.otheros_esp_image() + ".tmp";
- if (!NewfsMsdos(tmp_esp_image, 257 /* mb */, 0 /* mb (offset) */)) {
- LOG(ERROR) << "Failed to create filesystem for " << tmp_esp_image;
- return false;
- }
+ auto builder = EspBuilder(instance_.otheros_esp_image());
// For licensing and build reproducibility reasons, pick up the bootloaders
// from the host Linux distribution (if present) and pack them into the
@@ -418,91 +371,54 @@
// they can use -esp_image=/path/to/esp.img to override, so we don't need
// to accommodate customizations of this packing process.
- int success;
- const std::pair<std::string, std::string> *kBlobTable;
- std::size_t size;
- // Skip GRUB on Gem5
- if (config_.vm_manager() != vm_manager::Gem5Manager::name()) {
- // Currently we only support Debian based distributions, and GRUB is built
- // for those distros to always load grub.cfg from EFI/debian/grub.cfg, and
- // nowhere else. If you want to add support for other distros, make the
- // extra directories below and copy the initial grub.cfg there as well
- auto mmd = HostBinaryPath("mmd");
- success =
- execute({mmd, "-i", tmp_esp_image, "EFI", "EFI/BOOT", "EFI/debian", "EFI/modules"});
- if (success != 0) {
- LOG(ERROR) << "Failed to create directories in " << tmp_esp_image;
- return false;
- }
- size = sizeof(kGrubBlobTable)/sizeof(const std::pair<std::string, std::string>);
- kBlobTable = kGrubBlobTable;
- } else {
- size = sizeof(kM5BlobTable)/sizeof(const std::pair<std::string, std::string>);
- kBlobTable = kM5BlobTable;
- }
+ // Currently we only support Debian based distributions, and GRUB is built
+ // for those distros to always load grub.cfg from EFI/debian/grub.cfg, and
+ // nowhere else. If you want to add support for other distros, make the
+ // extra directories below and copy the initial grub.cfg there as well
+ builder.Directory("EFI")
+ .Directory("EFI/BOOT")
+ .Directory("EFI/debian")
+ .Directory("EFI/modules");
- // The grub binaries are small, so just copy all the architecture blobs
- // we can find, which minimizes complexity. If the user removed the grub bin
- // package from their system, the ESP will be empty and Other OS will not be
- // supported
- bool copied = false;
- for (int i=0; i<size; i++) {
- auto grub = kBlobTable[i];
- if (!FileExists(grub.first)) {
- continue;
- }
- if (!CopyToMsdos(tmp_esp_image, grub.first, "::" + grub.second)) {
- return false;
- }
- copied = true;
- }
-
- if (!copied) {
- LOG(ERROR) << "Binary dependencies were not found on this system; Other OS "
- "support will be broken";
- return false;
- }
-
- // Skip Gem5 case. Gem5 will never be able to use bootloaders like grub.
- if (config_.vm_manager() != vm_manager::Gem5Manager::name()) {
+ const auto flow = instance_.boot_flow();
+ if (flow == CuttlefishConfig::InstanceSpecific::BootFlow::Linux ||
+ flow == CuttlefishConfig::InstanceSpecific::BootFlow::Fuchsia) {
auto grub_cfg = DefaultHostArtifactsPath("etc/grub/grub.cfg");
- CHECK(FileExists(grub_cfg)) << "Missing file " << grub_cfg << "!";
- if (!CopyToMsdos(tmp_esp_image, grub_cfg, "::EFI/debian/")) {
- return false;
+ builder.File(grub_cfg, "EFI/debian/grub.cfg", /* required */ true);
+ switch (instance_.target_arch()) {
+ case Arch::Arm:
+ case Arch::Arm64:
+ builder.File(kBootSrcPathAA64, kBootDestPathAA64, /* required */ true);
+ builder.File(kMultibootModuleSrcPathAA64, kMultibootModuleDestPathAA64,
+ /* required */ true);
+ break;
+ case Arch::X86:
+ case Arch::X86_64:
+ builder.File(kBootSrcPathIA32, kBootDestPathIA32, /* required */ true);
+ builder.File(kMultibootModuleSrcPathIA32, kMultibootModuleDestPathIA32,
+ /* required */ true);
+ break;
}
}
- switch (instance_.boot_flow()) {
+ switch (flow) {
case CuttlefishConfig::InstanceSpecific::BootFlow::Linux:
- if (!CopyToMsdos(tmp_esp_image, instance_.linux_kernel_path(), "::vmlinuz")) {
- return false;
- }
-
+ builder.File(instance_.linux_kernel_path(), "vmlinuz", /* required */ true);
if (!instance_.linux_initramfs_path().empty()) {
- if (!CopyToMsdos(tmp_esp_image, instance_.linux_initramfs_path(), "::initrd.img")) {
- return false;
- }
+ builder.File(instance_.linux_initramfs_path(), "initrd.img", /* required */ true);
}
break;
case CuttlefishConfig::InstanceSpecific::BootFlow::Fuchsia:
- if (!CopyToMsdos(tmp_esp_image, instance_.fuchsia_zedboot_path(), "::zedboot.zbi")) {
- return false;
- }
- if (!CopyToMsdos(tmp_esp_image,
- instance_.fuchsia_multiboot_bin_path(), "::multiboot.bin")) {
- return false;
- }
+ builder.File(instance_.fuchsia_zedboot_path(), "zedboot.zbi",
+ /* required */ true);
+ builder.File(instance_.fuchsia_multiboot_bin_path(), "multiboot.bin",
+ /* required */ true);
break;
default:
break;
}
- if (!cuttlefish::RenameFile(tmp_esp_image, instance_.otheros_esp_image())) {
- LOG(ERROR) << "Renaming " << tmp_esp_image << " to "
- << instance_.otheros_esp_image() << " failed";
- return false;
- }
- return true;
+ return builder.Build();
}
private:
diff --git a/host/libs/config/esp.cpp b/host/libs/config/esp.cpp
new file mode 100644
index 0000000..f0bcf55
--- /dev/null
+++ b/host/libs/config/esp.cpp
@@ -0,0 +1,145 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "host/libs/config/esp.h"
+#include "common/libs/utils/subprocess.h"
+#include "common/libs/utils/files.h"
+#include "host/libs/config/cuttlefish_config.h"
+
+namespace cuttlefish {
+
+bool NewfsMsdos(const std::string& data_image, int data_image_mb,
+ int offset_num_mb) {
+ off_t image_size_bytes = static_cast<off_t>(data_image_mb) << 20;
+ off_t offset_size_bytes = static_cast<off_t>(offset_num_mb) << 20;
+ image_size_bytes -= offset_size_bytes;
+ off_t image_size_sectors = image_size_bytes / 512;
+ auto newfs_msdos_path = HostBinaryPath("newfs_msdos");
+ return execute({newfs_msdos_path,
+ "-F",
+ "32",
+ "-m",
+ "0xf8",
+ "-o",
+ "0",
+ "-c",
+ "8",
+ "-h",
+ "255",
+ "-u",
+ "63",
+ "-S",
+ "512",
+ "-s",
+ std::to_string(image_size_sectors),
+ "-C",
+ std::to_string(data_image_mb) + "M",
+ "-@",
+ std::to_string(offset_size_bytes),
+ data_image}) == 0;
+}
+
+bool MsdosMakeDirectories(const std::string& image_path,
+ const std::vector<std::string>& directories) {
+ auto mmd = HostBinaryPath("mmd");
+ std::vector<std::string> command {mmd, "-i", image_path};
+ command.insert(command.end(), directories.begin(), directories.end());
+
+ const auto success = execute(command);
+ if (success != 0) {
+ return false;
+ }
+ return true;
+}
+
+bool CopyToMsdos(const std::string& image, const std::string& path,
+ const std::string& destination) {
+ const auto mcopy = HostBinaryPath("mcopy");
+ const auto success = execute({mcopy, "-o", "-i", image, "-s", path, destination});
+ if (success != 0) {
+ return false;
+ }
+ return true;
+}
+
+EspBuilder& EspBuilder::File(std::string from, std::string to, bool required) & {
+ files_.push_back(FileToAdd {std::move(from), std::move(to), required});
+ return *this;
+}
+
+EspBuilder EspBuilder::File(std::string from, std::string to, bool required) && {
+ files_.push_back(FileToAdd {std::move(from), std::move(to), required});
+ return *this;
+}
+
+EspBuilder& EspBuilder::File(std::string from, std::string to) & {
+ return File(std::move(from), std::move(to), false);
+}
+
+EspBuilder EspBuilder::File(std::string from, std::string to) && {
+ return File(std::move(from), std::move(to), false);
+}
+
+EspBuilder& EspBuilder::Directory(std::string path) & {
+ directories_.push_back(std::move(path));
+ return *this;
+}
+
+EspBuilder EspBuilder::Directory(std::string path) && {
+ directories_.push_back(std::move(path));
+ return *this;
+}
+
+bool EspBuilder::Build() const {
+ // newfs_msdos won't make a partition smaller than 257 mb
+ // this should be enough for anybody..
+ const auto tmp_esp_image = image_path_ + ".tmp";
+ if (!NewfsMsdos(tmp_esp_image, 257 /* mb */, 0 /* mb (offset) */)) {
+ LOG(ERROR) << "Failed to create filesystem for " << tmp_esp_image;
+ return false;
+ }
+
+ if (!MsdosMakeDirectories(tmp_esp_image, directories_)) {
+ LOG(ERROR) << "Failed to create directories in " << tmp_esp_image;
+ return false;
+ }
+
+ for (const auto file : files_) {
+ if (!FileExists(file.from)) {
+ if (file.required) {
+ LOG(ERROR) << "Failed to copy " << file.from << " to " << tmp_esp_image
+ << ": File does not exist";
+ return false;
+ }
+ continue;
+ }
+
+ if (!CopyToMsdos(tmp_esp_image, file.from, "::" + file.to)) {
+ LOG(ERROR) << "Failed to copy " << file.from << " to " << tmp_esp_image
+ << ": mcopy execution failed";
+ return false;
+ }
+ }
+
+ if (!RenameFile(tmp_esp_image, image_path_)) {
+ LOG(ERROR) << "Renaming " << tmp_esp_image << " to "
+ << image_path_ << " failed";
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace cuttlefish
diff --git a/host/libs/config/esp.h b/host/libs/config/esp.h
new file mode 100644
index 0000000..f5a0f19
--- /dev/null
+++ b/host/libs/config/esp.h
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace cuttlefish {
+
+class EspBuilder final {
+ public:
+ EspBuilder() = delete;
+ EspBuilder(std::string image_path): image_path_(std::move(image_path)) {}
+
+ EspBuilder& File(std::string from, std::string to, bool required) &;
+ EspBuilder File(std::string from, std::string to, bool required) &&;
+
+ EspBuilder& File(std::string from, std::string to) &;
+ EspBuilder File(std::string from, std::string to) &&;
+
+ EspBuilder& Directory(std::string path) &;
+ EspBuilder Directory(std::string path) &&;
+
+ bool Build() const;
+
+ private:
+ std::string image_path_;
+
+ struct FileToAdd {
+ std::string from;
+ std::string to;
+ bool required;
+ };
+ std::vector<std::string> directories_;
+ std::vector<FileToAdd> files_;
+};
+
+bool NewfsMsdos(const std::string& data_image, int data_image_mb,
+ int offset_num_mb);
+
+} // namespace cuttlefish
diff --git a/host/libs/config/logging.cpp b/host/libs/config/logging.cpp
index 9cf1705..f0a17bc 100644
--- a/host/libs/config/logging.cpp
+++ b/host/libs/config/logging.cpp
@@ -38,7 +38,7 @@
prefix = instance.instance_name() + ": ";
}
- if (config->run_as_daemon()) {
+ if (instance.run_as_daemon()) {
SetLogger(LogToFiles({instance.launcher_log_path()}));
} else {
SetLogger(LogToStderrAndFiles({instance.launcher_log_path()}, prefix));
diff --git a/host/libs/confui/host_utils.cc b/host/libs/confui/host_utils.cc
index 6ff67b0..bc5d23e 100644
--- a/host/libs/confui/host_utils.cc
+++ b/host/libs/confui/host_utils.cc
@@ -21,7 +21,7 @@
namespace thread {
std::string ThreadTracer::Get(const std::thread::id tid) {
std::lock_guard<std::mutex> lock(mtx_);
- if (id2name_.find(tid) != id2name_.end()) {
+ if (Contains(id2name_, tid)) {
return id2name_[tid];
}
std::stringstream ss;
@@ -31,7 +31,7 @@
void ThreadTracer::Set(const std::string& name, const std::thread::id tid) {
std::lock_guard<std::mutex> lock(mtx_);
- if (name2id_.find(name) != name2id_.end()) {
+ if (Contains(name2id_, name)) {
// has the name already
if (name2id_[name] != tid) { // used for another thread
ConfUiLog(FATAL) << "Thread name is duplicated.";
@@ -39,7 +39,7 @@
// name and id are already set correctly
return;
}
- if (id2name_.find(tid) != id2name_.end()) {
+ if (Contains(id2name_, tid)) {
// tid exists but has a different name
name2id_.erase(id2name_[tid]); // delete old_name -> tid map
}
@@ -50,10 +50,10 @@
std::optional<std::thread::id> ThreadTracer::Get(const std::string& name) {
std::lock_guard<std::mutex> lock(mtx_);
- if (name2id_.find(name) != name2id_.end()) {
+ if (Contains(name2id_, name)) {
return {name2id_[name]};
}
- return std::nullopt; // unknown
+ return std::nullopt;
}
ThreadTracer& GetThreadTracer() {
diff --git a/host/libs/confui/host_utils.h b/host/libs/confui/host_utils.h
index bd4004b..4037419 100644
--- a/host/libs/confui/host_utils.h
+++ b/host/libs/confui/host_utils.h
@@ -27,6 +27,7 @@
#include <android-base/logging.h>
#include "common/libs/confui/confui.h"
+#include "common/libs/utils/contains.h"
#include "host/commands/kernel_log_monitor/utils.h"
#include "host/libs/config/logging.h"
@@ -68,7 +69,7 @@
template <typename F, typename... Args>
std::thread RunThread(const std::string& name, F&& f, Args&&... args) {
auto th = std::thread(std::forward<F>(f), std::forward<Args>(args)...);
- if (name2id_.find(name) != name2id_.end()) {
+ if (Contains(name2id_, name)) {
ConfUiLog(FATAL) << "Thread name is duplicated";
}
name2id_[name] = th.get_id();
diff --git a/host/libs/confui/session.cc b/host/libs/confui/session.cc
index 2b7069b..66ffdb6 100644
--- a/host/libs/confui/session.cc
+++ b/host/libs/confui/session.cc
@@ -18,6 +18,7 @@
#include <algorithm>
+#include "common/libs/utils/contains.h"
#include "host/libs/confui/secure_input.h"
namespace cuttlefish {
@@ -65,12 +66,6 @@
return false;
}
-template <typename C, typename T>
-static bool Contains(const C& c, T&& item) {
- auto itr = std::find(c.begin(), c.end(), std::forward<T>(item));
- return itr != c.end();
-}
-
bool Session::IsInverted() const {
return Contains(ui_options_, teeui::UIOption::AccessibilityInverted);
}
diff --git a/shared/device.mk b/shared/device.mk
index 4c1b8ea..eb2349c 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -291,6 +291,7 @@
device/google/cuttlefish/shared/config/media_profiles.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles_V1_0.xml \
device/google/cuttlefish/shared/permissions/privapp-permissions-cuttlefish.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/privapp-permissions-cuttlefish.xml \
frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
+ hardware/interfaces/audio/aidl/default/audio_effects_config.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects_config.xml \
frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_audio.xml \
frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_telephony.xml \
frameworks/av/services/audiopolicy/config/a2dp_in_audio_policy_configuration_7_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/a2dp_in_audio_policy_configuration_7_0.xml \
@@ -440,7 +441,8 @@
frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/r_submix_audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml \
frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
- frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml
+ frameworks/av/media/libeffects/data/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
+ hardware/interfaces/audio/aidl/default/audio_effects_config.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects_config.xml
endif
PRODUCT_PACKAGES += $(LOCAL_AUDIO_PRODUCT_PACKAGE)
diff --git a/shared/sepolicy/vendor/hal_keymint_remote.te b/shared/sepolicy/vendor/hal_keymint_remote.te
index 7d5f6d5..c1baebb 100644
--- a/shared/sepolicy/vendor/hal_keymint_remote.te
+++ b/shared/sepolicy/vendor/hal_keymint_remote.te
@@ -13,3 +13,4 @@
get_prop(hal_keymint_remote, vendor_security_patch_level_prop)
get_prop(hal_keymint_remote, vendor_boot_security_patch_level_prop)
+get_prop(hal_keymint_remote, serialno_prop)
diff --git a/tests/hal/hal_implementation_test.cpp b/tests/hal/hal_implementation_test.cpp
index 480b25f..0057d38 100644
--- a/tests/hal/hal_implementation_test.cpp
+++ b/tests/hal/hal_implementation_test.cpp
@@ -166,7 +166,7 @@
// Cuttlefish Identity Credential HAL implementation is currently
// stuck at version 3 while RKP support is being added. Will be
// updated soon.
- {"android.hardware.identity.", 5},
+ {"android.hardware.identity.", 4},
// The interface is in development (b/205884982)
{"android.hardware.audio.core.", 1},