1 /*
2 * Copyright (C) 2017 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 #include "host/commands/assemble_cvd/flags.h"
17
18 #include <sys/types.h>
19 #include <unistd.h>
20
21 #include <algorithm>
22 #include <fstream>
23 #include <iostream>
24 #include <optional>
25 #include <regex>
26 #include <set>
27 #include <sstream>
28 #include <unordered_map>
29
30 #include <android-base/file.h>
31 #include <android-base/logging.h>
32 #include <android-base/parseint.h>
33 #include <android-base/strings.h>
34 #include <fmt/format.h>
35 #include <fruit/fruit.h>
36 #include <gflags/gflags.h>
37 #include <google/protobuf/text_format.h>
38 #include <json/json.h>
39 #include <json/writer.h>
40
41 #include "common/libs/utils/architecture.h"
42 #include "common/libs/utils/base64.h"
43 #include "common/libs/utils/container.h"
44 #include "common/libs/utils/contains.h"
45 #include "common/libs/utils/environment.h"
46 #include "common/libs/utils/files.h"
47 #include "common/libs/utils/flag_parser.h"
48 #include "common/libs/utils/in_sandbox.h"
49 #include "common/libs/utils/json.h"
50 #include "common/libs/utils/known_paths.h"
51 #include "common/libs/utils/network.h"
52 #include "host/commands/assemble_cvd/alloc.h"
53 #include "host/commands/assemble_cvd/boot_config.h"
54 #include "host/commands/assemble_cvd/boot_image_utils.h"
55 #include "host/commands/assemble_cvd/disk_flags.h"
56 #include "host/commands/assemble_cvd/display.h"
57 #include "host/commands/assemble_cvd/flags_defaults.h"
58 #include "host/commands/assemble_cvd/graphics_flags.h"
59 #include "host/commands/assemble_cvd/misc_info.h"
60 #include "host/commands/assemble_cvd/network_flags.h"
61 #include "host/commands/assemble_cvd/touchpad.h"
62 #include "host/libs/config/config_flag.h"
63 #include "host/libs/config/cuttlefish_config.h"
64 #include "host/libs/config/display.h"
65 #include "host/libs/config/esp.h"
66 #include "host/libs/config/host_tools_version.h"
67 #include "host/libs/config/instance_nums.h"
68 #include "host/libs/config/secure_hals.h"
69 #include "host/libs/config/touchpad.h"
70 #include "host/libs/vhal_proxy_server/vhal_proxy_server_eth_addr.h"
71 #include "host/libs/vm_manager/crosvm_manager.h"
72 #include "host/libs/vm_manager/gem5_manager.h"
73 #include "host/libs/vm_manager/qemu_manager.h"
74 #include "host/libs/vm_manager/vm_manager.h"
75 #include "launch_cvd.pb.h"
76
77 using cuttlefish::DefaultHostArtifactsPath;
78 using cuttlefish::HostBinaryPath;
79 using cuttlefish::TempDir;
80 using cuttlefish::vm_manager::CrosvmManager;
81 using google::FlagSettingMode::SET_FLAGS_DEFAULT;
82 using google::FlagSettingMode::SET_FLAGS_VALUE;
83
84 #define DEFINE_vec DEFINE_string
85 #define DEFINE_proto DEFINE_string
86 #define GET_FLAG_STR_VALUE(name) GetFlagStrValueForInstances(FLAGS_ ##name, instances_size, #name, name_to_default_value)
87 #define GET_FLAG_INT_VALUE(name) GetFlagIntValueForInstances(FLAGS_ ##name, instances_size, #name, name_to_default_value)
88 #define GET_FLAG_BOOL_VALUE(name) GetFlagBoolValueForInstances(FLAGS_ ##name, instances_size, #name, name_to_default_value)
89
90 DEFINE_proto(displays_textproto, CF_DEFAULTS_DISPLAYS_TEXTPROTO,
91 "Text Proto input for multi-vd multi-displays");
92 DEFINE_proto(displays_binproto, CF_DEFAULTS_DISPLAYS_TEXTPROTO,
93 "Binary Proto input for multi-vd multi-displays");
94
95 DEFINE_vec(cpus, std::to_string(CF_DEFAULTS_CPUS),
96 "Virtual CPU count.");
97 DEFINE_vec(data_policy, CF_DEFAULTS_DATA_POLICY,
98 "How to handle userdata partition."
99 " Either 'use_existing', 'create_if_missing', 'resize_up_to', or "
100 "'always_create'.");
101 DEFINE_vec(blank_data_image_mb,
102 std::to_string(CF_DEFAULTS_BLANK_DATA_IMAGE_MB),
103 "The size of the blank data image to generate, MB.");
104 DEFINE_vec(gdb_port, std::to_string(CF_DEFAULTS_GDB_PORT),
105 "Port number to spawn kernel gdb on e.g. -gdb_port=1234. The"
106 "kernel must have been built with CONFIG_RANDOMIZE_BASE "
107 "disabled.");
108
109 // TODO(b/192495477): combine these into a single repeatable '--display' flag
110 // when assemble_cvd switches to using the new flag parsing library.
111 DEFINE_string(display0, CF_DEFAULTS_DISPLAY0, cuttlefish::kDisplayHelp);
112 DEFINE_string(display1, CF_DEFAULTS_DISPLAY1, cuttlefish::kDisplayHelp);
113 DEFINE_string(display2, CF_DEFAULTS_DISPLAY2, cuttlefish::kDisplayHelp);
114 DEFINE_string(display3, CF_DEFAULTS_DISPLAY3, cuttlefish::kDisplayHelp);
115
116 // TODO(b/171305898): mark these as deprecated after multi-display is fully
117 // enabled.
118 DEFINE_string(x_res, "0", "Width of the screen in pixels");
119 DEFINE_string(y_res, "0", "Height of the screen in pixels");
120 DEFINE_string(dpi, "0", "Pixels per inch for the screen");
121 DEFINE_string(refresh_rate_hz, "60", "Screen refresh rate in Hertz");
122 DEFINE_string(overlays, "",
123 "List of displays to overlay. Format is: 'vm_index:display_index "
124 "vm_index2:display_index2 [...]'");
125 DEFINE_bool(use_16k, false, "Launch using 16k kernel");
126 DEFINE_vec(kernel_path, CF_DEFAULTS_KERNEL_PATH,
127 "Path to the kernel. Overrides the one from the boot image");
128 DEFINE_vec(initramfs_path, CF_DEFAULTS_INITRAMFS_PATH,
129 "Path to the initramfs");
130 DEFINE_string(extra_kernel_cmdline, CF_DEFAULTS_EXTRA_KERNEL_CMDLINE,
131 "Additional flags to put on the kernel command line");
132 DEFINE_string(extra_bootconfig_args, CF_DEFAULTS_EXTRA_BOOTCONFIG_ARGS,
133 "Space-separated list of extra bootconfig args. "
134 "Note: overwriting an existing bootconfig argument "
135 "requires ':=' instead of '='.");
136 DEFINE_vec(guest_enforce_security,
137 fmt::format("{}", CF_DEFAULTS_GUEST_ENFORCE_SECURITY),
138 "Whether to run in enforcing mode (non permissive).");
139 DEFINE_vec(memory_mb, std::to_string(CF_DEFAULTS_MEMORY_MB),
140 "Total amount of memory available for guest, MB.");
141 DEFINE_vec(serial_number, CF_DEFAULTS_SERIAL_NUMBER,
142 "Serial number to use for the device");
143 DEFINE_vec(use_random_serial, fmt::format("{}", CF_DEFAULTS_USE_RANDOM_SERIAL),
144 "Whether to use random serial for the device.");
145 DEFINE_vec(vm_manager, CF_DEFAULTS_VM_MANAGER,
146 "What virtual machine manager to use, one of {qemu_cli, crosvm}");
147 DEFINE_vec(gpu_mode, CF_DEFAULTS_GPU_MODE,
148 "What gpu configuration to use, one of {auto, custom, drm_virgl, "
149 "gfxstream, gfxstream_guest_angle, "
150 "gfxstream_guest_angle_host_swiftshader, "
151 "gfxstream_guest_angle_host_lavapipe, guest_swiftshader}");
152 DEFINE_vec(gpu_vhost_user_mode,
153 fmt::format("{}", CF_DEFAULTS_GPU_VHOST_USER_MODE),
154 "Whether or not to run the Virtio GPU worker in a separate"
155 "process using vhost-user-gpu. One of {auto, on, off}.");
156 DEFINE_vec(hwcomposer, CF_DEFAULTS_HWCOMPOSER,
157 "What hardware composer to use, one of {auto, drm, ranchu} ");
158 DEFINE_vec(gpu_capture_binary, CF_DEFAULTS_GPU_CAPTURE_BINARY,
159 "Path to the GPU capture binary to use when capturing GPU traces"
160 "(ngfx, renderdoc, etc)");
161 DEFINE_vec(enable_gpu_udmabuf,
162 fmt::format("{}", CF_DEFAULTS_ENABLE_GPU_UDMABUF),
163 "Use the udmabuf driver for zero-copy virtio-gpu");
164 DEFINE_vec(
165 gpu_renderer_features, CF_DEFAULTS_GPU_RENDERER_FEATURES,
166 "Renderer specific features to enable. For Gfxstream, this should "
167 "be a semicolon separated list of \"<feature name>:[enabled|disabled]\""
168 "pairs.");
169
170 DEFINE_vec(gpu_context_types, CF_DEFAULTS_GPU_CONTEXT_TYPES,
171 "A colon separated list of virtio-gpu context types. Only valid "
172 "with --gpu_mode=custom."
173 " For example \"--gpu_context_types=cross_domain:gfxstream\"");
174
175 DEFINE_vec(
176 guest_hwui_renderer, CF_DEFAULTS_GUEST_HWUI_RENDERER,
177 "The default renderer that HWUI should use, one of {skiagl, skiavk}.");
178
179 DEFINE_vec(guest_renderer_preload, CF_DEFAULTS_GUEST_RENDERER_PRELOAD,
180 "Whether or not Zygote renderer preload is disabled, one of {auto, "
181 "enabled, disabled}. Auto will choose whether or not to disable "
182 "based on the gpu mode and guest hwui renderer.");
183
184 DEFINE_vec(
185 guest_vulkan_driver, CF_DEFAULTS_GUEST_VULKAN_DRIVER,
186 "Vulkan driver to use with Cuttlefish. Android VMs require specifying "
187 "this at boot time. Only valid with --gpu_mode=custom. "
188 "For example \"--guest_vulkan_driver=ranchu\"");
189
190 DEFINE_vec(
191 frames_socket_path, CF_DEFAULTS_FRAME_SOCKET_PATH,
192 "Frame socket path to use when launching a VM "
193 "For example, \"--frames_socket_path=${XDG_RUNTIME_DIR}/wayland-0\"");
194
195 DEFINE_vec(use_allocd, CF_DEFAULTS_USE_ALLOCD?"true":"false",
196 "Acquire static resources from the resource allocator daemon.");
197 DEFINE_vec(
198 enable_minimal_mode, CF_DEFAULTS_ENABLE_MINIMAL_MODE ? "true" : "false",
199 "Only enable the minimum features to boot a cuttlefish device and "
200 "support minimal UI interactions.\nNote: Currently only supports "
201 "handheld/phone targets");
202 DEFINE_vec(
203 pause_in_bootloader, CF_DEFAULTS_PAUSE_IN_BOOTLOADER?"true":"false",
204 "Stop the bootflow in u-boot. You can continue the boot by connecting "
205 "to the device console and typing in \"boot\".");
206 DEFINE_bool(enable_host_bluetooth, CF_DEFAULTS_ENABLE_HOST_BLUETOOTH,
207 "Enable the root-canal which is Bluetooth emulator in the host.");
208 DEFINE_int32(
209 rootcanal_instance_num, CF_DEFAULTS_ROOTCANAL_INSTANCE_NUM,
210 "If it is greater than 0, use an existing rootcanal instance which is "
211 "launched from cuttlefish instance "
212 "with rootcanal_instance_num. Else, launch a new rootcanal instance");
213 DEFINE_string(rootcanal_args, CF_DEFAULTS_ROOTCANAL_ARGS,
214 "Space-separated list of rootcanal args. ");
215 DEFINE_bool(enable_host_nfc, CF_DEFAULTS_ENABLE_HOST_NFC,
216 "Enable the NFC emulator in the host.");
217 DEFINE_int32(
218 casimir_instance_num, CF_DEFAULTS_CASIMIR_INSTANCE_NUM,
219 "If it is greater than 0, use an existing casimir instance which is "
220 "launched from cuttlefish instance "
221 "with casimir_instance_num. Else, launch a new casimir instance");
222 DEFINE_string(casimir_args, CF_DEFAULTS_CASIMIR_ARGS,
223 "Space-separated list of casimir args.");
224 DEFINE_bool(enable_host_uwb, CF_DEFAULTS_ENABLE_HOST_UWB,
225 "Enable the uwb host and the uwb connector.");
226 DEFINE_int32(
227 pica_instance_num, CF_DEFAULTS_ENABLE_PICA_INSTANCE_NUM,
228 "If it is greater than 0, use an existing pica instance which is "
229 "launched from cuttlefish instance "
230 "with pica_instance_num. Else, launch a new pica instance");
231 DEFINE_bool(netsim, CF_DEFAULTS_NETSIM,
232 "[Experimental] Connect all radios to netsim.");
233
234 DEFINE_bool(netsim_bt, CF_DEFAULTS_NETSIM_BT,
235 "Connect Bluetooth radio to netsim.");
236 DEFINE_bool(netsim_uwb, CF_DEFAULTS_NETSIM_UWB,
237 "[Experimental] Connect Uwb radio to netsim.");
238 DEFINE_string(netsim_args, CF_DEFAULTS_NETSIM_ARGS,
239 "Space-separated list of netsim args.");
240
241 DEFINE_bool(enable_automotive_proxy, CF_DEFAULTS_ENABLE_AUTOMOTIVE_PROXY,
242 "Enable the automotive proxy service on the host.");
243
244 DEFINE_bool(enable_vhal_proxy_server, CF_DEFAULTS_ENABLE_VHAL_PROXY_SERVER,
245 "Enable the vhal proxy service on the host.");
246 DEFINE_int32(vhal_proxy_server_instance_num,
247 CF_DEFAULTS_VHAL_PROXY_SERVER_INSTANCE_NUM,
248 "If it is greater than 0, use an existing vhal proxy server "
249 "instance which is "
250 "launched from cuttlefish instance "
251 "with vhal_proxy_server_instance_num. Else, launch a new vhal "
252 "proxy server instance");
253
254 /**
255 * crosvm sandbox feature requires /var/empty and seccomp directory
256 *
257 * Also see SetDefaultFlagsForCrosvm()
258 */
259 DEFINE_vec(
260 enable_sandbox, fmt::format("{}", CF_DEFAULTS_ENABLE_SANDBOX),
261 "Enable crosvm sandbox assuming /var/empty and seccomp directories exist. "
262 "--noenable-sandbox will disable crosvm sandbox. "
263 "When no option is given, sandbox is disabled if Cuttlefish is running "
264 "inside a container, or if GPU is enabled (b/152323505), "
265 "or if the empty /var/empty directory either does not exist and "
266 "cannot be created. Otherwise, sandbox is enabled on the supported "
267 "architecture when no option is given.");
268
269 DEFINE_vec(enable_virtiofs, fmt::format("{}", CF_DEFAULTS_ENABLE_VIRTIOFS),
270 "Enable shared folder using virtiofs");
271
272 DEFINE_string(
273 seccomp_policy_dir, CF_DEFAULTS_SECCOMP_POLICY_DIR,
274 "With sandbox'ed crosvm, overrieds the security comp policy directory");
275
276 DEFINE_vec(start_webrtc, fmt::format("{}", CF_DEFAULTS_START_WEBRTC),
277 "Whether to start the webrtc process.");
278
279 DEFINE_vec(webrtc_assets_dir, CF_DEFAULTS_WEBRTC_ASSETS_DIR,
280 "[Experimental] Path to WebRTC webpage assets.");
281
282 DEFINE_string(webrtc_certs_dir, CF_DEFAULTS_WEBRTC_CERTS_DIR,
283 "[Experimental] Path to WebRTC certificates directory.");
284
285 static constexpr auto HOST_OPERATOR_SOCKET_PATH = "/run/cuttlefish/operator";
286
287 DEFINE_bool(
288 // The actual default for this flag is set with SetCommandLineOption() in
289 // GetGuestConfigsAndSetDefaults() at the end of this file.
290 start_webrtc_sig_server, CF_DEFAULTS_START_WEBRTC_SIG_SERVER,
291 "Whether to start the webrtc signaling server. This option only applies to "
292 "the first instance, if multiple instances are launched they'll share the "
293 "same signaling server, which is owned by the first one.");
294
295 DEFINE_string(webrtc_sig_server_addr, CF_DEFAULTS_WEBRTC_SIG_SERVER_ADDR,
296 "The address of the webrtc signaling server.");
297
298 DEFINE_int32(
299 webrtc_sig_server_port, CF_DEFAULTS_WEBRTC_SIG_SERVER_PORT,
300 "The port of the signaling server if started outside of this launch. If "
301 "-start_webrtc_sig_server is given it will choose 8443+instance_num1-1 and "
302 "this parameter is ignored.");
303
304 // TODO (jemoreira): We need a much bigger range to reliably support several
305 // simultaneous connections.
306 DEFINE_vec(tcp_port_range, CF_DEFAULTS_TCP_PORT_RANGE,
307 "The minimum and maximum TCP port numbers to allocate for ICE "
308 "candidates as 'min:max'. To use any port just specify '0:0'");
309
310 DEFINE_vec(udp_port_range, CF_DEFAULTS_UDP_PORT_RANGE,
311 "The minimum and maximum UDP port numbers to allocate for ICE "
312 "candidates as 'min:max'. To use any port just specify '0:0'");
313
314 DEFINE_string(webrtc_sig_server_path, CF_DEFAULTS_WEBRTC_SIG_SERVER_PATH,
315 "The path section of the URL where the device should be "
316 "registered with the signaling server.");
317
318 DEFINE_bool(
319 webrtc_sig_server_secure, CF_DEFAULTS_WEBRTC_SIG_SERVER_SECURE,
320 "Whether the WebRTC signaling server uses secure protocols (WSS vs WS).");
321
322 DEFINE_bool(verify_sig_server_certificate,
323 CF_DEFAULTS_VERIFY_SIG_SERVER_CERTIFICATE,
324 "Whether to verify the signaling server's certificate with a "
325 "trusted signing authority (Disallow self signed certificates). "
326 "This is ignored if an insecure server is configured.");
327
328 DEFINE_string(group_id, "", "The group name of instance");
329
330 DEFINE_vec(
331 webrtc_device_id, CF_DEFAULTS_WEBRTC_DEVICE_ID,
332 "The for the device to register with the signaling server. Every "
333 "appearance of the substring '{num}' in the device id will be substituted "
334 "with the instance number to support multiple instances");
335
336 DEFINE_vec(uuid, CF_DEFAULTS_UUID,
337 "UUID to use for the device. Random if not specified");
338 DEFINE_vec(daemon, CF_DEFAULTS_DAEMON?"true":"false",
339 "Run cuttlefish in background, the launcher exits on boot "
340 "completed/failed");
341
342 DEFINE_vec(setupwizard_mode, CF_DEFAULTS_SETUPWIZARD_MODE,
343 "One of DISABLED,OPTIONAL,REQUIRED");
344 DEFINE_vec(enable_bootanimation,
345 fmt::format("{}", CF_DEFAULTS_ENABLE_BOOTANIMATION),
346 "Whether to enable the boot animation.");
347
348 DEFINE_vec(extra_bootconfig_args_base64, CF_DEFAULTS_EXTRA_BOOTCONFIG_ARGS,
349 "This is base64 encoded version of extra_bootconfig_args"
350 "Used for multi device clusters.");
351
352 DEFINE_string(qemu_binary_dir, CF_DEFAULTS_QEMU_BINARY_DIR,
353 "Path to the directory containing the qemu binary to use");
354 DEFINE_string(crosvm_binary, CF_DEFAULTS_CROSVM_BINARY,
355 "The Crosvm binary to use");
356 DEFINE_vec(gem5_binary_dir, CF_DEFAULTS_GEM5_BINARY_DIR,
357 "Path to the gem5 build tree root");
358 DEFINE_vec(gem5_checkpoint_dir, CF_DEFAULTS_GEM5_CHECKPOINT_DIR,
359 "Path to the gem5 restore checkpoint directory");
360 DEFINE_vec(gem5_debug_file, CF_DEFAULTS_GEM5_DEBUG_FILE,
361 "The file name where gem5 saves debug prints and logs");
362 DEFINE_string(gem5_debug_flags, CF_DEFAULTS_GEM5_DEBUG_FLAGS,
363 "The debug flags gem5 uses to print debugs to file");
364
365 DEFINE_vec(restart_subprocesses,
366 fmt::format("{}", CF_DEFAULTS_RESTART_SUBPROCESSES),
367 "Restart any crashed host process");
368 DEFINE_vec(bootloader, CF_DEFAULTS_BOOTLOADER, "Bootloader binary path");
369 DEFINE_vec(boot_slot, CF_DEFAULTS_BOOT_SLOT,
370 "Force booting into the given slot. If empty, "
371 "the slot will be chosen based on the misc partition if using a "
372 "bootloader. It will default to 'a' if empty and not using a "
373 "bootloader.");
374 DEFINE_int32(num_instances, CF_DEFAULTS_NUM_INSTANCES,
375 "Number of Android guests to launch");
376 DEFINE_string(instance_nums, CF_DEFAULTS_INSTANCE_NUMS,
377 "A comma-separated list of instance numbers "
378 "to use. Mutually exclusive with base_instance_num.");
379 DEFINE_string(report_anonymous_usage_stats,
380 CF_DEFAULTS_REPORT_ANONYMOUS_USAGE_STATS,
381 "Report anonymous usage "
382 "statistics for metrics collection and analysis.");
383 DEFINE_vec(ril_dns, CF_DEFAULTS_RIL_DNS,
384 "DNS address of mobile network (RIL)");
385 DEFINE_vec(kgdb, fmt::format("{}", CF_DEFAULTS_KGDB),
386 "Configure the virtual device for debugging the kernel "
387 "with kgdb/kdb. The kernel must have been built with "
388 "kgdb support, and serial console must be enabled.");
389
390 DEFINE_vec(start_gnss_proxy, fmt::format("{}", CF_DEFAULTS_START_GNSS_PROXY),
391 "Whether to start the gnss proxy.");
392
393 DEFINE_vec(gnss_file_path, CF_DEFAULTS_GNSS_FILE_PATH,
394 "Local gnss raw measurement file path for the gnss proxy");
395
396 DEFINE_vec(fixed_location_file_path, CF_DEFAULTS_FIXED_LOCATION_FILE_PATH,
397 "Local fixed location file path for the gnss proxy");
398
399 // by default, this modem-simulator is disabled
400 DEFINE_vec(enable_modem_simulator,
401 CF_DEFAULTS_ENABLE_MODEM_SIMULATOR ? "true" : "false",
402 "Enable the modem simulator to process RILD AT commands");
403 // modem_simulator_sim_type=2 for test CtsCarrierApiTestCases
404 DEFINE_vec(modem_simulator_sim_type,
405 std::to_string(CF_DEFAULTS_MODEM_SIMULATOR_SIM_TYPE),
406 "Sim type: 1 for normal, 2 for CtsCarrierApiTestCases");
407
408 DEFINE_vec(console, fmt::format("{}", CF_DEFAULTS_CONSOLE),
409 "Enable the serial console");
410
411 DEFINE_vec(enable_kernel_log, fmt::format("{}", CF_DEFAULTS_ENABLE_KERNEL_LOG),
412 "Enable kernel console/dmesg logging");
413
414 DEFINE_vec(vhost_net, fmt::format("{}", CF_DEFAULTS_VHOST_NET),
415 "Enable vhost acceleration of networking");
416
417 DEFINE_vec(vhost_user_vsock, fmt::format("{}", CF_DEFAULTS_VHOST_USER_VSOCK),
418 "Enable vhost-user-vsock");
419
420 DEFINE_string(
421 vhost_user_mac80211_hwsim, CF_DEFAULTS_VHOST_USER_MAC80211_HWSIM,
422 "Unix socket path for vhost-user of mac80211_hwsim, typically served by "
423 "wmediumd. You can set this when using an external wmediumd instance.");
424 DEFINE_string(wmediumd_config, CF_DEFAULTS_WMEDIUMD_CONFIG,
425 "Path to the wmediumd config file. When missing, the default "
426 "configuration is used which adds MAC addresses for up to 16 "
427 "cuttlefish instances including AP.");
428
429 DEFINE_string(ap_rootfs_image, CF_DEFAULTS_AP_ROOTFS_IMAGE,
430 "rootfs image for AP instance");
431 DEFINE_string(ap_kernel_image, CF_DEFAULTS_AP_KERNEL_IMAGE,
432 "kernel image for AP instance");
433
434 DEFINE_vec(record_screen, fmt::format("{}", CF_DEFAULTS_RECORD_SCREEN),
435 "Enable screen recording. "
436 "Requires --start_webrtc");
437
438 DEFINE_vec(smt, fmt::format("{}", CF_DEFAULTS_SMT),
439 "Enable simultaneous multithreading (SMT/HT)");
440
441 DEFINE_vec(
442 vsock_guest_cid, std::to_string(CF_DEFAULTS_VSOCK_GUEST_CID),
443 "vsock_guest_cid is used to determine the guest vsock cid as well as all "
444 "the ports"
445 "of all vsock servers such as tombstone or modem simulator(s)."
446 "The vsock ports and guest vsock cid are a function of vsock_guest_cid and "
447 "instance number."
448 "An instance number of i th instance is determined by --num_instances=N "
449 "and --base_instance_num=B"
450 "The instance number of i th instance is B + i where i in [0, N-1] and B "
451 ">= 1."
452 "See --num_instances, and --base_instance_num for more information"
453 "If --vsock_guest_cid=C is given and C >= 3, the guest vsock cid is C + i. "
454 "Otherwise,"
455 "the guest vsock cid is 2 + instance number, which is 2 + (B + i)."
456 "If --vsock_guest_cid is not given, each vsock server port number for i th "
457 "instance is"
458 "base + instance number - 1. vsock_guest_cid is by default B + i + 2."
459 "Thus, by default, each port is base + vsock_guest_cid - 3."
460 "The same formula holds when --vsock_guest_cid=C is given, for algorithm's "
461 "sake."
462 "Each vsock server port number is base + C - 3.");
463
464 DEFINE_vec(
465 vsock_guest_group, CF_DEFAULTS_VSOCK_GUEST_GROUP,
466 "vsock_guest_group is used to determine the guest vsock isolation groups."
467 "vsock communications can only happen between VMs which are tagged with "
468 "the same group name, or between VMs which have no group assigned.");
469
470 DEFINE_string(secure_hals, CF_DEFAULTS_SECURE_HALS,
471 "Which HALs to use enable host security features for. Supports "
472 "keymint and gatekeeper at the moment.");
473
474 DEFINE_vec(use_sdcard, CF_DEFAULTS_USE_SDCARD?"true":"false",
475 "Create blank SD-Card image and expose to guest");
476
477 DEFINE_vec(protected_vm, fmt::format("{}", CF_DEFAULTS_PROTECTED_VM),
478 "Boot in Protected VM mode");
479
480 DEFINE_vec(mte, fmt::format("{}", CF_DEFAULTS_MTE), "Enable MTE");
481
482 DEFINE_vec(enable_audio, fmt::format("{}", CF_DEFAULTS_ENABLE_AUDIO),
483 "Whether to play or capture audio");
484
485 DEFINE_vec(enable_usb, fmt::format("{}", CF_DEFAULTS_ENABLE_USB),
486 "Whether to allow USB passthrough on the device");
487
488 DEFINE_vec(camera_server_port, std::to_string(CF_DEFAULTS_CAMERA_SERVER_PORT),
489 "camera vsock port");
490
491 DEFINE_vec(userdata_format, CF_DEFAULTS_USERDATA_FORMAT,
492 "The userdata filesystem format");
493
494 DEFINE_bool(use_overlay, CF_DEFAULTS_USE_OVERLAY,
495 "Capture disk writes an overlay. This is a "
496 "prerequisite for powerwash_cvd or multiple instances.");
497
498 DEFINE_vec(modem_simulator_count,
499 std::to_string(CF_DEFAULTS_MODEM_SIMULATOR_COUNT),
500 "Modem simulator count corresponding to maximum sim number");
501
502 DEFINE_bool(track_host_tools_crc, CF_DEFAULTS_TRACK_HOST_TOOLS_CRC,
503 "Track changes to host executables");
504
505 // The default value should be set to the default of crosvm --balloon
506 DEFINE_vec(crosvm_use_balloon, "true",
507 "Controls the crosvm --no-balloon flag"
508 "The flag is given if crosvm_use_balloon is false");
509
510 DEFINE_vec(crosvm_use_rng, "true",
511 "Controls the crosvm --no-rng flag"
512 "The flag is given if crosvm_use_rng is false");
513
514 DEFINE_vec(crosvm_simple_media_device, "false",
515 "Controls the crosvm --simple-media-device flag"
516 "The flag is given if crosvm_simple_media_device is true.");
517
518 DEFINE_vec(crosvm_v4l2_proxy, CF_DEFAULTS_CROSVM_V4L2_PROXY,
519 "Controls the crosvm --v4l2-proxy flag"
520 "The flag is given if crosvm_v4l2_proxy is set with a valid string literal. "
521 "When this flag is set, crosvm_simple_media_device becomes ineffective.");
522
523 DEFINE_vec(use_pmem, "true",
524 "Make this flag false to disable pmem with crosvm");
525
526 DEFINE_bool(enable_wifi, true, "Enables the guest WIFI. Mainly for Minidroid");
527
528 DEFINE_vec(device_external_network, CF_DEFAULTS_DEVICE_EXTERNAL_NETWORK,
529 "The mechanism to connect to the public internet.");
530
531 // disable wifi, disable sandbox, use guest_swiftshader
532 DEFINE_bool(snapshot_compatible, false,
533 "Declaring that device is snapshot'able and runs with only "
534 "supported ones.");
535
536 DEFINE_vec(mcu_config_path, CF_DEFAULTS_MCU_CONFIG_PATH,
537 "configuration file for the MCU emulator");
538
539 DEFINE_string(straced_host_executables, CF_DEFAULTS_STRACED_HOST_EXECUTABLES,
540 "Comma-separated list of executable names to run under strace "
541 "to collect their system call information.");
542
543 DEFINE_vec(
544 fail_fast, CF_DEFAULTS_FAIL_FAST ? "true" : "false",
545 "Whether to exit when a heuristic predicts the boot will not complete");
546
547 DEFINE_vec(vhost_user_block, CF_DEFAULTS_VHOST_USER_BLOCK ? "true" : "false",
548 "(experimental) use crosvm vhost-user block device implementation ");
549
550 DEFINE_string(early_tmp_dir, TempDir(),
551 "Parent directory to use for temporary files in early startup");
552
553 DEFINE_vec(enable_tap_devices, "true",
554 "TAP devices are used on linux for connecting to the network "
555 "outside the current machine.");
556
557 DECLARE_string(assembly_dir);
558 DECLARE_string(boot_image);
559 DECLARE_string(system_image_dir);
560 DECLARE_string(snapshot_path);
561
562 DEFINE_vec(vcpu_config_path, CF_DEFAULTS_VCPU_CONFIG_PATH,
563 "configuration file for Virtual Cpufreq");
564
565 DEFINE_string(kvm_path, "",
566 "Device node file used to create VMs. Uses a default if empty.");
567
568 DEFINE_string(vhost_vsock_path, "",
569 "Device node file for the kernel vhost-vsock implementation. "
570 "Uses a default if empty. Ignored for QEMU.");
571
572 namespace cuttlefish {
573 using vm_manager::QemuManager;
574 using vm_manager::Gem5Manager;
575 using vm_manager::GetVmManager;
576
577 namespace {
578
ParsePortRange(const std::string & flag)579 std::pair<uint16_t, uint16_t> ParsePortRange(const std::string& flag) {
580 static const std::regex rgx("[0-9]+:[0-9]+");
581 CHECK(std::regex_match(flag, rgx))
582 << "Port range flag has invalid value: " << flag;
583 std::pair<uint16_t, uint16_t> port_range;
584 std::stringstream ss(flag);
585 char c;
586 ss >> port_range.first;
587 ss.read(&c, 1);
588 ss >> port_range.second;
589 return port_range;
590 }
591
StrForInstance(const std::string & prefix,int num)592 std::string StrForInstance(const std::string& prefix, int num) {
593 std::ostringstream stream;
594 stream << prefix << std::setfill('0') << std::setw(2) << num;
595 return stream.str();
596 }
597
GetAndroidInfoConfig(const std::string & android_info_file_path,const std::string & key)598 Result<std::string> GetAndroidInfoConfig(
599 const std::string& android_info_file_path, const std::string& key) {
600 CF_EXPECT(FileExists(android_info_file_path));
601
602 std::string android_info_contents = ReadFile(android_info_file_path);
603 auto android_info_map = CF_EXPECT(ParseMiscInfo(android_info_contents));
604 CF_EXPECT(android_info_map.find(key) != android_info_map.end());
605 return android_info_map[key];
606 }
607
608 #ifdef __ANDROID__
ReadGuestConfig()609 Result<std::vector<GuestConfig>> ReadGuestConfig() {
610 std::vector<GuestConfig> rets;
611 auto instance_nums =
612 CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
613 for (int instance_index = 0; instance_index < instance_nums.size(); instance_index++) {
614 // QEMU isn't on Android, so always follow host arch
615 GuestConfig ret{};
616 ret.target_arch = HostArch();
617 ret.bootconfig_supported = true;
618 ret.android_version_number = "0";
619 rets.push_back(ret);
620 }
621 return rets;
622 }
623 #else
ReadGuestConfig()624 Result<std::vector<GuestConfig>> ReadGuestConfig() {
625 std::vector<GuestConfig> guest_configs;
626 std::vector<std::string> boot_image =
627 android::base::Split(FLAGS_boot_image, ",");
628 std::vector<std::string> kernel_path =
629 android::base::Split(FLAGS_kernel_path, ",");
630 std::vector<std::string> system_image_dir =
631 android::base::Split(FLAGS_system_image_dir, ",");
632 std::string kernel_image_path = "";
633 std::string cur_boot_image;
634 std::string cur_kernel_path;
635
636 std::string current_path = StringFromEnv("PATH", "");
637 std::string bin_folder = DefaultHostArtifactsPath("bin");
638 std::string new_path = "PATH=";
639 new_path += current_path;
640 new_path += ":";
641 new_path += bin_folder;
642 auto instance_nums =
643 CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
644 for (int instance_index = 0; instance_index < instance_nums.size(); instance_index++) {
645 // extract-ikconfig can be called directly on the boot image since it looks
646 // for the ikconfig header in the image before extracting the config list.
647 // This code is liable to break if the boot image ever includes the
648 // ikconfig header outside the kernel.
649 cur_kernel_path = "";
650 if (instance_index < kernel_path.size()) {
651 cur_kernel_path = kernel_path[instance_index];
652 }
653
654 cur_boot_image = "";
655 if (instance_index < boot_image.size()) {
656 cur_boot_image = boot_image[instance_index];
657 }
658
659 if (cur_kernel_path.size() > 0) {
660 kernel_image_path = cur_kernel_path;
661 } else if (cur_boot_image.size() > 0) {
662 kernel_image_path = cur_boot_image;
663 }
664
665 GuestConfig guest_config;
666 guest_config.android_version_number = CF_EXPECT(
667 ReadAndroidVersionFromBootImage(FLAGS_early_tmp_dir, cur_boot_image),
668 "Failed to read guest's android version");
669
670 if (InSandbox()) {
671 // TODO: b/359309462 - real sandboxing for extract-ikconfig
672 guest_config.target_arch = HostArch();
673 guest_config.bootconfig_supported = true;
674 guest_config.hctr2_supported = true;
675 } else {
676 Command ikconfig_cmd(HostBinaryPath("extract-ikconfig"));
677 ikconfig_cmd.AddParameter(kernel_image_path);
678 ikconfig_cmd.UnsetFromEnvironment("PATH").AddEnvironmentVariable(
679 "PATH", new_path);
680 std::string ikconfig_path = FLAGS_early_tmp_dir + "/ikconfig.XXXXXX";
681 auto ikconfig_fd = SharedFD::Mkstemp(&ikconfig_path);
682 CF_EXPECT(ikconfig_fd->IsOpen(),
683 "Unable to create ikconfig file: " << ikconfig_fd->StrError());
684 ikconfig_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut,
685 ikconfig_fd);
686
687 auto ikconfig_proc = ikconfig_cmd.Start();
688 CF_EXPECT(ikconfig_proc.Started() && ikconfig_proc.Wait() == 0,
689 "Failed to extract ikconfig from " << kernel_image_path);
690
691 std::string config = ReadFile(ikconfig_path);
692
693 if (config.find("\nCONFIG_ARM=y") != std::string::npos) {
694 guest_config.target_arch = Arch::Arm;
695 } else if (config.find("\nCONFIG_ARM64=y") != std::string::npos) {
696 guest_config.target_arch = Arch::Arm64;
697 } else if (config.find("\nCONFIG_ARCH_RV64I=y") != std::string::npos) {
698 guest_config.target_arch = Arch::RiscV64;
699 } else if (config.find("\nCONFIG_X86_64=y") != std::string::npos) {
700 guest_config.target_arch = Arch::X86_64;
701 } else if (config.find("\nCONFIG_X86=y") != std::string::npos) {
702 guest_config.target_arch = Arch::X86;
703 } else {
704 return CF_ERR("Unknown target architecture");
705 }
706 guest_config.bootconfig_supported =
707 config.find("\nCONFIG_BOOT_CONFIG=y") != std::string::npos;
708 // Once all Cuttlefish kernel versions are at least 5.15, this code can be
709 // removed. CONFIG_CRYPTO_HCTR2=y will always be set.
710 // Note there's also a platform dep for hctr2 introduced in Android 14.
711 // Hence the version check.
712 guest_config.hctr2_supported =
713 (config.find("\nCONFIG_CRYPTO_HCTR2=y") != std::string::npos) &&
714 (guest_config.android_version_number != "11.0.0") &&
715 (guest_config.android_version_number != "13.0.0") &&
716 (guest_config.android_version_number != "11") &&
717 (guest_config.android_version_number != "13");
718
719 unlink(ikconfig_path.c_str());
720 }
721
722 std::string instance_android_info_txt;
723 if (instance_index >= system_image_dir.size()) {
724 // in case this is the same image being launhced multiple times
725 // the same flag is used for all instances
726 instance_android_info_txt = system_image_dir[0] + "/android-info.txt";
727 } else {
728 instance_android_info_txt =
729 system_image_dir[instance_index] + "/android-info.txt";
730 }
731
732 auto res = GetAndroidInfoConfig(instance_android_info_txt, "device_type");
733 // If that "device_type" is not explicitly set, fall back to parse "config".
734 if (!res.ok()) {
735 res = GetAndroidInfoConfig(instance_android_info_txt, "config");
736 }
737 guest_config.device_type = ParseDeviceType(res.value_or(""));
738
739 res = GetAndroidInfoConfig(instance_android_info_txt, "gfxstream");
740 guest_config.gfxstream_supported =
741 res.ok() && res.value() == "supported";
742
743 res = GetAndroidInfoConfig(instance_android_info_txt,
744 "gfxstream_gl_program_binary_link_status");
745 guest_config.gfxstream_gl_program_binary_link_status_supported =
746 res.ok() && res.value() == "supported";
747
748 auto res_mouse_support =
749 GetAndroidInfoConfig(instance_android_info_txt, "mouse");
750 guest_config.mouse_supported =
751 res_mouse_support.ok() && res_mouse_support.value() == "supported";
752
753 auto res_custom_keyboard_config =
754 GetAndroidInfoConfig(instance_android_info_txt, "custom_keyboard");
755 if (res_custom_keyboard_config.ok()) {
756 guest_config.custom_keyboard_config =
757 DefaultHostArtifactsPath(res_custom_keyboard_config.value());
758 }
759
760 auto res_domkey_mapping_config =
761 GetAndroidInfoConfig(instance_android_info_txt, "domkey_mapping");
762 if (res_domkey_mapping_config.ok()) {
763 guest_config.domkey_mapping_config =
764 DefaultHostArtifactsPath(res_domkey_mapping_config.value());
765 }
766
767 auto res_bgra_support = GetAndroidInfoConfig(instance_android_info_txt,
768 "supports_bgra_framebuffers");
769 guest_config.supports_bgra_framebuffers =
770 res_bgra_support.value_or("") == "true";
771
772 auto res_vhost_user_vsock =
773 GetAndroidInfoConfig(instance_android_info_txt, "vhost_user_vsock");
774 guest_config.vhost_user_vsock = res_vhost_user_vsock.value_or("") == "true";
775
776 auto res_prefer_drm_virgl_when_supported = GetAndroidInfoConfig(
777 instance_android_info_txt, "prefer_drm_virgl_when_supported");
778 guest_config.prefer_drm_virgl_when_supported =
779 res_prefer_drm_virgl_when_supported.value_or("") == "true";
780
781 auto res_ti50_emulator =
782 GetAndroidInfoConfig(instance_android_info_txt, "ti50_emulator");
783 guest_config.ti50_emulator = res_ti50_emulator.value_or("");
784 auto res_output_audio_streams_count = GetAndroidInfoConfig(
785 instance_android_info_txt, "output_audio_streams_count");
786 if (res_output_audio_streams_count.ok()) {
787 std::string output_audio_streams_count_str =
788 res_output_audio_streams_count.value();
789 CF_EXPECT(
790 android::base::ParseInt(output_audio_streams_count_str.c_str(),
791 &guest_config.output_audio_streams_count),
792 "Failed to parse value \"" << output_audio_streams_count_str
793 << "\" for output audio stream count");
794 }
795
796 guest_configs.push_back(guest_config);
797 }
798 return guest_configs;
799 }
800
801 #endif // #ifdef __ANDROID__
802
803 template <typename ProtoType>
ParseTextProtoFlagHelper(const std::string & flag_value,const std::string & flag_name)804 Result<ProtoType> ParseTextProtoFlagHelper(const std::string& flag_value,
805 const std::string& flag_name) {
806 ProtoType proto_result;
807 google::protobuf::TextFormat::Parser p;
808 CF_EXPECT(p.ParseFromString(flag_value, &proto_result),
809 "Failed to parse: " << flag_name << ", value: " << flag_value);
810 return proto_result;
811 }
812
813 template <typename ProtoType>
ParseBinProtoFlagHelper(const std::string & flag_value,const std::string & flag_name)814 Result<ProtoType> ParseBinProtoFlagHelper(const std::string& flag_value,
815 const std::string& flag_name) {
816 ProtoType proto_result;
817 std::vector<uint8_t> output;
818 CF_EXPECT(DecodeBase64(flag_value, &output));
819 std::string serialized = std::string(output.begin(), output.end());
820 bool result = proto_result.ParseFromString(serialized);
821 CF_EXPECT(proto_result.ParseFromString(serialized),
822 "Failed to parse binary proto, flag: " << flag_name << ", value: "
823 << flag_value);
824 return proto_result;
825 }
826
827 Result<std::vector<std::vector<CuttlefishConfig::DisplayConfig>>>
ParseDisplaysProto()828 ParseDisplaysProto() {
829 auto proto_result = FLAGS_displays_textproto.empty() ? \
830 ParseBinProtoFlagHelper<InstancesDisplays>(FLAGS_displays_binproto, "displays_binproto") : \
831 ParseTextProtoFlagHelper<InstancesDisplays>(FLAGS_displays_textproto, "displays_textproto");
832
833 InstancesDisplays display_proto = CF_EXPECT(std::move(proto_result));
834
835 std::vector<std::vector<CuttlefishConfig::DisplayConfig>> result;
836 for (int i = 0; i < display_proto.instances_size(); i++) {
837 std::vector<CuttlefishConfig::DisplayConfig> display_configs;
838 const InstanceDisplays& launch_cvd_instance = display_proto.instances(i);
839 for (int display_num=0; display_num<launch_cvd_instance.displays_size(); display_num++) {
840 const InstanceDisplay& display = launch_cvd_instance.displays(display_num);
841
842 // use same code logic from ParseDisplayConfig
843 int display_dpi = CF_DEFAULTS_DISPLAY_DPI;
844 if (display.dpi() != 0) {
845 display_dpi = display.dpi();
846 }
847
848 int display_refresh_rate_hz = CF_DEFAULTS_DISPLAY_REFRESH_RATE;
849 if (display.refresh_rate_hertz() != 0) {
850 display_refresh_rate_hz = display.refresh_rate_hertz();
851 }
852
853 std::string overlays = "";
854
855 for (const auto& overlay : display.overlays()) {
856 overlays +=
857 fmt::format("{}:{} ", overlay.vm_index(), overlay.display_index());
858 }
859
860 auto dc = CuttlefishConfig::DisplayConfig{
861 .width = display.width(),
862 .height = display.height(),
863 .dpi = display_dpi,
864 .refresh_rate_hz = display_refresh_rate_hz,
865 .overlays = overlays,
866 };
867
868 display_configs.push_back(dc);
869 }
870 result.push_back(display_configs);
871 }
872
873 return result;
874 }
875
CreateNumToWebrtcDeviceIdMap(const CuttlefishConfig & tmp_config_obj,const std::vector<std::int32_t> & instance_nums,const std::string & webrtc_device_id_flag)876 Result<std::unordered_map<int, std::string>> CreateNumToWebrtcDeviceIdMap(
877 const CuttlefishConfig& tmp_config_obj,
878 const std::vector<std::int32_t>& instance_nums,
879 const std::string& webrtc_device_id_flag) {
880 std::unordered_map<int, std::string> output_map;
881 if (webrtc_device_id_flag.empty()) {
882 for (const auto num : instance_nums) {
883 const auto const_instance = tmp_config_obj.ForInstance(num);
884 output_map[num] = const_instance.instance_name();
885 }
886 return output_map;
887 }
888 auto tokens = android::base::Tokenize(webrtc_device_id_flag, ",");
889 CF_EXPECT(tokens.size() == 1 || tokens.size() == instance_nums.size(),
890 "--webrtc_device_ids provided " << tokens.size()
891 << " tokens"
892 " while 1 or "
893 << instance_nums.size()
894 << " is expected.");
895 CF_EXPECT(!tokens.empty(), "--webrtc_device_ids is ill-formatted");
896
897 std::vector<std::string> device_ids;
898 if (tokens.size() != instance_nums.size()) {
899 /* this is only possible when tokens.size() == 1
900 * and instance_nums.size() > 1. The token must include {num}
901 * so that the token pattern can be expanded to multiple instances.
902 */
903 auto device_id = tokens.front();
904 CF_EXPECT(device_id.find("{num}") != std::string::npos,
905 "If one webrtc_device_ids is given for multiple instances, "
906 << " {num} should be included in webrtc_device_id.");
907 device_ids = std::vector<std::string>(instance_nums.size(), tokens.front());
908 }
909
910 if (tokens.size() == instance_nums.size()) {
911 // doesn't have to include {num}
912 device_ids = std::move(tokens);
913 }
914
915 auto itr = device_ids.begin();
916 for (const auto num : instance_nums) {
917 std::string_view device_id_view(itr->data(), itr->size());
918 output_map[num] = android::base::StringReplace(device_id_view, "{num}",
919 std::to_string(num), true);
920 ++itr;
921 }
922 return output_map;
923 }
924
925 /**
926 * Returns a mapping between flag name and "gflags default_value" as strings for flags
927 * defined in the binary.
928 */
CurrentFlagsToDefaultValue()929 std::map<std::string, std::string> CurrentFlagsToDefaultValue() {
930 std::map<std::string, std::string> name_to_default_value;
931 std::vector<gflags::CommandLineFlagInfo> self_flags;
932 gflags::GetAllFlags(&self_flags);
933 for (auto& flag : self_flags) {
934 name_to_default_value[flag.name] = flag.default_value;
935 }
936 return name_to_default_value;
937 }
938
GetFlagBoolValueForInstances(const std::string & flag_values,int32_t instances_size,const std::string & flag_name,std::map<std::string,std::string> & name_to_default_value)939 Result<std::vector<bool>> GetFlagBoolValueForInstances(
940 const std::string& flag_values, int32_t instances_size, const std::string& flag_name,
941 std::map<std::string, std::string>& name_to_default_value) {
942 std::vector<std::string> flag_vec = android::base::Split(flag_values, ",");
943 std::vector<bool> value_vec(instances_size);
944
945 CF_EXPECT(name_to_default_value.find(flag_name) != name_to_default_value.end());
946 std::vector<std::string> default_value_vec = android::base::Split(name_to_default_value[flag_name], ",");
947
948 for (int instance_index=0; instance_index<instances_size; instance_index++) {
949 if (instance_index >= flag_vec.size()) {
950 value_vec[instance_index] = CF_EXPECT(ParseBool(flag_vec[0], flag_name));
951 } else {
952 if (flag_vec[instance_index] == "unset" || flag_vec[instance_index] == "\"unset\"") {
953 std::string default_value = default_value_vec[0];
954 if (instance_index < default_value_vec.size()) {
955 default_value = default_value_vec[instance_index];
956 }
957 value_vec[instance_index] = CF_EXPECT(ParseBool(default_value, flag_name));
958 } else {
959 value_vec[instance_index] = CF_EXPECT(ParseBool(flag_vec[instance_index], flag_name));
960 }
961 }
962 }
963 return value_vec;
964 }
965
GetFlagIntValueForInstances(const std::string & flag_values,int32_t instances_size,const std::string & flag_name,std::map<std::string,std::string> & name_to_default_value)966 Result<std::vector<int>> GetFlagIntValueForInstances(
967 const std::string& flag_values, int32_t instances_size, const std::string& flag_name,
968 std::map<std::string, std::string>& name_to_default_value) {
969 std::vector<std::string> flag_vec = android::base::Split(flag_values, ",");
970 std::vector<int> value_vec(instances_size);
971
972 CF_EXPECT(name_to_default_value.find(flag_name) != name_to_default_value.end());
973 std::vector<std::string> default_value_vec = android::base::Split(name_to_default_value[flag_name], ",");
974
975 for (int instance_index=0; instance_index<instances_size; instance_index++) {
976 if (instance_index >= flag_vec.size()) {
977 CF_EXPECT(android::base::ParseInt(flag_vec[0].c_str(), &value_vec[instance_index]),
978 "Failed to parse value \"" << flag_vec[0] << "\" for " << flag_name);
979 } else {
980 if (flag_vec[instance_index] == "unset" || flag_vec[instance_index] == "\"unset\"") {
981 std::string default_value = default_value_vec[0];
982 if (instance_index < default_value_vec.size()) {
983 default_value = default_value_vec[instance_index];
984 }
985 CF_EXPECT(android::base::ParseInt(default_value,
986 &value_vec[instance_index]),
987 "Failed to parse value \"" << default_value << "\" for " << flag_name);
988 } else {
989 CF_EXPECT(android::base::ParseInt(flag_vec[instance_index].c_str(),
990 &value_vec[instance_index]),
991 "Failed to parse value \"" << flag_vec[instance_index] << "\" for " << flag_name);
992 }
993 }
994 }
995 return value_vec;
996 }
997
GetFlagStrValueForInstances(const std::string & flag_values,int32_t instances_size,const std::string & flag_name,std::map<std::string,std::string> & name_to_default_value)998 Result<std::vector<std::string>> GetFlagStrValueForInstances(
999 const std::string& flag_values, int32_t instances_size,
1000 const std::string& flag_name, std::map<std::string, std::string>& name_to_default_value) {
1001 std::vector<std::string> flag_vec = android::base::Split(flag_values, ",");
1002 std::vector<std::string> value_vec(instances_size);
1003
1004 CF_EXPECT(name_to_default_value.find(flag_name) != name_to_default_value.end());
1005 std::vector<std::string> default_value_vec = android::base::Split(name_to_default_value[flag_name], ",");
1006
1007 for (int instance_index=0; instance_index<instances_size; instance_index++) {
1008 if (instance_index >= flag_vec.size()) {
1009 value_vec[instance_index] = flag_vec[0];
1010 } else {
1011 if (flag_vec[instance_index] == "unset" || flag_vec[instance_index] == "\"unset\"") {
1012 std::string default_value = default_value_vec[0];
1013 if (instance_index < default_value_vec.size()) {
1014 default_value = default_value_vec[instance_index];
1015 }
1016 value_vec[instance_index] = default_value;
1017 } else {
1018 value_vec[instance_index] = flag_vec[instance_index];
1019 }
1020 }
1021 }
1022 return value_vec;
1023 }
1024
CheckSnapshotCompatible(const bool must_be_compatible,const std::map<int,std::string> & calculated_gpu_mode)1025 Result<void> CheckSnapshotCompatible(
1026 const bool must_be_compatible,
1027 const std::map<int, std::string>& calculated_gpu_mode) {
1028 if (!must_be_compatible) {
1029 return {};
1030 }
1031
1032 /*
1033 * TODO(kwstephenkim@): delete this block once virtio-fs is supported
1034 */
1035 CF_EXPECTF(
1036 gflags::GetCommandLineFlagInfoOrDie("enable_virtiofs").current_value ==
1037 "false",
1038 "--enable_virtiofs should be false for snapshot, consider \"{}\"",
1039 "--enable_virtiofs=false");
1040
1041 /*
1042 * TODO(khei@): delete this block once usb is supported
1043 */
1044 CF_EXPECTF(gflags::GetCommandLineFlagInfoOrDie("enable_usb").current_value ==
1045 "false",
1046 "--enable_usb should be false for snapshot, consider \"{}\"",
1047 "--enable_usb=false");
1048
1049 /*
1050 * TODO(kwstephenkim@): delete this block once 3D gpu mode snapshots are
1051 * supported
1052 */
1053 for (const auto& [instance_index, instance_gpu_mode] : calculated_gpu_mode) {
1054 CF_EXPECTF(
1055 instance_gpu_mode == "guest_swiftshader",
1056 "Only 2D guest_swiftshader is supported for snapshot. Consider \"{}\"",
1057 "--gpu_mode=guest_swiftshader");
1058 }
1059 return {};
1060 }
1061
EnvironmentUdsDir()1062 std::optional<std::string> EnvironmentUdsDir() {
1063 std::string environments_uds_dir =
1064 fmt::format("{}/cf_env_{}", TempDir(), getuid());
1065 if (DirectoryExists(environments_uds_dir) &&
1066 !CanAccess(environments_uds_dir, R_OK | W_OK | X_OK)) {
1067 return std::nullopt;
1068 }
1069 return environments_uds_dir;
1070 }
1071
InstancesUdsDir()1072 std::optional<std::string> InstancesUdsDir() {
1073 std::string instances_uds_dir =
1074 fmt::format("{}/cf_avd_{}", TempDir(), getuid());
1075 if (DirectoryExists(instances_uds_dir) &&
1076 !CanAccess(instances_uds_dir, R_OK | W_OK | X_OK)) {
1077 return std::nullopt;
1078 }
1079 return instances_uds_dir;
1080 }
1081
DefaultBootloaderArchDir(Arch arch)1082 std::string DefaultBootloaderArchDir(Arch arch) {
1083 switch (arch) {
1084 case Arch::Arm64:
1085 return "aarch64";
1086 case Arch::Arm:
1087 return "arm";
1088 case Arch::RiscV64:
1089 return "riscv64";
1090 case Arch::X86:
1091 case Arch::X86_64:
1092 return "x86_64";
1093 }
1094 }
1095
1096 } // namespace
1097
InitializeCuttlefishConfiguration(const std::string & root_dir,const std::vector<GuestConfig> & guest_configs,fruit::Injector<> & injector,const FetcherConfig & fetcher_config)1098 Result<CuttlefishConfig> InitializeCuttlefishConfiguration(
1099 const std::string& root_dir,
1100 const std::vector<GuestConfig>& guest_configs,
1101 fruit::Injector<>& injector, const FetcherConfig& fetcher_config) {
1102 CuttlefishConfig tmp_config_obj;
1103 // If a snapshot path is provided, do not read all flags to set up the config.
1104 // Instead, read the config that was saved at time of snapshot and restore
1105 // that for this run.
1106 // TODO (khei@/kwstephenkim@): b/310034839
1107 const std::string snapshot_path = FLAGS_snapshot_path;
1108 if (!snapshot_path.empty()) {
1109 const std::string snapshot_path_config =
1110 snapshot_path + "/assembly/cuttlefish_config.json";
1111 tmp_config_obj.LoadFromFile(snapshot_path_config.c_str());
1112 tmp_config_obj.set_snapshot_path(snapshot_path);
1113 return tmp_config_obj;
1114 }
1115
1116 for (const auto& fragment : injector.getMultibindings<ConfigFragment>()) {
1117 CHECK(tmp_config_obj.SaveFragment(*fragment))
1118 << "Failed to save fragment " << fragment->Name();
1119 }
1120
1121 tmp_config_obj.set_root_dir(root_dir);
1122
1123 tmp_config_obj.set_environments_uds_dir(
1124 EnvironmentUdsDir().value_or(tmp_config_obj.environments_dir()));
1125 tmp_config_obj.set_instances_uds_dir(
1126 InstancesUdsDir().value_or(tmp_config_obj.instances_dir()));
1127
1128 auto instance_nums =
1129 CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
1130
1131 // TODO(weihsu), b/250988697:
1132 // FLAGS_vm_manager used too early, have to handle this vectorized string early
1133 // Currently, all instances should use same vmm, added checking here
1134 std::vector<std::string> vm_manager_vec =
1135 android::base::Split(FLAGS_vm_manager, ",");
1136 for (int i=1; i<vm_manager_vec.size(); i++) {
1137 CF_EXPECT(
1138 vm_manager_vec[0] == vm_manager_vec[i],
1139 "All instances should have same vm_manager, " << FLAGS_vm_manager);
1140 }
1141 CF_EXPECT_GT(vm_manager_vec.size(), 0);
1142 while (vm_manager_vec.size() < instance_nums.size()) {
1143 vm_manager_vec.emplace_back(vm_manager_vec[0]);
1144 }
1145
1146 // TODO(weihsu), b/250988697: moved bootconfig_supported and hctr2_supported
1147 // into each instance, but target_arch is still in todo
1148 // target_arch should be in instance later
1149 auto vmm_mode = CF_EXPECT(ParseVmm(vm_manager_vec[0]));
1150 auto vmm = GetVmManager(vmm_mode, guest_configs[0].target_arch);
1151 if (!vmm) {
1152 LOG(FATAL) << "Invalid vm_manager: " << vm_manager_vec[0];
1153 }
1154 tmp_config_obj.set_vm_manager(vmm_mode);
1155 tmp_config_obj.set_ap_vm_manager(vm_manager_vec[0] + "_openwrt");
1156
1157 // TODO: schuffelen - fix behavior on riscv64
1158 if (guest_configs[0].target_arch == Arch::RiscV64) {
1159 static constexpr char kRiscv64Secure[] = "keymint,gatekeeper,oemlock";
1160 SetCommandLineOptionWithMode("secure_hals", kRiscv64Secure,
1161 google::FlagSettingMode::SET_FLAGS_DEFAULT);
1162 } else {
1163 static constexpr char kDefaultSecure[] =
1164 "oemlock,guest_keymint_insecure,guest_gatekeeper_insecure";
1165 SetCommandLineOptionWithMode("secure_hals", kDefaultSecure,
1166 google::FlagSettingMode::SET_FLAGS_DEFAULT);
1167 }
1168 auto secure_hals = CF_EXPECT(ParseSecureHals(FLAGS_secure_hals));
1169 CF_EXPECT(ValidateSecureHals(secure_hals));
1170 tmp_config_obj.set_secure_hals(secure_hals);
1171
1172 tmp_config_obj.set_extra_kernel_cmdline(FLAGS_extra_kernel_cmdline);
1173
1174 if (FLAGS_track_host_tools_crc) {
1175 tmp_config_obj.set_host_tools_version(HostToolsCrc());
1176 }
1177
1178 tmp_config_obj.set_gem5_debug_flags(FLAGS_gem5_debug_flags);
1179
1180 // streaming, webrtc setup
1181 tmp_config_obj.set_webrtc_certs_dir(FLAGS_webrtc_certs_dir);
1182 tmp_config_obj.set_sig_server_secure(FLAGS_webrtc_sig_server_secure);
1183 // Note: This will be overridden if the sig server is started by us
1184 tmp_config_obj.set_sig_server_port(FLAGS_webrtc_sig_server_port);
1185 tmp_config_obj.set_sig_server_address(FLAGS_webrtc_sig_server_addr);
1186 tmp_config_obj.set_sig_server_path(FLAGS_webrtc_sig_server_path);
1187 tmp_config_obj.set_sig_server_strict(FLAGS_verify_sig_server_certificate);
1188
1189 tmp_config_obj.set_enable_metrics(FLAGS_report_anonymous_usage_stats);
1190 // TODO(moelsherif): Handle this flag (set_metrics_binary) in the future
1191
1192 #ifdef ENFORCE_MAC80211_HWSIM
1193 tmp_config_obj.set_virtio_mac80211_hwsim(true);
1194 #else
1195 tmp_config_obj.set_virtio_mac80211_hwsim(false);
1196 #endif
1197
1198 if ((FLAGS_ap_rootfs_image.empty()) != (FLAGS_ap_kernel_image.empty())) {
1199 LOG(FATAL) << "Either both ap_rootfs_image and ap_kernel_image should be "
1200 "set or neither should be set.";
1201 }
1202 // If user input multiple values, we only take the 1st value and shared with
1203 // all instances
1204 std::string ap_rootfs_image = "";
1205 if (!FLAGS_ap_rootfs_image.empty()) {
1206 ap_rootfs_image = android::base::Split(FLAGS_ap_rootfs_image, ",")[0];
1207 }
1208
1209 tmp_config_obj.set_ap_rootfs_image(ap_rootfs_image);
1210 tmp_config_obj.set_ap_kernel_image(FLAGS_ap_kernel_image);
1211
1212 // netsim flags allow all radios or selecting a specific radio
1213 bool is_any_netsim = FLAGS_netsim || FLAGS_netsim_bt || FLAGS_netsim_uwb;
1214 bool is_bt_netsim = FLAGS_netsim || FLAGS_netsim_bt;
1215 bool is_uwb_netsim = FLAGS_netsim || FLAGS_netsim_uwb;
1216
1217 // crosvm should create fifos for Bluetooth
1218 tmp_config_obj.set_enable_host_bluetooth(FLAGS_enable_host_bluetooth ||
1219 is_bt_netsim);
1220
1221 // rootcanal and bt_connector should handle Bluetooth (instead of netsim)
1222 tmp_config_obj.set_enable_host_bluetooth_connector(FLAGS_enable_host_bluetooth && !is_bt_netsim);
1223
1224 tmp_config_obj.set_enable_host_nfc(FLAGS_enable_host_nfc);
1225 tmp_config_obj.set_enable_host_nfc_connector(FLAGS_enable_host_nfc);
1226
1227 // These flags inform NetsimServer::ResultSetup which radios it owns.
1228 if (is_bt_netsim) {
1229 tmp_config_obj.netsim_radio_enable(CuttlefishConfig::NetsimRadio::Bluetooth);
1230 }
1231 // end of vectorize ap_rootfs_image, ap_kernel_image, wmediumd_config
1232
1233 tmp_config_obj.set_enable_automotive_proxy(FLAGS_enable_automotive_proxy);
1234
1235 // get flag default values and store into map
1236 auto name_to_default_value = CurrentFlagsToDefaultValue();
1237 // old flags but vectorized for multi-device instances
1238 int32_t instances_size = instance_nums.size();
1239 std::vector<std::string> gnss_file_paths =
1240 CF_EXPECT(GET_FLAG_STR_VALUE(gnss_file_path));
1241 std::vector<std::string> fixed_location_file_paths =
1242 CF_EXPECT(GET_FLAG_STR_VALUE(fixed_location_file_path));
1243 std::vector<int> x_res_vec = CF_EXPECT(GET_FLAG_INT_VALUE(x_res));
1244 std::vector<int> y_res_vec = CF_EXPECT(GET_FLAG_INT_VALUE(y_res));
1245 std::vector<int> dpi_vec = CF_EXPECT(GET_FLAG_INT_VALUE(dpi));
1246 std::vector<int> refresh_rate_hz_vec = CF_EXPECT(GET_FLAG_INT_VALUE(
1247 refresh_rate_hz));
1248 std::vector<std::string> overlays_vec =
1249 CF_EXPECT(GET_FLAG_STR_VALUE(overlays));
1250 std::vector<int> memory_mb_vec = CF_EXPECT(GET_FLAG_INT_VALUE(memory_mb));
1251 std::vector<int> camera_server_port_vec = CF_EXPECT(GET_FLAG_INT_VALUE(
1252 camera_server_port));
1253 std::vector<int> vsock_guest_cid_vec = CF_EXPECT(GET_FLAG_INT_VALUE(
1254 vsock_guest_cid));
1255 std::vector<std::string> vsock_guest_group_vec =
1256 CF_EXPECT(GET_FLAG_STR_VALUE(vsock_guest_group));
1257 std::vector<int> cpus_vec = CF_EXPECT(GET_FLAG_INT_VALUE(cpus));
1258 std::vector<int> blank_data_image_mb_vec = CF_EXPECT(GET_FLAG_INT_VALUE(
1259 blank_data_image_mb));
1260 std::vector<int> gdb_port_vec = CF_EXPECT(GET_FLAG_INT_VALUE(gdb_port));
1261 std::vector<std::string> setupwizard_mode_vec =
1262 CF_EXPECT(GET_FLAG_STR_VALUE(setupwizard_mode));
1263 std::vector<std::string> userdata_format_vec =
1264 CF_EXPECT(GET_FLAG_STR_VALUE(userdata_format));
1265 std::vector<bool> guest_enforce_security_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1266 guest_enforce_security));
1267 std::vector<bool> use_random_serial_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1268 use_random_serial));
1269 std::vector<bool> use_allocd_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(use_allocd));
1270 std::vector<bool> use_sdcard_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(use_sdcard));
1271 std::vector<bool> pause_in_bootloader_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1272 pause_in_bootloader));
1273 std::vector<bool> daemon_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(daemon));
1274 std::vector<bool> enable_minimal_mode_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1275 enable_minimal_mode));
1276 std::vector<bool> enable_modem_simulator_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1277 enable_modem_simulator));
1278 std::vector<int> modem_simulator_count_vec = CF_EXPECT(GET_FLAG_INT_VALUE(
1279 modem_simulator_count));
1280 std::vector<int> modem_simulator_sim_type_vec = CF_EXPECT(GET_FLAG_INT_VALUE(
1281 modem_simulator_sim_type));
1282 std::vector<bool> console_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(console));
1283 std::vector<bool> enable_audio_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_audio));
1284 std::vector<bool> enable_usb_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_usb));
1285 std::vector<bool> start_gnss_proxy_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1286 start_gnss_proxy));
1287 std::vector<bool> enable_bootanimation_vec =
1288 CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_bootanimation));
1289
1290 std::vector<std::string> extra_bootconfig_args_base64_vec =
1291 CF_EXPECT(GET_FLAG_STR_VALUE(extra_bootconfig_args_base64));
1292
1293 std::vector<bool> record_screen_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1294 record_screen));
1295 std::vector<std::string> gem5_debug_file_vec =
1296 CF_EXPECT(GET_FLAG_STR_VALUE(gem5_debug_file));
1297 std::vector<bool> protected_vm_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1298 protected_vm));
1299 std::vector<bool> mte_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(mte));
1300 std::vector<bool> enable_kernel_log_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1301 enable_kernel_log));
1302 std::vector<bool> kgdb_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(kgdb));
1303 std::vector<std::string> boot_slot_vec =
1304 CF_EXPECT(GET_FLAG_STR_VALUE(boot_slot));
1305 std::vector<bool> start_webrtc_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1306 start_webrtc));
1307 std::vector<std::string> webrtc_assets_dir_vec =
1308 CF_EXPECT(GET_FLAG_STR_VALUE(webrtc_assets_dir));
1309 std::vector<std::string> tcp_port_range_vec =
1310 CF_EXPECT(GET_FLAG_STR_VALUE(tcp_port_range));
1311 std::vector<std::string> udp_port_range_vec =
1312 CF_EXPECT(GET_FLAG_STR_VALUE(udp_port_range));
1313 std::vector<bool> vhost_net_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1314 vhost_net));
1315 std::vector<std::string> vhost_user_vsock_vec =
1316 CF_EXPECT(GET_FLAG_STR_VALUE(vhost_user_vsock));
1317 std::vector<std::string> ril_dns_vec =
1318 CF_EXPECT(GET_FLAG_STR_VALUE(ril_dns));
1319
1320 // At this time, FLAGS_enable_sandbox comes from SetDefaultFlagsForCrosvm
1321 std::vector<bool> enable_sandbox_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1322 enable_sandbox));
1323 std::vector<bool> enable_virtiofs_vec =
1324 CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_virtiofs));
1325
1326 std::vector<std::string> gpu_mode_vec =
1327 CF_EXPECT(GET_FLAG_STR_VALUE(gpu_mode));
1328 std::map<int, std::string> calculated_gpu_mode_vec;
1329 std::vector<std::string> gpu_vhost_user_mode_vec =
1330 CF_EXPECT(GET_FLAG_STR_VALUE(gpu_vhost_user_mode));
1331 std::vector<std::string> gpu_renderer_features_vec =
1332 CF_EXPECT(GET_FLAG_STR_VALUE(gpu_renderer_features));
1333 std::vector<std::string> gpu_context_types_vec =
1334 CF_EXPECT(GET_FLAG_STR_VALUE(gpu_context_types));
1335 std::vector<std::string> guest_hwui_renderer_vec =
1336 CF_EXPECT(GET_FLAG_STR_VALUE(guest_hwui_renderer));
1337 std::vector<std::string> guest_renderer_preload_vec =
1338 CF_EXPECT(GET_FLAG_STR_VALUE(guest_renderer_preload));
1339 std::vector<std::string> guest_vulkan_driver_vec =
1340 CF_EXPECT(GET_FLAG_STR_VALUE(guest_vulkan_driver));
1341 std::vector<std::string> frames_socket_path_vec =
1342 CF_EXPECT(GET_FLAG_STR_VALUE(frames_socket_path));
1343
1344 std::vector<std::string> gpu_capture_binary_vec =
1345 CF_EXPECT(GET_FLAG_STR_VALUE(gpu_capture_binary));
1346 std::vector<bool> restart_subprocesses_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
1347 restart_subprocesses));
1348 std::vector<std::string> hwcomposer_vec =
1349 CF_EXPECT(GET_FLAG_STR_VALUE(hwcomposer));
1350 std::vector<bool> enable_gpu_udmabuf_vec =
1351 CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_gpu_udmabuf));
1352 std::vector<bool> smt_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(smt));
1353 std::vector<std::string> crosvm_binary_vec =
1354 CF_EXPECT(GET_FLAG_STR_VALUE(crosvm_binary));
1355 std::vector<std::string> seccomp_policy_dir_vec =
1356 CF_EXPECT(GET_FLAG_STR_VALUE(seccomp_policy_dir));
1357 std::vector<std::string> qemu_binary_dir_vec =
1358 CF_EXPECT(GET_FLAG_STR_VALUE(qemu_binary_dir));
1359
1360 // new instance specific flags (moved from common flags)
1361 std::vector<std::string> gem5_binary_dir_vec =
1362 CF_EXPECT(GET_FLAG_STR_VALUE(gem5_binary_dir));
1363 std::vector<std::string> gem5_checkpoint_dir_vec =
1364 CF_EXPECT(GET_FLAG_STR_VALUE(gem5_checkpoint_dir));
1365 std::vector<std::string> data_policy_vec =
1366 CF_EXPECT(GET_FLAG_STR_VALUE(data_policy));
1367
1368 // multi-dv multi-display proto input
1369 std::vector<std::vector<CuttlefishConfig::DisplayConfig>> instances_display_configs;
1370 if (!FLAGS_displays_textproto.empty() || !FLAGS_displays_binproto.empty()) {
1371 instances_display_configs = CF_EXPECT(ParseDisplaysProto());
1372 }
1373
1374 std::vector<bool> use_balloon_vec =
1375 CF_EXPECT(GET_FLAG_BOOL_VALUE(crosvm_use_balloon));
1376 std::vector<bool> use_rng_vec =
1377 CF_EXPECT(GET_FLAG_BOOL_VALUE(crosvm_use_rng));
1378 std::vector<bool> simple_media_device_vec =
1379 CF_EXPECT(GET_FLAG_BOOL_VALUE(crosvm_simple_media_device));
1380 std::vector<std::string> v4l2_proxy_vec =
1381 CF_EXPECT(GET_FLAG_STR_VALUE(crosvm_v4l2_proxy));
1382 std::vector<bool> use_pmem_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(use_pmem));
1383 const bool restore_from_snapshot = !std::string(FLAGS_snapshot_path).empty();
1384 std::vector<std::string> device_external_network_vec =
1385 CF_EXPECT(GET_FLAG_STR_VALUE(device_external_network));
1386
1387 std::vector<bool> fail_fast_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(fail_fast));
1388
1389 std::vector<bool> vhost_user_block_vec =
1390 CF_EXPECT(GET_FLAG_BOOL_VALUE(vhost_user_block));
1391
1392 std::vector<std::string> mcu_config_vec = CF_EXPECT(GET_FLAG_STR_VALUE(mcu_config_path));
1393
1394 std::vector<std::string> vcpu_config_vec =
1395 CF_EXPECT(GET_FLAG_STR_VALUE(vcpu_config_path));
1396
1397 std::vector<bool> enable_tap_devices_vec =
1398 CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_tap_devices));
1399
1400 std::string default_enable_sandbox = "";
1401 std::string default_enable_virtiofs = "";
1402 std::string comma_str = "";
1403
1404 CHECK(FLAGS_use_overlay || instance_nums.size() == 1)
1405 << "`--use_overlay=false` is incompatible with multiple instances";
1406 CHECK(instance_nums.size() > 0) << "Require at least one instance.";
1407 auto rootcanal_instance_num = *instance_nums.begin() - 1;
1408 if (FLAGS_rootcanal_instance_num > 0) {
1409 rootcanal_instance_num = FLAGS_rootcanal_instance_num - 1;
1410 }
1411 tmp_config_obj.set_rootcanal_args(FLAGS_rootcanal_args);
1412 tmp_config_obj.set_rootcanal_hci_port(7300 + rootcanal_instance_num);
1413 tmp_config_obj.set_rootcanal_link_port(7400 + rootcanal_instance_num);
1414 tmp_config_obj.set_rootcanal_test_port(7500 + rootcanal_instance_num);
1415 tmp_config_obj.set_rootcanal_link_ble_port(7600 + rootcanal_instance_num);
1416 LOG(DEBUG) << "rootcanal_instance_num: " << rootcanal_instance_num;
1417 LOG(DEBUG) << "launch rootcanal: " << (FLAGS_rootcanal_instance_num <= 0);
1418
1419 tmp_config_obj.set_casimir_args(FLAGS_casimir_args);
1420 auto casimir_instance_num = *instance_nums.begin() - 1;
1421 if (FLAGS_casimir_instance_num > 0) {
1422 casimir_instance_num = FLAGS_casimir_instance_num - 1;
1423 }
1424 tmp_config_obj.set_casimir_nci_port(7800 + casimir_instance_num);
1425 tmp_config_obj.set_casimir_rf_port(7900 + casimir_instance_num);
1426 LOG(DEBUG) << "casimir_instance_num: " << casimir_instance_num;
1427 LOG(DEBUG) << "launch casimir: " << (FLAGS_casimir_instance_num <= 0);
1428
1429 int netsim_instance_num = *instance_nums.begin() - 1;
1430 tmp_config_obj.set_netsim_instance_num(netsim_instance_num);
1431 LOG(DEBUG) << "netsim_instance_num: " << netsim_instance_num;
1432 tmp_config_obj.set_netsim_args(FLAGS_netsim_args);
1433 // netsim built-in connector will forward packets to another daemon instance,
1434 // filling the role of bluetooth_connector when is_bt_netsim is true.
1435 auto netsim_connector_instance_num = netsim_instance_num;
1436 if (netsim_instance_num != rootcanal_instance_num) {
1437 netsim_connector_instance_num = rootcanal_instance_num;
1438 }
1439 tmp_config_obj.set_netsim_connector_instance_num(
1440 netsim_connector_instance_num);
1441
1442 // crosvm should create fifos for UWB
1443 auto pica_instance_num = *instance_nums.begin() - 1;
1444 if (FLAGS_pica_instance_num > 0) {
1445 pica_instance_num = FLAGS_pica_instance_num - 1;
1446 }
1447 tmp_config_obj.set_enable_host_uwb(FLAGS_enable_host_uwb || is_uwb_netsim);
1448
1449 // netsim has its own connector for uwb
1450 tmp_config_obj.set_enable_host_uwb_connector(FLAGS_enable_host_uwb &&
1451 !is_uwb_netsim);
1452
1453 if (is_uwb_netsim) {
1454 tmp_config_obj.netsim_radio_enable(CuttlefishConfig::NetsimRadio::Uwb);
1455 }
1456
1457 tmp_config_obj.set_pica_uci_port(7000 + pica_instance_num);
1458 LOG(DEBUG) << "launch pica: " << (FLAGS_pica_instance_num <= 0);
1459
1460 auto straced = android::base::Tokenize(FLAGS_straced_host_executables, ",");
1461 std::set<std::string> straced_set(straced.begin(), straced.end());
1462 tmp_config_obj.set_straced_host_executables(straced_set);
1463
1464 auto vhal_proxy_server_instance_num = *instance_nums.begin() - 1;
1465 if (FLAGS_vhal_proxy_server_instance_num > 0) {
1466 vhal_proxy_server_instance_num = FLAGS_vhal_proxy_server_instance_num - 1;
1467 }
1468 tmp_config_obj.set_vhal_proxy_server_port(
1469 cuttlefish::vhal_proxy_server::kDefaultEthPort +
1470 vhal_proxy_server_instance_num);
1471 LOG(DEBUG) << "launch vhal proxy server: "
1472 << (FLAGS_enable_vhal_proxy_server &&
1473 vhal_proxy_server_instance_num <= 0);
1474
1475 tmp_config_obj.set_kvm_path(FLAGS_kvm_path);
1476 tmp_config_obj.set_vhost_vsock_path(FLAGS_vhost_vsock_path);
1477
1478 // Environment specific configs
1479 // Currently just setting for the default environment
1480 auto environment_name =
1481 std::string("env-") + std::to_string(instance_nums[0]);
1482 auto mutable_env_config = tmp_config_obj.ForEnvironment(environment_name);
1483 auto env_config = const_cast<const CuttlefishConfig&>(tmp_config_obj)
1484 .ForEnvironment(environment_name);
1485
1486 mutable_env_config.set_group_uuid(std::time(0));
1487
1488 mutable_env_config.set_enable_wifi(FLAGS_enable_wifi);
1489
1490 mutable_env_config.set_vhost_user_mac80211_hwsim(
1491 FLAGS_vhost_user_mac80211_hwsim);
1492
1493 mutable_env_config.set_wmediumd_config(FLAGS_wmediumd_config);
1494
1495 // Start wmediumd process for the first instance if
1496 // vhost_user_mac80211_hwsim is not specified.
1497 const bool start_wmediumd = tmp_config_obj.virtio_mac80211_hwsim() &&
1498 FLAGS_vhost_user_mac80211_hwsim.empty() &&
1499 FLAGS_enable_wifi;
1500 if (start_wmediumd) {
1501 auto vhost_user_socket_path =
1502 env_config.PerEnvironmentUdsPath("vhost_user_mac80211");
1503 auto wmediumd_api_socket_path =
1504 env_config.PerEnvironmentUdsPath("wmediumd_api_server");
1505
1506 if (instance_nums.size()) {
1507 mutable_env_config.set_wmediumd_mac_prefix(5554);
1508 }
1509 mutable_env_config.set_vhost_user_mac80211_hwsim(vhost_user_socket_path);
1510 mutable_env_config.set_wmediumd_api_server_socket(wmediumd_api_socket_path);
1511
1512 mutable_env_config.set_start_wmediumd(true);
1513 } else {
1514 mutable_env_config.set_start_wmediumd(false);
1515 }
1516
1517 const auto graphics_availability =
1518 GetGraphicsAvailabilityWithSubprocessCheck();
1519
1520 // Instance specific configs
1521 bool is_first_instance = true;
1522 int instance_index = 0;
1523 auto num_to_webrtc_device_id_flag_map =
1524 CF_EXPECT(CreateNumToWebrtcDeviceIdMap(tmp_config_obj, instance_nums,
1525 FLAGS_webrtc_device_id));
1526 for (const auto& num : instance_nums) {
1527 IfaceConfig iface_config;
1528 if (use_allocd_vec[instance_index]) {
1529 auto iface_opt = AllocateNetworkInterfaces();
1530 if (!iface_opt.has_value()) {
1531 LOG(FATAL) << "Failed to acquire network interfaces";
1532 }
1533 iface_config = iface_opt.value();
1534 } else {
1535 iface_config = DefaultNetworkInterfaces(num);
1536 }
1537
1538 auto instance = tmp_config_obj.ForInstance(num);
1539 auto const_instance =
1540 const_cast<const CuttlefishConfig&>(tmp_config_obj).ForInstance(num);
1541
1542 instance.set_crosvm_use_balloon(use_balloon_vec[instance_index]);
1543 instance.set_crosvm_use_rng(use_rng_vec[instance_index]);
1544 instance.set_crosvm_simple_media_device(simple_media_device_vec[instance_index]);
1545 instance.set_crosvm_v4l2_proxy(v4l2_proxy_vec[instance_index]);
1546 instance.set_use_pmem(use_pmem_vec[instance_index]);
1547 instance.set_bootconfig_supported(guest_configs[instance_index].bootconfig_supported);
1548 instance.set_enable_mouse(guest_configs[instance_index].mouse_supported);
1549 if (guest_configs[instance_index].custom_keyboard_config.has_value()) {
1550 instance.set_custom_keyboard_config(
1551 guest_configs[instance_index].custom_keyboard_config.value());
1552 }
1553 if (guest_configs[instance_index].domkey_mapping_config.has_value()) {
1554 instance.set_domkey_mapping_config(
1555 guest_configs[instance_index].domkey_mapping_config.value());
1556 }
1557 instance.set_filename_encryption_mode(
1558 guest_configs[instance_index].hctr2_supported ? "hctr2" : "cts");
1559 instance.set_use_allocd(use_allocd_vec[instance_index]);
1560 instance.set_enable_audio(enable_audio_vec[instance_index]);
1561 instance.set_enable_usb(enable_usb_vec[instance_index]);
1562 instance.set_enable_gnss_grpc_proxy(start_gnss_proxy_vec[instance_index]);
1563 instance.set_enable_bootanimation(enable_bootanimation_vec[instance_index]);
1564
1565 instance.set_extra_bootconfig_args(FLAGS_extra_bootconfig_args);
1566 if (!extra_bootconfig_args_base64_vec[instance_index].empty()) {
1567 std::vector<uint8_t> decoded_args;
1568 CF_EXPECT(DecodeBase64(extra_bootconfig_args_base64_vec[instance_index],
1569 &decoded_args));
1570 std::string decoded_args_str(decoded_args.begin(), decoded_args.end());
1571 instance.set_extra_bootconfig_args(decoded_args_str);
1572 }
1573
1574 instance.set_record_screen(record_screen_vec[instance_index]);
1575 instance.set_gem5_debug_file(gem5_debug_file_vec[instance_index]);
1576 instance.set_protected_vm(protected_vm_vec[instance_index]);
1577 instance.set_mte(mte_vec[instance_index]);
1578 instance.set_enable_kernel_log(enable_kernel_log_vec[instance_index]);
1579 if (!boot_slot_vec[instance_index].empty()) {
1580 instance.set_boot_slot(boot_slot_vec[instance_index]);
1581 }
1582
1583 instance.set_crosvm_binary(crosvm_binary_vec[instance_index]);
1584 instance.set_seccomp_policy_dir(seccomp_policy_dir_vec[instance_index]);
1585 instance.set_qemu_binary_dir(qemu_binary_dir_vec[instance_index]);
1586
1587 // wifi, bluetooth, Thread, connectivity setup
1588
1589 instance.set_vhost_net(vhost_net_vec[instance_index]);
1590 instance.set_openthread_node_id(num);
1591
1592 // end of wifi, bluetooth, Thread, connectivity setup
1593
1594 instance.set_audio_output_streams_count(
1595 guest_configs[instance_index].output_audio_streams_count);
1596
1597 if (vhost_user_vsock_vec[instance_index] == kVhostUserVsockModeAuto) {
1598 std::set<Arch> default_on_arch = {Arch::Arm64};
1599 if (guest_configs[instance_index].vhost_user_vsock) {
1600 instance.set_vhost_user_vsock(true);
1601 } else if (tmp_config_obj.vm_manager() == VmmMode::kCrosvm &&
1602 default_on_arch.find(
1603 guest_configs[instance_index].target_arch) !=
1604 default_on_arch.end()) {
1605 instance.set_vhost_user_vsock(true);
1606 } else {
1607 instance.set_vhost_user_vsock(false);
1608 }
1609 } else if (vhost_user_vsock_vec[instance_index] ==
1610 kVhostUserVsockModeTrue) {
1611 CHECK(tmp_config_obj.vm_manager() == VmmMode::kCrosvm)
1612 << "For now, only crosvm supports vhost_user_vsock";
1613 instance.set_vhost_user_vsock(true);
1614 } else if (vhost_user_vsock_vec[instance_index] ==
1615 kVhostUserVsockModeFalse) {
1616 instance.set_vhost_user_vsock(false);
1617 } else {
1618 CHECK(false)
1619 << "--vhost_user_vsock should be one of 'auto', 'true', 'false', but "
1620 << vhost_user_vsock_vec[instance_index];
1621 }
1622
1623 if (use_random_serial_vec[instance_index]) {
1624 instance.set_serial_number(
1625 RandomSerialNumber("CFCVD" + std::to_string(num)));
1626 } else {
1627 instance.set_serial_number(FLAGS_serial_number + std::to_string(num));
1628 }
1629
1630 instance.set_grpc_socket_path(const_instance.PerInstanceGrpcSocketPath(""));
1631
1632 // call this before all stuff that has vsock server: e.g. touchpad, keyboard, etc
1633 const auto vsock_guest_cid = vsock_guest_cid_vec[instance_index] + num - GetInstance();
1634 instance.set_vsock_guest_cid(vsock_guest_cid);
1635 auto calc_vsock_port = [vsock_guest_cid](const int base_port) {
1636 // a base (vsock) port is like 9600 for modem_simulator, etc
1637 return cuttlefish::GetVsockServerPort(base_port, vsock_guest_cid);
1638 };
1639
1640 const auto vsock_guest_group = vsock_guest_group_vec[instance_index];
1641 instance.set_vsock_guest_group(vsock_guest_group);
1642
1643 instance.set_session_id(iface_config.mobile_tap.session_id);
1644
1645 instance.set_cpus(cpus_vec[instance_index]);
1646 // make sure all instances have multiple of 2 then SMT mode
1647 // if any of instance doesn't have multiple of 2 then NOT SMT
1648 CF_EXPECT(!smt_vec[instance_index] || cpus_vec[instance_index] % 2 == 0,
1649 "CPUs must be a multiple of 2 in SMT mode");
1650 instance.set_smt(smt_vec[instance_index]);
1651
1652 // new instance specific flags (moved from common flags)
1653 CF_EXPECT(instance_index < guest_configs.size(),
1654 "instance_index " << instance_index << " out of boundary "
1655 << guest_configs.size());
1656 instance.set_target_arch(guest_configs[instance_index].target_arch);
1657 instance.set_device_type(guest_configs[instance_index].device_type);
1658 instance.set_guest_android_version(
1659 guest_configs[instance_index].android_version_number);
1660 instance.set_console(console_vec[instance_index]);
1661 instance.set_kgdb(console_vec[instance_index] && kgdb_vec[instance_index]);
1662 instance.set_blank_data_image_mb(blank_data_image_mb_vec[instance_index]);
1663 instance.set_gdb_port(gdb_port_vec[instance_index]);
1664 instance.set_fail_fast(fail_fast_vec[instance_index]);
1665 if (vhost_user_block_vec[instance_index]) {
1666 CF_EXPECT_EQ(tmp_config_obj.vm_manager(), VmmMode::kCrosvm,
1667 "vhost-user block only supported on crosvm");
1668 }
1669 instance.set_vhost_user_block(vhost_user_block_vec[instance_index]);
1670
1671 std::optional<std::vector<CuttlefishConfig::DisplayConfig>>
1672 binding_displays_configs;
1673 auto displays_configs_bindings =
1674 injector.getMultibindings<DisplaysConfigs>();
1675 CF_EXPECT_EQ(displays_configs_bindings.size(), 1,
1676 "Expected a single binding?");
1677 if (auto configs = displays_configs_bindings[0]->GetConfigs();
1678 !configs.empty()) {
1679 binding_displays_configs = configs;
1680 }
1681
1682 std::vector<CuttlefishConfig::DisplayConfig> display_configs;
1683 // assume displays proto input has higher priority than original display inputs
1684 if (!FLAGS_displays_textproto.empty() || !FLAGS_displays_binproto.empty()) {
1685 if (instance_index < instances_display_configs.size()) {
1686 display_configs = instances_display_configs[instance_index];
1687 } // else display_configs is an empty vector
1688 } else if (binding_displays_configs) {
1689 display_configs = *binding_displays_configs;
1690 }
1691
1692 if (x_res_vec[instance_index] > 0 && y_res_vec[instance_index] > 0) {
1693 if (display_configs.empty()) {
1694 display_configs.push_back({
1695 .width = x_res_vec[instance_index],
1696 .height = y_res_vec[instance_index],
1697 .dpi = dpi_vec[instance_index],
1698 .refresh_rate_hz = refresh_rate_hz_vec[instance_index],
1699 .overlays = overlays_vec[instance_index],
1700 });
1701 } else {
1702 LOG(WARNING)
1703 << "Ignoring --x_res and --y_res when --display specified.";
1704 }
1705 }
1706 instance.set_display_configs(display_configs);
1707
1708 auto touchpad_configs_bindings =
1709 injector.getMultibindings<TouchpadsConfigs>();
1710 CF_EXPECT_EQ(touchpad_configs_bindings.size(), 1,
1711 "Expected a single binding?");
1712 auto touchpad_configs = touchpad_configs_bindings[0]->GetConfigs();
1713 instance.set_touchpad_configs(touchpad_configs);
1714
1715 instance.set_memory_mb(memory_mb_vec[instance_index]);
1716 instance.set_ddr_mem_mb(memory_mb_vec[instance_index] * 1.2);
1717 CF_EXPECT(
1718 instance.set_setupwizard_mode(setupwizard_mode_vec[instance_index]));
1719 instance.set_userdata_format(userdata_format_vec[instance_index]);
1720 instance.set_guest_enforce_security(guest_enforce_security_vec[instance_index]);
1721 instance.set_pause_in_bootloader(pause_in_bootloader_vec[instance_index]);
1722 instance.set_run_as_daemon(daemon_vec[instance_index]);
1723 instance.set_enable_modem_simulator(enable_modem_simulator_vec[instance_index] &&
1724 !enable_minimal_mode_vec[instance_index]);
1725 instance.set_modem_simulator_instance_number(modem_simulator_count_vec[instance_index]);
1726 instance.set_modem_simulator_sim_type(modem_simulator_sim_type_vec[instance_index]);
1727
1728 instance.set_enable_minimal_mode(enable_minimal_mode_vec[instance_index]);
1729 instance.set_camera_server_port(camera_server_port_vec[instance_index]);
1730 instance.set_gem5_binary_dir(gem5_binary_dir_vec[instance_index]);
1731 instance.set_gem5_checkpoint_dir(gem5_checkpoint_dir_vec[instance_index]);
1732 instance.set_data_policy(data_policy_vec[instance_index]);
1733
1734 instance.set_mobile_bridge_name(StrForInstance("cvd-mbr-", num));
1735 instance.set_wifi_bridge_name("cvd-wbr");
1736 instance.set_ethernet_bridge_name("cvd-ebr");
1737 instance.set_mobile_tap_name(iface_config.mobile_tap.name);
1738
1739 CF_EXPECT(ConfigureNetworkSettings(ril_dns_vec[instance_index],
1740 const_instance, instance));
1741
1742 if (NetworkInterfaceExists(iface_config.non_bridged_wireless_tap.name) &&
1743 tmp_config_obj.virtio_mac80211_hwsim()) {
1744 instance.set_use_bridged_wifi_tap(false);
1745 instance.set_wifi_tap_name(iface_config.non_bridged_wireless_tap.name);
1746 } else {
1747 instance.set_use_bridged_wifi_tap(true);
1748 instance.set_wifi_tap_name(iface_config.bridged_wireless_tap.name);
1749 }
1750
1751 instance.set_ethernet_tap_name(iface_config.ethernet_tap.name);
1752
1753 instance.set_uuid(FLAGS_uuid);
1754
1755 instance.set_environment_name(environment_name);
1756
1757 instance.set_modem_simulator_host_id(1000 + num); // Must be 4 digits
1758 // the deprecated vnc was 6444 + num - 1, and qemu_vnc was vnc - 5900
1759 instance.set_qemu_vnc_server_port(544 + num - 1);
1760 instance.set_adb_host_port(6520 + num - 1);
1761 instance.set_adb_ip_and_port("0.0.0.0:" + std::to_string(6520 + num - 1));
1762 instance.set_fastboot_host_port(const_instance.adb_host_port());
1763
1764 std::uint8_t ethernet_mac[6] = {};
1765 std::uint8_t mobile_mac[6] = {};
1766 std::uint8_t wifi_mac[6] = {};
1767 std::uint8_t ethernet_ipv6[16] = {};
1768 GenerateEthMacForInstance(num - 1, ethernet_mac);
1769 GenerateMobileMacForInstance(num - 1, mobile_mac);
1770 GenerateWifiMacForInstance(num - 1, wifi_mac);
1771 GenerateCorrespondingIpv6ForMac(ethernet_mac, ethernet_ipv6);
1772
1773 instance.set_ethernet_mac(MacAddressToString(ethernet_mac));
1774 instance.set_mobile_mac(MacAddressToString(mobile_mac));
1775 instance.set_wifi_mac(MacAddressToString(wifi_mac));
1776 instance.set_ethernet_ipv6(Ipv6ToString(ethernet_ipv6));
1777
1778 instance.set_tombstone_receiver_port(calc_vsock_port(6600));
1779 instance.set_audiocontrol_server_port(
1780 9410); /* OK to use the same port number across instances */
1781 instance.set_lights_server_port(calc_vsock_port(6900));
1782
1783 // gpu related settings
1784 const std::string gpu_mode = CF_EXPECT(ConfigureGpuSettings(
1785 graphics_availability, gpu_mode_vec[instance_index],
1786 gpu_vhost_user_mode_vec[instance_index],
1787 gpu_renderer_features_vec[instance_index],
1788 gpu_context_types_vec[instance_index],
1789 guest_hwui_renderer_vec[instance_index],
1790 guest_renderer_preload_vec[instance_index], vmm_mode,
1791 guest_configs[instance_index], instance));
1792 calculated_gpu_mode_vec[instance_index] = gpu_mode_vec[instance_index];
1793
1794 instance.set_restart_subprocesses(restart_subprocesses_vec[instance_index]);
1795 instance.set_gpu_capture_binary(gpu_capture_binary_vec[instance_index]);
1796 if (!gpu_capture_binary_vec[instance_index].empty()) {
1797 CF_EXPECT(gpu_mode == kGpuModeGfxstream ||
1798 gpu_mode == kGpuModeGfxstreamGuestAngle,
1799 "GPU capture only supported with --gpu_mode=gfxstream");
1800
1801 // GPU capture runs in a detached mode where the "launcher" process
1802 // intentionally exits immediately.
1803 CF_EXPECT(!restart_subprocesses_vec[instance_index],
1804 "GPU capture only supported with --norestart_subprocesses");
1805 }
1806
1807 instance.set_hwcomposer(hwcomposer_vec[instance_index]);
1808 if (!hwcomposer_vec[instance_index].empty()) {
1809 if (hwcomposer_vec[instance_index] == kHwComposerRanchu) {
1810 CF_EXPECT(gpu_mode != kGpuModeDrmVirgl,
1811 "ranchu hwcomposer not supported with --gpu_mode=drm_virgl");
1812 }
1813 }
1814
1815 if (hwcomposer_vec[instance_index] == kHwComposerAuto) {
1816 if (gpu_mode == kGpuModeDrmVirgl) {
1817 instance.set_hwcomposer(kHwComposerDrm);
1818 } else if (gpu_mode == kGpuModeNone) {
1819 instance.set_hwcomposer(kHwComposerNone);
1820 } else {
1821 instance.set_hwcomposer(kHwComposerRanchu);
1822 }
1823 }
1824
1825 instance.set_enable_gpu_udmabuf(enable_gpu_udmabuf_vec[instance_index]);
1826
1827 instance.set_gpu_context_types(gpu_context_types_vec[instance_index]);
1828 instance.set_guest_vulkan_driver(guest_vulkan_driver_vec[instance_index]);
1829
1830 instance.set_guest_uses_bgra_framebuffers(
1831 guest_configs[instance_index].supports_bgra_framebuffers);
1832
1833 if (!frames_socket_path_vec[instance_index].empty()) {
1834 instance.set_frames_socket_path(frames_socket_path_vec[instance_index]);
1835 } else {
1836 instance.set_frames_socket_path(
1837 const_instance.PerInstanceInternalUdsPath("frames.sock"));
1838 }
1839
1840 // 1. Keep original code order SetCommandLineOptionWithMode("enable_sandbox")
1841 // then set_enable_sandbox later.
1842 // 2. SetCommandLineOptionWithMode condition: if gpu_mode or console,
1843 // then SetCommandLineOptionWithMode false as original code did,
1844 // otherwise keep default enable_sandbox value.
1845 // 3. Sepolicy rules need to be updated to support gpu mode. Temporarily disable
1846 // auto-enabling sandbox when gpu is enabled (b/152323505).
1847 default_enable_sandbox += comma_str;
1848 default_enable_virtiofs += comma_str;
1849 if (gpu_mode != kGpuModeGuestSwiftshader) {
1850 // original code, just moved to each instance setting block
1851 default_enable_sandbox += "false";
1852 default_enable_virtiofs += "false";
1853 } else {
1854 default_enable_sandbox +=
1855 fmt::format("{}", enable_sandbox_vec[instance_index]);
1856 default_enable_virtiofs +=
1857 fmt::format("{}", enable_virtiofs_vec[instance_index]);
1858 }
1859 comma_str = ",";
1860
1861 CF_EXPECT(vmm->ConfigureGraphics(const_instance));
1862
1863 // end of gpu related settings
1864
1865 instance.set_gnss_grpc_proxy_server_port(7200 + num -1);
1866 instance.set_gnss_file_path(gnss_file_paths[instance_index]);
1867 instance.set_fixed_location_file_path(fixed_location_file_paths[instance_index]);
1868
1869 std::vector<std::string> virtual_disk_paths;
1870
1871 bool os_overlay = true;
1872 os_overlay &= !protected_vm_vec[instance_index];
1873 // Gem5 already uses CoW wrappers around disk images
1874 os_overlay &= vmm_mode != VmmMode::kGem5;
1875 os_overlay &= FLAGS_use_overlay;
1876 if (os_overlay) {
1877 auto path = const_instance.PerInstancePath("overlay.img");
1878 virtual_disk_paths.push_back(path);
1879 } else {
1880 virtual_disk_paths.push_back(const_instance.os_composite_disk_path());
1881 }
1882
1883 bool persistent_disk = true;
1884 persistent_disk &= !protected_vm_vec[instance_index];
1885 persistent_disk &= vmm_mode != VmmMode::kGem5;
1886 if (persistent_disk) {
1887 #ifdef __APPLE__
1888 const std::string persistent_composite_img_base =
1889 "persistent_composite.img";
1890 #else
1891 const bool is_vm_qemu_cli =
1892 (tmp_config_obj.vm_manager() == VmmMode::kQemu);
1893 const std::string persistent_composite_img_base =
1894 is_vm_qemu_cli ? "persistent_composite_overlay.img"
1895 : "persistent_composite.img";
1896 #endif
1897 auto path =
1898 const_instance.PerInstancePath(persistent_composite_img_base.data());
1899 virtual_disk_paths.push_back(path);
1900 }
1901
1902 instance.set_use_sdcard(use_sdcard_vec[instance_index]);
1903
1904 bool sdcard = true;
1905 sdcard &= use_sdcard_vec[instance_index];
1906 sdcard &= !protected_vm_vec[instance_index];
1907 if (sdcard) {
1908 if (tmp_config_obj.vm_manager() == VmmMode::kQemu) {
1909 virtual_disk_paths.push_back(const_instance.sdcard_overlay_path());
1910 } else {
1911 virtual_disk_paths.push_back(const_instance.sdcard_path());
1912 }
1913 }
1914
1915 instance.set_virtual_disk_paths(virtual_disk_paths);
1916
1917 // We'd like to set mac prefix to be 5554, 5555, 5556, ... in normal cases.
1918 // When --base_instance_num=3, this might be 5556, 5557, 5558, ... (skipping
1919 // first two)
1920 instance.set_wifi_mac_prefix(5554 + (num - 1));
1921
1922 // streaming, webrtc setup
1923 instance.set_enable_webrtc(start_webrtc_vec[instance_index]);
1924 instance.set_webrtc_assets_dir(webrtc_assets_dir_vec[instance_index]);
1925
1926 auto tcp_range = ParsePortRange(tcp_port_range_vec[instance_index]);
1927 instance.set_webrtc_tcp_port_range(tcp_range);
1928
1929 auto udp_range = ParsePortRange(udp_port_range_vec[instance_index]);
1930 instance.set_webrtc_udp_port_range(udp_range);
1931
1932 // end of streaming, webrtc setup
1933
1934 instance.set_start_webrtc_signaling_server(false);
1935
1936 CF_EXPECT(Contains(num_to_webrtc_device_id_flag_map, num),
1937 "Error in looking up num to webrtc_device_id_flag_map");
1938 instance.set_webrtc_device_id(num_to_webrtc_device_id_flag_map[num]);
1939
1940 instance.set_group_id(FLAGS_group_id);
1941
1942 if (!is_first_instance || !start_webrtc_vec[instance_index]) {
1943 // Only the first instance starts the signaling server or proxy
1944 instance.set_start_webrtc_signaling_server(false);
1945 instance.set_start_webrtc_sig_server_proxy(false);
1946 } else {
1947 auto port = 8443 + num - 1;
1948 // Change the signaling server port for all instances
1949 tmp_config_obj.set_sig_server_port(port);
1950 // Either the signaling server or the proxy is started, never both
1951 instance.set_start_webrtc_signaling_server(FLAGS_start_webrtc_sig_server);
1952 // The proxy is only started if the host operator is available
1953 instance.set_start_webrtc_sig_server_proxy(
1954 cuttlefish::FileIsSocket(HOST_OPERATOR_SOCKET_PATH) &&
1955 !FLAGS_start_webrtc_sig_server);
1956 }
1957
1958 instance.set_start_netsim(is_first_instance && is_any_netsim);
1959
1960 instance.set_start_rootcanal(is_first_instance && !is_bt_netsim &&
1961 (FLAGS_rootcanal_instance_num <= 0));
1962
1963 instance.set_start_casimir(is_first_instance && FLAGS_casimir_instance_num <= 0);
1964
1965 instance.set_start_pica(is_first_instance && !is_uwb_netsim &&
1966 FLAGS_pica_instance_num <= 0);
1967 instance.set_start_vhal_proxy_server(
1968 is_first_instance && FLAGS_enable_vhal_proxy_server &&
1969 FLAGS_vhal_proxy_server_instance_num <= 0);
1970
1971 // TODO(b/288987294) Remove this when separating environment is done
1972 bool instance_start_wmediumd = is_first_instance && start_wmediumd;
1973 instance.set_start_wmediumd_instance(instance_start_wmediumd);
1974
1975 if (!FLAGS_ap_rootfs_image.empty() && !FLAGS_ap_kernel_image.empty() &&
1976 const_instance.start_wmediumd_instance()) {
1977 // TODO(264537774): Ubuntu grub modules / grub monoliths cannot be used to boot
1978 // 64 bit kernel using 32 bit u-boot / grub.
1979 // Enable this code back after making sure it works across all popular environments
1980 // if (CanGenerateEsp(guest_configs[0].target_arch)) {
1981 // instance.set_ap_boot_flow(CuttlefishConfig::InstanceSpecific::APBootFlow::Grub);
1982 // } else {
1983 // instance.set_ap_boot_flow(CuttlefishConfig::InstanceSpecific::APBootFlow::LegacyDirect);
1984 // }
1985 instance.set_ap_boot_flow(CuttlefishConfig::InstanceSpecific::APBootFlow::LegacyDirect);
1986 } else {
1987 instance.set_ap_boot_flow(CuttlefishConfig::InstanceSpecific::APBootFlow::None);
1988 }
1989
1990 is_first_instance = false;
1991
1992 // instance.modem_simulator_ports := "" or "[port,]*port"
1993 if (modem_simulator_count_vec[instance_index] > 0) {
1994 std::stringstream modem_ports;
1995 for (auto index {0}; index < modem_simulator_count_vec[instance_index] - 1; index++) {
1996 auto port = 9600 + (modem_simulator_count_vec[instance_index] * (num - 1)) + index;
1997 modem_ports << calc_vsock_port(port) << ",";
1998 }
1999 auto port = 9600 + (modem_simulator_count_vec[instance_index] * (num - 1)) +
2000 modem_simulator_count_vec[instance_index] - 1;
2001 modem_ports << calc_vsock_port(port);
2002 instance.set_modem_simulator_ports(modem_ports.str());
2003 } else {
2004 instance.set_modem_simulator_ports("");
2005 }
2006
2007 auto external_network_mode = CF_EXPECT(
2008 ParseExternalNetworkMode(device_external_network_vec[instance_index]));
2009 CF_EXPECT(external_network_mode == ExternalNetworkMode::kTap ||
2010 vmm_mode == VmmMode::kQemu,
2011 "TODO(b/286284441): slirp only works on QEMU");
2012 instance.set_external_network_mode(external_network_mode);
2013
2014 if (!mcu_config_vec[instance_index].empty()) {
2015 auto mcu_cfg_path = mcu_config_vec[instance_index];
2016 CF_EXPECT(FileExists(mcu_cfg_path), "MCU config file does not exist");
2017 std::string file_content;
2018 using android::base::ReadFileToString;
2019 CF_EXPECT(ReadFileToString(mcu_cfg_path.c_str(), &file_content,
2020 /* follow_symlinks */ true),
2021 "Failed to read mcu config file");
2022 instance.set_mcu(CF_EXPECT(ParseJson(file_content), "Failed parsing JSON file"));
2023 }
2024
2025 if (!vcpu_config_vec[instance_index].empty()) {
2026 auto vcpu_cfg_path = vcpu_config_vec[instance_index];
2027 CF_EXPECT(FileExists(vcpu_cfg_path), "vCPU config file does not exist");
2028 instance.set_vcpu_config_path(AbsolutePath(vcpu_cfg_path));
2029 }
2030
2031 if (!guest_configs[instance_index].ti50_emulator.empty()) {
2032 auto ti50_emulator =
2033 DefaultHostArtifactsPath(guest_configs[instance_index].ti50_emulator);
2034 CF_EXPECT(FileExists(ti50_emulator),
2035 "ti50 emulator binary does not exist");
2036 instance.set_ti50_emulator(ti50_emulator);
2037 }
2038
2039 instance.set_enable_tap_devices(enable_tap_devices_vec[instance_index]);
2040
2041 instance_index++;
2042 } // end of num_instances loop
2043
2044 std::vector<std::string> names;
2045 names.reserve(tmp_config_obj.Instances().size());
2046 for (const auto& instance : tmp_config_obj.Instances()) {
2047 names.emplace_back(instance.instance_name());
2048 }
2049 tmp_config_obj.set_instance_names(names);
2050
2051 // keep legacy values for acloud or other related tools (b/262284453)
2052 tmp_config_obj.set_crosvm_binary(crosvm_binary_vec[0]);
2053
2054 // Keep the original code here to set enable_sandbox commandline flag value
2055 SetCommandLineOptionWithMode("enable_sandbox", default_enable_sandbox.c_str(),
2056 google::FlagSettingMode::SET_FLAGS_DEFAULT);
2057
2058 // Set virtiofs to match enable_sandbox as it did before adding
2059 // enable_virtiofs flag.
2060 SetCommandLineOptionWithMode("enable_virtiofs",
2061 default_enable_sandbox.c_str(),
2062 google::FlagSettingMode::SET_FLAGS_DEFAULT);
2063
2064 // After SetCommandLineOptionWithMode,
2065 // default flag values changed, need recalculate name_to_default_value
2066 name_to_default_value = CurrentFlagsToDefaultValue();
2067 // After last SetCommandLineOptionWithMode, we could set these special flags
2068 enable_sandbox_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
2069 enable_sandbox));
2070 enable_virtiofs_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(enable_virtiofs));
2071
2072 instance_index = 0;
2073 for (const auto& num : instance_nums) {
2074 auto instance = tmp_config_obj.ForInstance(num);
2075 instance.set_enable_sandbox(enable_sandbox_vec[instance_index]);
2076 instance.set_enable_virtiofs(enable_virtiofs_vec[instance_index]);
2077 instance_index++;
2078 }
2079
2080 const auto& environment_specific =
2081 (static_cast<const CuttlefishConfig&>(tmp_config_obj))
2082 .ForEnvironment(environment_name);
2083 CF_EXPECT(CheckSnapshotCompatible(
2084 FLAGS_snapshot_compatible &&
2085 (tmp_config_obj.vm_manager() == VmmMode::kCrosvm) &&
2086 instance_nums.size() == 1,
2087 calculated_gpu_mode_vec),
2088 "The set of flags is incompatible with snapshot");
2089
2090 CF_EXPECT(DiskImageFlagsVectorization(tmp_config_obj, fetcher_config));
2091
2092 return tmp_config_obj;
2093 }
2094
SetDefaultFlagsForQemu(const std::vector<GuestConfig> & guest_configs,std::map<std::string,std::string> & name_to_default_value)2095 Result<void> SetDefaultFlagsForQemu(
2096 const std::vector<GuestConfig>& guest_configs,
2097 std::map<std::string, std::string>& name_to_default_value) {
2098 auto instance_nums =
2099 CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
2100 int32_t instances_size = instance_nums.size();
2101 std::vector<std::string> gpu_mode_vec =
2102 CF_EXPECT(GET_FLAG_STR_VALUE(gpu_mode));
2103 std::vector<bool> start_webrtc_vec =
2104 CF_EXPECT(GET_FLAG_BOOL_VALUE(start_webrtc));
2105 std::vector<std::string> system_image_dir =
2106 CF_EXPECT(GET_FLAG_STR_VALUE(system_image_dir));
2107 std::string curr_bootloader = "";
2108 std::string curr_android_efi_loader = "";
2109 std::string default_bootloader = "";
2110 std::string default_android_efi_loader = "";
2111 std::string default_start_webrtc = "";
2112
2113 for (int instance_index = 0; instance_index < instance_nums.size();
2114 instance_index++) {
2115 if (instance_index >= system_image_dir.size()) {
2116 curr_bootloader = system_image_dir[0];
2117 curr_android_efi_loader = system_image_dir[0];
2118 } else {
2119 curr_bootloader = system_image_dir[instance_index];
2120 curr_android_efi_loader = system_image_dir[instance_index];
2121 }
2122 curr_bootloader += "/bootloader";
2123 curr_android_efi_loader += "/android_efi_loader.efi";
2124
2125 // /bootloader isn't presented in the output folder by default and can be
2126 // only fetched by --bootloader in fetch_cvd, so pick it only in case
2127 // it's presented.
2128 if (!FileExists(curr_bootloader)) {
2129 // Fallback to default bootloader
2130 curr_bootloader = DefaultHostArtifactsPath(std::format(
2131 "etc/bootloader_{}/bootloader.qemu",
2132 DefaultBootloaderArchDir(guest_configs[instance_index].target_arch)));
2133 }
2134
2135 if (instance_index > 0) {
2136 default_bootloader += ",";
2137 default_android_efi_loader += ",";
2138 default_start_webrtc += ",";
2139 }
2140
2141 default_bootloader += curr_bootloader;
2142 // EFI loader isn't presented in the output folder by default and can be
2143 // only fetched by --uefi_app_build in fetch_cvd, so pick it only in case
2144 // it's presented.
2145 if (FileExists(curr_android_efi_loader)) {
2146 default_android_efi_loader += curr_android_efi_loader;
2147 }
2148 if (gpu_mode_vec[instance_index] == kGpuModeGuestSwiftshader &&
2149 !start_webrtc_vec[instance_index]) {
2150 // This makes WebRTC the default streamer unless the user requests
2151 // another via a --star_<streamer> flag, while at the same time it's
2152 // possible to run without any streamer by setting --start_webrtc=false.
2153 default_start_webrtc += "true";
2154 } else {
2155 default_start_webrtc +=
2156 fmt::format("{}", start_webrtc_vec[instance_index]);
2157 }
2158 }
2159 // This is the 1st place to set "start_webrtc" flag value
2160 // for now, we don't set non-default options for QEMU
2161 SetCommandLineOptionWithMode("start_webrtc", default_start_webrtc.c_str(),
2162 SET_FLAGS_DEFAULT);
2163
2164 SetCommandLineOptionWithMode("bootloader", default_bootloader.c_str(),
2165 SET_FLAGS_DEFAULT);
2166 SetCommandLineOptionWithMode("android_efi_loader",
2167 default_android_efi_loader.c_str(),
2168 SET_FLAGS_DEFAULT);
2169 return {};
2170 }
2171
SetDefaultFlagsForCrosvm(const std::vector<GuestConfig> & guest_configs,std::map<std::string,std::string> & name_to_default_value)2172 Result<void> SetDefaultFlagsForCrosvm(
2173 const std::vector<GuestConfig>& guest_configs,
2174 std::map<std::string, std::string>& name_to_default_value) {
2175 auto instance_nums =
2176 CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
2177 int32_t instances_size = instance_nums.size();
2178 std::vector<bool> start_webrtc_vec =
2179 CF_EXPECT(GET_FLAG_BOOL_VALUE(start_webrtc));
2180 std::string default_start_webrtc = "";
2181
2182 std::set<Arch> supported_archs{Arch::X86_64};
2183 bool default_enable_sandbox =
2184 supported_archs.find(HostArch()) != supported_archs.end() &&
2185 EnsureDirectoryExists(kCrosvmVarEmptyDir).ok() &&
2186 IsDirectoryEmpty(kCrosvmVarEmptyDir) && !IsRunningInContainer();
2187
2188 std::vector<std::string> system_image_dir =
2189 CF_EXPECT(GET_FLAG_STR_VALUE(system_image_dir));
2190 std::string curr_android_efi_loader = "";
2191 std::string curr_bootloader = "";
2192 std::string default_android_efi_loader = "";
2193 std::string default_bootloader = "";
2194 std::string default_enable_sandbox_str = "";
2195 for (int instance_index = 0; instance_index < instance_nums.size();
2196 instance_index++) {
2197 if (instance_index >= system_image_dir.size()) {
2198 curr_bootloader = system_image_dir[0];
2199 curr_android_efi_loader = system_image_dir[0];
2200 } else {
2201 curr_bootloader = system_image_dir[instance_index];
2202 curr_android_efi_loader = system_image_dir[instance_index];
2203 }
2204 curr_bootloader += "/bootloader";
2205 curr_android_efi_loader += "/android_efi_loader.efi";
2206
2207 // /bootloader isn't presented in the output folder by default and can be
2208 // only fetched by --bootloader in fetch_cvd, so pick it only in case
2209 // it's presented.
2210 if (!FileExists(curr_bootloader)) {
2211 // Fallback to default bootloader
2212 curr_bootloader = DefaultHostArtifactsPath(std::format(
2213 "etc/bootloader_{}/bootloader.crosvm",
2214 DefaultBootloaderArchDir(guest_configs[instance_index].target_arch)));
2215 }
2216
2217 if (instance_index > 0) {
2218 default_bootloader += ",";
2219 default_android_efi_loader += ",";
2220 default_enable_sandbox_str += ",";
2221 default_start_webrtc += ",";
2222 }
2223
2224 default_bootloader += curr_bootloader;
2225 // EFI loader isn't presented in the output folder by default and can be
2226 // only fetched by --uefi_app_build in fetch_cvd, so pick it only in case
2227 // it's presented.
2228 if (FileExists(curr_android_efi_loader)) {
2229 default_android_efi_loader += curr_android_efi_loader;
2230 }
2231 default_enable_sandbox_str += fmt::format("{}", default_enable_sandbox);
2232 if (!start_webrtc_vec[instance_index]) {
2233 // This makes WebRTC the default streamer unless the user requests
2234 // another via a --star_<streamer> flag, while at the same time it's
2235 // possible to run without any streamer by setting --start_webrtc=false.
2236 default_start_webrtc += "true";
2237 } else {
2238 default_start_webrtc +=
2239 fmt::format("{}", start_webrtc_vec[instance_index]);
2240 }
2241 }
2242 SetCommandLineOptionWithMode("bootloader", default_bootloader.c_str(),
2243 SET_FLAGS_DEFAULT);
2244 SetCommandLineOptionWithMode("android_efi_loader",
2245 default_android_efi_loader.c_str(),
2246 SET_FLAGS_DEFAULT);
2247 // This is the 1st place to set "start_webrtc" flag value
2248 SetCommandLineOptionWithMode("start_webrtc", default_start_webrtc.c_str(),
2249 SET_FLAGS_DEFAULT);
2250 // This is the 1st place to set "enable_sandbox" flag value
2251 SetCommandLineOptionWithMode(
2252 "enable_sandbox", default_enable_sandbox_str.c_str(), SET_FLAGS_DEFAULT);
2253 SetCommandLineOptionWithMode(
2254 "enable_virtiofs", default_enable_sandbox_str.c_str(), SET_FLAGS_DEFAULT);
2255 return {};
2256 }
2257
SetDefaultFlagsForGem5()2258 void SetDefaultFlagsForGem5() {
2259 // TODO: Add support for gem5 gpu models
2260 SetCommandLineOptionWithMode("gpu_mode", kGpuModeGuestSwiftshader,
2261 SET_FLAGS_DEFAULT);
2262
2263 SetCommandLineOptionWithMode("cpus", "1", SET_FLAGS_DEFAULT);
2264 }
2265
SetDefaultFlagsForMcu()2266 void SetDefaultFlagsForMcu() {
2267 auto path = DefaultHostArtifactsPath("etc/mcu_config.json");
2268 if (!CanAccess(path, R_OK)) {
2269 return;
2270 }
2271 SetCommandLineOptionWithMode("mcu_config_path", path.c_str(), SET_FLAGS_DEFAULT);
2272 }
2273
SetDefaultFlagsForOpenwrt(Arch target_arch)2274 void SetDefaultFlagsForOpenwrt(Arch target_arch) {
2275 if (target_arch == Arch::X86_64) {
2276 SetCommandLineOptionWithMode(
2277 "ap_kernel_image",
2278 DefaultHostArtifactsPath("etc/openwrt/images/openwrt_kernel_x86_64")
2279 .c_str(),
2280 SET_FLAGS_DEFAULT);
2281 SetCommandLineOptionWithMode(
2282 "ap_rootfs_image",
2283 DefaultHostArtifactsPath("etc/openwrt/images/openwrt_rootfs_x86_64")
2284 .c_str(),
2285 SET_FLAGS_DEFAULT);
2286 } else if (target_arch == Arch::Arm64) {
2287 SetCommandLineOptionWithMode(
2288 "ap_kernel_image",
2289 DefaultHostArtifactsPath("etc/openwrt/images/openwrt_kernel_aarch64")
2290 .c_str(),
2291 SET_FLAGS_DEFAULT);
2292 SetCommandLineOptionWithMode(
2293 "ap_rootfs_image",
2294 DefaultHostArtifactsPath("etc/openwrt/images/openwrt_rootfs_aarch64")
2295 .c_str(),
2296 SET_FLAGS_DEFAULT);
2297 }
2298 }
2299
GetGuestConfigAndSetDefaults()2300 Result<std::vector<GuestConfig>> GetGuestConfigAndSetDefaults() {
2301 auto instance_nums =
2302 CF_EXPECT(InstanceNumsCalculator().FromGlobalGflags().Calculate());
2303 int32_t instances_size = instance_nums.size();
2304 CF_EXPECT(ResolveInstanceFiles(), "Failed to resolve instance files");
2305
2306 std::vector<GuestConfig> guest_configs = CF_EXPECT(ReadGuestConfig());
2307
2308 // TODO(weihsu), b/250988697:
2309 // assume all instances are using same VM manager/app/arch,
2310 // later that multiple instances may use different VM manager/app/arch
2311
2312 // Temporary add this checking to make sure all instances have same target_arch.
2313 // This checking should be removed later.
2314 for (int instance_index = 1; instance_index < guest_configs.size(); instance_index++) {
2315 CF_EXPECT(guest_configs[0].target_arch == guest_configs[instance_index].target_arch,
2316 "all instance target_arch should be same");
2317 }
2318 if (FLAGS_vm_manager == "") {
2319 if (IsHostCompatible(guest_configs[0].target_arch)) {
2320 FLAGS_vm_manager = ToString(VmmMode::kCrosvm);
2321 } else {
2322 FLAGS_vm_manager = ToString(VmmMode::kQemu);
2323 }
2324 }
2325
2326 std::vector<std::string> vm_manager_vec =
2327 android::base::Split(FLAGS_vm_manager, ",");
2328
2329 // TODO(weihsu), b/250988697:
2330 // Currently, all instances should use same vmm
2331 auto vmm = CF_EXPECT(ParseVmm(vm_manager_vec[0]));
2332
2333 // get flag default values and store into map
2334 auto name_to_default_value = CurrentFlagsToDefaultValue();
2335
2336 if (vmm == VmmMode::kQemu) {
2337 CF_EXPECT(SetDefaultFlagsForQemu(guest_configs, name_to_default_value));
2338 } else if (vmm == VmmMode::kCrosvm) {
2339 CF_EXPECT(SetDefaultFlagsForCrosvm(guest_configs, name_to_default_value));
2340 } else if (vmm == VmmMode::kGem5) {
2341 // TODO: Get the other architectures working
2342 if (guest_configs[0].target_arch != Arch::Arm64) {
2343 return CF_ERR("Gem5 only supports ARM64");
2344 }
2345 SetDefaultFlagsForGem5();
2346 } else {
2347 return CF_ERR("Unknown Virtual Machine Manager: " << FLAGS_vm_manager);
2348 }
2349 if (vmm != VmmMode::kGem5) {
2350 // After SetCommandLineOptionWithMode in SetDefaultFlagsForCrosvm/Qemu,
2351 // default flag values changed, need recalculate name_to_default_value
2352 name_to_default_value = CurrentFlagsToDefaultValue();
2353 std::vector<bool> start_webrtc_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(
2354 start_webrtc));
2355 bool start_webrtc = false;
2356 for(bool value : start_webrtc_vec) {
2357 start_webrtc |= value;
2358 }
2359
2360 auto host_operator_present =
2361 cuttlefish::FileIsSocket(HOST_OPERATOR_SOCKET_PATH);
2362 // The default for starting signaling server depends on whether or not webrtc
2363 // is to be started and the presence of the host orchestrator.
2364 SetCommandLineOptionWithMode(
2365 "start_webrtc_sig_server",
2366 start_webrtc && !host_operator_present ? "true" : "false",
2367 SET_FLAGS_DEFAULT);
2368 SetCommandLineOptionWithMode(
2369 "webrtc_sig_server_addr",
2370 host_operator_present ? HOST_OPERATOR_SOCKET_PATH : "0.0.0.0",
2371 SET_FLAGS_DEFAULT);
2372 }
2373
2374 SetDefaultFlagsForOpenwrt(guest_configs[0].target_arch);
2375
2376 SetDefaultFlagsForMcu();
2377
2378 // Set the env variable to empty (in case the caller passed a value for it).
2379 unsetenv(kCuttlefishConfigEnvVarName);
2380
2381 return guest_configs;
2382 }
2383
GetConfigFilePath(const CuttlefishConfig & config)2384 std::string GetConfigFilePath(const CuttlefishConfig& config) {
2385 return config.AssemblyPath("cuttlefish_config.json");
2386 }
2387
GetSeccompPolicyDir()2388 std::string GetSeccompPolicyDir() {
2389 std::string kSeccompDir =
2390 "usr/share/crosvm/" + HostArchStr() + "-linux-gnu/seccomp";
2391 return DefaultHostArtifactsPath(kSeccompDir);
2392 }
2393
2394 } // namespace cuttlefish
2395