blob: 771093cfc910c43eec8d615addc15a2b385226ba [file] [log] [blame]
/*
* Copyright (C) 2018 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/cuttlefish_config.h"
#include <algorithm>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iterator>
#include <sstream>
#include <string>
#include <glog/logging.h>
#include <json/json.h>
#include "common/libs/utils/environment.h"
#include "common/libs/utils/files.h"
namespace {
int InstanceFromEnvironment() {
static constexpr char kInstanceEnvironmentVariable[] = "CUTTLEFISH_INSTANCE";
static constexpr int kDefaultInstance = 1;
// CUTTLEFISH_INSTANCE environment variable
const char* instance_str = std::getenv(kInstanceEnvironmentVariable);
if (!instance_str) {
// Try to get it from the user instead
instance_str = std::getenv("USER");
if (!instance_str || std::strncmp(instance_str, vsoc::kVsocUserPrefix,
sizeof(vsoc::kVsocUserPrefix) - 1)) {
// No user or we don't recognize this user
LOG(WARNING) << "No user or non-vsoc user, returning default config";
return kDefaultInstance;
}
instance_str += sizeof(vsoc::kVsocUserPrefix) - 1;
// Set the environment variable so that child processes see it
setenv(kInstanceEnvironmentVariable, instance_str, 0);
}
int instance = std::atoi(instance_str);
if (instance <= 0) {
instance = kDefaultInstance;
}
return instance;
}
const char* kSerialNumber = "serial_number";
const char* kInstanceDir = "instance_dir";
const char* kVmManager = "vm_manager";
const char* kDeviceTitle = "device_title";
const char* kCpus = "cpus";
const char* kMemoryMb = "memory_mb";
const char* kDpi = "dpi";
const char* kXRes = "x_res";
const char* kYRes = "y_res";
const char* kRefreshRateHz = "refresh_rate_hz";
const char* kKernelImagePath = "kernel_image_path";
const char* kGdbFlag = "gdb_flag";
const char* kKernelCmdline = "kernel_cmdline";
const char* kRamdiskImagePath = "ramdisk_image_path";
const char* kSystemImagePath = "system_image_path";
const char* kCacheImagePath = "cache_image_path";
const char* kDataImagePath = "data_image_path";
const char* kVendorImagePath = "vendor_image_path";
const char* kUsbV1SocketName = "usb_v1_socket_name";
const char* kVhciPort = "vhci_port";
const char* kUsbIpSocketName = "usb_ip_socket_name";
const char* kKernelLogSocketName = "kernel_log_socket_name";
const char* kDeprecatedBootCompleted = "deprecated_boot_completed";
const char* kConsolePath = "console_path";
const char* kLogcatPath = "logcat_path";
const char* kLauncherLogPath = "launcher_log_path";
const char* kLauncherMonitorPath = "launcher_monitor_socket";
const char* kDtbPath = "dtb_path";
const char* kMempath = "mempath";
const char* kIvshmemQemuSocketPath = "ivshmem_qemu_socket_path";
const char* kIvshmemClientSocketPath = "ivshmem_client_socket_path";
const char* kIvshmemVectorCount = "ivshmem_vector_count";
const char* kMobileBridgeName = "mobile_bridge_name";
const char* kMobileTapName = "mobile_tap_name";
const char* kWifiBridgeName = "wifi_bridge_name";
const char* kWifiTapName = "wifi_tap_name";
const char* kWifiGuestMacAddr = "wifi_guest_mac_addr";
const char* kWifiHostMacAddr = "wifi_host_mac_addr";
const char* kEntropySource = "entropy_source";
const char* kVsockGuestCid = "vsock_guest_cid";
const char* kUuid = "uuid";
const char* kDisableDacSecurity = "disable_dac_security";
const char* kDisableAppArmorSecurity = "disable_app_armor_security";
const char* kCuttlefishEnvPath = "cuttlefish_env_path";
const char* kAdbMode = "adb_mode";
const char* kAdbIPAndPort = "adb_ip_and_port";
const char* kSetupWizardMode = "setupwizard_mode";
const char* kLogXml = "log_xml";
const char* kHypervisorUri = "hypervisor_uri";
const char* kQemuBinary = "qemu_binary";
} // namespace
namespace vsoc {
std::string CuttlefishConfig::instance_dir() const {
return (*dictionary_)[kInstanceDir].asString();
}
void CuttlefishConfig::set_instance_dir(const std::string& instance_dir) {
(*dictionary_)[kInstanceDir] = instance_dir;
}
std::string CuttlefishConfig::vm_manager() const {
return (*dictionary_)[kVmManager].asString();
}
void CuttlefishConfig::set_vm_manager(const std::string& name) {
(*dictionary_)[kVmManager] = name;
}
std::string CuttlefishConfig::serial_number() const {
return (*dictionary_)[kSerialNumber].asString();
}
void CuttlefishConfig::set_serial_number(const std::string& serial_number) {
(*dictionary_)[kSerialNumber] = serial_number;
}
int CuttlefishConfig::cpus() const { return (*dictionary_)[kCpus].asInt(); }
void CuttlefishConfig::set_cpus(int cpus) { (*dictionary_)[kCpus] = cpus; }
int CuttlefishConfig::memory_mb() const {
return (*dictionary_)[kMemoryMb].asInt();
}
void CuttlefishConfig::set_memory_mb(int memory_mb) {
(*dictionary_)[kMemoryMb] = memory_mb;
}
int CuttlefishConfig::dpi() const { return (*dictionary_)[kDpi].asInt(); }
void CuttlefishConfig::set_dpi(int dpi) { (*dictionary_)[kDpi] = dpi; }
int CuttlefishConfig::x_res() const { return (*dictionary_)[kXRes].asInt(); }
void CuttlefishConfig::set_x_res(int x_res) { (*dictionary_)[kXRes] = x_res; }
int CuttlefishConfig::y_res() const { return (*dictionary_)[kYRes].asInt(); }
void CuttlefishConfig::set_y_res(int y_res) { (*dictionary_)[kYRes] = y_res; }
int CuttlefishConfig::refresh_rate_hz() const {
return (*dictionary_)[kRefreshRateHz].asInt();
}
void CuttlefishConfig::set_refresh_rate_hz(int refresh_rate_hz) {
(*dictionary_)[kRefreshRateHz] = refresh_rate_hz;
}
std::string CuttlefishConfig::kernel_image_path() const {
return (*dictionary_)[kKernelImagePath].asString();
}
void CuttlefishConfig::SetPath(const std::string& key,
const std::string& path) {
if (!path.empty()) {
(*dictionary_)[key] = cvd::AbsolutePath(path);
}
}
void CuttlefishConfig::set_kernel_image_path(
const std::string& kernel_image_path) {
SetPath(kKernelImagePath, kernel_image_path);
}
std::string CuttlefishConfig::gdb_flag() const {
return (*dictionary_)[kGdbFlag].asString();
}
void CuttlefishConfig::set_gdb_flag(const std::string& device) {
SetPath(kGdbFlag, device);
}
std::set<std::string> CuttlefishConfig::kernel_cmdline() const {
std::set<std::string> args_set;
auto args_json_obj = (*dictionary_)[kKernelCmdline];
std::transform(args_json_obj.begin(), args_json_obj.end(),
std::inserter(args_set, args_set.begin()),
[](const Json::Value& it) { return it.asString(); });
return args_set;
}
void CuttlefishConfig::set_kernel_cmdline(
const std::set<std::string>& kernel_cmdline) {
Json::Value args_json_obj(Json::arrayValue);
for (const auto& arg : kernel_cmdline) {
args_json_obj.append(arg);
}
(*dictionary_)[kKernelCmdline] = args_json_obj;
}
void CuttlefishConfig::add_kernel_cmdline(
const std::set<std::string>& extra_args) {
std::set<std::string> cmdline = kernel_cmdline();
for (const auto& arg : extra_args) {
if (cmdline.count(arg)) {
LOG(ERROR) << "Kernel argument " << arg << " is duplicated";
}
cmdline.insert(arg);
}
set_kernel_cmdline(cmdline);
}
void CuttlefishConfig::add_kernel_cmdline(const std::string& kernel_cmdline) {
std::stringstream args_stream(kernel_cmdline);
std::set<std::string> kernel_cmdline_set;
using is_iter = std::istream_iterator<std::string>;
std::copy(is_iter(args_stream), is_iter(),
std::inserter(kernel_cmdline_set, kernel_cmdline_set.begin()));
add_kernel_cmdline(kernel_cmdline_set);
}
std::string CuttlefishConfig::kernel_cmdline_as_string() const {
auto args_set = kernel_cmdline();
std::stringstream output;
std::copy(args_set.begin(), args_set.end(),
std::ostream_iterator<std::string>(output, " "));
return output.str();
}
std::string CuttlefishConfig::ramdisk_image_path() const {
return (*dictionary_)[kRamdiskImagePath].asString();
}
void CuttlefishConfig::set_ramdisk_image_path(
const std::string& ramdisk_image_path) {
SetPath(kRamdiskImagePath, ramdisk_image_path);
}
std::string CuttlefishConfig::system_image_path() const {
return (*dictionary_)[kSystemImagePath].asString();
}
void CuttlefishConfig::set_system_image_path(
const std::string& system_image_path) {
SetPath(kSystemImagePath, system_image_path);
}
std::string CuttlefishConfig::cache_image_path() const {
return (*dictionary_)[kCacheImagePath].asString();
}
void CuttlefishConfig::set_cache_image_path(
const std::string& cache_image_path) {
SetPath(kCacheImagePath, cache_image_path);
}
std::string CuttlefishConfig::data_image_path() const {
return (*dictionary_)[kDataImagePath].asString();
}
void CuttlefishConfig::set_data_image_path(const std::string& data_image_path) {
SetPath(kDataImagePath, data_image_path);
}
std::string CuttlefishConfig::vendor_image_path() const {
return (*dictionary_)[kVendorImagePath].asString();
}
void CuttlefishConfig::set_vendor_image_path(
const std::string& vendor_image_path) {
SetPath(kVendorImagePath, vendor_image_path);
}
std::string CuttlefishConfig::dtb_path() const {
return (*dictionary_)[kDtbPath].asString();
}
void CuttlefishConfig::set_dtb_path(const std::string& dtb_path) {
SetPath(kDtbPath, dtb_path);
}
std::string CuttlefishConfig::mempath() const {
return (*dictionary_)[kMempath].asString();
}
void CuttlefishConfig::set_mempath(const std::string& mempath) {
SetPath(kMempath, mempath);
}
std::string CuttlefishConfig::ivshmem_qemu_socket_path() const {
return (*dictionary_)[kIvshmemQemuSocketPath].asString();
}
void CuttlefishConfig::set_ivshmem_qemu_socket_path(
const std::string& ivshmem_qemu_socket_path) {
SetPath(kIvshmemQemuSocketPath, ivshmem_qemu_socket_path);
}
std::string CuttlefishConfig::ivshmem_client_socket_path() const {
return (*dictionary_)[kIvshmemClientSocketPath].asString();
}
void CuttlefishConfig::set_ivshmem_client_socket_path(
const std::string& ivshmem_client_socket_path) {
SetPath(kIvshmemClientSocketPath, ivshmem_client_socket_path);
}
int CuttlefishConfig::ivshmem_vector_count() const {
return (*dictionary_)[kIvshmemVectorCount].asInt();
}
void CuttlefishConfig::set_ivshmem_vector_count(int ivshmem_vector_count) {
(*dictionary_)[kIvshmemVectorCount] = ivshmem_vector_count;
}
std::string CuttlefishConfig::usb_v1_socket_name() const {
return (*dictionary_)[kUsbV1SocketName].asString();
}
void CuttlefishConfig::set_usb_v1_socket_name(
const std::string& usb_v1_socket_name) {
(*dictionary_)[kUsbV1SocketName] = usb_v1_socket_name;
}
int CuttlefishConfig::vhci_port() const {
return (*dictionary_)[kVhciPort].asInt();
}
void CuttlefishConfig::set_vhci_port(int vhci_port) {
(*dictionary_)[kVhciPort] = vhci_port;
}
std::string CuttlefishConfig::usb_ip_socket_name() const {
return (*dictionary_)[kUsbIpSocketName].asString();
}
void CuttlefishConfig::set_usb_ip_socket_name(
const std::string& usb_ip_socket_name) {
(*dictionary_)[kUsbIpSocketName] = usb_ip_socket_name;
}
std::string CuttlefishConfig::kernel_log_socket_name() const {
return (*dictionary_)[kKernelLogSocketName].asString();
}
void CuttlefishConfig::set_kernel_log_socket_name(
const std::string& kernel_log_socket_name) {
(*dictionary_)[kKernelLogSocketName] = kernel_log_socket_name;
}
bool CuttlefishConfig::deprecated_boot_completed() const {
return (*dictionary_)[kDeprecatedBootCompleted].asBool();
}
void CuttlefishConfig::set_deprecated_boot_completed(
bool deprecated_boot_completed) {
(*dictionary_)[kDeprecatedBootCompleted] = deprecated_boot_completed;
}
std::string CuttlefishConfig::console_path() const {
return (*dictionary_)[kConsolePath].asString();
}
void CuttlefishConfig::set_console_path(const std::string& console_path) {
SetPath(kConsolePath, console_path);
}
std::string CuttlefishConfig::logcat_path() const {
return (*dictionary_)[kLogcatPath].asString();
}
void CuttlefishConfig::set_logcat_path(const std::string& logcat_path) {
SetPath(kLogcatPath, logcat_path);
}
std::string CuttlefishConfig::launcher_monitor_socket_path() const {
return (*dictionary_)[kLauncherMonitorPath].asString();
}
void CuttlefishConfig::set_launcher_monitor_socket_path(
const std::string& launcher_monitor_path) {
SetPath(kLauncherMonitorPath, launcher_monitor_path);
}
std::string CuttlefishConfig::launcher_log_path() const {
return (*dictionary_)[kLauncherLogPath].asString();
}
void CuttlefishConfig::set_launcher_log_path(
const std::string& launcher_log_path) {
(*dictionary_)[kLauncherLogPath] = launcher_log_path;
}
std::string CuttlefishConfig::mobile_bridge_name() const {
return (*dictionary_)[kMobileBridgeName].asString();
}
void CuttlefishConfig::set_mobile_bridge_name(
const std::string& mobile_bridge_name) {
(*dictionary_)[kMobileBridgeName] = mobile_bridge_name;
}
std::string CuttlefishConfig::wifi_bridge_name() const {
return (*dictionary_)[kWifiBridgeName].asString();
}
void CuttlefishConfig::set_wifi_bridge_name(
const std::string& wifi_bridge_name) {
(*dictionary_)[kWifiBridgeName] = wifi_bridge_name;
}
std::string CuttlefishConfig::wifi_guest_mac_addr() const {
return (*dictionary_)[kWifiGuestMacAddr].asString();
}
void CuttlefishConfig::set_wifi_guest_mac_addr(
const std::string& wifi_guest_mac_addr) {
(*dictionary_)[kWifiGuestMacAddr] = wifi_guest_mac_addr;
}
std::string CuttlefishConfig::wifi_host_mac_addr() const {
return (*dictionary_)[kWifiHostMacAddr].asString();
}
void CuttlefishConfig::set_wifi_host_mac_addr(
const std::string& wifi_host_mac_addr) {
(*dictionary_)[kWifiHostMacAddr] = wifi_host_mac_addr;
}
std::string CuttlefishConfig::mobile_tap_name() const {
return (*dictionary_)[kMobileTapName].asString();
}
void CuttlefishConfig::set_mobile_tap_name(const std::string& mobile_tap_name) {
(*dictionary_)[kMobileTapName] = mobile_tap_name;
}
std::string CuttlefishConfig::wifi_tap_name() const {
return (*dictionary_)[kWifiTapName].asString();
}
void CuttlefishConfig::set_wifi_tap_name(const std::string& wifi_tap_name) {
(*dictionary_)[kWifiTapName] = wifi_tap_name;
}
std::string CuttlefishConfig::entropy_source() const {
return (*dictionary_)[kEntropySource].asString();
}
void CuttlefishConfig::set_entropy_source(const std::string& entropy_source) {
(*dictionary_)[kEntropySource] = entropy_source;
}
int CuttlefishConfig::vsock_guest_cid() const {
return (*dictionary_)[kVsockGuestCid].asInt();
}
void CuttlefishConfig::set_vsock_guest_cid(int vsock_guest_cid) {
(*dictionary_)[kVsockGuestCid] = vsock_guest_cid;
}
std::string CuttlefishConfig::uuid() const {
return (*dictionary_)[kUuid].asString();
}
void CuttlefishConfig::set_uuid(const std::string& uuid) {
(*dictionary_)[kUuid] = uuid;
}
bool CuttlefishConfig::disable_dac_security() const {
return (*dictionary_)[kDisableDacSecurity].asBool();
}
void CuttlefishConfig::set_disable_dac_security(bool disable_dac_security) {
(*dictionary_)[kDisableDacSecurity] = disable_dac_security;
}
void CuttlefishConfig::set_cuttlefish_env_path(const std::string& path) {
SetPath(kCuttlefishEnvPath, path);
}
std::string CuttlefishConfig::cuttlefish_env_path() const {
return (*dictionary_)[kCuttlefishEnvPath].asString();
}
bool CuttlefishConfig::disable_app_armor_security() const {
return (*dictionary_)[kDisableAppArmorSecurity].asBool();
}
void CuttlefishConfig::set_disable_app_armor_security(
bool disable_app_armor_security) {
(*dictionary_)[kDisableAppArmorSecurity] = disable_app_armor_security;
}
std::string CuttlefishConfig::adb_mode() const {
return (*dictionary_)[kAdbMode].asString();
}
void CuttlefishConfig::set_adb_mode(const std::string& mode) {
(*dictionary_)[kAdbMode] = mode;
}
std::string CuttlefishConfig::adb_ip_and_port() const {
return (*dictionary_)[kAdbIPAndPort].asString();
}
void CuttlefishConfig::set_adb_ip_and_port(const std::string& ip_port) {
(*dictionary_)[kAdbIPAndPort] = ip_port;
}
std::string CuttlefishConfig::adb_device_name() const {
if (adb_mode().find("tunnel") != std::string::npos) {
return adb_ip_and_port();
} else if (adb_mode().find("usb") != std::string::npos) {
return serial_number();
}
LOG(ERROR) << "no adb_mode found, returning bad device name";
return "NO_ADB_MODE_SET_NO_VALID_DEVICE_NAME";
}
std::string CuttlefishConfig::device_title() const {
return (*dictionary_)[kDeviceTitle].asString();
}
void CuttlefishConfig::set_device_title(const std::string& title) {
(*dictionary_)[kDeviceTitle] = title;
}
std::string CuttlefishConfig::setupwizard_mode() const {
return (*dictionary_)[kSetupWizardMode].asString();
}
void CuttlefishConfig::set_setupwizard_mode(const std::string& mode) {
(*dictionary_)[kSetupWizardMode] = mode;
}
bool CuttlefishConfig::log_xml() const {
return (*dictionary_)[kLogXml].asBool();
}
void CuttlefishConfig::set_log_xml(bool log_xml) {
(*dictionary_)[kLogXml] = log_xml;
}
std::string CuttlefishConfig::hypervisor_uri() const {
return (*dictionary_)[kHypervisorUri].asString();
}
void CuttlefishConfig::set_hypervisor_uri(const std::string& hypervisor_uri) {
(*dictionary_)[kHypervisorUri] = hypervisor_uri;
}
std::string CuttlefishConfig::qemu_binary() const {
return (*dictionary_)[kQemuBinary].asString();
}
void CuttlefishConfig::set_qemu_binary(const std::string& qemu_binary) {
(*dictionary_)[kQemuBinary] = qemu_binary;
}
// Creates the (initially empty) config object and populates it with values from
// the config file if the CUTTLEFISH_CONFIG_FILE env variable is present.
// Returns nullptr if there was an error loading from file
/*static*/ CuttlefishConfig* CuttlefishConfig::BuildConfigImpl() {
auto config_file_path = cvd::StringFromEnv(kCuttlefishConfigEnvVarName,
vsoc::GetGlobalConfigFileLink());
auto ret = new CuttlefishConfig();
if (ret) {
auto loaded = ret->LoadFromFile(config_file_path.c_str());
if (!loaded) {
delete ret;
return nullptr;
}
}
return ret;
}
/*static*/ CuttlefishConfig* CuttlefishConfig::Get() {
static std::shared_ptr<CuttlefishConfig> config(BuildConfigImpl());
return config.get();
}
CuttlefishConfig::CuttlefishConfig() : dictionary_(new Json::Value()) {}
// Can't use '= default' on the header because the compiler complains of
// Json::Value being an incomplete type
CuttlefishConfig::~CuttlefishConfig() {}
bool CuttlefishConfig::LoadFromFile(const char* file) {
auto real_file_path = cvd::AbsolutePath(file);
if (real_file_path.empty()) {
LOG(ERROR) << "Could not get real path for file " << file;
return false;
}
Json::Reader reader;
std::ifstream ifs(real_file_path);
if (!reader.parse(ifs, *dictionary_)) {
LOG(ERROR) << "Could not read config file " << file << ": "
<< reader.getFormattedErrorMessages();
return false;
}
return true;
}
bool CuttlefishConfig::SaveToFile(const std::string& file) const {
std::ofstream ofs(file);
if (!ofs.is_open()) {
LOG(ERROR) << "Unable to write to file " << file;
return false;
}
ofs << *dictionary_;
return !ofs.fail();
}
std::string CuttlefishConfig::PerInstancePath(const char* file_name) const {
return (instance_dir() + "/") + file_name;
}
std::string CuttlefishConfig::instance_name() const {
return GetPerInstanceDefault("cvd-");
}
int GetInstance() {
static int instance_id = InstanceFromEnvironment();
return instance_id;
}
std::string GetGlobalConfigFileLink() {
return cvd::StringFromEnv("HOME", ".") + "/.cuttlefish_config.json";
}
std::string GetDomain() {
return CuttlefishConfig::Get()->ivshmem_client_socket_path();
}
std::string GetPerInstanceDefault(const char* prefix) {
std::ostringstream stream;
stream << prefix << std::setfill('0') << std::setw(2) << GetInstance();
return stream.str();
}
int GetPerInstanceDefault(int base) { return base + GetInstance() - 1; }
std::string GetDefaultPerInstanceDir() {
std::ostringstream stream;
if (HostSupportsQemuCli()) {
stream << std::getenv("HOME") << "/cuttlefish_runtime";
} else {
stream << "/var/run/libvirt-" << kDefaultUuidPrefix << std::setfill('0')
<< std::setw(2) << GetInstance();
}
return stream.str();
}
std::string GetDefaultMempath() {
return GetPerInstanceDefault("/var/run/shm/cvd-");
}
int GetDefaultPerInstanceVsockCid() {
constexpr int kFirstGuestCid = 3;
return vsoc::HostSupportsVsock() ? GetPerInstanceDefault(kFirstGuestCid) : 0;
}
std::string DefaultHostArtifactsPath(const std::string& file_name) {
return (cvd::StringFromEnv("ANDROID_HOST_OUT",
cvd::StringFromEnv("HOME", ".")) +
"/") +
file_name;
}
std::string DefaultGuestImagePath(const std::string& file_name) {
return (cvd::StringFromEnv("ANDROID_PRODUCT_OUT",
cvd::StringFromEnv("HOME", ".")) +
"/") +
file_name;
}
bool HostSupportsQemuCli() {
static bool supported =
std::system(
"/usr/lib/cuttlefish-common/bin/capability_query.py qemu_cli") == 0;
return supported;
}
bool HostSupportsVsock() {
static bool supported =
std::system(
"/usr/lib/cuttlefish-common/bin/capability_query.py vsock") == 0;
return supported;
}
} // namespace vsoc