1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "host/libs/config/adb/adb.h"
17 
18 #include <string>
19 #include <unordered_set>
20 #include <utility>
21 #include <vector>
22 
23 #include <fruit/fruit.h>
24 #include <gflags/gflags.h>
25 
26 #include "common/libs/utils/result.h"
27 #include "host/commands/kernel_log_monitor/utils.h"
28 #include "host/libs/config/command_source.h"
29 #include "host/libs/config/cuttlefish_config.h"
30 #include "host/libs/config/known_paths.h"
31 
32 namespace cuttlefish {
33 namespace {
34 
35 class AdbHelper {
36  public:
INJECT(AdbHelper (const CuttlefishConfig::InstanceSpecific & instance,const AdbConfig & config))37   INJECT(AdbHelper(const CuttlefishConfig::InstanceSpecific& instance,
38                    const AdbConfig& config))
39       : instance_(instance), config_(config) {}
40 
ModeEnabled(const AdbMode & mode) const41   bool ModeEnabled(const AdbMode& mode) const {
42     return config_.Modes().count(mode) > 0;
43   }
44 
ConnectorTcpArg() const45   std::string ConnectorTcpArg() const {
46     return "0.0.0.0:" + std::to_string(instance_.adb_host_port());
47   }
48 
ConnectorVsockArg() const49   std::string ConnectorVsockArg() const {
50     return "vsock:" + std::to_string(instance_.vsock_guest_cid()) + ":5555";
51   }
52 
VsockTunnelEnabled() const53   bool VsockTunnelEnabled() const {
54     return instance_.vsock_guest_cid() > 2 && ModeEnabled(AdbMode::VsockTunnel);
55   }
56 
VsockHalfTunnelEnabled() const57   bool VsockHalfTunnelEnabled() const {
58     return instance_.vsock_guest_cid() > 2 &&
59            ModeEnabled(AdbMode::VsockHalfTunnel);
60   }
61 
TcpConnectorEnabled() const62   bool TcpConnectorEnabled() const {
63     bool vsock_tunnel = VsockTunnelEnabled();
64     bool vsock_half_tunnel = VsockHalfTunnelEnabled();
65     return config_.RunConnector() && (vsock_tunnel || vsock_half_tunnel);
66   }
67 
VsockConnectorEnabled() const68   bool VsockConnectorEnabled() const {
69     return config_.RunConnector() && ModeEnabled(AdbMode::NativeVsock);
70   }
71 
72  private:
73   const CuttlefishConfig::InstanceSpecific& instance_;
74   const AdbConfig& config_;
75 };
76 
77 class AdbConnector : public CommandSource {
78  public:
INJECT(AdbConnector (const AdbHelper & helper))79   INJECT(AdbConnector(const AdbHelper& helper)) : helper_(helper) {}
80 
81   // CommandSource
Commands()82   Result<std::vector<MonitorCommand>> Commands() override {
83     Command adb_connector(AdbConnectorBinary());
84     std::set<std::string> addresses;
85 
86     if (helper_.TcpConnectorEnabled()) {
87       addresses.insert(helper_.ConnectorTcpArg());
88     }
89     if (helper_.VsockConnectorEnabled()) {
90       addresses.insert(helper_.ConnectorVsockArg());
91     }
92 
93     if (addresses.size() == 0) {
94       return {};
95     }
96     std::string address_arg = "--addresses=";
97     for (auto& arg : addresses) {
98       address_arg += arg + ",";
99     }
100     address_arg.pop_back();
101     adb_connector.AddParameter(address_arg);
102 
103     std::vector<MonitorCommand> commands;
104     commands.emplace_back(std::move(adb_connector));
105     return commands;
106   }
107 
108   // SetupFeature
Name() const109   std::string Name() const override { return "AdbConnector"; }
Enabled() const110   bool Enabled() const override {
111     return helper_.TcpConnectorEnabled() || helper_.VsockConnectorEnabled();
112   }
113 
114  private:
Dependencies() const115   std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
ResultSetup()116   Result<void> ResultSetup() override { return {}; }
117 
118   const AdbHelper& helper_;
119 };
120 
121 class SocketVsockProxy : public CommandSource, public KernelLogPipeConsumer {
122  public:
INJECT(SocketVsockProxy (const AdbHelper & helper,const CuttlefishConfig & cuttlefish_config,const CuttlefishConfig::InstanceSpecific & instance,KernelLogPipeProvider & log_pipe_provider))123   INJECT(SocketVsockProxy(const AdbHelper& helper,
124                           const CuttlefishConfig& cuttlefish_config,
125                           const CuttlefishConfig::InstanceSpecific& instance,
126                           KernelLogPipeProvider& log_pipe_provider))
127       : helper_(helper),
128         cuttlefish_config_(cuttlefish_config),
129         instance_(instance),
130         log_pipe_provider_(log_pipe_provider) {}
131 
132   // CommandSource
Commands()133   Result<std::vector<MonitorCommand>> Commands() override {
134     std::vector<MonitorCommand> commands;
135     const auto vsock_tunnel_enabled = helper_.VsockTunnelEnabled();
136     const auto vsock_half_tunnel_enabled = helper_.VsockHalfTunnelEnabled();
137     CF_EXPECT(!vsock_half_tunnel_enabled || !vsock_tunnel_enabled,
138               "Up to one of vsock_tunnel or vsock_half_tunnel is allowed.");
139     if (!vsock_half_tunnel_enabled && !vsock_tunnel_enabled) {
140       return commands;
141     }
142 
143     Command adb_tunnel(SocketVsockProxyBinary());
144     adb_tunnel.AddParameter("--vhost_user_vsock=",
145                             instance_.vhost_user_vsock());
146     adb_tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
147     adb_tunnel.AddParameter("--start_event_id=", monitor::Event::AdbdStarted);
148     adb_tunnel.AddParameter("--stop_event_id=",
149                             monitor::Event::FastbootStarted);
150     // We assume that snapshots are always taken after ADBD has started. That
151     // means the start event will never come for a restored device, so we pass
152     // a flag to the proxy to allow it to alter its behavior.
153     if (IsRestoring(cuttlefish_config_)) {
154       adb_tunnel.AddParameter("--restore=true");
155     }
156     adb_tunnel.AddParameter("--server_type=tcp");
157     adb_tunnel.AddParameter("--server_tcp_port=", instance_.adb_host_port());
158 
159     if (vsock_tunnel_enabled) {
160       /**
161        * This socket_vsock_proxy (a.k.a. sv proxy) runs on the host. It assumes
162        * that another sv proxy runs inside the guest. see:
163        * shared/config/init.vendor.rc The sv proxy in the guest exposes
164        * vsock:cid:6520 across the cuttlefish instances in multi-tenancy. cid is
165        * different per instance.
166        *
167        * This host sv proxy should cooperate with the guest sv proxy. Thus, one
168        * end of the tunnel is vsock:cid:6520 regardless of instance number.
169        * Another end faces the host adb daemon via tcp. Thus, the server type is
170        * tcp here. The tcp port differs from instance to instance, and is
171        * instance.adb_host_port()
172        *
173        */
174       adb_tunnel.AddParameter("--client_type=vsock");
175       adb_tunnel.AddParameter("--client_vsock_port=6520");
176     } else {
177       /*
178        * This socket_vsock_proxy (a.k.a. sv proxy) runs on the host, and
179        * cooperates with the adbd inside the guest. See this file:
180        *  shared/device.mk, especially the line says "persist.adb.tcp.port="
181        *
182        * The guest adbd is listening on vsock:cid:5555 across cuttlefish
183        * instances. Sv proxy faces the host adb daemon via tcp. The server type
184        * should be therefore tcp, and the port should differ from instance to
185        * instance and be equal to instance.adb_host_port()
186        */
187       adb_tunnel.AddParameter("--client_type=vsock");
188       adb_tunnel.AddParameter("--client_vsock_port=", 5555);
189     }
190 
191     adb_tunnel.AddParameter("--client_vsock_id=", instance_.vsock_guest_cid());
192     adb_tunnel.AddParameter("--label=", "adb");
193     commands.emplace_back(std::move(adb_tunnel));
194     return commands;
195   }
196 
197   // SetupFeature
Name() const198   std::string Name() const override { return "SocketVsockProxy"; }
Enabled() const199   bool Enabled() const override {
200     return helper_.VsockTunnelEnabled() || helper_.VsockHalfTunnelEnabled();
201   }
202 
203  private:
Dependencies() const204   std::unordered_set<SetupFeature*> Dependencies() const override {
205     return {static_cast<SetupFeature*>(&log_pipe_provider_)};
206   }
207 
ResultSetup()208   Result<void> ResultSetup() override {
209     kernel_log_pipe_ = log_pipe_provider_.KernelLogPipe();
210     return {};
211   }
212 
213   const AdbHelper& helper_;
214   const CuttlefishConfig& cuttlefish_config_;
215   const CuttlefishConfig::InstanceSpecific& instance_;
216   KernelLogPipeProvider& log_pipe_provider_;
217   SharedFD kernel_log_pipe_;
218 };
219 
220 }  // namespace
221 
222 fruit::Component<fruit::Required<KernelLogPipeProvider, const AdbConfig,
223                                  const CuttlefishConfig,
224                                  const CuttlefishConfig::InstanceSpecific>>
LaunchAdbComponent()225 LaunchAdbComponent() {
226   return fruit::createComponent()
227       .addMultibinding<CommandSource, AdbConnector>()
228       .addMultibinding<CommandSource, SocketVsockProxy>()
229       .addMultibinding<SetupFeature, AdbConnector>()
230       .addMultibinding<KernelLogPipeConsumer, SocketVsockProxy>()
231       .addMultibinding<SetupFeature, SocketVsockProxy>();
232 }
233 
234 }  // namespace cuttlefish
235