• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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