blob: 7d8892d18c359309ed5726954866b43c8b0481b3 [file] [log] [blame]
Cody Schuffelen5bc697c2019-01-28 21:05:29 -08001#include "host/commands/launch/launch.h"
2
Cody Schuffelen55676ca2019-01-28 22:00:05 -08003#include <glog/logging.h>
4
Cody Schuffelen5bc697c2019-01-28 21:05:29 -08005#include "common/libs/fs/shared_fd.h"
Ram Muthiah792e2ad2019-04-19 11:19:46 -07006#include "common/libs/utils/files.h"
Cody Schuffelen5bc697c2019-01-28 21:05:29 -08007#include "common/libs/utils/size_utils.h"
8#include "common/vsoc/shm/screen_layout.h"
Cody Schuffelen55676ca2019-01-28 22:00:05 -08009#include "host/commands/launch/launcher_defs.h"
Jorge E. Moreiraba626622019-01-28 17:47:50 -080010#include "host/commands/launch/pre_launch_initializers.h"
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080011#include "host/commands/launch/vsoc_shared_memory.h"
12
Cody Schuffelen55676ca2019-01-28 22:00:05 -080013using cvd::LauncherExitCodes;
Cody Schuffelen17b34722019-01-28 22:57:14 -080014using cvd::MonitorEntry;
Cody Schuffelen55676ca2019-01-28 22:00:05 -080015
16namespace {
Cody Schuffelen660d9e82019-01-29 16:33:33 -080017
18constexpr char kAdbModeTunnel[] = "tunnel";
Cody Schuffelenfd96b232019-02-05 14:12:43 -080019constexpr char kAdbModeNativeVsock[] = "native_vsock";
Cody Schuffelen660d9e82019-01-29 16:33:33 -080020constexpr char kAdbModeVsockTunnel[] = "vsock_tunnel";
Cody Schuffelen63d10052019-02-26 12:21:53 -080021constexpr char kAdbModeVsockHalfTunnel[] = "vsock_half_tunnel";
Cody Schuffelen660d9e82019-01-29 16:33:33 -080022constexpr char kAdbModeUsb[] = "usb";
23
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080024cvd::SharedFD CreateIvServerUnixSocket(const std::string& path) {
25 return cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM,
26 0666);
27}
Cody Schuffelen660d9e82019-01-29 16:33:33 -080028
29std::string GetGuestPortArg() {
30 constexpr int kEmulatorPort = 5555;
31 return std::string{"--guest_ports="} + std::to_string(kEmulatorPort);
32}
33
34std::string GetHostPortArg() {
35 return std::string{"--host_ports="} + std::to_string(GetHostPort());
36}
37
Cody Schuffelenda018ca2019-02-05 13:49:56 -080038std::string GetAdbConnectorTcpArg() {
39 return std::string{"--addresses=127.0.0.1:"} + std::to_string(GetHostPort());
Cody Schuffelen660d9e82019-01-29 16:33:33 -080040}
41
Cody Schuffelenfd96b232019-02-05 14:12:43 -080042std::string GetAdbConnectorVsockArg(const vsoc::CuttlefishConfig& config) {
43 return std::string{"--addresses=vsock:"}
44 + std::to_string(config.vsock_guest_cid())
45 + std::string{":5555"};
46}
47
Cody Schuffelen660d9e82019-01-29 16:33:33 -080048bool AdbModeEnabled(const vsoc::CuttlefishConfig& config, const char* mode) {
Cody Schuffelen90b2fb22019-02-28 18:55:21 -080049 return config.adb_mode().count(mode) > 0;
Cody Schuffelen660d9e82019-01-29 16:33:33 -080050}
51
52bool AdbTunnelEnabled(const vsoc::CuttlefishConfig& config) {
Jorge E. Moreirab200e352019-02-05 18:01:03 -080053 return AdbModeEnabled(config, kAdbModeTunnel);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080054}
55
56bool AdbVsockTunnelEnabled(const vsoc::CuttlefishConfig& config) {
57 return config.vsock_guest_cid() > 2
58 && AdbModeEnabled(config, kAdbModeVsockTunnel);
59}
60
Cody Schuffelen63d10052019-02-26 12:21:53 -080061bool AdbVsockHalfTunnelEnabled(const vsoc::CuttlefishConfig& config) {
62 return config.vsock_guest_cid() > 2
63 && AdbModeEnabled(config, kAdbModeVsockHalfTunnel);
64}
65
Cody Schuffelenda018ca2019-02-05 13:49:56 -080066bool AdbTcpConnectorEnabled(const vsoc::CuttlefishConfig& config) {
Cody Schuffelen63d10052019-02-26 12:21:53 -080067 bool tunnel = AdbTunnelEnabled(config);
Cody Schuffelen8a14d692019-03-01 14:09:35 -080068 bool vsock_tunnel = AdbVsockTunnelEnabled(config);
Cody Schuffelen63d10052019-02-26 12:21:53 -080069 bool vsock_half_tunnel = AdbVsockHalfTunnelEnabled(config);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080070 return config.run_adb_connector()
Cody Schuffelen63d10052019-02-26 12:21:53 -080071 && (tunnel || vsock_tunnel || vsock_half_tunnel);
Cody Schuffelen660d9e82019-01-29 16:33:33 -080072}
73
Cody Schuffelenfd96b232019-02-05 14:12:43 -080074bool AdbVsockConnectorEnabled(const vsoc::CuttlefishConfig& config) {
75 return config.run_adb_connector()
76 && AdbModeEnabled(config, kAdbModeNativeVsock);
77}
78
Cody Schuffelen660d9e82019-01-29 16:33:33 -080079cvd::OnSocketReadyCb GetOnSubprocessExitCallback(
80 const vsoc::CuttlefishConfig& config) {
81 if (config.restart_subprocesses()) {
82 return cvd::ProcessMonitor::RestartOnExitCb;
83 } else {
84 return cvd::ProcessMonitor::DoNotMonitorCb;
85 }
86}
Cody Schuffelen55676ca2019-01-28 22:00:05 -080087} // namespace
Cody Schuffelen5bc697c2019-01-28 21:05:29 -080088
Cody Schuffelen660d9e82019-01-29 16:33:33 -080089int GetHostPort() {
90 constexpr int kFirstHostPort = 6520;
91 return vsoc::GetPerInstanceDefault(kFirstHostPort);
92}
93
Jorge E. Moreirafd10cae2019-02-19 15:35:42 -080094bool LogcatReceiverEnabled(const vsoc::CuttlefishConfig& config) {
95 return config.logcat_mode() == cvd::kLogcatVsockMode;
96}
97
Cody Schuffelen660d9e82019-01-29 16:33:33 -080098bool AdbUsbEnabled(const vsoc::CuttlefishConfig& config) {
Jorge E. Moreirab200e352019-02-05 18:01:03 -080099 return AdbModeEnabled(config, kAdbModeUsb);
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800100}
101
102void ValidateAdbModeFlag(const vsoc::CuttlefishConfig& config) {
103 if (!AdbUsbEnabled(config) && !AdbTunnelEnabled(config)
Cody Schuffelen7c3d5a52019-04-26 17:50:30 -0700104 && !AdbVsockTunnelEnabled(config) && !AdbVsockHalfTunnelEnabled(config)) {
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800105 LOG(INFO) << "ADB not enabled";
106 }
107}
108
Cody Schuffelen5bc697c2019-01-28 21:05:29 -0800109cvd::Command GetIvServerCommand(const vsoc::CuttlefishConfig& config) {
Jorge E. Moreira91ce18a2019-04-05 16:14:03 -0700110 // Resize screen region
Cody Schuffelen5bc697c2019-01-28 21:05:29 -0800111 auto actual_width = cvd::AlignToPowerOf2(config.x_res() * 4, 4);// align to 16
112 uint32_t screen_buffers_size =
113 config.num_screen_buffers() *
114 cvd::AlignToPageSize(actual_width * config.y_res() + 16 /* padding */);
115 screen_buffers_size +=
116 (config.num_screen_buffers() - 1) * 4096; /* Guard pages */
117
118 // TODO(b/79170615) Resize gralloc region too.
119
120 vsoc::CreateSharedMemoryFile(
121 config.mempath(),
122 {{vsoc::layout::screen::ScreenLayout::region_name, screen_buffers_size}});
123
124
125 cvd::Command ivserver(config.ivserver_binary());
126 ivserver.AddParameter(
127 "-qemu_socket_fd=",
128 CreateIvServerUnixSocket(config.ivshmem_qemu_socket_path()));
129 ivserver.AddParameter(
130 "-client_socket_fd=",
131 CreateIvServerUnixSocket(config.ivshmem_client_socket_path()));
132 return ivserver;
133}
Cody Schuffelen55676ca2019-01-28 22:00:05 -0800134
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700135std::vector<cvd::SharedFD> LaunchKernelLogMonitor(
136 const vsoc::CuttlefishConfig& config,
137 cvd::ProcessMonitor* process_monitor,
138 unsigned int number_of_event_pipes) {
Cody Schuffelen55676ca2019-01-28 22:00:05 -0800139 auto log_name = config.kernel_log_socket_name();
140 auto server = cvd::SharedFD::SocketLocalServer(log_name.c_str(), false,
141 SOCK_STREAM, 0666);
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700142 cvd::Command command(config.kernel_log_monitor_binary());
143 command.AddParameter("-log_server_fd=", server);
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700144
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700145 std::vector<cvd::SharedFD> ret;
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700146
Jorge E. Moreira277e1c42019-05-06 17:24:27 -0700147 if (number_of_event_pipes > 0) {
148 auto param_builder = command.GetParameterBuilder();
149 param_builder << "-subscriber_fds=";
150 for (unsigned int i = 0; i < number_of_event_pipes; ++i) {
151 cvd::SharedFD event_pipe_write_end, event_pipe_read_end;
152 if (!cvd::SharedFD::Pipe(&event_pipe_read_end, &event_pipe_write_end)) {
153 LOG(ERROR) << "Unable to create boot events pipe: " << strerror(errno);
154 std::exit(LauncherExitCodes::kPipeIOError);
155 }
156 if (i > 0) {
157 param_builder << ",";
158 }
159 param_builder << event_pipe_write_end;
160 ret.push_back(event_pipe_read_end);
161 }
162 param_builder.Build();
163 }
164
165 process_monitor->StartSubprocess(std::move(command),
166 GetOnSubprocessExitCallback(config));
167
168 return ret;
Cody Schuffelen55676ca2019-01-28 22:00:05 -0800169}
Cody Schuffelen17b34722019-01-28 22:57:14 -0800170
Jorge E. Moreirafd10cae2019-02-19 15:35:42 -0800171void LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
172 cvd::ProcessMonitor* process_monitor) {
173 if (!LogcatReceiverEnabled(config)) {
174 return;
175 }
176 auto port = config.logcat_vsock_port();
177 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
178 if (!socket->IsOpen()) {
179 LOG(ERROR) << "Unable to create logcat server socket: "
180 << socket->StrError();
181 std::exit(LauncherExitCodes::kLogcatServerError);
182 }
183 cvd::Command cmd(config.logcat_receiver_binary());
184 cmd.AddParameter("-server_fd=", socket);
185 process_monitor->StartSubprocess(std::move(cmd),
186 GetOnSubprocessExitCallback(config));
187}
188
Jorge E. Moreiraf1f7cb32019-04-15 18:44:41 -0700189void LaunchConfigServer(const vsoc::CuttlefishConfig& config,
190 cvd::ProcessMonitor* process_monitor) {
191 auto port = config.config_server_port();
192 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
193 if (!socket->IsOpen()) {
194 LOG(ERROR) << "Unable to create configuration server socket: "
195 << socket->StrError();
196 std::exit(LauncherExitCodes::kConfigServerError);
197 }
198 cvd::Command cmd(config.config_server_binary());
199 cmd.AddParameter("-server_fd=", socket);
200 process_monitor->StartSubprocess(std::move(cmd),
201 GetOnSubprocessExitCallback(config));
202}
203
Ram Muthiah792e2ad2019-04-19 11:19:46 -0700204void LaunchTombstoneReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
205 cvd::ProcessMonitor* process_monitor) {
206 if (!config.enable_tombstone_receiver()) {
207 return;
208 }
209
210 std::string tombstoneDir = config.PerInstancePath("tombstones");
211 if (!cvd::DirectoryExists(tombstoneDir.c_str())) {
212 LOG(INFO) << "Setting up " << tombstoneDir;
213 if (mkdir(tombstoneDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) <
214 0) {
215 LOG(ERROR) << "Failed to create tombstone directory: " << tombstoneDir
216 << ". Error: " << errno;
217 exit(LauncherExitCodes::kTombstoneDirCreationError);
218 }
219 }
220
221 auto port = config.tombstone_receiver_port();
222 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
223 if (!socket->IsOpen()) {
224 LOG(ERROR) << "Unable to create tombstone server socket: "
225 << socket->StrError();
226 std::exit(LauncherExitCodes::kTombstoneServerError);
227 }
228 cvd::Command cmd(config.tombstone_receiver_binary());
229 cmd.AddParameter("-server_fd=", socket);
230 cmd.AddParameter("-tombstone_dir=", tombstoneDir);
231
232 process_monitor->StartSubprocess(std::move(cmd),
233 GetOnSubprocessExitCallback(config));
234}
235
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800236void LaunchUsbServerIfEnabled(const vsoc::CuttlefishConfig& config,
237 cvd::ProcessMonitor* process_monitor) {
238 if (!AdbUsbEnabled(config)) {
239 return;
240 }
241 auto socket_name = config.usb_v1_socket_name();
242 auto usb_v1_server = cvd::SharedFD::SocketLocalServer(
243 socket_name.c_str(), false, SOCK_STREAM, 0666);
244 if (!usb_v1_server->IsOpen()) {
245 LOG(ERROR) << "Unable to create USB v1 server socket: "
246 << usb_v1_server->StrError();
247 std::exit(cvd::LauncherExitCodes::kUsbV1SocketError);
248 }
249 cvd::Command usb_server(config.virtual_usb_manager_binary());
250 usb_server.AddParameter("-usb_v1_fd=", usb_v1_server);
251 process_monitor->StartSubprocess(std::move(usb_server),
252 GetOnSubprocessExitCallback(config));
253}
254
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800255cvd::SharedFD CreateVncInputServer(const std::string& path) {
256 auto server = cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 0666);
257 if (!server->IsOpen()) {
258 LOG(ERROR) << "Unable to create mouse server: "
259 << server->StrError();
260 return cvd::SharedFD();
261 }
262 return server;
263}
264
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700265bool LaunchVNCServerIfEnabled(const vsoc::CuttlefishConfig& config,
Cody Schuffelen17b34722019-01-28 22:57:14 -0800266 cvd::ProcessMonitor* process_monitor,
267 std::function<bool(MonitorEntry*)> callback) {
Jorge E. Moreiracf4fc2a2019-02-05 17:33:20 -0800268 if (config.enable_vnc_server()) {
Cody Schuffelen17b34722019-01-28 22:57:14 -0800269 // Launch the vnc server, don't wait for it to complete
270 auto port_options = "-port=" + std::to_string(config.vnc_server_port());
271 cvd::Command vnc_server(config.vnc_server_binary());
272 vnc_server.AddParameter(port_options);
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800273 if (!config.enable_ivserver()) {
274 // When the ivserver is not enabled, the vnc touch_server needs to serve
275 // on unix sockets and send input events to whoever connects to it (namely
276 // crosvm)
277 auto touch_server = CreateVncInputServer(config.touch_socket_path());
278 if (!touch_server->IsOpen()) {
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700279 return false;
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800280 }
281 vnc_server.AddParameter("-touch_fd=", touch_server);
282
283 auto keyboard_server =
284 CreateVncInputServer(config.keyboard_socket_path());
285 if (!keyboard_server->IsOpen()) {
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700286 return false;
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800287 }
288 vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
289 // TODO(b/128852363): This should be handled through the wayland mock
290 // instead.
291 // Additionally it receives the frame updates from a virtual socket
292 // instead
293 auto frames_server =
294 cvd::SharedFD::VsockServer(config.frames_vsock_port(), SOCK_STREAM);
295 if (!frames_server->IsOpen()) {
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700296 return false;
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -0800297 }
298 vnc_server.AddParameter("-frame_server_fd=", frames_server);
299 }
Cody Schuffelen17b34722019-01-28 22:57:14 -0800300 process_monitor->StartSubprocess(std::move(vnc_server), callback);
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700301 return true;
Cody Schuffelen17b34722019-01-28 22:57:14 -0800302 }
Jorge E. Moreira7e1df152019-05-14 15:05:33 -0700303 return false;
Cody Schuffelen17b34722019-01-28 22:57:14 -0800304}
305
306void LaunchStreamAudioIfEnabled(const vsoc::CuttlefishConfig& config,
307 cvd::ProcessMonitor* process_monitor,
308 std::function<bool(MonitorEntry*)> callback) {
Jorge E. Moreirafb95b0d2019-02-05 17:40:20 -0800309 if (config.enable_stream_audio()) {
Cody Schuffelen17b34722019-01-28 22:57:14 -0800310 auto port_options = "-port=" + std::to_string(config.stream_audio_port());
311 cvd::Command stream_audio(config.stream_audio_binary());
312 stream_audio.AddParameter(port_options);
313 process_monitor->StartSubprocess(std::move(stream_audio), callback);
314 }
315}
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800316
317void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700318 const vsoc::CuttlefishConfig& config,
319 cvd::SharedFD adbd_events_pipe) {
320 bool launch = false;
321 cvd::Command adb_connector(config.adb_connector_binary());
322 adb_connector.AddParameter("-adbd_events_fd=", adbd_events_pipe);
323
Cody Schuffelenda018ca2019-02-05 13:49:56 -0800324 if (AdbTcpConnectorEnabled(config)) {
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700325 launch = true;
Cody Schuffelenda018ca2019-02-05 13:49:56 -0800326 adb_connector.AddParameter(GetAdbConnectorTcpArg());
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800327 }
Cody Schuffelenfd96b232019-02-05 14:12:43 -0800328 if (AdbVsockConnectorEnabled(config)) {
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700329 launch = true;
Cody Schuffelenfd96b232019-02-05 14:12:43 -0800330 adb_connector.AddParameter(GetAdbConnectorVsockArg(config));
Jorge E. Moreira9ec15852019-05-02 17:52:58 -0700331 }
332
333 if (launch) {
Cody Schuffelenfd96b232019-02-05 14:12:43 -0800334 process_monitor->StartSubprocess(std::move(adb_connector),
335 GetOnSubprocessExitCallback(config));
336 }
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800337}
338
339void LaunchSocketForwardProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
340 const vsoc::CuttlefishConfig& config) {
341 if (AdbTunnelEnabled(config)) {
342 cvd::Command adb_tunnel(config.socket_forward_proxy_binary());
343 adb_tunnel.AddParameter(GetGuestPortArg());
344 adb_tunnel.AddParameter(GetHostPortArg());
345 process_monitor->StartSubprocess(std::move(adb_tunnel),
346 GetOnSubprocessExitCallback(config));
347 }
348}
349
350void LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
351 const vsoc::CuttlefishConfig& config) {
352 if (AdbVsockTunnelEnabled(config)) {
353 cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
Cody Schuffelen27163842019-02-07 15:36:51 -0800354 adb_tunnel.AddParameter("--vsock_port=6520");
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800355 adb_tunnel.AddParameter(
Cody Schuffelen27163842019-02-07 15:36:51 -0800356 std::string{"--tcp_port="} + std::to_string(GetHostPort()));
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800357 adb_tunnel.AddParameter(std::string{"--vsock_guest_cid="} +
358 std::to_string(config.vsock_guest_cid()));
359 process_monitor->StartSubprocess(std::move(adb_tunnel),
360 GetOnSubprocessExitCallback(config));
361 }
Cody Schuffelen63d10052019-02-26 12:21:53 -0800362 if (AdbVsockHalfTunnelEnabled(config)) {
363 cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
364 adb_tunnel.AddParameter("--vsock_port=5555");
365 adb_tunnel.AddParameter(
366 std::string{"--tcp_port="} + std::to_string(GetHostPort()));
367 adb_tunnel.AddParameter(std::string{"--vsock_guest_cid="} +
368 std::to_string(config.vsock_guest_cid()));
369 process_monitor->StartSubprocess(std::move(adb_tunnel),
370 GetOnSubprocessExitCallback(config));
371 }
Cody Schuffelen660d9e82019-01-29 16:33:33 -0800372}
Jorge E. Moreiraba626622019-01-28 17:47:50 -0800373
374void LaunchIvServerIfEnabled(cvd::ProcessMonitor* process_monitor,
375 const vsoc::CuttlefishConfig& config) {
Jorge E. Moreiraf4b202b2019-02-05 17:51:06 -0800376 if (config.enable_ivserver()) {
377 process_monitor->StartSubprocess(GetIvServerCommand(config),
378 GetOnSubprocessExitCallback(config));
Jorge E. Moreiraba626622019-01-28 17:47:50 -0800379
Jorge E. Moreiraf4b202b2019-02-05 17:51:06 -0800380 // Initialize the regions that require so before the VM starts.
381 PreLaunchInitializers::Initialize(config);
382 }
Cody Schuffelenda018ca2019-02-05 13:49:56 -0800383}