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 23 cvd::SharedFD CreateIvServerUnixSocket(const std::string& path) { 24 return cvd::SharedFD::SocketLocalServer(path.c_str(), false, SOCK_STREAM, 25 0666); 26 } 27 28 std::string GetGuestPortArg() { 29 constexpr int kEmulatorPort = 5555; 30 return std::string{"--guest_ports="} + std::to_string(kEmulatorPort); 31 } 32 33 std::string GetHostPortArg() { 34 return std::string{"--host_ports="} + std::to_string(GetHostPort()); 35 } 36 37 std::string GetAdbConnectorTcpArg() { 38 return std::string{"--addresses=127.0.0.1:"} + std::to_string(GetHostPort()); 39 } 40 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 47 bool AdbModeEnabled(const vsoc::CuttlefishConfig& config, const char* mode) { 48 return config.adb_mode().count(mode) > 0; 49 } 50 51 bool AdbTunnelEnabled(const vsoc::CuttlefishConfig& config) { 52 return AdbModeEnabled(config, kAdbModeTunnel); 53 } 54 55 bool AdbVsockTunnelEnabled(const vsoc::CuttlefishConfig& config) { 56 return config.vsock_guest_cid() > 2 57 && AdbModeEnabled(config, kAdbModeVsockTunnel); 58 } 59 60 bool AdbVsockHalfTunnelEnabled(const vsoc::CuttlefishConfig& config) { 61 return config.vsock_guest_cid() > 2 62 && AdbModeEnabled(config, kAdbModeVsockHalfTunnel); 63 } 64 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 73 bool AdbVsockConnectorEnabled(const vsoc::CuttlefishConfig& config) { 74 return config.run_adb_connector() 75 && AdbModeEnabled(config, kAdbModeNativeVsock); 76 } 77 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 88 int GetHostPort() { 89 constexpr int kFirstHostPort = 6520; 90 return vsoc::GetPerInstanceDefault(kFirstHostPort); 91 } 92 93 bool LogcatReceiverEnabled(const vsoc::CuttlefishConfig& config) { 94 return config.logcat_mode() == cvd::kLogcatVsockMode; 95 } 96 97 bool AdbUsbEnabled(const vsoc::CuttlefishConfig& config) { 98 return AdbModeEnabled(config, kAdbModeUsb); 99 } 100 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 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 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 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 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 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 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 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 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 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 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 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