Home | History | Annotate | Download | only in launch
      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