• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 kGpuModeGfxstreamGuestAngleHostLavapipe =
60     "gfxstream_guest_angle_host_lavapipe";
61 const char* const kGpuModeGuestSwiftshader = "guest_swiftshader";
62 const char* const kGpuModeNone = "none";
63 
64 const char* const kGpuVhostUserModeAuto = "auto";
65 const char* const kGpuVhostUserModeOn = "on";
66 const char* const kGpuVhostUserModeOff = "off";
67 
68 const char* const kHwComposerAuto = "auto";
69 const char* const kHwComposerDrm = "drm_hwcomposer";
70 const char* const kHwComposerRanchu = "ranchu";
71 const char* const kHwComposerNone = "none";
72 
DefaultEnvironmentPath(const char * environment_key,const char * default_value,const char * subpath)73 std::string DefaultEnvironmentPath(const char* environment_key,
74                                    const char* default_value,
75                                    const char* subpath) {
76   return StringFromEnv(environment_key, default_value) + "/" + subpath;
77 }
78 
IsRestoring(const CuttlefishConfig & config)79 bool IsRestoring(const CuttlefishConfig& config) {
80   return FileExists(config.AssemblyPath("restore"));
81 }
82 ConfigFragment::~ConfigFragment() = default;
83 
84 static constexpr char kFragments[] = "fragments";
LoadFragment(ConfigFragment & fragment) const85 bool CuttlefishConfig::LoadFragment(ConfigFragment& fragment) const {
86   if (!dictionary_->isMember(kFragments)) {
87     LOG(ERROR) << "Fragments member was missing";
88     return false;
89   }
90   const Json::Value& json_fragments = (*dictionary_)[kFragments];
91   if (!json_fragments.isMember(fragment.Name())) {
92     LOG(ERROR) << "Could not find a fragment called " << fragment.Name();
93     return false;
94   }
95   return fragment.Deserialize(json_fragments[fragment.Name()]);
96 }
SaveFragment(const ConfigFragment & fragment)97 bool CuttlefishConfig::SaveFragment(const ConfigFragment& fragment) {
98   Json::Value& json_fragments = (*dictionary_)[kFragments];
99   if (json_fragments.isMember(fragment.Name())) {
100     LOG(ERROR) << "Already have a fragment called " << fragment.Name();
101     return false;
102   }
103   json_fragments[fragment.Name()] = fragment.Serialize();
104   return true;
105 }
106 
107 static constexpr char kRootDir[] = "root_dir";
root_dir() const108 std::string CuttlefishConfig::root_dir() const {
109   return (*dictionary_)[kRootDir].asString();
110 }
set_root_dir(const std::string & root_dir)111 void CuttlefishConfig::set_root_dir(const std::string& root_dir) {
112   (*dictionary_)[kRootDir] = root_dir;
113 }
114 
115 static constexpr char kVmManager[] = "vm_manager";
vm_manager() const116 VmmMode CuttlefishConfig::vm_manager() const {
117   auto str = (*dictionary_)[kVmManager].asString();
118   return ParseVmm(str).value_or(VmmMode::kUnknown);
119 }
set_vm_manager(VmmMode vmm)120 void CuttlefishConfig::set_vm_manager(VmmMode vmm) {
121   (*dictionary_)[kVmManager] = fmt::format("{}", vmm);
122 }
123 
124 static constexpr char kApVmManager[] = "ap_vm_manager";
ap_vm_manager() const125 std::string CuttlefishConfig::ap_vm_manager() const {
126   return (*dictionary_)[kApVmManager].asString();
127 }
set_ap_vm_manager(const std::string & name)128 void CuttlefishConfig::set_ap_vm_manager(const std::string& name) {
129   (*dictionary_)[kApVmManager] = name;
130 }
131 
132 static constexpr char kSecureHals[] = "secure_hals";
secure_hals() const133 Result<std::set<SecureHal>> CuttlefishConfig::secure_hals() const {
134   std::set<SecureHal> args_set;
135   for (auto& hal : (*dictionary_)[kSecureHals]) {
136     args_set.insert(CF_EXPECT(ParseSecureHal(hal.asString())));
137   }
138   return args_set;
139 }
set_secure_hals(const std::set<SecureHal> & hals)140 void CuttlefishConfig::set_secure_hals(const std::set<SecureHal>& hals) {
141   Json::Value hals_json_obj(Json::arrayValue);
142   for (const auto& hal : hals) {
143     hals_json_obj.append(ToString(hal));
144   }
145   (*dictionary_)[kSecureHals] = hals_json_obj;
146 }
147 
148 static constexpr char kCrosvmBinary[] = "crosvm_binary";
crosvm_binary() const149 std::string CuttlefishConfig::crosvm_binary() const {
150   return (*dictionary_)[kCrosvmBinary].asString();
151 }
set_crosvm_binary(const std::string & crosvm_binary)152 void CuttlefishConfig::set_crosvm_binary(const std::string& crosvm_binary) {
153   (*dictionary_)[kCrosvmBinary] = crosvm_binary;
154 }
155 
IsCrosvm() const156 bool CuttlefishConfig::IsCrosvm() const {
157   return vm_manager() == VmmMode::kCrosvm;
158 }
159 
160 static constexpr char kGem5DebugFlags[] = "gem5_debug_flags";
gem5_debug_flags() const161 std::string CuttlefishConfig::gem5_debug_flags() const {
162   return (*dictionary_)[kGem5DebugFlags].asString();
163 }
set_gem5_debug_flags(const std::string & gem5_debug_flags)164 void CuttlefishConfig::set_gem5_debug_flags(const std::string& gem5_debug_flags) {
165   (*dictionary_)[kGem5DebugFlags] = gem5_debug_flags;
166 }
167 
168 static constexpr char kWebRTCCertsDir[] = "webrtc_certs_dir";
set_webrtc_certs_dir(const std::string & certs_dir)169 void CuttlefishConfig::set_webrtc_certs_dir(const std::string& certs_dir) {
170   (*dictionary_)[kWebRTCCertsDir] = certs_dir;
171 }
webrtc_certs_dir() const172 std::string CuttlefishConfig::webrtc_certs_dir() const {
173   return (*dictionary_)[kWebRTCCertsDir].asString();
174 }
175 
176 static constexpr char kSigServerPort[] = "webrtc_sig_server_port";
set_sig_server_port(int port)177 void CuttlefishConfig::set_sig_server_port(int port) {
178   (*dictionary_)[kSigServerPort] = port;
179 }
sig_server_port() const180 int CuttlefishConfig::sig_server_port() const {
181   return (*dictionary_)[kSigServerPort].asInt();
182 }
183 
184 static constexpr char kSigServerAddress[] = "webrtc_sig_server_addr";
set_sig_server_address(const std::string & addr)185 void CuttlefishConfig::set_sig_server_address(const std::string& addr) {
186   (*dictionary_)[kSigServerAddress] = addr;
187 }
sig_server_address() const188 std::string CuttlefishConfig::sig_server_address() const {
189   return (*dictionary_)[kSigServerAddress].asString();
190 }
191 
192 static constexpr char kSigServerPath[] = "webrtc_sig_server_path";
set_sig_server_path(const std::string & path)193 void CuttlefishConfig::set_sig_server_path(const std::string& path) {
194   // Don't use SetPath here, it's a URL path not a file system path
195   (*dictionary_)[kSigServerPath] = path;
196 }
sig_server_path() const197 std::string CuttlefishConfig::sig_server_path() const {
198   return (*dictionary_)[kSigServerPath].asString();
199 }
200 
201 static constexpr char kSigServerSecure[] = "webrtc_sig_server_secure";
set_sig_server_secure(bool secure)202 void CuttlefishConfig::set_sig_server_secure(bool secure) {
203   (*dictionary_)[kSigServerSecure] = secure;
204 }
sig_server_secure() const205 bool CuttlefishConfig::sig_server_secure() const {
206   return (*dictionary_)[kSigServerSecure].asBool();
207 }
208 
209 static constexpr char kSigServerStrict[] = "webrtc_sig_server_strict";
set_sig_server_strict(bool strict)210 void CuttlefishConfig::set_sig_server_strict(bool strict) {
211   (*dictionary_)[kSigServerStrict] = strict;
212 }
sig_server_strict() const213 bool CuttlefishConfig::sig_server_strict() const {
214   return (*dictionary_)[kSigServerStrict].asBool();
215 }
216 
OverlaysEnabled() const217 bool CuttlefishConfig::OverlaysEnabled() const {
218   for (const auto& curinstance : Instances()) {
219     if (curinstance.display_configs().size() > 0) {
220       for (const auto& curdisplay : curinstance.display_configs()) {
221         if (curdisplay.overlays.length() > 0) {
222           return true;
223         }
224       }
225     }
226   }
227   return false;
228 }
229 
230 static constexpr char kHostToolsVersion[] = "host_tools_version";
set_host_tools_version(const std::map<std::string,uint32_t> & versions)231 void CuttlefishConfig::set_host_tools_version(
232     const std::map<std::string, uint32_t>& versions) {
233   Json::Value json(Json::objectValue);
234   for (const auto& [key, value] : versions) {
235     json[key] = value;
236   }
237   (*dictionary_)[kHostToolsVersion] = json;
238 }
host_tools_version() const239 std::map<std::string, uint32_t> CuttlefishConfig::host_tools_version() const {
240   if (!dictionary_->isMember(kHostToolsVersion)) {
241     return {};
242   }
243   std::map<std::string, uint32_t> versions;
244   const auto& elem = (*dictionary_)[kHostToolsVersion];
245   for (auto it = elem.begin(); it != elem.end(); it++) {
246     versions[it.key().asString()] = it->asUInt();
247   }
248   return versions;
249 }
250 
251 static constexpr char kEnableHostUwb[] = "enable_host_uwb";
set_enable_host_uwb(bool enable_host_uwb)252 void CuttlefishConfig::set_enable_host_uwb(bool enable_host_uwb) {
253   (*dictionary_)[kEnableHostUwb] = enable_host_uwb;
254 }
enable_host_uwb() const255 bool CuttlefishConfig::enable_host_uwb() const {
256   return (*dictionary_)[kEnableHostUwb].asBool();
257 }
258 
259 static constexpr char kEnableHostUwbConnector[] = "enable_host_uwb_connector";
set_enable_host_uwb_connector(bool enable_host_uwb)260 void CuttlefishConfig::set_enable_host_uwb_connector(bool enable_host_uwb) {
261   (*dictionary_)[kEnableHostUwbConnector] = enable_host_uwb;
262 }
enable_host_uwb_connector() const263 bool CuttlefishConfig::enable_host_uwb_connector() const {
264   return (*dictionary_)[kEnableHostUwbConnector].asBool();
265 }
266 
267 static constexpr char kPicaUciPort[] = "pica_uci_port";
pica_uci_port() const268 int CuttlefishConfig::pica_uci_port() const {
269   return (*dictionary_)[kPicaUciPort].asInt();
270 }
set_pica_uci_port(int pica_uci_port)271 void CuttlefishConfig::set_pica_uci_port(int pica_uci_port) {
272   (*dictionary_)[kPicaUciPort] = pica_uci_port;
273 }
274 
275 static constexpr char kEnableHostBluetooth[] = "enable_host_bluetooth";
set_enable_host_bluetooth(bool enable_host_bluetooth)276 void CuttlefishConfig::set_enable_host_bluetooth(bool enable_host_bluetooth) {
277   (*dictionary_)[kEnableHostBluetooth] = enable_host_bluetooth;
278 }
enable_host_bluetooth() const279 bool CuttlefishConfig::enable_host_bluetooth() const {
280   return (*dictionary_)[kEnableHostBluetooth].asBool();
281 }
282 
283 static constexpr char kEnableHostBluetoothConnector[] =
284     "enable_host_bluetooth_connector";
set_enable_host_bluetooth_connector(bool enable_host_bluetooth)285 void CuttlefishConfig::set_enable_host_bluetooth_connector(bool enable_host_bluetooth) {
286   (*dictionary_)[kEnableHostBluetoothConnector] = enable_host_bluetooth;
287 }
enable_host_bluetooth_connector() const288 bool CuttlefishConfig::enable_host_bluetooth_connector() const {
289   return (*dictionary_)[kEnableHostBluetoothConnector].asBool();
290 }
291 
292 static constexpr char kEnableAutomotiveProxy[] = "enable_automotive_proxy";
set_enable_automotive_proxy(bool enable_automotive_proxy)293 void CuttlefishConfig::set_enable_automotive_proxy(
294     bool enable_automotive_proxy) {
295   (*dictionary_)[kEnableAutomotiveProxy] = enable_automotive_proxy;
296 }
enable_automotive_proxy() const297 bool CuttlefishConfig::enable_automotive_proxy() const {
298   return (*dictionary_)[kEnableAutomotiveProxy].asBool();
299 }
300 
301 static constexpr char kVhalProxyServerPort[] = "vhal_proxy_server_port";
set_vhal_proxy_server_port(int port)302 void CuttlefishConfig::set_vhal_proxy_server_port(int port) {
303   (*dictionary_)[kVhalProxyServerPort] = port;
304 }
vhal_proxy_server_port() const305 int CuttlefishConfig::vhal_proxy_server_port() const {
306   return (*dictionary_)[kVhalProxyServerPort].asInt();
307 }
308 
309 static constexpr char kEnableHostNfc[] = "enable_host_nfc";
set_enable_host_nfc(bool enable_host_nfc)310 void CuttlefishConfig::set_enable_host_nfc(bool enable_host_nfc) {
311   (*dictionary_)[kEnableHostNfc] = enable_host_nfc;
312 }
enable_host_nfc() const313 bool CuttlefishConfig::enable_host_nfc() const {
314   return (*dictionary_)[kEnableHostNfc].asBool();
315 }
316 
317 static constexpr char kEnableHostNfcConnector[] = "enable_host_nfc_connector";
set_enable_host_nfc_connector(bool enable_host_nfc)318 void CuttlefishConfig::set_enable_host_nfc_connector(bool enable_host_nfc) {
319   (*dictionary_)[kEnableHostNfcConnector] = enable_host_nfc;
320 }
enable_host_nfc_connector() const321 bool CuttlefishConfig::enable_host_nfc_connector() const {
322   return (*dictionary_)[kEnableHostNfcConnector].asBool();
323 }
324 
325 static constexpr char kCasimirInstanceNum[] = "casimir_instance_num";
set_casimir_instance_num(int casimir_instance_num)326 void CuttlefishConfig::set_casimir_instance_num(int casimir_instance_num) {
327   (*dictionary_)[kCasimirInstanceNum] = casimir_instance_num;
328 }
casimir_instance_num() const329 int CuttlefishConfig::casimir_instance_num() const {
330   return (*dictionary_)[kCasimirInstanceNum].asInt();
331 }
332 
333 static constexpr char kCasimirArgs[] = "casimir_args";
set_casimir_args(const std::string & casimir_args)334 void CuttlefishConfig::set_casimir_args(const std::string& casimir_args) {
335   Json::Value args_json_obj(Json::arrayValue);
336   for (const auto& arg : android::base::Split(casimir_args, " ")) {
337     if (!arg.empty()) {
338       args_json_obj.append(arg);
339     }
340   }
341   (*dictionary_)[kCasimirArgs] = args_json_obj;
342 }
casimir_args() const343 std::vector<std::string> CuttlefishConfig::casimir_args() const {
344   std::vector<std::string> casimir_args;
345   for (const Json::Value& arg : (*dictionary_)[kCasimirArgs]) {
346     casimir_args.push_back(arg.asString());
347   }
348   return casimir_args;
349 }
350 
351 static constexpr char kCasimirNciPort[] = "casimir_nci_port";
set_casimir_nci_port(int port)352 void CuttlefishConfig::set_casimir_nci_port(int port) {
353   (*dictionary_)[kCasimirNciPort] = port;
354 }
casimir_nci_port() const355 int CuttlefishConfig::casimir_nci_port() const {
356   return (*dictionary_)[kCasimirNciPort].asInt();
357 }
358 
359 static constexpr char kCasimirRfPort[] = "casimir_rf_port";
set_casimir_rf_port(int port)360 void CuttlefishConfig::set_casimir_rf_port(int port) {
361   (*dictionary_)[kCasimirRfPort] = port;
362 }
casimir_rf_port() const363 int CuttlefishConfig::casimir_rf_port() const {
364   return (*dictionary_)[kCasimirRfPort].asInt();
365 }
366 
367 static constexpr char kNetsimRadios[] = "netsim_radios";
368 
netsim_radio_enable(NetsimRadio flag)369 void CuttlefishConfig::netsim_radio_enable(NetsimRadio flag) {
370   if (dictionary_->isMember(kNetsimRadios)) {
371     // OR the radio to current set of radios
372     (*dictionary_)[kNetsimRadios] = (*dictionary_)[kNetsimRadios].asInt() | flag;
373   } else {
374     (*dictionary_)[kNetsimRadios] = flag;
375   }
376 }
377 
netsim_radio_enabled(NetsimRadio flag) const378 bool CuttlefishConfig::netsim_radio_enabled(NetsimRadio flag) const {
379   return (*dictionary_)[kNetsimRadios].asInt() & flag;
380 }
381 
382 static constexpr char kNetsimInstanceNum[] = "netsim_instance_num";
netsim_instance_num() const383 int CuttlefishConfig::netsim_instance_num() const {
384   return (*dictionary_)[kNetsimInstanceNum].asInt();
385 }
set_netsim_instance_num(int netsim_instance_num)386 void CuttlefishConfig::set_netsim_instance_num(int netsim_instance_num) {
387   (*dictionary_)[kNetsimInstanceNum] = netsim_instance_num;
388 }
389 
390 static constexpr char kNetsimConnectorInstanceNum[] =
391     "netsim_connector_instance_num";
netsim_connector_instance_num() const392 int CuttlefishConfig::netsim_connector_instance_num() const {
393   return (*dictionary_)[kNetsimConnectorInstanceNum].asInt();
394 }
set_netsim_connector_instance_num(int netsim_instance_num)395 void CuttlefishConfig::set_netsim_connector_instance_num(
396     int netsim_instance_num) {
397   (*dictionary_)[kNetsimConnectorInstanceNum] = netsim_instance_num;
398 }
399 
400 static constexpr char kNetsimArgs[] = "netsim_args";
set_netsim_args(const std::string & netsim_args)401 void CuttlefishConfig::set_netsim_args(const std::string& netsim_args) {
402   Json::Value args_json_obj(Json::arrayValue);
403   for (const auto& arg : android::base::Tokenize(netsim_args, " ")) {
404     args_json_obj.append(arg);
405   }
406   (*dictionary_)[kNetsimArgs] = args_json_obj;
407 }
netsim_args() const408 std::vector<std::string> CuttlefishConfig::netsim_args() const {
409   std::vector<std::string> netsim_args;
410   for (const Json::Value& arg : (*dictionary_)[kNetsimArgs]) {
411     netsim_args.push_back(arg.asString());
412   }
413   return netsim_args;
414 }
415 
416 static constexpr char kEnableMetrics[] = "enable_metrics";
set_enable_metrics(std::string enable_metrics)417 void CuttlefishConfig::set_enable_metrics(std::string enable_metrics) {
418   (*dictionary_)[kEnableMetrics] =
419       static_cast<int>(cuttlefish::CuttlefishConfig::Answer::kUnknown);
420   if (!enable_metrics.empty()) {
421     switch (enable_metrics.at(0)) {
422       case 'y':
423       case 'Y':
424         (*dictionary_)[kEnableMetrics] =
425             static_cast<int>(cuttlefish::CuttlefishConfig::Answer::kYes);
426         break;
427       case 'n':
428       case 'N':
429         (*dictionary_)[kEnableMetrics] =
430             static_cast<int>(cuttlefish::CuttlefishConfig::Answer::kNo);
431         break;
432     }
433   }
434 }
435 
436 // validate the casting and conversion from json configs to
437 // CuttlefishConfig::Answer class
IsValidMetricsConfigs(int value)438 bool IsValidMetricsConfigs(int value) {
439   return value == static_cast<int>(CuttlefishConfig::Answer::kUnknown) ||
440          value == static_cast<int>(CuttlefishConfig::Answer::kNo) ||
441          value == static_cast<int>(CuttlefishConfig::Answer::kYes);
442 }
443 
enable_metrics() const444 CuttlefishConfig::Answer CuttlefishConfig::enable_metrics() const {
445   int value = (*dictionary_)[kEnableMetrics].asInt();
446   if (!IsValidMetricsConfigs(value)) {
447     LOG(ERROR) << "Invalid integer value for Answer enum";
448     return static_cast<Answer>(CuttlefishConfig::Answer::kUnknown);
449   }
450   return static_cast<Answer>(value);
451 }
452 
453 static constexpr char kMetricsBinary[] = "metrics_binary";
set_metrics_binary(const std::string & metrics_binary)454 void CuttlefishConfig::set_metrics_binary(const std::string& metrics_binary) {
455   (*dictionary_)[kMetricsBinary] = metrics_binary;
456 }
metrics_binary() const457 std::string CuttlefishConfig::metrics_binary() const {
458   return (*dictionary_)[kMetricsBinary].asString();
459 }
460 
461 static constexpr char kExtraKernelCmdline[] = "extra_kernel_cmdline";
set_extra_kernel_cmdline(const std::string & extra_cmdline)462 void CuttlefishConfig::set_extra_kernel_cmdline(
463     const std::string& extra_cmdline) {
464   Json::Value args_json_obj(Json::arrayValue);
465   for (const auto& arg : android::base::Split(extra_cmdline, " ")) {
466     args_json_obj.append(arg);
467   }
468   (*dictionary_)[kExtraKernelCmdline] = args_json_obj;
469 }
extra_kernel_cmdline() const470 std::vector<std::string> CuttlefishConfig::extra_kernel_cmdline() const {
471   std::vector<std::string> cmdline;
472   for (const Json::Value& arg : (*dictionary_)[kExtraKernelCmdline]) {
473     cmdline.push_back(arg.asString());
474   }
475   return cmdline;
476 }
477 
478 static constexpr char kVirtioMac80211Hwsim[] = "virtio_mac80211_hwsim";
set_virtio_mac80211_hwsim(bool virtio_mac80211_hwsim)479 void CuttlefishConfig::set_virtio_mac80211_hwsim(bool virtio_mac80211_hwsim) {
480   (*dictionary_)[kVirtioMac80211Hwsim] = virtio_mac80211_hwsim;
481 }
virtio_mac80211_hwsim() const482 bool CuttlefishConfig::virtio_mac80211_hwsim() const {
483   return (*dictionary_)[kVirtioMac80211Hwsim].asBool();
484 }
485 
486 static constexpr char kApRootfsImage[] = "ap_rootfs_image";
ap_rootfs_image() const487 std::string CuttlefishConfig::ap_rootfs_image() const {
488   return (*dictionary_)[kApRootfsImage].asString();
489 }
set_ap_rootfs_image(const std::string & ap_rootfs_image)490 void CuttlefishConfig::set_ap_rootfs_image(const std::string& ap_rootfs_image) {
491   (*dictionary_)[kApRootfsImage] = ap_rootfs_image;
492 }
493 
494 static constexpr char kApKernelImage[] = "ap_kernel_image";
ap_kernel_image() const495 std::string CuttlefishConfig::ap_kernel_image() const {
496   return (*dictionary_)[kApKernelImage].asString();
497 }
set_ap_kernel_image(const std::string & ap_kernel_image)498 void CuttlefishConfig::set_ap_kernel_image(const std::string& ap_kernel_image) {
499   (*dictionary_)[kApKernelImage] = ap_kernel_image;
500 }
501 
502 static constexpr char kRootcanalArgs[] = "rootcanal_args";
set_rootcanal_args(const std::string & rootcanal_args)503 void CuttlefishConfig::set_rootcanal_args(const std::string& rootcanal_args) {
504   Json::Value args_json_obj(Json::arrayValue);
505   for (const auto& arg : android::base::Split(rootcanal_args, " ")) {
506     args_json_obj.append(arg);
507   }
508   (*dictionary_)[kRootcanalArgs] = args_json_obj;
509 }
rootcanal_args() const510 std::vector<std::string> CuttlefishConfig::rootcanal_args() const {
511   std::vector<std::string> rootcanal_args;
512   for (const Json::Value& arg : (*dictionary_)[kRootcanalArgs]) {
513     rootcanal_args.push_back(arg.asString());
514   }
515   return rootcanal_args;
516 }
517 
518 static constexpr char kRootcanalHciPort[] = "rootcanal_hci_port";
rootcanal_hci_port() const519 int CuttlefishConfig::rootcanal_hci_port() const {
520   return (*dictionary_)[kRootcanalHciPort].asInt();
521 }
set_rootcanal_hci_port(int rootcanal_hci_port)522 void CuttlefishConfig::set_rootcanal_hci_port(int rootcanal_hci_port) {
523   (*dictionary_)[kRootcanalHciPort] = rootcanal_hci_port;
524 }
525 
526 static constexpr char kRootcanalLinkPort[] = "rootcanal_link_port";
rootcanal_link_port() const527 int CuttlefishConfig::rootcanal_link_port() const {
528   return (*dictionary_)[kRootcanalLinkPort].asInt();
529 }
set_rootcanal_link_port(int rootcanal_link_port)530 void CuttlefishConfig::set_rootcanal_link_port(int rootcanal_link_port) {
531   (*dictionary_)[kRootcanalLinkPort] = rootcanal_link_port;
532 }
533 
534 static constexpr char kRootcanalLinkBlePort[] = "rootcanal_link_ble_port";
rootcanal_link_ble_port() const535 int CuttlefishConfig::rootcanal_link_ble_port() const {
536   return (*dictionary_)[kRootcanalLinkBlePort].asInt();
537 }
set_rootcanal_link_ble_port(int rootcanal_link_ble_port)538 void CuttlefishConfig::set_rootcanal_link_ble_port(
539     int rootcanal_link_ble_port) {
540   (*dictionary_)[kRootcanalLinkBlePort] = rootcanal_link_ble_port;
541 }
542 
543 static constexpr char kRootcanalTestPort[] = "rootcanal_test_port";
rootcanal_test_port() const544 int CuttlefishConfig::rootcanal_test_port() const {
545   return (*dictionary_)[kRootcanalTestPort].asInt();
546 }
set_rootcanal_test_port(int rootcanal_test_port)547 void CuttlefishConfig::set_rootcanal_test_port(int rootcanal_test_port) {
548   (*dictionary_)[kRootcanalTestPort] = rootcanal_test_port;
549 }
550 
551 static constexpr char kSnapshotPath[] = "snapshot_path";
snapshot_path() const552 std::string CuttlefishConfig::snapshot_path() const {
553   return (*dictionary_)[kSnapshotPath].asString();
554 }
set_snapshot_path(const std::string & snapshot_path)555 void CuttlefishConfig::set_snapshot_path(const std::string& snapshot_path) {
556   (*dictionary_)[kSnapshotPath] = snapshot_path;
557 }
558 
559 static constexpr char kKvmPath[] = "kvm_path";
kvm_path() const560 std::string CuttlefishConfig::kvm_path() const {
561   return (*dictionary_)[kKvmPath].asString();
562 }
set_kvm_path(const std::string & kvm_path)563 void CuttlefishConfig::set_kvm_path(const std::string& kvm_path) {
564   (*dictionary_)[kKvmPath] = kvm_path;
565 }
566 
567 static constexpr char kVhostVsockPath[] = "vhost_vsock_path";
vhost_vsock_path() const568 std::string CuttlefishConfig::vhost_vsock_path() const {
569   return (*dictionary_)[kVhostVsockPath].asString();
570 }
set_vhost_vsock_path(const std::string & path)571 void CuttlefishConfig::set_vhost_vsock_path(const std::string& path) {
572   (*dictionary_)[kVhostVsockPath] = path;
573 }
574 
575 static constexpr char kStracedExecutables[] = "straced_host_executables";
set_straced_host_executables(const std::set<std::string> & straced_host_executables)576 void CuttlefishConfig::set_straced_host_executables(
577     const std::set<std::string>& straced_host_executables) {
578   Json::Value args_json_obj(Json::arrayValue);
579   for (const auto& arg : straced_host_executables) {
580     args_json_obj.append(arg);
581   }
582   (*dictionary_)[kStracedExecutables] = args_json_obj;
583 }
straced_host_executables() const584 std::set<std::string> CuttlefishConfig::straced_host_executables() const {
585   std::set<std::string> straced_host_executables;
586   for (const Json::Value& arg : (*dictionary_)[kStracedExecutables]) {
587     straced_host_executables.insert(arg.asString());
588   }
589   return straced_host_executables;
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 
679 static constexpr char kInstancesUdsDir[] = "instances_uds_dir";
set_instances_uds_dir(const std::string & dir)680 void CuttlefishConfig::set_instances_uds_dir(const std::string& dir) {
681   (*dictionary_)[kInstancesUdsDir] = dir;
682 }
instances_uds_dir() const683 std::string CuttlefishConfig::instances_uds_dir() const {
684   return (*dictionary_)[kInstancesUdsDir].asString();
685 }
686 
InstancesUdsPath(const std::string & file_name) const687 std::string CuttlefishConfig::InstancesUdsPath(
688     const std::string& file_name) const {
689   return AbsolutePath(instances_uds_dir() + "/" + file_name);
690 }
691 
environments_dir() const692 std::string CuttlefishConfig::environments_dir() const {
693   return AbsolutePath(root_dir() + "/environments");
694 }
695 
EnvironmentsPath(const std::string & file_name) const696 std::string CuttlefishConfig::EnvironmentsPath(
697     const std::string& file_name) const {
698   return AbsolutePath(environments_dir() + "/" + file_name);
699 }
700 
701 static constexpr char kEnvironmentsUdsDir[] = "environments_uds_dir";
set_environments_uds_dir(const std::string & dir)702 void CuttlefishConfig::set_environments_uds_dir(const std::string& dir) {
703   (*dictionary_)[kEnvironmentsUdsDir] = dir;
704 }
environments_uds_dir() const705 std::string CuttlefishConfig::environments_uds_dir() const {
706   return (*dictionary_)[kEnvironmentsUdsDir].asString();
707 }
708 
EnvironmentsUdsPath(const std::string & file_name) const709 std::string CuttlefishConfig::EnvironmentsUdsPath(
710     const std::string& file_name) const {
711   return AbsolutePath(environments_uds_dir() + "/" + file_name);
712 }
713 
ForInstance(int num)714 CuttlefishConfig::MutableInstanceSpecific CuttlefishConfig::ForInstance(int num) {
715   return MutableInstanceSpecific(this, std::to_string(num));
716 }
717 
ForInstance(int num) const718 CuttlefishConfig::InstanceSpecific CuttlefishConfig::ForInstance(int num) const {
719   return InstanceSpecific(this, std::to_string(num));
720 }
721 
ForInstanceName(const std::string & name) const722 CuttlefishConfig::InstanceSpecific CuttlefishConfig::ForInstanceName(
723     const std::string& name) const {
724   return ForInstance(InstanceFromString(name));
725 }
726 
ForDefaultInstance() const727 CuttlefishConfig::InstanceSpecific CuttlefishConfig::ForDefaultInstance() const {
728   return ForInstance(GetInstance());
729 }
730 
Instances() const731 std::vector<CuttlefishConfig::InstanceSpecific> CuttlefishConfig::Instances() const {
732   const auto& json = (*dictionary_)[kInstances];
733   std::vector<CuttlefishConfig::InstanceSpecific> instances;
734   for (const auto& name : json.getMemberNames()) {
735     instances.push_back(CuttlefishConfig::InstanceSpecific(this, name));
736   }
737   return instances;
738 }
739 
instance_dirs() const740 std::vector<std::string> CuttlefishConfig::instance_dirs() const {
741   std::vector<std::string> result;
742   for (const auto& instance : Instances()) {
743     result.push_back(instance.instance_dir());
744     result.push_back(instance.instance_uds_dir());
745   }
746   return result;
747 }
748 
749 static constexpr char kInstanceNames[] = "instance_names";
set_instance_names(const std::vector<std::string> & instance_names)750 void CuttlefishConfig::set_instance_names(
751     const std::vector<std::string>& instance_names) {
752   Json::Value args_json_obj(Json::arrayValue);
753   for (const auto& name : instance_names) {
754     args_json_obj.append(name);
755   }
756   (*dictionary_)[kInstanceNames] = args_json_obj;
757 }
instance_names() const758 std::vector<std::string> CuttlefishConfig::instance_names() const {
759   // NOTE: The structure of this field needs to remain stable, since
760   // cvd_server may call this on config JSON files from various builds.
761   //
762   // This info is duplicated into its own field here so it is simpler
763   // to keep stable, rather than parsing from Instances()::instance_name.
764   //
765   // Any non-stable changes must be accompanied by an uprev to the
766   // cvd_server major version.
767   std::vector<std::string> names;
768   for (const Json::Value& name : (*dictionary_)[kInstanceNames]) {
769     names.push_back(name.asString());
770   }
771   return names;
772 }
773 
ForEnvironment(const std::string & envName)774 CuttlefishConfig::MutableEnvironmentSpecific CuttlefishConfig::ForEnvironment(
775     const std::string& envName) {
776   return MutableEnvironmentSpecific(this, envName);
777 }
778 
ForEnvironment(const std::string & envName) const779 CuttlefishConfig::EnvironmentSpecific CuttlefishConfig::ForEnvironment(
780     const std::string& envName) const {
781   return EnvironmentSpecific(this, envName);
782 }
783 
784 CuttlefishConfig::MutableEnvironmentSpecific
ForDefaultEnvironment()785 CuttlefishConfig::ForDefaultEnvironment() {
786   return MutableEnvironmentSpecific(this,
787                                     ForDefaultInstance().environment_name());
788 }
789 
ForDefaultEnvironment() const790 CuttlefishConfig::EnvironmentSpecific CuttlefishConfig::ForDefaultEnvironment()
791     const {
792   return EnvironmentSpecific(this, ForDefaultInstance().environment_name());
793 }
794 
environment_dirs() const795 std::vector<std::string> CuttlefishConfig::environment_dirs() const {
796   auto environment = ForDefaultEnvironment();
797 
798   std::vector<std::string> result;
799 
800   result.push_back(environment.environment_dir());
801   result.push_back(environment.environment_uds_dir());
802 
803   return result;
804 }
805 
806 }  // namespace cuttlefish
807