blob: 7f43bb64a09bf2a7a765a42f54697624a480fba6 [file] [log] [blame]
Yifan Hongf7760012021-06-04 16:04:42 -07001/*
2 * Copyright (C) 2021 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
17#include "ServiceManagerHost.h"
18
19#include <android-base/parseint.h>
20#include <android-base/strings.h>
21#include <binder/IServiceManager.h>
22#include <binder/RpcSession.h>
23
24#include "UtilsHost.h"
25
26namespace android {
27
28namespace {
29
30const void* kDeviceServiceExtraId = "DeviceServiceExtra";
31
32// Parse stdout of program execution to string. If any error, return 0.
33unsigned int parsePortNumber(const std::string& out, const std::string& what) {
34 auto trimmed = android::base::Trim(out);
35 unsigned int port = 0;
36 if (!android::base::ParseUint(trimmed, &port)) {
37 int savedErrno = errno;
38 ALOGE("%s is not a valid %s: %s", trimmed.c_str(), what.c_str(), strerror(savedErrno));
39 return 0;
40 }
41 if (port == 0) {
42 ALOGE("0 is not a valid %s", what.c_str());
43 return 0; // explicitly
44 }
45 return port;
46}
47
48// RAII object for adb forwarding
49class AdbForwarder {
50public:
51 AdbForwarder() = default;
52 static std::optional<AdbForwarder> forward(unsigned int devicePort);
53 AdbForwarder(AdbForwarder&& other) noexcept { (*this) = std::move(other); }
54 AdbForwarder& operator=(AdbForwarder&&) noexcept;
55 ~AdbForwarder();
56 [[nodiscard]] const std::optional<unsigned int>& hostPort() const { return mPort; }
57
58private:
Tomasz Wasilczykdf07f942023-11-02 15:07:45 -070059 AdbForwarder(const AdbForwarder&) = delete;
60 void operator=(const AdbForwarder&) = delete;
Yifan Hongf7760012021-06-04 16:04:42 -070061 explicit AdbForwarder(unsigned int port) : mPort(port) {}
62 std::optional<unsigned int> mPort;
63};
64std::optional<AdbForwarder> AdbForwarder::forward(unsigned int devicePort) {
65 auto result =
66 execute({"adb", "forward", "tcp:0", "tcp:" + std::to_string(devicePort)}, nullptr);
67 if (!result.ok()) {
68 ALOGE("Unable to run `adb forward tcp:0 tcp:%d`: %s", devicePort,
69 result.error().message().c_str());
70 return std::nullopt;
71 }
72 // Must end with exit code 0 (`has_value() && value() == 0`)
73 if (result->exitCode.value_or(1) != 0) {
74 ALOGE("Unable to run `adb forward tcp:0 tcp:%d`, command exits with %s", devicePort,
75 result->toString().c_str());
76 return std::nullopt;
77 }
Colin Crossc9a77aa2021-09-13 16:31:38 -070078 if (!result->stderrStr.empty()) {
Yifan Hongf7760012021-06-04 16:04:42 -070079 LOG_HOST("`adb forward tcp:0 tcp:%d` writes to stderr: %s", devicePort,
Colin Crossc9a77aa2021-09-13 16:31:38 -070080 result->stderrStr.c_str());
Yifan Hongf7760012021-06-04 16:04:42 -070081 }
82
Colin Crossc9a77aa2021-09-13 16:31:38 -070083 unsigned int hostPort = parsePortNumber(result->stdoutStr, "host port");
Yifan Hongf7760012021-06-04 16:04:42 -070084 if (hostPort == 0) return std::nullopt;
85
86 return AdbForwarder(hostPort);
87}
88
89AdbForwarder& AdbForwarder::operator=(AdbForwarder&& other) noexcept {
90 std::swap(mPort, other.mPort);
91 return *this;
92}
93
94AdbForwarder::~AdbForwarder() {
95 if (!mPort.has_value()) return;
96
97 auto result = execute({"adb", "forward", "--remove", "tcp:" + std::to_string(*mPort)}, nullptr);
98 if (!result.ok()) {
99 ALOGE("Unable to run `adb forward --remove tcp:%d`: %s", *mPort,
100 result.error().message().c_str());
101 return;
102 }
103 // Must end with exit code 0 (`has_value() && value() == 0`)
104 if (result->exitCode.value_or(1) != 0) {
105 ALOGE("Unable to run `adb forward --remove tcp:%d`, command exits with %s", *mPort,
106 result->toString().c_str());
107 return;
108 }
Colin Crossc9a77aa2021-09-13 16:31:38 -0700109 if (!result->stderrStr.empty()) {
Yifan Hongf7760012021-06-04 16:04:42 -0700110 LOG_HOST("`adb forward --remove tcp:%d` writes to stderr: %s", *mPort,
Colin Crossc9a77aa2021-09-13 16:31:38 -0700111 result->stderrStr.c_str());
Yifan Hongf7760012021-06-04 16:04:42 -0700112 }
113
114 LOG_HOST("Successfully run `adb forward --remove tcp:%d`", *mPort);
115}
116
117void cleanupCommandResult(const void* id, void* obj, void* /* cookie */) {
118 LOG_ALWAYS_FATAL_IF(id != kDeviceServiceExtraId,
119 "cleanupCommandResult invoked with mismatched ID %p, "
120 "expected %p",
121 id, kDeviceServiceExtraId);
122 auto ptr = static_cast<CommandResult*>(obj);
123 delete ptr;
124}
125
126} // namespace
127
Yifan Hong5a05ef72021-10-08 17:33:47 -0700128sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs,
129 const RpcDelegateServiceManagerOptions& options) {
Yifan Hongf7760012021-06-04 16:04:42 -0700130 std::vector<std::string> prefix{"adb", "shell", "servicedispatcher"};
131 serviceDispatcherArgs.insert(serviceDispatcherArgs.begin(), prefix.begin(), prefix.end());
132
133 auto result = execute(std::move(serviceDispatcherArgs), &CommandResult::stdoutEndsWithNewLine);
134 if (!result.ok()) {
135 ALOGE("%s", result.error().message().c_str());
136 return nullptr;
137 }
138
139 // `servicedispatcher` process must be alive to keep the port open.
140 if (result->exitCode.has_value()) {
141 ALOGE("Command exits with: %s", result->toString().c_str());
142 return nullptr;
143 }
Colin Crossc9a77aa2021-09-13 16:31:38 -0700144 if (!result->stderrStr.empty()) {
145 LOG_HOST("servicedispatcher writes to stderr: %s", result->stderrStr.c_str());
Yifan Hongf7760012021-06-04 16:04:42 -0700146 }
147
148 if (!result->stdoutEndsWithNewLine()) {
149 ALOGE("Unexpected command result: %s", result->toString().c_str());
150 return nullptr;
151 }
152
Colin Crossc9a77aa2021-09-13 16:31:38 -0700153 unsigned int devicePort = parsePortNumber(result->stdoutStr, "device port");
Yifan Hongf7760012021-06-04 16:04:42 -0700154 if (devicePort == 0) return nullptr;
155
156 auto forwardResult = AdbForwarder::forward(devicePort);
157 if (!forwardResult.has_value()) {
158 return nullptr;
159 }
160 LOG_ALWAYS_FATAL_IF(!forwardResult->hostPort().has_value());
161
162 auto rpcSession = RpcSession::make();
Steven Morelandfeb13e82023-03-01 01:25:33 +0000163 if (options.maxOutgoingConnections.has_value()) {
164 rpcSession->setMaxOutgoingConnections(*options.maxOutgoingConnections);
Yifan Hong5a05ef72021-10-08 17:33:47 -0700165 }
166
Steven Moreland2372f9d2021-08-05 15:42:01 -0700167 if (status_t status = rpcSession->setupInetClient("127.0.0.1", *forwardResult->hostPort());
168 status != OK) {
169 ALOGE("Unable to set up inet client on host port %u: %s", *forwardResult->hostPort(),
170 statusToString(status).c_str());
Yifan Hongf7760012021-06-04 16:04:42 -0700171 return nullptr;
172 }
173 auto binder = rpcSession->getRootObject();
174 if (binder == nullptr) {
175 ALOGE("RpcSession::getRootObject returns nullptr");
176 return nullptr;
177 }
Steven Moreland9234c432021-06-29 23:01:10 +0000178
179 LOG_ALWAYS_FATAL_IF(
180 nullptr !=
181 binder->attachObject(kDeviceServiceExtraId,
182 static_cast<void*>(new CommandResult(std::move(*result))), nullptr,
183 &cleanupCommandResult));
Yifan Hongf7760012021-06-04 16:04:42 -0700184 return binder;
185}
186
187} // namespace android