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
25 #include "common/libs/utils/result.h"
26 #include "host/commands/kernel_log_monitor/utils.h"
27 #include "host/libs/config/command_source.h"
28 #include "host/libs/config/cuttlefish_config.h"
29 #include "host/libs/config/known_paths.h"
30
31 namespace cuttlefish {
32 namespace {
33
34 class AdbHelper {
35 public:
INJECT(AdbHelper (const CuttlefishConfig::InstanceSpecific & instance,const AdbConfig & config))36 INJECT(AdbHelper(const CuttlefishConfig::InstanceSpecific& instance,
37 const AdbConfig& config))
38 : instance_(instance), config_(config) {}
39
ModeEnabled(const AdbMode & mode) const40 bool ModeEnabled(const AdbMode& mode) const {
41 return config_.Modes().count(mode) > 0;
42 }
43
ConnectorTcpArg() const44 std::string ConnectorTcpArg() const {
45 return "0.0.0.0:" + std::to_string(instance_.adb_host_port());
46 }
47
ConnectorVsockArg() const48 std::string ConnectorVsockArg() const {
49 return "vsock:" + std::to_string(instance_.vsock_guest_cid()) + ":5555";
50 }
51
VsockTunnelEnabled() const52 bool VsockTunnelEnabled() const {
53 return instance_.vsock_guest_cid() > 2 && ModeEnabled(AdbMode::VsockTunnel);
54 }
55
VsockHalfTunnelEnabled() const56 bool VsockHalfTunnelEnabled() const {
57 return instance_.vsock_guest_cid() > 2 &&
58 ModeEnabled(AdbMode::VsockHalfTunnel);
59 }
60
TcpConnectorEnabled() const61 bool TcpConnectorEnabled() const {
62 bool vsock_tunnel = VsockTunnelEnabled();
63 bool vsock_half_tunnel = VsockHalfTunnelEnabled();
64 return config_.RunConnector() && (vsock_tunnel || vsock_half_tunnel);
65 }
66
VsockConnectorEnabled() const67 bool VsockConnectorEnabled() const {
68 return config_.RunConnector() && ModeEnabled(AdbMode::NativeVsock);
69 }
70
71 private:
72 const CuttlefishConfig::InstanceSpecific& instance_;
73 const AdbConfig& config_;
74 };
75
76 class AdbConnector : public CommandSource {
77 public:
INJECT(AdbConnector (const AdbHelper & helper))78 INJECT(AdbConnector(const AdbHelper& helper)) : helper_(helper) {}
79
80 // CommandSource
Commands()81 Result<std::vector<MonitorCommand>> Commands() override {
82 Command adb_connector(AdbConnectorBinary());
83 std::set<std::string> addresses;
84
85 if (helper_.TcpConnectorEnabled()) {
86 addresses.insert(helper_.ConnectorTcpArg());
87 }
88 if (helper_.VsockConnectorEnabled()) {
89 addresses.insert(helper_.ConnectorVsockArg());
90 }
91
92 if (addresses.size() == 0) {
93 return {};
94 }
95 std::string address_arg = "--addresses=";
96 for (auto& arg : addresses) {
97 address_arg += arg + ",";
98 }
99 address_arg.pop_back();
100 adb_connector.AddParameter(address_arg);
101
102 std::vector<MonitorCommand> commands;
103 commands.emplace_back(std::move(adb_connector));
104 return commands;
105 }
106
107 // SetupFeature
Name() const108 std::string Name() const override { return "AdbConnector"; }
Enabled() const109 bool Enabled() const override {
110 return helper_.TcpConnectorEnabled() || helper_.VsockConnectorEnabled();
111 }
112
113 private:
Dependencies() const114 std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
Setup()115 bool Setup() override { return true; }
116
117 const AdbHelper& helper_;
118 };
119
120 class SocketVsockProxy : public CommandSource, public KernelLogPipeConsumer {
121 public:
INJECT(SocketVsockProxy (const AdbHelper & helper,const CuttlefishConfig::InstanceSpecific & instance,KernelLogPipeProvider & log_pipe_provider))122 INJECT(SocketVsockProxy(const AdbHelper& helper,
123 const CuttlefishConfig::InstanceSpecific& instance,
124 KernelLogPipeProvider& log_pipe_provider))
125 : helper_(helper),
126 instance_(instance),
127 log_pipe_provider_(log_pipe_provider) {}
128
129 // CommandSource
Commands()130 Result<std::vector<MonitorCommand>> Commands() override {
131 std::vector<MonitorCommand> commands;
132 if (helper_.VsockTunnelEnabled()) {
133 Command adb_tunnel(SocketVsockProxyBinary());
134 /**
135 * This socket_vsock_proxy (a.k.a. sv proxy) runs on the host. It assumes
136 * that another sv proxy runs inside the guest. see:
137 * shared/config/init.vendor.rc The sv proxy in the guest exposes
138 * vsock:cid:6520 across the cuttlefish instances in multi-tenancy. cid is
139 * different per instance.
140 *
141 * This host sv proxy should cooperate with the guest sv proxy. Thus, one
142 * end of the tunnel is vsock:cid:6520 regardless of instance number.
143 * Another end faces the host adb daemon via tcp. Thus, the server type is
144 * tcp here. The tcp port differs from instance to instance, and is
145 * instance.adb_host_port()
146 *
147 */
148 adb_tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
149 adb_tunnel.AddParameter("--start_event_id=", monitor::Event::AdbdStarted);
150 adb_tunnel.AddParameter("--server_type=tcp");
151 adb_tunnel.AddParameter("--server_fd=", tcp_server_);
152 adb_tunnel.AddParameter("--client_type=vsock");
153 adb_tunnel.AddParameter("--client_vsock_port=6520");
154 adb_tunnel.AddParameter("--client_vsock_id=", instance_.vsock_guest_cid());
155 commands.emplace_back(std::move(adb_tunnel));
156 }
157 if (helper_.VsockHalfTunnelEnabled()) {
158 Command adb_tunnel(SocketVsockProxyBinary());
159 /*
160 * This socket_vsock_proxy (a.k.a. sv proxy) runs on the host, and
161 * cooperates with the adbd inside the guest. See this file:
162 * shared/device.mk, especially the line says "persist.adb.tcp.port="
163 *
164 * The guest adbd is listening on vsock:cid:5555 across cuttlefish
165 * instances. Sv proxy faces the host adb daemon via tcp. The server type
166 * should be therefore tcp, and the port should differ from instance to
167 * instance and be equal to instance.adb_host_port()
168 */
169 adb_tunnel.AddParameter("--events_fd=", kernel_log_pipe_);
170 adb_tunnel.AddParameter("--start_event_id=", monitor::Event::AdbdStarted);
171 adb_tunnel.AddParameter("--server_type=tcp");
172 adb_tunnel.AddParameter("--server_fd=", tcp_server_);
173 adb_tunnel.AddParameter("--client_type=vsock");
174 adb_tunnel.AddParameter("--client_vsock_port=", 5555);
175 adb_tunnel.AddParameter("--client_vsock_id=", instance_.vsock_guest_cid());
176 adb_tunnel.AddParameter("--label=", "adb");
177 commands.emplace_back(std::move(adb_tunnel));
178 }
179 return commands;
180 }
181
182 // SetupFeature
Name() const183 std::string Name() const override { return "SocketVsockProxy"; }
Enabled() const184 bool Enabled() const override {
185 return helper_.VsockTunnelEnabled() || helper_.VsockHalfTunnelEnabled();
186 }
187
188 private:
Dependencies() const189 std::unordered_set<SetupFeature*> Dependencies() const override {
190 return {static_cast<SetupFeature*>(&log_pipe_provider_)};
191 }
Setup()192 bool Setup() override {
193 tcp_server_ =
194 SharedFD::SocketLocalServer(instance_.adb_host_port(), SOCK_STREAM);
195 if (!tcp_server_->IsOpen()) {
196 LOG(ERROR) << "Unable to create socket_vsock_proxy server socket: "
197 << tcp_server_->StrError();
198 return false;
199 }
200 kernel_log_pipe_ = log_pipe_provider_.KernelLogPipe();
201 return true;
202 }
203
204 const AdbHelper& helper_;
205 const CuttlefishConfig::InstanceSpecific& instance_;
206 KernelLogPipeProvider& log_pipe_provider_;
207 SharedFD kernel_log_pipe_;
208 SharedFD tcp_server_;
209 };
210
211 } // namespace
212
213 fruit::Component<fruit::Required<KernelLogPipeProvider, const AdbConfig,
214 const CuttlefishConfig::InstanceSpecific>>
LaunchAdbComponent()215 LaunchAdbComponent() {
216 return fruit::createComponent()
217 .addMultibinding<CommandSource, AdbConnector>()
218 .addMultibinding<CommandSource, SocketVsockProxy>()
219 .addMultibinding<SetupFeature, AdbConnector>()
220 .addMultibinding<KernelLogPipeConsumer, SocketVsockProxy>()
221 .addMultibinding<SetupFeature, SocketVsockProxy>();
222 }
223
224 } // namespace cuttlefish
225