• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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