blob: 24120d5be5cd7d45f8629055067785b08170abde [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "host/commands/cvd/parser/cf_flags_validator.h"
#include <map>
#include <string>
#include <unordered_set>
#include <json/json.h>
#include "common/libs/utils/files.h"
#include "common/libs/utils/flags_validator.h"
#include "common/libs/utils/result.h"
#include "host/commands/cvd/parser/cf_configs_common.h"
namespace cuttlefish {
namespace {
static std::map<std::string, Json::ValueType> kConfigsKeyMap = {
{"netsim_bt", Json::ValueType::booleanValue},
{"instances", Json::ValueType::arrayValue},
{"fetch", Json::ValueType::objectValue},
{"metrics", Json::ValueType::objectValue},
{"common", Json::ValueType::objectValue},
};
static std::map<std::string, Json::ValueType> kCommonKeyMap = {
{"group_name", Json::ValueType::stringValue}};
static std::map<std::string, Json::ValueType> kFetchKeyMap = {
{"api_key", Json::ValueType::stringValue},
{"credential_source", Json::ValueType::stringValue},
{"wait_retry_period", Json::ValueType::uintValue},
{"external_dns_resolver", Json::ValueType::booleanValue},
{"keep_downloaded_archives", Json::ValueType::booleanValue},
{"api_base_url", Json::ValueType::stringValue},
};
static std::map<std::string, Json::ValueType> kInstanceKeyMap = {
{"@import", Json::ValueType::stringValue},
{"name", Json::ValueType::stringValue},
{"vm", Json::ValueType::objectValue},
{"boot", Json::ValueType::objectValue},
{"security", Json::ValueType::objectValue},
{"disk", Json::ValueType::objectValue},
{"graphics", Json::ValueType::objectValue},
{"camera", Json::ValueType::objectValue},
{"connectivity", Json::ValueType::objectValue},
{"audio", Json::ValueType::objectValue},
{"streaming", Json::ValueType::objectValue},
{"adb", Json::ValueType::objectValue},
{"vehicle", Json::ValueType::objectValue},
{"location", Json::ValueType::objectValue}};
static std::unordered_set<std::string> kSupportedImportValues = {
"phone", "tablet", "tv", "wearable", "auto", "slim", "go", "foldable"};
static std::map<std::string, Json::ValueType> kVmKeyMap = {
{"cpus", Json::ValueType::uintValue},
{"memory_mb", Json::ValueType::uintValue},
{"use_sdcard", Json::ValueType::booleanValue},
{"setupwizard_mode", Json::ValueType::stringValue},
{"uuid", Json::ValueType::stringValue},
{"crosvm", Json::ValueType::objectValue},
{"qemu", Json::ValueType::objectValue},
{"gem5", Json::ValueType::objectValue},
{"custom_actions", Json::ValueType::arrayValue},
};
static std::map<std::string, Json::ValueType> kCrosvmKeyMap = {
{"enable_sandbox", Json::ValueType::booleanValue},
};
static std::map<std::string, Json::ValueType> kBootKeyMap = {
{"kernel", Json::ValueType::objectValue},
{"enable_bootanimation", Json::ValueType::booleanValue},
{"build", Json::ValueType::stringValue},
{"bootloader", Json::ValueType::objectValue},
};
static std::map<std::string, Json::ValueType> kKernelKeyMap = {
{"extra_kernel_cmdline", Json::ValueType::stringValue},
{"build", Json::ValueType::stringValue},
};
static std::map<std::string, Json::ValueType> kBootloaderKeyMap = {
{"build", Json::ValueType::stringValue},
};
static std::map<std::string, Json::ValueType> kGraphicsKeyMap = {
{"displays", Json::ValueType::arrayValue},
{"record_screen", Json::ValueType::booleanValue},
};
static std::map<std::string, Json::ValueType> kDisplayKeyMap = {
{"width", Json::ValueType::uintValue},
{"height", Json::ValueType::uintValue},
{"dpi", Json::ValueType::uintValue},
{"refresh_rate_hertz", Json::ValueType::uintValue},
};
static std::map<std::string, Json::ValueType> kSecurityKeyMap = {
{"serial_number", Json::ValueType::stringValue},
{"use_random_serial", Json::ValueType::stringValue},
{"guest_enforce_security", Json::ValueType::booleanValue},
};
static std::map<std::string, Json::ValueType> kDiskKeyMap = {
{"default_build", Json::ValueType::stringValue},
{"super", Json::ValueType::objectValue},
{"download_img_zip", Json::ValueType::booleanValue},
{"download_target_zip_files", Json::ValueType::booleanValue},
{"blank_data_image_mb", Json::ValueType::uintValue},
{"otatools", Json::ValueType::stringValue},
{"host_package", Json::ValueType::stringValue},
};
static std::map<std::string, Json::ValueType> kSuperKeyMap = {
{"system", Json::ValueType::stringValue},
};
Result<void> ValidateSecurityConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kSecurityKeyMap),
"ValidateSecurityConfigs ValidateTypo fail");
return {};
}
Result<void> ValidateDiskConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kDiskKeyMap),
"ValidateDiskConfigs ValidateTypo fail");
if (root.isMember("super")) {
CF_EXPECT(ValidateTypo(root["super"], kSuperKeyMap),
"ValidateDiskSuperConfigs ValidateTypo fail");
}
return {};
}
Result<void> ValidateDisplaysConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kDisplayKeyMap),
"ValidateDisplaysConfigs ValidateTypo fail");
return {};
}
Result<void> ValidateGraphicsConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kGraphicsKeyMap),
"ValidateGraphicsConfigs ValidateTypo fail");
if (root.isMember("displays") && root["displays"].size() != 0) {
for (const auto& display : root["displays"]) {
CF_EXPECT(ValidateDisplaysConfigs(display));
}
}
return {};
}
Result<void> ValidateVmConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kVmKeyMap),
"ValidateVmConfigs ValidateTypo fail");
if (root.isMember("crosvm")) {
CF_EXPECT(ValidateTypo(root["crosvm"], kCrosvmKeyMap),
"ValidateVmConfigs ValidateTypo crosvm fail");
}
return {};
}
Result<void> ValidateKernelConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kKernelKeyMap),
"ValidateKernelConfigs ValidateTypo fail");
return {};
}
Result<void> ValidateBootloaderConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kBootloaderKeyMap),
"ValidateBootloaderConfigs ValidateTypo fail");
return {};
}
Result<void> ValidateBootConfigs(const Json::Value& root) {
CF_EXPECT(ValidateTypo(root, kBootKeyMap),
"ValidateBootConfigs ValidateTypo fail");
if (root.isMember("kernel")) {
CF_EXPECT(ValidateKernelConfigs(root["kernel"]));
}
if (root.isMember("bootloader")) {
CF_EXPECT(ValidateBootloaderConfigs(root["bootloader"]));
}
return {};
}
Result<void> ValidateStreamingConfigs(const Json::Value& root) {
static const auto& kStreamingKeyMap =
*new std::map<std::string, Json::ValueType>{
{"device_id", Json::ValueType::stringValue},
};
CF_EXPECT(ValidateTypo(root, kStreamingKeyMap),
"ValidateStreamingConfigs ValidateTypo fail");
return {};
}
Result<void> ValidateInstancesConfigs(const Json::Value& instances) {
for (const auto& instance : instances) {
CF_EXPECT(ValidateTypo(instance, kInstanceKeyMap),
"instance ValidateTypo fail");
if (instance.isMember("vm")) {
CF_EXPECT(ValidateVmConfigs(instance["vm"]));
}
if (instance.isMember("@import")) {
CF_EXPECT(
kSupportedImportValues.count(instance["@import"].asString()) > 0,
"@Import flag values are not supported");
}
if (instance.isMember("boot")) {
CF_EXPECT(ValidateBootConfigs(instance["boot"]));
}
if (instance.isMember("security")) {
CF_EXPECT(ValidateSecurityConfigs(instance["security"]));
}
if (instance.isMember("disk")) {
CF_EXPECT(ValidateDiskConfigs(instance["disk"]));
}
if (instance.isMember("graphics")) {
CF_EXPECT(ValidateGraphicsConfigs(instance["graphics"]));
}
if (instance.isMember("streaming")) {
CF_EXPECT(ValidateStreamingConfigs(instance["streaming"]));
}
CF_EXPECT(ValidateConfig<std::string>(instance, ValidateSetupWizardMode,
{"vm", "setupwizard_mode"}),
"Invalid value for setupwizard_mode flag");
}
return {};
}
} // namespace
Result<void> ValidateCfConfigs(const Json::Value& root) {
static const auto& kMetricsMap = *new std::map<std::string, Json::ValueType>{
{"enable", Json::ValueType::booleanValue},
};
CF_EXPECT(ValidateTypo(root, kConfigsKeyMap),
"Typo in config main parameters");
CF_EXPECT(ValidateTypo(root["common"], kCommonKeyMap),
"Typo in config common parameters");
CF_EXPECT(ValidateTypo(root["fetch"], kFetchKeyMap),
"Typo in config fetch parameters");
CF_EXPECT(ValidateTypo(root["metrics"], kMetricsMap),
"Typo in config metrics parameters");
CF_EXPECT(root.isMember("instances"), "instances object is missing");
CF_EXPECT(ValidateInstancesConfigs(root["instances"]),
"ValidateInstancesConfigs failed");
return {};
}
} // namespace cuttlefish