1 #include "host/commands/launch/launch.h"
2
3 #include <glog/logging.h>
4
5 #include "common/libs/fs/shared_fd.h"
6 #include "common/libs/utils/size_utils.h"
7 #include "common/vsoc/shm/screen_layout.h"
8 #include "host/commands/launch/launcher_defs.h"
9 #include "host/commands/launch/pre_launch_initializers.h"
10 #include "host/commands/launch/vsoc_shared_memory.h"
11
12 using cvd::LauncherExitCodes;
13 using cvd::MonitorEntry;
14
15 namespace {
16
17 constexpr char kAdbModeTunnel[] = "tunnel";
18 constexpr char kAdbModeNativeVsock[] = "native_vsock";
19 constexpr char kAdbModeVsockTunnel[] = "vsock_tunnel";
20 constexpr char kAdbModeVsockHalfTunnel[] = "vsock_half_tunnel";
21 constexpr char kAdbModeUsb[] = "usb";
22
CreateIvServerUnixSocket(const std::string & path)23 cvd::SharedFD CreateIvServerUnixSocket(const std::string& path) {
24 return cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM,
25 0666);
26 }
27
GetGuestPortArg()28 std::string GetGuestPortArg() {
29 constexpr int kEmulatorPort = 5555;
30 return std::string{"--guest_ports="} + std::to_string(kEmulatorPort);
31 }
32
GetHostPortArg()33 std::string GetHostPortArg() {
34 return std::string{"--host_ports="} + std::to_string(GetHostPort());
35 }
36
GetAdbConnectorTcpArg()37 std::string GetAdbConnectorTcpArg() {
38 return std::string{"--addresses=127.0.0.1:"} + std::to_string(GetHostPort());
39 }
40
GetAdbConnectorVsockArg(const vsoc::CuttlefishConfig & config)41 std::string GetAdbConnectorVsockArg(const vsoc::CuttlefishConfig& config) {
42 return std::string{"--addresses=vsock:"}
43 + std::to_string(config.vsock_guest_cid())
44 + std::string{":5555"};
45 }
46
AdbModeEnabled(const vsoc::CuttlefishConfig & config,const char * mode)47 bool AdbModeEnabled(const vsoc::CuttlefishConfig& config, const char* mode) {
48 return config.adb_mode().count(mode) > 0;
49 }
50
AdbTunnelEnabled(const vsoc::CuttlefishConfig & config)51 bool AdbTunnelEnabled(const vsoc::CuttlefishConfig& config) {
52 return AdbModeEnabled(config, kAdbModeTunnel);
53 }
54
AdbVsockTunnelEnabled(const vsoc::CuttlefishConfig & config)55 bool AdbVsockTunnelEnabled(const vsoc::CuttlefishConfig& config) {
56 return config.vsock_guest_cid() > 2
57 && AdbModeEnabled(config, kAdbModeVsockTunnel);
58 }
59
AdbVsockHalfTunnelEnabled(const vsoc::CuttlefishConfig & config)60 bool AdbVsockHalfTunnelEnabled(const vsoc::CuttlefishConfig& config) {
61 return config.vsock_guest_cid() > 2
62 && AdbModeEnabled(config, kAdbModeVsockHalfTunnel);
63 }
64
AdbTcpConnectorEnabled(const vsoc::CuttlefishConfig & config)65 bool AdbTcpConnectorEnabled(const vsoc::CuttlefishConfig& config) {
66 bool tunnel = AdbTunnelEnabled(config);
67 bool vsock_tunnel = AdbVsockTunnelEnabled(config);
68 bool vsock_half_tunnel = AdbVsockHalfTunnelEnabled(config);
69 return config.run_adb_connector()
70 && (tunnel || vsock_tunnel || vsock_half_tunnel);
71 }
72
AdbVsockConnectorEnabled(const vsoc::CuttlefishConfig & config)73 bool AdbVsockConnectorEnabled(const vsoc::CuttlefishConfig& config) {
74 return config.run_adb_connector()
75 && AdbModeEnabled(config, kAdbModeNativeVsock);
76 }
77
GetOnSubprocessExitCallback(const vsoc::CuttlefishConfig & config)78 cvd::OnSocketReadyCb GetOnSubprocessExitCallback(
79 const vsoc::CuttlefishConfig& config) {
80 if (config.restart_subprocesses()) {
81 return cvd::ProcessMonitor::RestartOnExitCb;
82 } else {
83 return cvd::ProcessMonitor::DoNotMonitorCb;
84 }
85 }
86 } // namespace
87
GetHostPort()88 int GetHostPort() {
89 constexpr int kFirstHostPort = 6520;
90 return vsoc::GetPerInstanceDefault(kFirstHostPort);
91 }
92
LogcatReceiverEnabled(const vsoc::CuttlefishConfig & config)93 bool LogcatReceiverEnabled(const vsoc::CuttlefishConfig& config) {
94 return config.logcat_mode() == cvd::kLogcatVsockMode;
95 }
96
AdbUsbEnabled(const vsoc::CuttlefishConfig & config)97 bool AdbUsbEnabled(const vsoc::CuttlefishConfig& config) {
98 return AdbModeEnabled(config, kAdbModeUsb);
99 }
100
ValidateAdbModeFlag(const vsoc::CuttlefishConfig & config)101 void ValidateAdbModeFlag(const vsoc::CuttlefishConfig& config) {
102 if (!AdbUsbEnabled(config) && !AdbTunnelEnabled(config)
103 && !AdbVsockTunnelEnabled(config) && !AdbVsockHalfTunnelEnabled(config)) {
104 LOG(INFO) << "ADB not enabled";
105 }
106 }
107
GetIvServerCommand(const vsoc::CuttlefishConfig & config)108 cvd::Command GetIvServerCommand(const vsoc::CuttlefishConfig& config) {
109 // Resize screen region
110 auto actual_width = cvd::AlignToPowerOf2(config.x_res() * 4, 4);// align to 16
111 uint32_t screen_buffers_size =
112 config.num_screen_buffers() *
113 cvd::AlignToPageSize(actual_width * config.y_res() + 16 /* padding */);
114 screen_buffers_size +=
115 (config.num_screen_buffers() - 1) * 4096; /* Guard pages */
116
117 // TODO(b/79170615) Resize gralloc region too.
118
119 vsoc::CreateSharedMemoryFile(
120 config.mempath(),
121 {{vsoc::layout::screen::ScreenLayout::region_name, screen_buffers_size}});
122
123
124 cvd::Command ivserver(config.ivserver_binary());
125 ivserver.AddParameter(
126 "-qemu_socket_fd=",
127 CreateIvServerUnixSocket(config.ivshmem_qemu_socket_path()));
128 ivserver.AddParameter(
129 "-client_socket_fd=",
130 CreateIvServerUnixSocket(config.ivshmem_client_socket_path()));
131 return ivserver;
132 }
133
134 // Build the kernel log monitor command. If boot_event_pipe is not NULL, a
135 // subscription to boot events from the kernel log monitor will be created and
136 // events will appear on *boot_events_pipe
GetKernelLogMonitorCommand(const vsoc::CuttlefishConfig & config,cvd::SharedFD * boot_events_pipe,cvd::SharedFD * adbd_events_pipe)137 cvd::Command GetKernelLogMonitorCommand(const vsoc::CuttlefishConfig& config,
138 cvd::SharedFD* boot_events_pipe,
139 cvd::SharedFD* adbd_events_pipe) {
140 auto log_name = config.kernel_log_socket_name();
141 auto server = cvd::SharedFD::SocketLocalServer(log_name.c_str(), false,
142 SOCK_STREAM, 0666);
143 cvd::Command kernel_log_monitor(config.kernel_log_monitor_binary());
144 kernel_log_monitor.AddParameter("-log_server_fd=", server);
145
146 cvd::SharedFD boot_pipe_write_end;
147 if (!cvd::SharedFD::Pipe(boot_events_pipe, &boot_pipe_write_end)) {
148 LOG(ERROR) << "Unable to create boot events pipe: " << strerror(errno);
149 std::exit(LauncherExitCodes::kPipeIOError);
150 }
151 cvd::SharedFD adbd_pipe_write_end;
152 if (!cvd::SharedFD::Pipe(adbd_events_pipe, &adbd_pipe_write_end)) {
153 LOG(ERROR) << "Unable to create adbd events pipe: " << strerror(errno);
154 std::exit(LauncherExitCodes::kPipeIOError);
155 }
156 kernel_log_monitor.AddParameter("-subscriber_fds=", boot_pipe_write_end, ",",
157 adbd_pipe_write_end);
158
159 return kernel_log_monitor;
160 }
161
LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig & config,cvd::ProcessMonitor * process_monitor)162 void LaunchLogcatReceiverIfEnabled(const vsoc::CuttlefishConfig& config,
163 cvd::ProcessMonitor* process_monitor) {
164 if (!LogcatReceiverEnabled(config)) {
165 return;
166 }
167 auto port = config.logcat_vsock_port();
168 auto socket = cvd::SharedFD::VsockServer(port, SOCK_STREAM);
169 if (!socket->IsOpen()) {
170 LOG(ERROR) << "Unable to create logcat server socket: "
171 << socket->StrError();
172 std::exit(LauncherExitCodes::kLogcatServerError);
173 }
174 cvd::Command cmd(config.logcat_receiver_binary());
175 cmd.AddParameter("-server_fd=", socket);
176 process_monitor->StartSubprocess(std::move(cmd),
177 GetOnSubprocessExitCallback(config));
178 }
179
LaunchUsbServerIfEnabled(const vsoc::CuttlefishConfig & config,cvd::ProcessMonitor * process_monitor)180 void LaunchUsbServerIfEnabled(const vsoc::CuttlefishConfig& config,
181 cvd::ProcessMonitor* process_monitor) {
182 if (!AdbUsbEnabled(config)) {
183 return;
184 }
185 auto socket_name = config.usb_v1_socket_name();
186 auto usb_v1_server = cvd::SharedFD::SocketLocalServer(
187 socket_name.c_str(), false, SOCK_STREAM, 0666);
188 if (!usb_v1_server->IsOpen()) {
189 LOG(ERROR) << "Unable to create USB v1 server socket: "
190 << usb_v1_server->StrError();
191 std::exit(cvd::LauncherExitCodes::kUsbV1SocketError);
192 }
193 cvd::Command usb_server(config.virtual_usb_manager_binary());
194 usb_server.AddParameter("-usb_v1_fd=", usb_v1_server);
195 process_monitor->StartSubprocess(std::move(usb_server),
196 GetOnSubprocessExitCallback(config));
197 }
198
CreateVncInputServer(const std::string & path)199 cvd::SharedFD CreateVncInputServer(const std::string& path) {
200 auto server = cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 0666);
201 if (!server->IsOpen()) {
202 LOG(ERROR) << "Unable to create mouse server: "
203 << server->StrError();
204 return cvd::SharedFD();
205 }
206 return server;
207 }
208
LaunchVNCServerIfEnabled(const vsoc::CuttlefishConfig & config,cvd::ProcessMonitor * process_monitor,std::function<bool (MonitorEntry *)> callback)209 void LaunchVNCServerIfEnabled(const vsoc::CuttlefishConfig& config,
210 cvd::ProcessMonitor* process_monitor,
211 std::function<bool(MonitorEntry*)> callback) {
212 if (config.enable_vnc_server()) {
213 // Launch the vnc server, don't wait for it to complete
214 auto port_options = "-port=" + std::to_string(config.vnc_server_port());
215 cvd::Command vnc_server(config.vnc_server_binary());
216 vnc_server.AddParameter(port_options);
217 if (!config.enable_ivserver()) {
218 // When the ivserver is not enabled, the vnc touch_server needs to serve
219 // on unix sockets and send input events to whoever connects to it (namely
220 // crosvm)
221 auto touch_server = CreateVncInputServer(config.touch_socket_path());
222 if (!touch_server->IsOpen()) {
223 return;
224 }
225 vnc_server.AddParameter("-touch_fd=", touch_server);
226
227 auto keyboard_server =
228 CreateVncInputServer(config.keyboard_socket_path());
229 if (!keyboard_server->IsOpen()) {
230 return;
231 }
232 vnc_server.AddParameter("-keyboard_fd=", keyboard_server);
233 // TODO(b/128852363): This should be handled through the wayland mock
234 // instead.
235 // Additionally it receives the frame updates from a virtual socket
236 // instead
237 auto frames_server =
238 cvd::SharedFD::VsockServer(config.frames_vsock_port(), SOCK_STREAM);
239 if (!frames_server->IsOpen()) {
240 return;
241 }
242 vnc_server.AddParameter("-frame_server_fd=", frames_server);
243 }
244 process_monitor->StartSubprocess(std::move(vnc_server), callback);
245 }
246 }
247
LaunchStreamAudioIfEnabled(const vsoc::CuttlefishConfig & config,cvd::ProcessMonitor * process_monitor,std::function<bool (MonitorEntry *)> callback)248 void LaunchStreamAudioIfEnabled(const vsoc::CuttlefishConfig& config,
249 cvd::ProcessMonitor* process_monitor,
250 std::function<bool(MonitorEntry*)> callback) {
251 if (config.enable_stream_audio()) {
252 auto port_options = "-port=" + std::to_string(config.stream_audio_port());
253 cvd::Command stream_audio(config.stream_audio_binary());
254 stream_audio.AddParameter(port_options);
255 process_monitor->StartSubprocess(std::move(stream_audio), callback);
256 }
257 }
258
LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor * process_monitor,const vsoc::CuttlefishConfig & config,cvd::SharedFD adbd_events_pipe)259 void LaunchAdbConnectorIfEnabled(cvd::ProcessMonitor* process_monitor,
260 const vsoc::CuttlefishConfig& config,
261 cvd::SharedFD adbd_events_pipe) {
262 bool launch = false;
263 cvd::Command adb_connector(config.adb_connector_binary());
264 adb_connector.AddParameter("-adbd_events_fd=", adbd_events_pipe);
265
266 if (AdbTcpConnectorEnabled(config)) {
267 launch = true;
268 adb_connector.AddParameter(GetAdbConnectorTcpArg());
269 }
270 if (AdbVsockConnectorEnabled(config)) {
271 launch = true;
272 adb_connector.AddParameter(GetAdbConnectorVsockArg(config));
273 }
274
275 if (launch) {
276 process_monitor->StartSubprocess(std::move(adb_connector),
277 GetOnSubprocessExitCallback(config));
278 }
279 }
280
LaunchSocketForwardProxyIfEnabled(cvd::ProcessMonitor * process_monitor,const vsoc::CuttlefishConfig & config)281 void LaunchSocketForwardProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
282 const vsoc::CuttlefishConfig& config) {
283 if (AdbTunnelEnabled(config)) {
284 cvd::Command adb_tunnel(config.socket_forward_proxy_binary());
285 adb_tunnel.AddParameter(GetGuestPortArg());
286 adb_tunnel.AddParameter(GetHostPortArg());
287 process_monitor->StartSubprocess(std::move(adb_tunnel),
288 GetOnSubprocessExitCallback(config));
289 }
290 }
291
LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor * process_monitor,const vsoc::CuttlefishConfig & config)292 void LaunchSocketVsockProxyIfEnabled(cvd::ProcessMonitor* process_monitor,
293 const vsoc::CuttlefishConfig& config) {
294 if (AdbVsockTunnelEnabled(config)) {
295 cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
296 adb_tunnel.AddParameter("--vsock_port=6520");
297 adb_tunnel.AddParameter(
298 std::string{"--tcp_port="} + std::to_string(GetHostPort()));
299 adb_tunnel.AddParameter(std::string{"--vsock_guest_cid="} +
300 std::to_string(config.vsock_guest_cid()));
301 process_monitor->StartSubprocess(std::move(adb_tunnel),
302 GetOnSubprocessExitCallback(config));
303 }
304 if (AdbVsockHalfTunnelEnabled(config)) {
305 cvd::Command adb_tunnel(config.socket_vsock_proxy_binary());
306 adb_tunnel.AddParameter("--vsock_port=5555");
307 adb_tunnel.AddParameter(
308 std::string{"--tcp_port="} + std::to_string(GetHostPort()));
309 adb_tunnel.AddParameter(std::string{"--vsock_guest_cid="} +
310 std::to_string(config.vsock_guest_cid()));
311 process_monitor->StartSubprocess(std::move(adb_tunnel),
312 GetOnSubprocessExitCallback(config));
313 }
314 }
315
LaunchIvServerIfEnabled(cvd::ProcessMonitor * process_monitor,const vsoc::CuttlefishConfig & config)316 void LaunchIvServerIfEnabled(cvd::ProcessMonitor* process_monitor,
317 const vsoc::CuttlefishConfig& config) {
318 if (config.enable_ivserver()) {
319 process_monitor->StartSubprocess(GetIvServerCommand(config),
320 GetOnSubprocessExitCallback(config));
321
322 // Initialize the regions that require so before the VM starts.
323 PreLaunchInitializers::Initialize(config);
324 }
325 }
326