blob: 47cf2e26696649fd200ca63ad26e9642ec6d0f10 [file] [log] [blame]
Cody Schuffelen147b88e2019-09-09 16:00:11 -07001#include "host/commands/run_cvd/launch.h"
Cody Schuffelen5bc697c2019-01-28 21:05:29 -08002
Jorge E. Moreirab1ec4352019-06-04 11:43:08 -07003#include <sys/types.h>
4#include <sys/stat.h>
5
Cody Schuffelen55676ca2019-01-28 22:00:05 -08006#include <glog/logging.h>
7
Cody Schuffelen5bc697c2019-01-28 21:05:29 -08008#include "common/libs/fs/shared_fd.h"
Ram Muthiah792e2ad2019-04-19 11:19:46 -07009#include "common/libs/utils/files.h"
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080010#include "common/libs/utils/size_utils.h"
11#include "common/vsoc/shm/screen_layout.h"
Cody Schuffelen147b88e2019-09-09 16:00:11 -070012#include "host/commands/run_cvd/runner_defs.h"
13#include "host/commands/run_cvd/pre_launch_initializers.h"
14#include "host/commands/run_cvd/vsoc_shared_memory.h"
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080015
Cody Schuffelena9d9a862019-09-10 16:16:06 -070016using cvd::RunnerExitCodes;
Cody Schuffelen17b34722019-01-28 22:57:14 -080017using cvd::MonitorEntry;
Cody Schuffelen55676ca2019-01-28 22:00:05 -080018
19namespace {
Cody Schuffelen660d9e82019-01-29 16:33:33 -080020
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080021cvd::SharedFD CreateIvServerUnixSocket(const std::string& path) {
22 return cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM,
23 0666);
24}
Cody Schuffelen660d9e82019-01-29 16:33:33 -080025
26std::string GetGuestPortArg() {
27 constexpr int kEmulatorPort = 5555;
28 return std::string{"--guest_ports="} + std::to_string(kEmulatorPort);
29}
30
Cody Schuffelene0d0c462019-09-09 14:13:01 -070031std::string GetHostPortArg(const vsoc::CuttlefishConfig& config) {
32 return std::string{"--host_ports="} + std::to_string(config.host_port());
Cody Schuffelen660d9e82019-01-29 16:33:33 -080033}
34
Cody Schuffelene0d0c462019-09-09 14:13:01 -070035std::string GetAdbConnectorTcpArg(const vsoc::CuttlefishConfig& config) {
36 return std::string{"127.0.0.1:"} + std::to_string(config.host_port());
Cody Schuffelen660d9e82019-01-29 16:33:33 -080037}
38
Cody Schuffelenfd96b232019-02-05 14:12:43 -080039std::string GetAdbConnectorVsockArg(const vsoc::CuttlefishConfig& config) {
Cody Schuffelen05385d02019-05-08 12:39:12 -070040 return std::string{"vsock:"}
Cody Schuffelenfd96b232019-02-05 14:12:43 -080041 + std::to_string(config.vsock_guest_cid())
42 + std::string{":5555"};
43}
44
Cody Schuffelenb6fa7362019-05-08 11:58:14 -070045bool AdbModeEnabled(const vsoc::CuttlefishConfig& config, vsoc::AdbMode mode) {
Cody Schuffelen90b2fb22019-02-28 18:55:21 -080046 return config.adb_mode().count(mode) > 0;
Cody Schuffelen660d9e82019-01-29 16:33:33 -080047}
48
49bool AdbTunnelEnabled(const vsoc::CuttlefishConfig& config) {
Cody Schuffelenb6fa7362019-05-08 11:58:14 -070050 return AdbModeEnabled(config, vsoc::AdbMode::Tunnel);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080051}
52
53bool AdbVsockTunnelEnabled(const vsoc::CuttlefishConfig& config) {
54 return config.vsock_guest_cid() > 2
Cody Schuffelenb6fa7362019-05-08 11:58:14 -070055 && AdbModeEnabled(config, vsoc::AdbMode::VsockTunnel);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080056}
57
Cody Schuffelen63d10052019-02-26 12:21:53 -080058bool AdbVsockHalfTunnelEnabled(const vsoc::CuttlefishConfig& config) {
59 return config.vsock_guest_cid() > 2
Cody Schuffelenb6fa7362019-05-08 11:58:14 -070060 && AdbModeEnabled(config, vsoc::AdbMode::VsockHalfTunnel);
Cody Schuffelen63d10052019-02-26 12:21:53 -080061}
62
Cody Schuffelenda018ca2019-02-05 13:49:56 -080063bool AdbTcpConnectorEnabled(const vsoc::CuttlefishConfig& config) {
Cody Schuffelen63d10052019-02-26 12:21:53 -080064 bool tunnel = AdbTunnelEnabled(config);
Cody Schuffelen8a14d692019-03-01 14:09:35 -080065 bool vsock_tunnel = AdbVsockTunnelEnabled(config);
Cody Schuffelen63d10052019-02-26 12:21:53 -080066 bool vsock_half_tunnel = AdbVsockHalfTunnelEnabled(config);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080067 return config.run_adb_connector()
Cody Schuffelen63d10052019-02-26 12:21:53 -080068 && (tunnel || vsock_tunnel || vsock_half_tunnel);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080069}
70
Cody Schuffelenfd96b232019-02-05 14:12:43 -080071bool AdbVsockConnectorEnabled(const vsoc::CuttlefishConfig& config) {
72 return config.run_adb_connector()
Cody Schuffelenb6fa7362019-05-08 11:58:14 -070073 && AdbModeEnabled(config, vsoc::AdbMode::NativeVsock);
Cody Schuffelenfd96b232019-02-05 14:12:43 -080074}
75
Cody Schuffelen75ef8872019-09-06 17:35:54 -070076bool AdbUsbEnabled(const vsoc::CuttlefishConfig& config) {
77 return AdbModeEnabled(config, vsoc::AdbMode::Usb);
78}
79
Cody Schuffelen660d9e82019-01-29 16:33:33 -080080cvd::OnSocketReadyCb GetOnSubprocessExitCallback(
81 const vsoc::CuttlefishConfig& config) {
82 if (config.restart_subprocesses()) {
83 return cvd::ProcessMonitor::RestartOnExitCb;
84 } else {
85 return cvd::ProcessMonitor::DoNotMonitorCb;
86 }
87}
Cody Schuffelen55676ca2019-01-28 22:00:05 -080088} // namespace
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080089
Jorge E. Moreirafd10cae2019-02-19 15:35:42 -080090bool LogcatReceiverEnabled(const vsoc::CuttlefishConfig& config) {
91 return config.logcat_mode() == cvd::kLogcatVsockMode;
92}
93
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080094cvd::Command GetIvServerCommand(const vsoc::CuttlefishConfig& config) {
Jorge E. Moreira91ce18a2019-04-05 16:14:03 -070095 // Resize screen region
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080096 auto actual_width = cvd::AlignToPowerOf2(config.x_res() * 4, 4);// align to 16
97 uint32_t screen_buffers_size =
98 config.num_screen_buffers() *
99 cvd::AlignToPageSize(actual_width * config.y_res() + 16 /* padding */);
100 screen_buffers_size +=
101 (config.num_screen_buffers() - 1) * 4096; /* Guard pages */
102
103 // TODO(b/79170615) Resize gralloc region too.
104
105 vsoc::CreateSharedMemoryFile(
106 config.mempath(),
107 {{vsoc::layout::screen::ScreenLayout::region_name, screen_buffers_size}});
108
109
110 cvd::Command ivserver(config.ivserver_binary());
111 ivserver.AddParameter(
112 "-qemu_socket_fd=",
113 CreateIvServerUnixSocket(config.ivshmem_qemu_socket_path()));
114 ivserver.AddParameter(
115 "-client_socket_fd=",
116 CreateIvServerUnixSocket(config.ivshmem_client_socket_path()));
117 return ivserver;
118}
Cody Schuffelen55676ca2019-01-28 22:00:05 -0800119
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700120std::vector<cvd::SharedFD> LaunchKernelLogMonitor(
121 const vsoc::CuttlefishConfig& config,
122 cvd::ProcessMonitor* process_monitor,
123 unsigned int number_of_event_pipes) {
Jorge E. Moreirab1ec4352019-06-04 11:43:08 -0700124 auto log_name = config.kernel_log_pipe_name();
125 if (mkfifo(log_name.c_str(), 0600) != 0) {
126 LOG(ERROR) << "Unable to create named pipe at " << log_name << ": "
127 << strerror(errno);
128 return {};
129 }
130
131 cvd::SharedFD pipe;
132 // Open the pipe here (from the launcher) to ensure the pipe is not deleted
133 // due to the usage counters in the kernel reaching zero. If this is not done
134 // and the kernel_log_monitor crashes for some reason the VMM may get SIGPIPE.
135 pipe = cvd::SharedFD::Open(log_name.c_str(), O_RDWR);
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700136 cvd::Command command(config.kernel_log_monitor_binary());
Jorge E. Moreirab1ec4352019-06-04 11:43:08 -0700137 command.AddParameter("-log_pipe_fd=", pipe);
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700138
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700139 std::vector<cvd::SharedFD> ret;
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700140
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700141 if (number_of_event_pipes > 0) {
142 auto param_builder = command.GetParameterBuilder();
143 param_builder << "-subscriber_fds=";
144 for (unsigned int i = 0; i < number_of_event_pipes; ++i) {
145 cvd::SharedFD event_pipe_write_end, event_pipe_read_end;
146 if (!cvd::SharedFD::Pipe(&event_pipe_read_end, &event_pipe_write_end)) {
147 LOG(ERROR) << "Unable to create boot events pipe: " << strerror(errno);
Cody Schuffelena9d9a862019-09-10 16:16:06 -0700148 std::exit(RunnerExitCodes::kPipeIOError);
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700149 }
150 if (i > 0) {
151 param_builder << ",";
152 }
153 param_builder << event_pipe_write_end;
154 ret.push_back(event_pipe_read_end);
155 }
156 param_builder.Build();
157 }
158
159 process_monitor->StartSubprocess(std::move(command),
160 GetOnSubprocessExitCallback(config));
161
162 return ret;
Cody Schuffelen55676ca2019-01-28 22:00:05 -0800163}
Cody Schuffelen17b34722019-01-28 22:57:14 -0800164
Jorge E. Moreirafd10cae2019-02-19 15:35:42 -0800165void LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
166 cvd::ProcessMonitor* process_monitor) {
167 if (!LogcatReceiverEnabled(config)) {
168 return;
169 }
170 auto port = config.logcat_vsock_port();
171 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
172 if (!socket->IsOpen()) {
173 LOG(ERROR) << "Unable to create logcat server socket: "
174 << socket->StrError();
Cody Schuffelena9d9a862019-09-10 16:16:06 -0700175 std::exit(RunnerExitCodes::kLogcatServerError);
Jorge E. Moreirafd10cae2019-02-19 15:35:42 -0800176 }
177 cvd::Command cmd(config.logcat_receiver_binary());
178 cmd.AddParameter("-server_fd=", socket);
179 process_monitor->StartSubprocess(std::move(cmd),
180 GetOnSubprocessExitCallback(config));
181}
182
Jorge E. Moreiraf1f7cb32019-04-15 18:44:41 -0700183void LaunchConfigServer(const vsoc::CuttlefishConfig& config,
184 cvd::ProcessMonitor* process_monitor) {
185 auto port = config.config_server_port();
186 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
187 if (!socket->IsOpen()) {
188 LOG(ERROR) << "Unable to create configuration server socket: "
189 << socket->StrError();
Cody Schuffelena9d9a862019-09-10 16:16:06 -0700190 std::exit(RunnerExitCodes::kConfigServerError);
Jorge E. Moreiraf1f7cb32019-04-15 18:44:41 -0700191 }
192 cvd::Command cmd(config.config_server_binary());
193 cmd.AddParameter("-server_fd=", socket);
194 process_monitor->StartSubprocess(std::move(cmd),
195 GetOnSubprocessExitCallback(config));
196}
197
Ram Muthiah792e2ad2019-04-19 11:19:46 -0700198void LaunchTombstoneReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
199 cvd::ProcessMonitor* process_monitor) {
200 if (!config.enable_tombstone_receiver()) {
201 return;
202 }
203
204 std::string tombstoneDir = config.PerInstancePath("tombstones");
205 if (!cvd::DirectoryExists(tombstoneDir.c_str())) {
206 LOG(INFO) << "Setting up " << tombstoneDir;
207 if (mkdir(tombstoneDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) <
208 0) {
209 LOG(ERROR) << "Failed to create tombstone directory: " << tombstoneDir
210 << ". Error: " << errno;
Cody Schuffelena9d9a862019-09-10 16:16:06 -0700211 exit(RunnerExitCodes::kTombstoneDirCreationError);
Ram Muthiah792e2ad2019-04-19 11:19:46 -0700212 }
213 }
214
215 auto port = config.tombstone_receiver_port();
216 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
217 if (!socket->IsOpen()) {
218 LOG(ERROR) << "Unable to create tombstone server socket: "
219 << socket->StrError();
Cody Schuffelena9d9a862019-09-10 16:16:06 -0700220 std::exit(RunnerExitCodes::kTombstoneServerError);
Ram Muthiah792e2ad2019-04-19 11:19:46 -0700221 }
222 cvd::Command cmd(config.tombstone_receiver_binary());
223 cmd.AddParameter("-server_fd=", socket);
224 cmd.AddParameter("-tombstone_dir=", tombstoneDir);
225
226 process_monitor->StartSubprocess(std::move(cmd),
227 GetOnSubprocessExitCallback(config));
228}
229
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800230void LaunchUsbServerIfEnabled(const vsoc::CuttlefishConfig& config,
231 cvd::ProcessMonitor* process_monitor) {
232 if (!AdbUsbEnabled(config)) {
233 return;
234 }
235 auto socket_name = config.usb_v1_socket_name();
236 auto usb_v1_server = cvd::SharedFD::SocketLocalServer(
237 socket_name.c_str(), false, SOCK_STREAM, 0666);
238 if (!usb_v1_server->IsOpen()) {
239 LOG(ERROR) << "Unable to create USB v1 server socket: "
240 << usb_v1_server->StrError();
Cody Schuffelena9d9a862019-09-10 16:16:06 -0700241 std::exit(cvd::RunnerExitCodes::kUsbV1SocketError);
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800242 }
243 cvd::Command usb_server(config.virtual_usb_manager_binary());
244 usb_server.AddParameter("-usb_v1_fd=", usb_v1_server);
245 process_monitor->StartSubprocess(std::move(usb_server),
246 GetOnSubprocessExitCallback(config));
247}
248
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800249cvd::SharedFD CreateVncInputServer(const std::string& path) {
250 auto server = cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 0666);
251 if (!server->IsOpen()) {
252 LOG(ERROR) << "Unable to create mouse server: "
253 << server->StrError();
254 return cvd::SharedFD();
255 }
256 return server;
257}
258
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700259bool LaunchVNCServerIfEnabled(const vsoc::CuttlefishConfig& config,
Cody Schuffelen17b34722019-01-28 22:57:14 -0800260 cvd::ProcessMonitor* process_monitor,
261 std::function<bool(MonitorEntry*)> callback) {
Jorge E. Moreiracf4fc2a2019-02-05 17:33:20 -0800262 if (config.enable_vnc_server()) {
Cody Schuffelen17b34722019-01-28 22:57:14 -0800263 // Launch the vnc server, don't wait for it to complete
264 auto port_options = "-port=" + std::to_string(config.vnc_server_port());
265 cvd::Command vnc_server(config.vnc_server_binary());
266 vnc_server.AddParameter(port_options);
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800267 if (!config.enable_ivserver()) {
268 // When the ivserver is not enabled, the vnc touch_server needs to serve
269 // on unix sockets and send input events to whoever connects to it (namely
270 // crosvm)
271 auto touch_server = CreateVncInputServer(config.touch_socket_path());
272 if (!touch_server->IsOpen()) {
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700273 return false;
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800274 }
275 vnc_server.AddParameter("-touch_fd=", touch_server);
276
277 auto keyboard_server =
278 CreateVncInputServer(config.keyboard_socket_path());
279 if (!keyboard_server->IsOpen()) {
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700280 return false;
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800281 }
282 vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
283 // TODO(b/128852363): This should be handled through the wayland mock
284 // instead.
285 // Additionally it receives the frame updates from a virtual socket
286 // instead
287 auto frames_server =
288 cvd::SharedFD::VsockServer(config.frames_vsock_port(), SOCK_STREAM);
289 if (!frames_server->IsOpen()) {
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700290 return false;
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800291 }
292 vnc_server.AddParameter("-frame_server_fd=", frames_server);
293 }
Cody Schuffelen17b34722019-01-28 22:57:14 -0800294 process_monitor->StartSubprocess(std::move(vnc_server), callback);
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700295 return true;
Cody Schuffelen17b34722019-01-28 22:57:14 -0800296 }
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700297 return false;
Cody Schuffelen17b34722019-01-28 22:57:14 -0800298}
299
300void LaunchStreamAudioIfEnabled(const vsoc::CuttlefishConfig& config,
301 cvd::ProcessMonitor* process_monitor,
302 std::function<bool(MonitorEntry*)> callback) {
Jorge E. Moreirafb95b0d2019-02-05 17:40:20 -0800303 if (config.enable_stream_audio()) {
Cody Schuffelen17b34722019-01-28 22:57:14 -0800304 auto port_options = "-port=" + std::to_string(config.stream_audio_port());
305 cvd::Command stream_audio(config.stream_audio_binary());
306 stream_audio.AddParameter(port_options);
307 process_monitor->StartSubprocess(std::move(stream_audio), callback);
308 }
309}
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800310
311void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700312 const vsoc::CuttlefishConfig& config,
313 cvd::SharedFD adbd_events_pipe) {
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700314 cvd::Command adb_connector(config.adb_connector_binary());
315 adb_connector.AddParameter("-adbd_events_fd=", adbd_events_pipe);
Cody Schuffelen05385d02019-05-08 12:39:12 -0700316 std::set<std::string> addresses;
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700317
Cody Schuffelenda018ca2019-02-05 13:49:56 -0800318 if (AdbTcpConnectorEnabled(config)) {
Cody Schuffelene0d0c462019-09-09 14:13:01 -0700319 addresses.insert(GetAdbConnectorTcpArg(config));
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800320 }
Cody Schuffelenfd96b232019-02-05 14:12:43 -0800321 if (AdbVsockConnectorEnabled(config)) {
Cody Schuffelen05385d02019-05-08 12:39:12 -0700322 addresses.insert(GetAdbConnectorVsockArg(config));
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700323 }
324
Cody Schuffelen05385d02019-05-08 12:39:12 -0700325 if (addresses.size() > 0) {
326 std::string address_arg = "--addresses=";
327 for (auto& arg : addresses) {
328 address_arg += arg + ",";
329 }
330 address_arg.pop_back();
331 adb_connector.AddParameter(address_arg);
Cody Schuffelenfd96b232019-02-05 14:12:43 -0800332 process_monitor->StartSubprocess(std::move(adb_connector),
333 GetOnSubprocessExitCallback(config));
334 }
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800335}
336
337void LaunchSocketForwardProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
338 const vsoc::CuttlefishConfig& config) {
339 if (AdbTunnelEnabled(config)) {
340 cvd::Command adb_tunnel(config.socket_forward_proxy_binary());
341 adb_tunnel.AddParameter(GetGuestPortArg());
Cody Schuffelene0d0c462019-09-09 14:13:01 -0700342 adb_tunnel.AddParameter(GetHostPortArg(config));
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800343 process_monitor->StartSubprocess(std::move(adb_tunnel),
344 GetOnSubprocessExitCallback(config));
345 }
346}
347
348void LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
349 const vsoc::CuttlefishConfig& config) {
350 if (AdbVsockTunnelEnabled(config)) {
351 cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
Cody Schuffelen27163842019-02-07 15:36:51 -0800352 adb_tunnel.AddParameter("--vsock_port=6520");
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800353 adb_tunnel.AddParameter(
Cody Schuffelene0d0c462019-09-09 14:13:01 -0700354 std::string{"--tcp_port="} + std::to_string(config.host_port()));
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800355 adb_tunnel.AddParameter(std::string{"--vsock_guest_cid="} +
356 std::to_string(config.vsock_guest_cid()));
357 process_monitor->StartSubprocess(std::move(adb_tunnel),
358 GetOnSubprocessExitCallback(config));
359 }
Cody Schuffelen63d10052019-02-26 12:21:53 -0800360 if (AdbVsockHalfTunnelEnabled(config)) {
361 cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
362 adb_tunnel.AddParameter("--vsock_port=5555");
363 adb_tunnel.AddParameter(
Cody Schuffelene0d0c462019-09-09 14:13:01 -0700364 std::string{"--tcp_port="} + std::to_string(config.host_port()));
Cody Schuffelen63d10052019-02-26 12:21:53 -0800365 adb_tunnel.AddParameter(std::string{"--vsock_guest_cid="} +
366 std::to_string(config.vsock_guest_cid()));
367 process_monitor->StartSubprocess(std::move(adb_tunnel),
368 GetOnSubprocessExitCallback(config));
369 }
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800370}
Jorge E. Moreiraba626622019-01-28 17:47:50 -0800371
372void LaunchIvServerIfEnabled(cvd::ProcessMonitor* process_monitor,
373 const vsoc::CuttlefishConfig& config) {
Jorge E. Moreiraf4b202b2019-02-05 17:51:06 -0800374 if (config.enable_ivserver()) {
375 process_monitor->StartSubprocess(GetIvServerCommand(config),
376 GetOnSubprocessExitCallback(config));
Jorge E. Moreiraba626622019-01-28 17:47:50 -0800377
Jorge E. Moreiraf4b202b2019-02-05 17:51:06 -0800378 // Initialize the regions that require so before the VM starts.
379 PreLaunchInitializers::Initialize(config);
380 }
Cody Schuffelenda018ca2019-02-05 13:49:56 -0800381}