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