1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "host/libs/config/cuttlefish_config.h"
18
19 #include <algorithm>
20 #include <climits>
21 #include <cstdint>
22 #include <cstdlib>
23 #include <cstring>
24 #include <fstream>
25 #include <iomanip>
26 #include <iterator>
27 #include <sstream>
28 #include <string>
29 #include <time.h>
30
31 #include <android-base/strings.h>
32 #include <android-base/logging.h>
33 #include <json/json.h>
34
35 #include "common/libs/utils/environment.h"
36 #include "common/libs/utils/files.h"
37 #include "host/libs/vm_manager/crosvm_manager.h"
38 #include "host/libs/vm_manager/gem5_manager.h"
39 #include "host/libs/vm_manager/qemu_manager.h"
40
41 namespace cuttlefish {
42 namespace {
43
44 const char* kInstances = "instances";
45
46 } // namespace
47
48 const char* const kVhostUserVsockModeAuto = "auto";
49 const char* const kVhostUserVsockModeTrue = "true";
50 const char* const kVhostUserVsockModeFalse = "false";
51
52 const char* const kGpuModeAuto = "auto";
53 const char* const kGpuModeCustom = "custom";
54 const char* const kGpuModeDrmVirgl = "drm_virgl";
55 const char* const kGpuModeGfxstream = "gfxstream";
56 const char* const kGpuModeGfxstreamGuestAngle = "gfxstream_guest_angle";
57 const char* const kGpuModeGfxstreamGuestAngleHostSwiftShader =
58 "gfxstream_guest_angle_host_swiftshader";
59 const char* const kGpuModeGuestSwiftshader = "guest_swiftshader";
60 const char* const kGpuModeNone = "none";
61
62 const char* const kGpuVhostUserModeAuto = "auto";
63 const char* const kGpuVhostUserModeOn = "on";
64 const char* const kGpuVhostUserModeOff = "off";
65
66 const char* const kHwComposerAuto = "auto";
67 const char* const kHwComposerDrm = "drm";
68 const char* const kHwComposerRanchu = "ranchu";
69 const char* const kHwComposerNone = "none";
70
DefaultEnvironmentPath(const char * environment_key,const char * default_value,const char * subpath)71 std::string DefaultEnvironmentPath(const char* environment_key,
72 const char* default_value,
73 const char* subpath) {
74 return StringFromEnv(environment_key, default_value) + "/" + subpath;
75 }
76
IsRestoring(const CuttlefishConfig & config)77 bool IsRestoring(const CuttlefishConfig& config) {
78 return FileExists(config.AssemblyPath("restore"));
79 }
80 ConfigFragment::~ConfigFragment() = default;
81
82 static constexpr char kFragments[] = "fragments";
LoadFragment(ConfigFragment & fragment) const83 bool CuttlefishConfig::LoadFragment(ConfigFragment& fragment) const {
84 if (!dictionary_->isMember(kFragments)) {
85 LOG(ERROR) << "Fragments member was missing";
86 return false;
87 }
88 const Json::Value& json_fragments = (*dictionary_)[kFragments];
89 if (!json_fragments.isMember(fragment.Name())) {
90 LOG(ERROR) << "Could not find a fragment called " << fragment.Name();
91 return false;
92 }
93 return fragment.Deserialize(json_fragments[fragment.Name()]);
94 }
SaveFragment(const ConfigFragment & fragment)95 bool CuttlefishConfig::SaveFragment(const ConfigFragment& fragment) {
96 Json::Value& json_fragments = (*dictionary_)[kFragments];
97 if (json_fragments.isMember(fragment.Name())) {
98 LOG(ERROR) << "Already have a fragment called " << fragment.Name();
99 return false;
100 }
101 json_fragments[fragment.Name()] = fragment.Serialize();
102 return true;
103 }
104
105 static constexpr char kRootDir[] = "root_dir";
root_dir() const106 std::string CuttlefishConfig::root_dir() const {
107 return (*dictionary_)[kRootDir].asString();
108 }
set_root_dir(const std::string & root_dir)109 void CuttlefishConfig::set_root_dir(const std::string& root_dir) {
110 (*dictionary_)[kRootDir] = root_dir;
111 }
112
113 static constexpr char kVmManager[] = "vm_manager";
vm_manager() const114 VmmMode CuttlefishConfig::vm_manager() const {
115 auto str = (*dictionary_)[kVmManager].asString();
116 return ParseVmm(str).value_or(VmmMode::kUnknown);
117 }
set_vm_manager(VmmMode vmm)118 void CuttlefishConfig::set_vm_manager(VmmMode vmm) {
119 (*dictionary_)[kVmManager] = fmt::format("{}", vmm);
120 }
121
122 static constexpr char kApVmManager[] = "ap_vm_manager";
ap_vm_manager() const123 std::string CuttlefishConfig::ap_vm_manager() const {
124 return (*dictionary_)[kApVmManager].asString();
125 }
set_ap_vm_manager(const std::string & name)126 void CuttlefishConfig::set_ap_vm_manager(const std::string& name) {
127 (*dictionary_)[kApVmManager] = name;
128 }
129
StringToSecureHal(std::string mode)130 static SecureHal StringToSecureHal(std::string mode) {
131 std::transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
132 std::unordered_map<std::string, SecureHal> mapping = {
133 {"keymint", SecureHal::HostKeymintSecure},
134 {"host_secure_keymint", SecureHal::HostKeymintSecure},
135 {"host_keymint_secure", SecureHal::HostKeymintSecure},
136 {"guest_gatekeeper_insecure", SecureHal::GuestGatekeeperInsecure},
137 {"guest_insecure_gatekeeper", SecureHal::GuestGatekeeperInsecure},
138 {"guest_insecure_keymint", SecureHal::GuestKeymintInsecure},
139 {"guest_keymint_insecure", SecureHal::GuestKeymintInsecure},
140 {"gatekeeper", SecureHal::HostGatekeeperSecure},
141 {"host_gatekeeper_secure", SecureHal::HostGatekeeperSecure},
142 {"host_secure_gatekeeper", SecureHal::HostGatekeeperSecure},
143 {"host_gatekeeper_insecure", SecureHal::HostGatekeeperInsecure},
144 {"host_insecure_gatekeeper", SecureHal::HostGatekeeperInsecure},
145 {"oemlock", SecureHal::HostOemlockSecure},
146 {"host_oemlock_secure", SecureHal::HostOemlockSecure},
147 {"host_secure_oemlock", SecureHal::HostOemlockSecure},
148 };
149 auto it = mapping.find(mode);
150 return it == mapping.end() ? SecureHal::Unknown : it->second;
151 }
152
153 static constexpr char kSecureHals[] = "secure_hals";
secure_hals() const154 std::set<SecureHal> CuttlefishConfig::secure_hals() const {
155 std::set<SecureHal> args_set;
156 for (auto& hal : (*dictionary_)[kSecureHals]) {
157 args_set.insert(StringToSecureHal(hal.asString()));
158 }
159 return args_set;
160 }
set_secure_hals(const std::set<std::string> & hals)161 void CuttlefishConfig::set_secure_hals(const std::set<std::string>& hals) {
162 Json::Value hals_json_obj(Json::arrayValue);
163 for (const auto& hal : hals) {
164 hals_json_obj.append(hal);
165 }
166 (*dictionary_)[kSecureHals] = hals_json_obj;
167 }
168
169 static constexpr char kCrosvmBinary[] = "crosvm_binary";
crosvm_binary() const170 std::string CuttlefishConfig::crosvm_binary() const {
171 return (*dictionary_)[kCrosvmBinary].asString();
172 }
set_crosvm_binary(const std::string & crosvm_binary)173 void CuttlefishConfig::set_crosvm_binary(const std::string& crosvm_binary) {
174 (*dictionary_)[kCrosvmBinary] = crosvm_binary;
175 }
176
IsCrosvm() const177 bool CuttlefishConfig::IsCrosvm() const {
178 return vm_manager() == VmmMode::kCrosvm;
179 }
180
181 static constexpr char kGem5DebugFlags[] = "gem5_debug_flags";
gem5_debug_flags() const182 std::string CuttlefishConfig::gem5_debug_flags() const {
183 return (*dictionary_)[kGem5DebugFlags].asString();
184 }
set_gem5_debug_flags(const std::string & gem5_debug_flags)185 void CuttlefishConfig::set_gem5_debug_flags(const std::string& gem5_debug_flags) {
186 (*dictionary_)[kGem5DebugFlags] = gem5_debug_flags;
187 }
188
189 static constexpr char kWebRTCCertsDir[] = "webrtc_certs_dir";
set_webrtc_certs_dir(const std::string & certs_dir)190 void CuttlefishConfig::set_webrtc_certs_dir(const std::string& certs_dir) {
191 (*dictionary_)[kWebRTCCertsDir] = certs_dir;
192 }
webrtc_certs_dir() const193 std::string CuttlefishConfig::webrtc_certs_dir() const {
194 return (*dictionary_)[kWebRTCCertsDir].asString();
195 }
196
197 static constexpr char kSigServerPort[] = "webrtc_sig_server_port";
set_sig_server_port(int port)198 void CuttlefishConfig::set_sig_server_port(int port) {
199 (*dictionary_)[kSigServerPort] = port;
200 }
sig_server_port() const201 int CuttlefishConfig::sig_server_port() const {
202 return (*dictionary_)[kSigServerPort].asInt();
203 }
204
205 static constexpr char kSigServerAddress[] = "webrtc_sig_server_addr";
set_sig_server_address(const std::string & addr)206 void CuttlefishConfig::set_sig_server_address(const std::string& addr) {
207 (*dictionary_)[kSigServerAddress] = addr;
208 }
sig_server_address() const209 std::string CuttlefishConfig::sig_server_address() const {
210 return (*dictionary_)[kSigServerAddress].asString();
211 }
212
213 static constexpr char kSigServerPath[] = "webrtc_sig_server_path";
set_sig_server_path(const std::string & path)214 void CuttlefishConfig::set_sig_server_path(const std::string& path) {
215 // Don't use SetPath here, it's a URL path not a file system path
216 (*dictionary_)[kSigServerPath] = path;
217 }
sig_server_path() const218 std::string CuttlefishConfig::sig_server_path() const {
219 return (*dictionary_)[kSigServerPath].asString();
220 }
221
222 static constexpr char kSigServerSecure[] = "webrtc_sig_server_secure";
set_sig_server_secure(bool secure)223 void CuttlefishConfig::set_sig_server_secure(bool secure) {
224 (*dictionary_)[kSigServerSecure] = secure;
225 }
sig_server_secure() const226 bool CuttlefishConfig::sig_server_secure() const {
227 return (*dictionary_)[kSigServerSecure].asBool();
228 }
229
230 static constexpr char kSigServerStrict[] = "webrtc_sig_server_strict";
set_sig_server_strict(bool strict)231 void CuttlefishConfig::set_sig_server_strict(bool strict) {
232 (*dictionary_)[kSigServerStrict] = strict;
233 }
sig_server_strict() const234 bool CuttlefishConfig::sig_server_strict() const {
235 return (*dictionary_)[kSigServerStrict].asBool();
236 }
237
238 static constexpr char kHostToolsVersion[] = "host_tools_version";
set_host_tools_version(const std::map<std::string,uint32_t> & versions)239 void CuttlefishConfig::set_host_tools_version(
240 const std::map<std::string, uint32_t>& versions) {
241 Json::Value json(Json::objectValue);
242 for (const auto& [key, value] : versions) {
243 json[key] = value;
244 }
245 (*dictionary_)[kHostToolsVersion] = json;
246 }
host_tools_version() const247 std::map<std::string, uint32_t> CuttlefishConfig::host_tools_version() const {
248 if (!dictionary_->isMember(kHostToolsVersion)) {
249 return {};
250 }
251 std::map<std::string, uint32_t> versions;
252 const auto& elem = (*dictionary_)[kHostToolsVersion];
253 for (auto it = elem.begin(); it != elem.end(); it++) {
254 versions[it.key().asString()] = it->asUInt();
255 }
256 return versions;
257 }
258
259 static constexpr char kEnableHostUwb[] = "enable_host_uwb";
set_enable_host_uwb(bool enable_host_uwb)260 void CuttlefishConfig::set_enable_host_uwb(bool enable_host_uwb) {
261 (*dictionary_)[kEnableHostUwb] = enable_host_uwb;
262 }
enable_host_uwb() const263 bool CuttlefishConfig::enable_host_uwb() const {
264 return (*dictionary_)[kEnableHostUwb].asBool();
265 }
266
267 static constexpr char kEnableHostUwbConnector[] = "enable_host_uwb_connector";
set_enable_host_uwb_connector(bool enable_host_uwb)268 void CuttlefishConfig::set_enable_host_uwb_connector(bool enable_host_uwb) {
269 (*dictionary_)[kEnableHostUwbConnector] = enable_host_uwb;
270 }
enable_host_uwb_connector() const271 bool CuttlefishConfig::enable_host_uwb_connector() const {
272 return (*dictionary_)[kEnableHostUwbConnector].asBool();
273 }
274
275 static constexpr char kPicaUciPort[] = "pica_uci_port";
pica_uci_port() const276 int CuttlefishConfig::pica_uci_port() const {
277 return (*dictionary_)[kPicaUciPort].asInt();
278 }
set_pica_uci_port(int pica_uci_port)279 void CuttlefishConfig::set_pica_uci_port(int pica_uci_port) {
280 (*dictionary_)[kPicaUciPort] = pica_uci_port;
281 }
282
283 static constexpr char kEnableHostBluetooth[] = "enable_host_bluetooth";
set_enable_host_bluetooth(bool enable_host_bluetooth)284 void CuttlefishConfig::set_enable_host_bluetooth(bool enable_host_bluetooth) {
285 (*dictionary_)[kEnableHostBluetooth] = enable_host_bluetooth;
286 }
enable_host_bluetooth() const287 bool CuttlefishConfig::enable_host_bluetooth() const {
288 return (*dictionary_)[kEnableHostBluetooth].asBool();
289 }
290
291 static constexpr char kEnableHostBluetoothConnector[] =
292 "enable_host_bluetooth_connector";
set_enable_host_bluetooth_connector(bool enable_host_bluetooth)293 void CuttlefishConfig::set_enable_host_bluetooth_connector(bool enable_host_bluetooth) {
294 (*dictionary_)[kEnableHostBluetoothConnector] = enable_host_bluetooth;
295 }
enable_host_bluetooth_connector() const296 bool CuttlefishConfig::enable_host_bluetooth_connector() const {
297 return (*dictionary_)[kEnableHostBluetoothConnector].asBool();
298 }
299
300 static constexpr char kEnableAutomotiveProxy[] = "enable_automotive_proxy";
set_enable_automotive_proxy(bool enable_automotive_proxy)301 void CuttlefishConfig::set_enable_automotive_proxy(
302 bool enable_automotive_proxy) {
303 (*dictionary_)[kEnableAutomotiveProxy] = enable_automotive_proxy;
304 }
enable_automotive_proxy() const305 bool CuttlefishConfig::enable_automotive_proxy() const {
306 return (*dictionary_)[kEnableAutomotiveProxy].asBool();
307 }
308
309 static constexpr char kVhalProxyServerPort[] = "vhal_proxy_server_port";
set_vhal_proxy_server_port(int port)310 void CuttlefishConfig::set_vhal_proxy_server_port(int port) {
311 (*dictionary_)[kVhalProxyServerPort] = port;
312 }
vhal_proxy_server_port() const313 int CuttlefishConfig::vhal_proxy_server_port() const {
314 return (*dictionary_)[kVhalProxyServerPort].asInt();
315 }
316
317 static constexpr char kEnableHostNfc[] = "enable_host_nfc";
set_enable_host_nfc(bool enable_host_nfc)318 void CuttlefishConfig::set_enable_host_nfc(bool enable_host_nfc) {
319 (*dictionary_)[kEnableHostNfc] = enable_host_nfc;
320 }
enable_host_nfc() const321 bool CuttlefishConfig::enable_host_nfc() const {
322 return (*dictionary_)[kEnableHostNfc].asBool();
323 }
324
325 static constexpr char kEnableHostNfcConnector[] = "enable_host_nfc_connector";
set_enable_host_nfc_connector(bool enable_host_nfc)326 void CuttlefishConfig::set_enable_host_nfc_connector(bool enable_host_nfc) {
327 (*dictionary_)[kEnableHostNfcConnector] = enable_host_nfc;
328 }
enable_host_nfc_connector() const329 bool CuttlefishConfig::enable_host_nfc_connector() const {
330 return (*dictionary_)[kEnableHostNfcConnector].asBool();
331 }
332
333 static constexpr char kCasimirInstanceNum[] = "casimir_instance_num";
set_casimir_instance_num(int casimir_instance_num)334 void CuttlefishConfig::set_casimir_instance_num(int casimir_instance_num) {
335 (*dictionary_)[kCasimirInstanceNum] = casimir_instance_num;
336 }
casimir_instance_num() const337 int CuttlefishConfig::casimir_instance_num() const {
338 return (*dictionary_)[kCasimirInstanceNum].asInt();
339 }
340
341 static constexpr char kCasimirArgs[] = "casimir_args";
set_casimir_args(const std::string & casimir_args)342 void CuttlefishConfig::set_casimir_args(const std::string& casimir_args) {
343 Json::Value args_json_obj(Json::arrayValue);
344 for (const auto& arg : android::base::Split(casimir_args, " ")) {
345 if (!arg.empty()) {
346 args_json_obj.append(arg);
347 }
348 }
349 (*dictionary_)[kCasimirArgs] = args_json_obj;
350 }
casimir_args() const351 std::vector<std::string> CuttlefishConfig::casimir_args() const {
352 std::vector<std::string> casimir_args;
353 for (const Json::Value& arg : (*dictionary_)[kCasimirArgs]) {
354 casimir_args.push_back(arg.asString());
355 }
356 return casimir_args;
357 }
358
359 static constexpr char kCasimirNciPort[] = "casimir_nci_port";
set_casimir_nci_port(int port)360 void CuttlefishConfig::set_casimir_nci_port(int port) {
361 (*dictionary_)[kCasimirNciPort] = port;
362 }
casimir_nci_port() const363 int CuttlefishConfig::casimir_nci_port() const {
364 return (*dictionary_)[kCasimirNciPort].asInt();
365 }
366
367 static constexpr char kCasimirRfPort[] = "casimir_rf_port";
set_casimir_rf_port(int port)368 void CuttlefishConfig::set_casimir_rf_port(int port) {
369 (*dictionary_)[kCasimirRfPort] = port;
370 }
casimir_rf_port() const371 int CuttlefishConfig::casimir_rf_port() const {
372 return (*dictionary_)[kCasimirRfPort].asInt();
373 }
374
375 static constexpr char kNetsimRadios[] = "netsim_radios";
376
netsim_radio_enable(NetsimRadio flag)377 void CuttlefishConfig::netsim_radio_enable(NetsimRadio flag) {
378 if (dictionary_->isMember(kNetsimRadios)) {
379 // OR the radio to current set of radios
380 (*dictionary_)[kNetsimRadios] = (*dictionary_)[kNetsimRadios].asInt() | flag;
381 } else {
382 (*dictionary_)[kNetsimRadios] = flag;
383 }
384 }
385
netsim_radio_enabled(NetsimRadio flag) const386 bool CuttlefishConfig::netsim_radio_enabled(NetsimRadio flag) const {
387 return (*dictionary_)[kNetsimRadios].asInt() & flag;
388 }
389
390 static constexpr char kNetsimInstanceNum[] = "netsim_instance_num";
netsim_instance_num() const391 int CuttlefishConfig::netsim_instance_num() const {
392 return (*dictionary_)[kNetsimInstanceNum].asInt();
393 }
set_netsim_instance_num(int netsim_instance_num)394 void CuttlefishConfig::set_netsim_instance_num(int netsim_instance_num) {
395 (*dictionary_)[kNetsimInstanceNum] = netsim_instance_num;
396 }
397
398 static constexpr char kNetsimConnectorInstanceNum[] =
399 "netsim_connector_instance_num";
netsim_connector_instance_num() const400 int CuttlefishConfig::netsim_connector_instance_num() const {
401 return (*dictionary_)[kNetsimConnectorInstanceNum].asInt();
402 }
set_netsim_connector_instance_num(int netsim_instance_num)403 void CuttlefishConfig::set_netsim_connector_instance_num(
404 int netsim_instance_num) {
405 (*dictionary_)[kNetsimConnectorInstanceNum] = netsim_instance_num;
406 }
407
408 static constexpr char kNetsimArgs[] = "netsim_args";
set_netsim_args(const std::string & netsim_args)409 void CuttlefishConfig::set_netsim_args(const std::string& netsim_args) {
410 Json::Value args_json_obj(Json::arrayValue);
411 for (const auto& arg : android::base::Tokenize(netsim_args, " ")) {
412 args_json_obj.append(arg);
413 }
414 (*dictionary_)[kNetsimArgs] = args_json_obj;
415 }
netsim_args() const416 std::vector<std::string> CuttlefishConfig::netsim_args() const {
417 std::vector<std::string> netsim_args;
418 for (const Json::Value& arg : (*dictionary_)[kNetsimArgs]) {
419 netsim_args.push_back(arg.asString());
420 }
421 return netsim_args;
422 }
423
424 static constexpr char kEnableMetrics[] = "enable_metrics";
set_enable_metrics(std::string enable_metrics)425 void CuttlefishConfig::set_enable_metrics(std::string enable_metrics) {
426 (*dictionary_)[kEnableMetrics] =
427 static_cast<int>(cuttlefish::CuttlefishConfig::Answer::kUnknown);
428 if (!enable_metrics.empty()) {
429 switch (enable_metrics.at(0)) {
430 case 'y':
431 case 'Y':
432 (*dictionary_)[kEnableMetrics] =
433 static_cast<int>(cuttlefish::CuttlefishConfig::Answer::kYes);
434 break;
435 case 'n':
436 case 'N':
437 (*dictionary_)[kEnableMetrics] =
438 static_cast<int>(cuttlefish::CuttlefishConfig::Answer::kNo);
439 break;
440 }
441 }
442 }
443
444 // validate the casting and conversion from json configs to
445 // CuttlefishConfig::Answer class
IsValidMetricsConfigs(int value)446 bool IsValidMetricsConfigs(int value) {
447 return value == static_cast<int>(CuttlefishConfig::Answer::kUnknown) ||
448 value == static_cast<int>(CuttlefishConfig::Answer::kNo) ||
449 value == static_cast<int>(CuttlefishConfig::Answer::kYes);
450 }
451
enable_metrics() const452 CuttlefishConfig::Answer CuttlefishConfig::enable_metrics() const {
453 int value = (*dictionary_)[kEnableMetrics].asInt();
454 if (!IsValidMetricsConfigs(value)) {
455 LOG(ERROR) << "Invalid integer value for Answer enum";
456 return static_cast<Answer>(CuttlefishConfig::Answer::kUnknown);
457 }
458 return static_cast<Answer>(value);
459 }
460
461 static constexpr char kMetricsBinary[] = "metrics_binary";
set_metrics_binary(const std::string & metrics_binary)462 void CuttlefishConfig::set_metrics_binary(const std::string& metrics_binary) {
463 (*dictionary_)[kMetricsBinary] = metrics_binary;
464 }
metrics_binary() const465 std::string CuttlefishConfig::metrics_binary() const {
466 return (*dictionary_)[kMetricsBinary].asString();
467 }
468
469 static constexpr char kExtraKernelCmdline[] = "extra_kernel_cmdline";
set_extra_kernel_cmdline(const std::string & extra_cmdline)470 void CuttlefishConfig::set_extra_kernel_cmdline(
471 const std::string& extra_cmdline) {
472 Json::Value args_json_obj(Json::arrayValue);
473 for (const auto& arg : android::base::Split(extra_cmdline, " ")) {
474 args_json_obj.append(arg);
475 }
476 (*dictionary_)[kExtraKernelCmdline] = args_json_obj;
477 }
extra_kernel_cmdline() const478 std::vector<std::string> CuttlefishConfig::extra_kernel_cmdline() const {
479 std::vector<std::string> cmdline;
480 for (const Json::Value& arg : (*dictionary_)[kExtraKernelCmdline]) {
481 cmdline.push_back(arg.asString());
482 }
483 return cmdline;
484 }
485
486 static constexpr char kVirtioMac80211Hwsim[] = "virtio_mac80211_hwsim";
set_virtio_mac80211_hwsim(bool virtio_mac80211_hwsim)487 void CuttlefishConfig::set_virtio_mac80211_hwsim(bool virtio_mac80211_hwsim) {
488 (*dictionary_)[kVirtioMac80211Hwsim] = virtio_mac80211_hwsim;
489 }
virtio_mac80211_hwsim() const490 bool CuttlefishConfig::virtio_mac80211_hwsim() const {
491 return (*dictionary_)[kVirtioMac80211Hwsim].asBool();
492 }
493
494 static constexpr char kApRootfsImage[] = "ap_rootfs_image";
ap_rootfs_image() const495 std::string CuttlefishConfig::ap_rootfs_image() const {
496 return (*dictionary_)[kApRootfsImage].asString();
497 }
set_ap_rootfs_image(const std::string & ap_rootfs_image)498 void CuttlefishConfig::set_ap_rootfs_image(const std::string& ap_rootfs_image) {
499 (*dictionary_)[kApRootfsImage] = ap_rootfs_image;
500 }
501
502 static constexpr char kApKernelImage[] = "ap_kernel_image";
ap_kernel_image() const503 std::string CuttlefishConfig::ap_kernel_image() const {
504 return (*dictionary_)[kApKernelImage].asString();
505 }
set_ap_kernel_image(const std::string & ap_kernel_image)506 void CuttlefishConfig::set_ap_kernel_image(const std::string& ap_kernel_image) {
507 (*dictionary_)[kApKernelImage] = ap_kernel_image;
508 }
509
510 static constexpr char kRootcanalArgs[] = "rootcanal_args";
set_rootcanal_args(const std::string & rootcanal_args)511 void CuttlefishConfig::set_rootcanal_args(const std::string& rootcanal_args) {
512 Json::Value args_json_obj(Json::arrayValue);
513 for (const auto& arg : android::base::Split(rootcanal_args, " ")) {
514 args_json_obj.append(arg);
515 }
516 (*dictionary_)[kRootcanalArgs] = args_json_obj;
517 }
rootcanal_args() const518 std::vector<std::string> CuttlefishConfig::rootcanal_args() const {
519 std::vector<std::string> rootcanal_args;
520 for (const Json::Value& arg : (*dictionary_)[kRootcanalArgs]) {
521 rootcanal_args.push_back(arg.asString());
522 }
523 return rootcanal_args;
524 }
525
526 static constexpr char kRootcanalHciPort[] = "rootcanal_hci_port";
rootcanal_hci_port() const527 int CuttlefishConfig::rootcanal_hci_port() const {
528 return (*dictionary_)[kRootcanalHciPort].asInt();
529 }
set_rootcanal_hci_port(int rootcanal_hci_port)530 void CuttlefishConfig::set_rootcanal_hci_port(int rootcanal_hci_port) {
531 (*dictionary_)[kRootcanalHciPort] = rootcanal_hci_port;
532 }
533
534 static constexpr char kRootcanalLinkPort[] = "rootcanal_link_port";
rootcanal_link_port() const535 int CuttlefishConfig::rootcanal_link_port() const {
536 return (*dictionary_)[kRootcanalLinkPort].asInt();
537 }
set_rootcanal_link_port(int rootcanal_link_port)538 void CuttlefishConfig::set_rootcanal_link_port(int rootcanal_link_port) {
539 (*dictionary_)[kRootcanalLinkPort] = rootcanal_link_port;
540 }
541
542 static constexpr char kRootcanalLinkBlePort[] = "rootcanal_link_ble_port";
rootcanal_link_ble_port() const543 int CuttlefishConfig::rootcanal_link_ble_port() const {
544 return (*dictionary_)[kRootcanalLinkBlePort].asInt();
545 }
set_rootcanal_link_ble_port(int rootcanal_link_ble_port)546 void CuttlefishConfig::set_rootcanal_link_ble_port(
547 int rootcanal_link_ble_port) {
548 (*dictionary_)[kRootcanalLinkBlePort] = rootcanal_link_ble_port;
549 }
550
551 static constexpr char kRootcanalTestPort[] = "rootcanal_test_port";
rootcanal_test_port() const552 int CuttlefishConfig::rootcanal_test_port() const {
553 return (*dictionary_)[kRootcanalTestPort].asInt();
554 }
set_rootcanal_test_port(int rootcanal_test_port)555 void CuttlefishConfig::set_rootcanal_test_port(int rootcanal_test_port) {
556 (*dictionary_)[kRootcanalTestPort] = rootcanal_test_port;
557 }
558
559 static constexpr char kSnapshotPath[] = "snapshot_path";
snapshot_path() const560 std::string CuttlefishConfig::snapshot_path() const {
561 return (*dictionary_)[kSnapshotPath].asString();
562 }
set_snapshot_path(const std::string & snapshot_path)563 void CuttlefishConfig::set_snapshot_path(const std::string& snapshot_path) {
564 (*dictionary_)[kSnapshotPath] = snapshot_path;
565 }
566
567 static constexpr char kStracedExecutables[] = "straced_host_executables";
set_straced_host_executables(const std::set<std::string> & straced_host_executables)568 void CuttlefishConfig::set_straced_host_executables(
569 const std::set<std::string>& straced_host_executables) {
570 Json::Value args_json_obj(Json::arrayValue);
571 for (const auto& arg : straced_host_executables) {
572 args_json_obj.append(arg);
573 }
574 (*dictionary_)[kStracedExecutables] = args_json_obj;
575 }
straced_host_executables() const576 std::set<std::string> CuttlefishConfig::straced_host_executables() const {
577 std::set<std::string> straced_host_executables;
578 for (const Json::Value& arg : (*dictionary_)[kStracedExecutables]) {
579 straced_host_executables.insert(arg.asString());
580 }
581 return straced_host_executables;
582 }
583
584 static constexpr char kHostSandbox[] = "host_sandbox";
host_sandbox() const585 bool CuttlefishConfig::host_sandbox() const {
586 return (*dictionary_)[kHostSandbox].asBool();
587 }
set_host_sandbox(bool host_sandbox)588 void CuttlefishConfig::set_host_sandbox(bool host_sandbox) {
589 (*dictionary_)[kHostSandbox] = host_sandbox;
590 }
591
BuildConfigImpl(const std::string & path)592 /*static*/ CuttlefishConfig* CuttlefishConfig::BuildConfigImpl(
593 const std::string& path) {
594 auto ret = new CuttlefishConfig();
595 if (ret) {
596 auto loaded = ret->LoadFromFile(path.c_str());
597 if (!loaded) {
598 delete ret;
599 return nullptr;
600 }
601 }
602 return ret;
603 }
604
605 /*static*/ std::unique_ptr<const CuttlefishConfig>
GetFromFile(const std::string & path)606 CuttlefishConfig::GetFromFile(const std::string& path) {
607 return std::unique_ptr<const CuttlefishConfig>(BuildConfigImpl(path));
608 }
609
610 // Creates the (initially empty) config object and populates it with values from
611 // the config file if the CUTTLEFISH_CONFIG_FILE env variable is present.
612 // Returns nullptr if there was an error loading from file
Get()613 /*static*/ const CuttlefishConfig* CuttlefishConfig::Get() {
614 auto config_file_path =
615 StringFromEnv(kCuttlefishConfigEnvVarName, GetGlobalConfigFileLink());
616 static std::shared_ptr<CuttlefishConfig> config(
617 BuildConfigImpl(config_file_path));
618 return config.get();
619 }
620
ConfigExists()621 /*static*/ bool CuttlefishConfig::ConfigExists() {
622 auto config_file_path = StringFromEnv(kCuttlefishConfigEnvVarName,
623 GetGlobalConfigFileLink());
624 auto real_file_path = AbsolutePath(config_file_path.c_str());
625 return FileExists(real_file_path);
626 }
627
CuttlefishConfig()628 CuttlefishConfig::CuttlefishConfig() : dictionary_(new Json::Value()) {}
629 // Can't use '= default' on the header because the compiler complains of
630 // Json::Value being an incomplete type
631 CuttlefishConfig::~CuttlefishConfig() = default;
632
633 CuttlefishConfig::CuttlefishConfig(CuttlefishConfig&&) = default;
634 CuttlefishConfig& CuttlefishConfig::operator=(CuttlefishConfig&&) = default;
635
LoadFromFile(const char * file)636 bool CuttlefishConfig::LoadFromFile(const char* file) {
637 auto real_file_path = AbsolutePath(file);
638 if (real_file_path.empty()) {
639 LOG(ERROR) << "Could not get real path for file " << file;
640 return false;
641 }
642 Json::CharReaderBuilder builder;
643 std::ifstream ifs(real_file_path);
644 std::string errorMessage;
645 if (!Json::parseFromStream(builder, ifs, dictionary_.get(), &errorMessage)) {
646 LOG(ERROR) << "Could not read config file " << file << ": " << errorMessage;
647 return false;
648 }
649 return true;
650 }
SaveToFile(const std::string & file) const651 bool CuttlefishConfig::SaveToFile(const std::string& file) const {
652 std::ofstream ofs(file);
653 if (!ofs.is_open()) {
654 LOG(ERROR) << "Unable to write to file " << file;
655 return false;
656 }
657 ofs << *dictionary_;
658 return !ofs.fail();
659 }
660
instances_dir() const661 std::string CuttlefishConfig::instances_dir() const {
662 return AbsolutePath(root_dir() + "/instances");
663 }
664
InstancesPath(const std::string & file_name) const665 std::string CuttlefishConfig::InstancesPath(
666 const std::string& file_name) const {
667 return AbsolutePath(instances_dir() + "/" + file_name);
668 }
669
assembly_dir() const670 std::string CuttlefishConfig::assembly_dir() const {
671 return AbsolutePath(root_dir() + "/assembly");
672 }
673
AssemblyPath(const std::string & file_name) const674 std::string CuttlefishConfig::AssemblyPath(
675 const std::string& file_name) const {
676 return AbsolutePath(assembly_dir() + "/" + file_name);
677 }
678
instances_uds_dir() const679 std::string CuttlefishConfig::instances_uds_dir() const {
680 // Try to use /tmp/cf_avd_{uid}/ for UDS directory.
681 // If it fails, use HOME directory(legacy) instead.
682
683 auto defaultPath = AbsolutePath("/tmp/cf_avd_" + std::to_string(getuid()));
684
685 if (!DirectoryExists(defaultPath) ||
686 CanAccess(defaultPath, R_OK | W_OK | X_OK)) {
687 return defaultPath;
688 }
689
690 return instances_dir();
691 }
692
InstancesUdsPath(const std::string & file_name) const693 std::string CuttlefishConfig::InstancesUdsPath(
694 const std::string& file_name) const {
695 return AbsolutePath(instances_uds_dir() + "/" + file_name);
696 }
697
environments_dir() const698 std::string CuttlefishConfig::environments_dir() const {
699 return AbsolutePath(root_dir() + "/environments");
700 }
701
EnvironmentsPath(const std::string & file_name) const702 std::string CuttlefishConfig::EnvironmentsPath(
703 const std::string& file_name) const {
704 return AbsolutePath(environments_dir() + "/" + file_name);
705 }
706
environments_uds_dir() const707 std::string CuttlefishConfig::environments_uds_dir() const {
708 // Try to use /tmp/cf_env_{uid}/ for UDS directory.
709 // If it fails, use HOME directory instead.
710
711 auto defaultPath = AbsolutePath("/tmp/cf_env_" + std::to_string(getuid()));
712
713 if (!DirectoryExists(defaultPath) ||
714 CanAccess(defaultPath, R_OK | W_OK | X_OK)) {
715 return defaultPath;
716 }
717
718 return environments_dir();
719 }
720
EnvironmentsUdsPath(const std::string & file_name) const721 std::string CuttlefishConfig::EnvironmentsUdsPath(
722 const std::string& file_name) const {
723 return AbsolutePath(environments_uds_dir() + "/" + file_name);
724 }
725
ForInstance(int num)726 CuttlefishConfig::MutableInstanceSpecific CuttlefishConfig::ForInstance(int num) {
727 return MutableInstanceSpecific(this, std::to_string(num));
728 }
729
ForInstance(int num) const730 CuttlefishConfig::InstanceSpecific CuttlefishConfig::ForInstance(int num) const {
731 return InstanceSpecific(this, std::to_string(num));
732 }
733
ForInstanceName(const std::string & name) const734 CuttlefishConfig::InstanceSpecific CuttlefishConfig::ForInstanceName(
735 const std::string& name) const {
736 return ForInstance(InstanceFromString(name));
737 }
738
ForDefaultInstance() const739 CuttlefishConfig::InstanceSpecific CuttlefishConfig::ForDefaultInstance() const {
740 return ForInstance(GetInstance());
741 }
742
Instances() const743 std::vector<CuttlefishConfig::InstanceSpecific> CuttlefishConfig::Instances() const {
744 const auto& json = (*dictionary_)[kInstances];
745 std::vector<CuttlefishConfig::InstanceSpecific> instances;
746 for (const auto& name : json.getMemberNames()) {
747 instances.push_back(CuttlefishConfig::InstanceSpecific(this, name));
748 }
749 return instances;
750 }
751
instance_dirs() const752 std::vector<std::string> CuttlefishConfig::instance_dirs() const {
753 std::vector<std::string> result;
754 for (const auto& instance : Instances()) {
755 result.push_back(instance.instance_dir());
756 result.push_back(instance.instance_uds_dir());
757 }
758 return result;
759 }
760
761 static constexpr char kInstanceNames[] = "instance_names";
set_instance_names(const std::vector<std::string> & instance_names)762 void CuttlefishConfig::set_instance_names(
763 const std::vector<std::string>& instance_names) {
764 Json::Value args_json_obj(Json::arrayValue);
765 for (const auto& name : instance_names) {
766 args_json_obj.append(name);
767 }
768 (*dictionary_)[kInstanceNames] = args_json_obj;
769 }
instance_names() const770 std::vector<std::string> CuttlefishConfig::instance_names() const {
771 // NOTE: The structure of this field needs to remain stable, since
772 // cvd_server may call this on config JSON files from various builds.
773 //
774 // This info is duplicated into its own field here so it is simpler
775 // to keep stable, rather than parsing from Instances()::instance_name.
776 //
777 // Any non-stable changes must be accompanied by an uprev to the
778 // cvd_server major version.
779 std::vector<std::string> names;
780 for (const Json::Value& name : (*dictionary_)[kInstanceNames]) {
781 names.push_back(name.asString());
782 }
783 return names;
784 }
785
ForEnvironment(const std::string & envName)786 CuttlefishConfig::MutableEnvironmentSpecific CuttlefishConfig::ForEnvironment(
787 const std::string& envName) {
788 return MutableEnvironmentSpecific(this, envName);
789 }
790
ForEnvironment(const std::string & envName) const791 CuttlefishConfig::EnvironmentSpecific CuttlefishConfig::ForEnvironment(
792 const std::string& envName) const {
793 return EnvironmentSpecific(this, envName);
794 }
795
796 CuttlefishConfig::MutableEnvironmentSpecific
ForDefaultEnvironment()797 CuttlefishConfig::ForDefaultEnvironment() {
798 return MutableEnvironmentSpecific(this,
799 ForDefaultInstance().environment_name());
800 }
801
ForDefaultEnvironment() const802 CuttlefishConfig::EnvironmentSpecific CuttlefishConfig::ForDefaultEnvironment()
803 const {
804 return EnvironmentSpecific(this, ForDefaultInstance().environment_name());
805 }
806
environment_dirs() const807 std::vector<std::string> CuttlefishConfig::environment_dirs() const {
808 auto environment = ForDefaultEnvironment();
809
810 std::vector<std::string> result;
811
812 result.push_back(environment.environment_dir());
813 result.push_back(environment.environment_uds_dir());
814
815 return result;
816 }
817
818 } // namespace cuttlefish
819