1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "RpcSession"
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcSession.h>
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #include <dlfcn.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <netinet/tcp.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <poll.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <unistd.h>
26*38e8c45fSAndroid Build Coastguard Worker
27*38e8c45fSAndroid Build Coastguard Worker #include <string_view>
28*38e8c45fSAndroid Build Coastguard Worker
29*38e8c45fSAndroid Build Coastguard Worker #include <binder/BpBinder.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <binder/Functional.h>
31*38e8c45fSAndroid Build Coastguard Worker #include <binder/Parcel.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcServer.h>
33*38e8c45fSAndroid Build Coastguard Worker #include <binder/RpcTransportRaw.h>
34*38e8c45fSAndroid Build Coastguard Worker #include <binder/Stability.h>
35*38e8c45fSAndroid Build Coastguard Worker #include <utils/String8.h>
36*38e8c45fSAndroid Build Coastguard Worker
37*38e8c45fSAndroid Build Coastguard Worker #include "BuildFlags.h"
38*38e8c45fSAndroid Build Coastguard Worker #include "FdTrigger.h"
39*38e8c45fSAndroid Build Coastguard Worker #include "OS.h"
40*38e8c45fSAndroid Build Coastguard Worker #include "RpcSocketAddress.h"
41*38e8c45fSAndroid Build Coastguard Worker #include "RpcState.h"
42*38e8c45fSAndroid Build Coastguard Worker #include "RpcTransportUtils.h"
43*38e8c45fSAndroid Build Coastguard Worker #include "RpcWireFormat.h"
44*38e8c45fSAndroid Build Coastguard Worker #include "Utils.h"
45*38e8c45fSAndroid Build Coastguard Worker
46*38e8c45fSAndroid Build Coastguard Worker #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
47*38e8c45fSAndroid Build Coastguard Worker #include <jni.h>
48*38e8c45fSAndroid Build Coastguard Worker extern "C" JavaVM* AndroidRuntimeGetJavaVM();
49*38e8c45fSAndroid Build Coastguard Worker #endif
50*38e8c45fSAndroid Build Coastguard Worker
51*38e8c45fSAndroid Build Coastguard Worker namespace android {
52*38e8c45fSAndroid Build Coastguard Worker
53*38e8c45fSAndroid Build Coastguard Worker using namespace android::binder::impl;
54*38e8c45fSAndroid Build Coastguard Worker using android::binder::borrowed_fd;
55*38e8c45fSAndroid Build Coastguard Worker using android::binder::unique_fd;
56*38e8c45fSAndroid Build Coastguard Worker
RpcSession(std::unique_ptr<RpcTransportCtx> ctx)57*38e8c45fSAndroid Build Coastguard Worker RpcSession::RpcSession(std::unique_ptr<RpcTransportCtx> ctx) : mCtx(std::move(ctx)) {
58*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("RpcSession created %p", this);
59*38e8c45fSAndroid Build Coastguard Worker
60*38e8c45fSAndroid Build Coastguard Worker mRpcBinderState = std::make_unique<RpcState>();
61*38e8c45fSAndroid Build Coastguard Worker }
~RpcSession()62*38e8c45fSAndroid Build Coastguard Worker RpcSession::~RpcSession() {
63*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("RpcSession destroyed %p", this);
64*38e8c45fSAndroid Build Coastguard Worker
65*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
66*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mConnections.mIncoming.size() != 0,
67*38e8c45fSAndroid Build Coastguard Worker "Should not be able to destroy a session with servers in use.");
68*38e8c45fSAndroid Build Coastguard Worker }
69*38e8c45fSAndroid Build Coastguard Worker
make()70*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession> RpcSession::make() {
71*38e8c45fSAndroid Build Coastguard Worker // Default is without TLS.
72*38e8c45fSAndroid Build Coastguard Worker return make(binder::os::makeDefaultRpcTransportCtxFactory());
73*38e8c45fSAndroid Build Coastguard Worker }
74*38e8c45fSAndroid Build Coastguard Worker
make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory)75*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession> RpcSession::make(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory) {
76*38e8c45fSAndroid Build Coastguard Worker auto ctx = rpcTransportCtxFactory->newClientCtx();
77*38e8c45fSAndroid Build Coastguard Worker if (ctx == nullptr) return nullptr;
78*38e8c45fSAndroid Build Coastguard Worker return sp<RpcSession>::make(std::move(ctx));
79*38e8c45fSAndroid Build Coastguard Worker }
80*38e8c45fSAndroid Build Coastguard Worker
setMaxIncomingThreads(size_t threads)81*38e8c45fSAndroid Build Coastguard Worker void RpcSession::setMaxIncomingThreads(size_t threads) {
82*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
83*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mStartedSetup,
84*38e8c45fSAndroid Build Coastguard Worker "Must set max incoming threads before setting up connections");
85*38e8c45fSAndroid Build Coastguard Worker mMaxIncomingThreads = threads;
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker
getMaxIncomingThreads()88*38e8c45fSAndroid Build Coastguard Worker size_t RpcSession::getMaxIncomingThreads() {
89*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
90*38e8c45fSAndroid Build Coastguard Worker return mMaxIncomingThreads;
91*38e8c45fSAndroid Build Coastguard Worker }
92*38e8c45fSAndroid Build Coastguard Worker
setMaxOutgoingConnections(size_t connections)93*38e8c45fSAndroid Build Coastguard Worker void RpcSession::setMaxOutgoingConnections(size_t connections) {
94*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
95*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mStartedSetup,
96*38e8c45fSAndroid Build Coastguard Worker "Must set max outgoing threads before setting up connections");
97*38e8c45fSAndroid Build Coastguard Worker mMaxOutgoingConnections = connections;
98*38e8c45fSAndroid Build Coastguard Worker }
99*38e8c45fSAndroid Build Coastguard Worker
getMaxOutgoingThreads()100*38e8c45fSAndroid Build Coastguard Worker size_t RpcSession::getMaxOutgoingThreads() {
101*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
102*38e8c45fSAndroid Build Coastguard Worker return mMaxOutgoingConnections;
103*38e8c45fSAndroid Build Coastguard Worker }
104*38e8c45fSAndroid Build Coastguard Worker
setProtocolVersionInternal(uint32_t version,bool checkStarted)105*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::setProtocolVersionInternal(uint32_t version, bool checkStarted) {
106*38e8c45fSAndroid Build Coastguard Worker if (!RpcState::validateProtocolVersion(version)) {
107*38e8c45fSAndroid Build Coastguard Worker return false;
108*38e8c45fSAndroid Build Coastguard Worker }
109*38e8c45fSAndroid Build Coastguard Worker
110*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
111*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(checkStarted && mStartedSetup,
112*38e8c45fSAndroid Build Coastguard Worker "Must set protocol version before setting up connections");
113*38e8c45fSAndroid Build Coastguard Worker if (mProtocolVersion && version > *mProtocolVersion) {
114*38e8c45fSAndroid Build Coastguard Worker ALOGE("Cannot upgrade explicitly capped protocol version %u to newer version %u",
115*38e8c45fSAndroid Build Coastguard Worker *mProtocolVersion, version);
116*38e8c45fSAndroid Build Coastguard Worker return false;
117*38e8c45fSAndroid Build Coastguard Worker }
118*38e8c45fSAndroid Build Coastguard Worker
119*38e8c45fSAndroid Build Coastguard Worker mProtocolVersion = version;
120*38e8c45fSAndroid Build Coastguard Worker return true;
121*38e8c45fSAndroid Build Coastguard Worker }
122*38e8c45fSAndroid Build Coastguard Worker
setProtocolVersion(uint32_t version)123*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::setProtocolVersion(uint32_t version) {
124*38e8c45fSAndroid Build Coastguard Worker return setProtocolVersionInternal(version, true);
125*38e8c45fSAndroid Build Coastguard Worker }
126*38e8c45fSAndroid Build Coastguard Worker
getProtocolVersion()127*38e8c45fSAndroid Build Coastguard Worker std::optional<uint32_t> RpcSession::getProtocolVersion() {
128*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
129*38e8c45fSAndroid Build Coastguard Worker return mProtocolVersion;
130*38e8c45fSAndroid Build Coastguard Worker }
131*38e8c45fSAndroid Build Coastguard Worker
setFileDescriptorTransportMode(FileDescriptorTransportMode mode)132*38e8c45fSAndroid Build Coastguard Worker void RpcSession::setFileDescriptorTransportMode(FileDescriptorTransportMode mode) {
133*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
134*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mStartedSetup,
135*38e8c45fSAndroid Build Coastguard Worker "Must set file descriptor transport mode before setting up connections");
136*38e8c45fSAndroid Build Coastguard Worker mFileDescriptorTransportMode = mode;
137*38e8c45fSAndroid Build Coastguard Worker }
138*38e8c45fSAndroid Build Coastguard Worker
getFileDescriptorTransportMode()139*38e8c45fSAndroid Build Coastguard Worker RpcSession::FileDescriptorTransportMode RpcSession::getFileDescriptorTransportMode() {
140*38e8c45fSAndroid Build Coastguard Worker return mFileDescriptorTransportMode;
141*38e8c45fSAndroid Build Coastguard Worker }
142*38e8c45fSAndroid Build Coastguard Worker
setupUnixDomainClient(const char * path)143*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupUnixDomainClient(const char* path) {
144*38e8c45fSAndroid Build Coastguard Worker return setupSocketClient(UnixSocketAddress(path));
145*38e8c45fSAndroid Build Coastguard Worker }
146*38e8c45fSAndroid Build Coastguard Worker
setupUnixDomainSocketBootstrapClient(unique_fd bootstrapFd)147*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupUnixDomainSocketBootstrapClient(unique_fd bootstrapFd) {
148*38e8c45fSAndroid Build Coastguard Worker mBootstrapTransport =
149*38e8c45fSAndroid Build Coastguard Worker mCtx->newTransport(RpcTransportFd(std::move(bootstrapFd)), mShutdownTrigger.get());
150*38e8c45fSAndroid Build Coastguard Worker return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) {
151*38e8c45fSAndroid Build Coastguard Worker int socks[2];
152*38e8c45fSAndroid Build Coastguard Worker if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, socks) < 0) {
153*38e8c45fSAndroid Build Coastguard Worker int savedErrno = errno;
154*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed socketpair: %s", strerror(savedErrno));
155*38e8c45fSAndroid Build Coastguard Worker return -savedErrno;
156*38e8c45fSAndroid Build Coastguard Worker }
157*38e8c45fSAndroid Build Coastguard Worker unique_fd clientFd(socks[0]), serverFd(socks[1]);
158*38e8c45fSAndroid Build Coastguard Worker
159*38e8c45fSAndroid Build Coastguard Worker int zero = 0;
160*38e8c45fSAndroid Build Coastguard Worker iovec iov{&zero, sizeof(zero)};
161*38e8c45fSAndroid Build Coastguard Worker std::vector<std::variant<unique_fd, borrowed_fd>> fds;
162*38e8c45fSAndroid Build Coastguard Worker fds.push_back(std::move(serverFd));
163*38e8c45fSAndroid Build Coastguard Worker
164*38e8c45fSAndroid Build Coastguard Worker status_t status = mBootstrapTransport->interruptableWriteFully(mShutdownTrigger.get(), &iov,
165*38e8c45fSAndroid Build Coastguard Worker 1, std::nullopt, &fds);
166*38e8c45fSAndroid Build Coastguard Worker if (status != OK) {
167*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to send fd over bootstrap transport: %s", statusToString(status).c_str());
168*38e8c45fSAndroid Build Coastguard Worker return status;
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker
171*38e8c45fSAndroid Build Coastguard Worker return initAndAddConnection(RpcTransportFd(std::move(clientFd)), sessionId, incoming);
172*38e8c45fSAndroid Build Coastguard Worker });
173*38e8c45fSAndroid Build Coastguard Worker }
174*38e8c45fSAndroid Build Coastguard Worker
setupVsockClient(unsigned int cid,unsigned int port)175*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupVsockClient(unsigned int cid, unsigned int port) {
176*38e8c45fSAndroid Build Coastguard Worker return setupSocketClient(VsockSocketAddress(cid, port));
177*38e8c45fSAndroid Build Coastguard Worker }
178*38e8c45fSAndroid Build Coastguard Worker
setupInetClient(const char * addr,unsigned int port)179*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupInetClient(const char* addr, unsigned int port) {
180*38e8c45fSAndroid Build Coastguard Worker auto aiStart = InetSocketAddress::getAddrInfo(addr, port);
181*38e8c45fSAndroid Build Coastguard Worker if (aiStart == nullptr) return UNKNOWN_ERROR;
182*38e8c45fSAndroid Build Coastguard Worker for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
183*38e8c45fSAndroid Build Coastguard Worker InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, addr, port);
184*38e8c45fSAndroid Build Coastguard Worker if (status_t status = setupSocketClient(socketAddress); status == OK) return OK;
185*38e8c45fSAndroid Build Coastguard Worker }
186*38e8c45fSAndroid Build Coastguard Worker ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port);
187*38e8c45fSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
188*38e8c45fSAndroid Build Coastguard Worker }
189*38e8c45fSAndroid Build Coastguard Worker
setupPreconnectedClient(unique_fd fd,std::function<unique_fd ()> && request)190*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) {
191*38e8c45fSAndroid Build Coastguard Worker return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t {
192*38e8c45fSAndroid Build Coastguard Worker if (!fd.ok()) {
193*38e8c45fSAndroid Build Coastguard Worker fd = request();
194*38e8c45fSAndroid Build Coastguard Worker if (!fd.ok()) return BAD_VALUE;
195*38e8c45fSAndroid Build Coastguard Worker }
196*38e8c45fSAndroid Build Coastguard Worker if (status_t res = binder::os::setNonBlocking(fd); res != OK) return res;
197*38e8c45fSAndroid Build Coastguard Worker
198*38e8c45fSAndroid Build Coastguard Worker RpcTransportFd transportFd(std::move(fd));
199*38e8c45fSAndroid Build Coastguard Worker status_t status = initAndAddConnection(std::move(transportFd), sessionId, incoming);
200*38e8c45fSAndroid Build Coastguard Worker fd = unique_fd(); // Explicitly reset after move to avoid analyzer warning.
201*38e8c45fSAndroid Build Coastguard Worker return status;
202*38e8c45fSAndroid Build Coastguard Worker });
203*38e8c45fSAndroid Build Coastguard Worker }
204*38e8c45fSAndroid Build Coastguard Worker
addNullDebuggingClient()205*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::addNullDebuggingClient() {
206*38e8c45fSAndroid Build Coastguard Worker // Note: only works on raw sockets.
207*38e8c45fSAndroid Build Coastguard Worker if (auto status = initShutdownTrigger(); status != OK) return status;
208*38e8c45fSAndroid Build Coastguard Worker
209*38e8c45fSAndroid Build Coastguard Worker unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
210*38e8c45fSAndroid Build Coastguard Worker
211*38e8c45fSAndroid Build Coastguard Worker if (!serverFd.ok()) {
212*38e8c45fSAndroid Build Coastguard Worker int savedErrno = errno;
213*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not connect to /dev/null: %s", strerror(savedErrno));
214*38e8c45fSAndroid Build Coastguard Worker return -savedErrno;
215*38e8c45fSAndroid Build Coastguard Worker }
216*38e8c45fSAndroid Build Coastguard Worker
217*38e8c45fSAndroid Build Coastguard Worker RpcTransportFd transportFd(std::move(serverFd));
218*38e8c45fSAndroid Build Coastguard Worker auto server = mCtx->newTransport(std::move(transportFd), mShutdownTrigger.get());
219*38e8c45fSAndroid Build Coastguard Worker if (server == nullptr) {
220*38e8c45fSAndroid Build Coastguard Worker ALOGE("Unable to set up RpcTransport");
221*38e8c45fSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
222*38e8c45fSAndroid Build Coastguard Worker }
223*38e8c45fSAndroid Build Coastguard Worker return addOutgoingConnection(std::move(server), false);
224*38e8c45fSAndroid Build Coastguard Worker }
225*38e8c45fSAndroid Build Coastguard Worker
getRootObject()226*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> RpcSession::getRootObject() {
227*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection connection;
228*38e8c45fSAndroid Build Coastguard Worker status_t status = ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
229*38e8c45fSAndroid Build Coastguard Worker ConnectionUse::CLIENT, &connection);
230*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return nullptr;
231*38e8c45fSAndroid Build Coastguard Worker return state()->getRootObject(connection.get(), sp<RpcSession>::fromExisting(this));
232*38e8c45fSAndroid Build Coastguard Worker }
233*38e8c45fSAndroid Build Coastguard Worker
getRemoteMaxThreads(size_t * maxThreads)234*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::getRemoteMaxThreads(size_t* maxThreads) {
235*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection connection;
236*38e8c45fSAndroid Build Coastguard Worker status_t status = ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
237*38e8c45fSAndroid Build Coastguard Worker ConnectionUse::CLIENT, &connection);
238*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return status;
239*38e8c45fSAndroid Build Coastguard Worker return state()->getMaxThreads(connection.get(), sp<RpcSession>::fromExisting(this), maxThreads);
240*38e8c45fSAndroid Build Coastguard Worker }
241*38e8c45fSAndroid Build Coastguard Worker
shutdownAndWait(bool wait)242*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::shutdownAndWait(bool wait) {
243*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock _l(mMutex);
244*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Shutdown trigger not installed");
245*38e8c45fSAndroid Build Coastguard Worker
246*38e8c45fSAndroid Build Coastguard Worker mShutdownTrigger->trigger();
247*38e8c45fSAndroid Build Coastguard Worker
248*38e8c45fSAndroid Build Coastguard Worker if (wait) {
249*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mShutdownListener == nullptr, "Shutdown listener not installed");
250*38e8c45fSAndroid Build Coastguard Worker mShutdownListener->waitForShutdown(_l, sp<RpcSession>::fromExisting(this));
251*38e8c45fSAndroid Build Coastguard Worker
252*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!mConnections.mThreads.empty(), "Shutdown failed");
253*38e8c45fSAndroid Build Coastguard Worker }
254*38e8c45fSAndroid Build Coastguard Worker
255*38e8c45fSAndroid Build Coastguard Worker _l.unlock();
256*38e8c45fSAndroid Build Coastguard Worker
257*38e8c45fSAndroid Build Coastguard Worker if (status_t res = state()->sendObituaries(sp<RpcSession>::fromExisting(this)); res != OK) {
258*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to send obituaries as the RpcSession is shutting down: %s",
259*38e8c45fSAndroid Build Coastguard Worker statusToString(res).c_str());
260*38e8c45fSAndroid Build Coastguard Worker }
261*38e8c45fSAndroid Build Coastguard Worker
262*38e8c45fSAndroid Build Coastguard Worker mRpcBinderState->clear();
263*38e8c45fSAndroid Build Coastguard Worker
264*38e8c45fSAndroid Build Coastguard Worker return true;
265*38e8c45fSAndroid Build Coastguard Worker }
266*38e8c45fSAndroid Build Coastguard Worker
transact(const sp<IBinder> & binder,uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)267*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::transact(const sp<IBinder>& binder, uint32_t code, const Parcel& data,
268*38e8c45fSAndroid Build Coastguard Worker Parcel* reply, uint32_t flags) {
269*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection connection;
270*38e8c45fSAndroid Build Coastguard Worker status_t status =
271*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
272*38e8c45fSAndroid Build Coastguard Worker (flags & IBinder::FLAG_ONEWAY) ? ConnectionUse::CLIENT_ASYNC
273*38e8c45fSAndroid Build Coastguard Worker : ConnectionUse::CLIENT,
274*38e8c45fSAndroid Build Coastguard Worker &connection);
275*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return status;
276*38e8c45fSAndroid Build Coastguard Worker return state()->transact(connection.get(), binder, code, data,
277*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession>::fromExisting(this), reply, flags);
278*38e8c45fSAndroid Build Coastguard Worker }
279*38e8c45fSAndroid Build Coastguard Worker
sendDecStrong(const BpBinder * binder)280*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::sendDecStrong(const BpBinder* binder) {
281*38e8c45fSAndroid Build Coastguard Worker // target is 0 because this is used to free BpBinder objects
282*38e8c45fSAndroid Build Coastguard Worker return sendDecStrongToTarget(binder->getPrivateAccessor().rpcAddress(), 0 /*target*/);
283*38e8c45fSAndroid Build Coastguard Worker }
284*38e8c45fSAndroid Build Coastguard Worker
sendDecStrongToTarget(uint64_t address,size_t target)285*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::sendDecStrongToTarget(uint64_t address, size_t target) {
286*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection connection;
287*38e8c45fSAndroid Build Coastguard Worker status_t status = ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
288*38e8c45fSAndroid Build Coastguard Worker ConnectionUse::CLIENT_REFCOUNT, &connection);
289*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return status;
290*38e8c45fSAndroid Build Coastguard Worker return state()->sendDecStrongToTarget(connection.get(), sp<RpcSession>::fromExisting(this),
291*38e8c45fSAndroid Build Coastguard Worker address, target);
292*38e8c45fSAndroid Build Coastguard Worker }
293*38e8c45fSAndroid Build Coastguard Worker
readId()294*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::readId() {
295*38e8c45fSAndroid Build Coastguard Worker {
296*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
297*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mForServer != nullptr, "Can only update ID for client.");
298*38e8c45fSAndroid Build Coastguard Worker }
299*38e8c45fSAndroid Build Coastguard Worker
300*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection connection;
301*38e8c45fSAndroid Build Coastguard Worker status_t status = ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
302*38e8c45fSAndroid Build Coastguard Worker ConnectionUse::CLIENT, &connection);
303*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return status;
304*38e8c45fSAndroid Build Coastguard Worker
305*38e8c45fSAndroid Build Coastguard Worker status = state()->getSessionId(connection.get(), sp<RpcSession>::fromExisting(this), &mId);
306*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return status;
307*38e8c45fSAndroid Build Coastguard Worker
308*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("RpcSession %p has id %s", this, HexString(mId.data(), mId.size()).c_str());
309*38e8c45fSAndroid Build Coastguard Worker return OK;
310*38e8c45fSAndroid Build Coastguard Worker }
311*38e8c45fSAndroid Build Coastguard Worker
onSessionAllIncomingThreadsEnded(const sp<RpcSession> & session)312*38e8c45fSAndroid Build Coastguard Worker void RpcSession::WaitForShutdownListener::onSessionAllIncomingThreadsEnded(
313*38e8c45fSAndroid Build Coastguard Worker const sp<RpcSession>& session) {
314*38e8c45fSAndroid Build Coastguard Worker (void)session;
315*38e8c45fSAndroid Build Coastguard Worker }
316*38e8c45fSAndroid Build Coastguard Worker
onSessionIncomingThreadEnded()317*38e8c45fSAndroid Build Coastguard Worker void RpcSession::WaitForShutdownListener::onSessionIncomingThreadEnded() {
318*38e8c45fSAndroid Build Coastguard Worker mShutdownCount += 1;
319*38e8c45fSAndroid Build Coastguard Worker mCv.notify_all();
320*38e8c45fSAndroid Build Coastguard Worker }
321*38e8c45fSAndroid Build Coastguard Worker
waitForShutdown(RpcMutexUniqueLock & lock,const sp<RpcSession> & session)322*38e8c45fSAndroid Build Coastguard Worker void RpcSession::WaitForShutdownListener::waitForShutdown(RpcMutexUniqueLock& lock,
323*38e8c45fSAndroid Build Coastguard Worker const sp<RpcSession>& session) {
324*38e8c45fSAndroid Build Coastguard Worker while (mShutdownCount < session->mConnections.mMaxIncoming) {
325*38e8c45fSAndroid Build Coastguard Worker if (std::cv_status::timeout == mCv.wait_for(lock, std::chrono::seconds(1))) {
326*38e8c45fSAndroid Build Coastguard Worker ALOGE("Waiting for RpcSession to shut down (1s w/o progress): %zu incoming connections "
327*38e8c45fSAndroid Build Coastguard Worker "still %zu/%zu fully shutdown.",
328*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mIncoming.size(), mShutdownCount.load(),
329*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mMaxIncoming);
330*38e8c45fSAndroid Build Coastguard Worker }
331*38e8c45fSAndroid Build Coastguard Worker }
332*38e8c45fSAndroid Build Coastguard Worker }
333*38e8c45fSAndroid Build Coastguard Worker
preJoinThreadOwnership(RpcMaybeThread thread)334*38e8c45fSAndroid Build Coastguard Worker void RpcSession::preJoinThreadOwnership(RpcMaybeThread thread) {
335*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(thread.get_id() != rpc_this_thread::get_id(), "Must own this thread");
336*38e8c45fSAndroid Build Coastguard Worker
337*38e8c45fSAndroid Build Coastguard Worker {
338*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
339*38e8c45fSAndroid Build Coastguard Worker mConnections.mThreads[thread.get_id()] = std::move(thread);
340*38e8c45fSAndroid Build Coastguard Worker }
341*38e8c45fSAndroid Build Coastguard Worker }
342*38e8c45fSAndroid Build Coastguard Worker
preJoinSetup(std::unique_ptr<RpcTransport> rpcTransport)343*38e8c45fSAndroid Build Coastguard Worker RpcSession::PreJoinSetupResult RpcSession::preJoinSetup(
344*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<RpcTransport> rpcTransport) {
345*38e8c45fSAndroid Build Coastguard Worker // must be registered to allow arbitrary client code executing commands to
346*38e8c45fSAndroid Build Coastguard Worker // be able to do nested calls (we can't only read from it)
347*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection> connection = assignIncomingConnectionToThisThread(std::move(rpcTransport));
348*38e8c45fSAndroid Build Coastguard Worker
349*38e8c45fSAndroid Build Coastguard Worker status_t status;
350*38e8c45fSAndroid Build Coastguard Worker
351*38e8c45fSAndroid Build Coastguard Worker if (connection == nullptr) {
352*38e8c45fSAndroid Build Coastguard Worker status = DEAD_OBJECT;
353*38e8c45fSAndroid Build Coastguard Worker } else {
354*38e8c45fSAndroid Build Coastguard Worker status =
355*38e8c45fSAndroid Build Coastguard Worker mRpcBinderState->readConnectionInit(connection, sp<RpcSession>::fromExisting(this));
356*38e8c45fSAndroid Build Coastguard Worker }
357*38e8c45fSAndroid Build Coastguard Worker
358*38e8c45fSAndroid Build Coastguard Worker return PreJoinSetupResult{
359*38e8c45fSAndroid Build Coastguard Worker .connection = std::move(connection),
360*38e8c45fSAndroid Build Coastguard Worker .status = status,
361*38e8c45fSAndroid Build Coastguard Worker };
362*38e8c45fSAndroid Build Coastguard Worker }
363*38e8c45fSAndroid Build Coastguard Worker
364*38e8c45fSAndroid Build Coastguard Worker namespace {
365*38e8c45fSAndroid Build Coastguard Worker #if !defined(__ANDROID__) || defined(__ANDROID_RECOVERY__)
366*38e8c45fSAndroid Build Coastguard Worker class JavaThreadAttacher {};
367*38e8c45fSAndroid Build Coastguard Worker #else
368*38e8c45fSAndroid Build Coastguard Worker // RAII object for attaching / detaching current thread to JVM if Android Runtime exists. If
369*38e8c45fSAndroid Build Coastguard Worker // Android Runtime doesn't exist, no-op.
370*38e8c45fSAndroid Build Coastguard Worker class JavaThreadAttacher {
371*38e8c45fSAndroid Build Coastguard Worker public:
372*38e8c45fSAndroid Build Coastguard Worker JavaThreadAttacher() {
373*38e8c45fSAndroid Build Coastguard Worker // Use dlsym to find androidJavaAttachThread because libandroid_runtime is loaded after
374*38e8c45fSAndroid Build Coastguard Worker // libbinder.
375*38e8c45fSAndroid Build Coastguard Worker auto vm = getJavaVM();
376*38e8c45fSAndroid Build Coastguard Worker if (vm == nullptr) return;
377*38e8c45fSAndroid Build Coastguard Worker
378*38e8c45fSAndroid Build Coastguard Worker char threadName[16];
379*38e8c45fSAndroid Build Coastguard Worker if (0 != pthread_getname_np(pthread_self(), threadName, sizeof(threadName))) {
380*38e8c45fSAndroid Build Coastguard Worker constexpr const char* defaultThreadName = "UnknownRpcSessionThread";
381*38e8c45fSAndroid Build Coastguard Worker memcpy(threadName, defaultThreadName,
382*38e8c45fSAndroid Build Coastguard Worker std::min<size_t>(sizeof(threadName), strlen(defaultThreadName) + 1));
383*38e8c45fSAndroid Build Coastguard Worker }
384*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("Attaching current thread %s to JVM", threadName);
385*38e8c45fSAndroid Build Coastguard Worker JavaVMAttachArgs args;
386*38e8c45fSAndroid Build Coastguard Worker args.version = JNI_VERSION_1_2;
387*38e8c45fSAndroid Build Coastguard Worker args.name = threadName;
388*38e8c45fSAndroid Build Coastguard Worker args.group = nullptr;
389*38e8c45fSAndroid Build Coastguard Worker JNIEnv* env;
390*38e8c45fSAndroid Build Coastguard Worker
391*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(vm->AttachCurrentThread(&env, &args) != JNI_OK,
392*38e8c45fSAndroid Build Coastguard Worker "Cannot attach thread %s to JVM", threadName);
393*38e8c45fSAndroid Build Coastguard Worker mAttached = true;
394*38e8c45fSAndroid Build Coastguard Worker }
395*38e8c45fSAndroid Build Coastguard Worker ~JavaThreadAttacher() {
396*38e8c45fSAndroid Build Coastguard Worker if (!mAttached) return;
397*38e8c45fSAndroid Build Coastguard Worker auto vm = getJavaVM();
398*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(vm == nullptr,
399*38e8c45fSAndroid Build Coastguard Worker "Unable to detach thread. No JavaVM, but it was present before!");
400*38e8c45fSAndroid Build Coastguard Worker
401*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("Detaching current thread from JVM");
402*38e8c45fSAndroid Build Coastguard Worker int ret = vm->DetachCurrentThread();
403*38e8c45fSAndroid Build Coastguard Worker if (ret == JNI_OK) {
404*38e8c45fSAndroid Build Coastguard Worker mAttached = false;
405*38e8c45fSAndroid Build Coastguard Worker } else {
406*38e8c45fSAndroid Build Coastguard Worker ALOGW("Unable to detach current thread from JVM (%d)", ret);
407*38e8c45fSAndroid Build Coastguard Worker }
408*38e8c45fSAndroid Build Coastguard Worker }
409*38e8c45fSAndroid Build Coastguard Worker
410*38e8c45fSAndroid Build Coastguard Worker private:
411*38e8c45fSAndroid Build Coastguard Worker JavaThreadAttacher(const JavaThreadAttacher&) = delete;
412*38e8c45fSAndroid Build Coastguard Worker void operator=(const JavaThreadAttacher&) = delete;
413*38e8c45fSAndroid Build Coastguard Worker
414*38e8c45fSAndroid Build Coastguard Worker bool mAttached = false;
415*38e8c45fSAndroid Build Coastguard Worker
416*38e8c45fSAndroid Build Coastguard Worker static JavaVM* getJavaVM() {
417*38e8c45fSAndroid Build Coastguard Worker static auto fn = reinterpret_cast<decltype(&AndroidRuntimeGetJavaVM)>(
418*38e8c45fSAndroid Build Coastguard Worker dlsym(RTLD_DEFAULT, "AndroidRuntimeGetJavaVM"));
419*38e8c45fSAndroid Build Coastguard Worker if (fn == nullptr) return nullptr;
420*38e8c45fSAndroid Build Coastguard Worker return fn();
421*38e8c45fSAndroid Build Coastguard Worker }
422*38e8c45fSAndroid Build Coastguard Worker };
423*38e8c45fSAndroid Build Coastguard Worker #endif
424*38e8c45fSAndroid Build Coastguard Worker } // namespace
425*38e8c45fSAndroid Build Coastguard Worker
join(sp<RpcSession> && session,PreJoinSetupResult && setupResult)426*38e8c45fSAndroid Build Coastguard Worker void RpcSession::join(sp<RpcSession>&& session, PreJoinSetupResult&& setupResult) {
427*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection>& connection = setupResult.connection;
428*38e8c45fSAndroid Build Coastguard Worker
429*38e8c45fSAndroid Build Coastguard Worker if (setupResult.status == OK) {
430*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!connection, "must have connection if setup succeeded");
431*38e8c45fSAndroid Build Coastguard Worker [[maybe_unused]] JavaThreadAttacher javaThreadAttacher;
432*38e8c45fSAndroid Build Coastguard Worker while (true) {
433*38e8c45fSAndroid Build Coastguard Worker status_t status = session->state()->getAndExecuteCommand(connection, session,
434*38e8c45fSAndroid Build Coastguard Worker RpcState::CommandType::ANY);
435*38e8c45fSAndroid Build Coastguard Worker if (status != OK) {
436*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("Binder connection thread closing w/ status %s",
437*38e8c45fSAndroid Build Coastguard Worker statusToString(status).c_str());
438*38e8c45fSAndroid Build Coastguard Worker break;
439*38e8c45fSAndroid Build Coastguard Worker }
440*38e8c45fSAndroid Build Coastguard Worker }
441*38e8c45fSAndroid Build Coastguard Worker } else {
442*38e8c45fSAndroid Build Coastguard Worker ALOGE("Connection failed to init, closing with status %s",
443*38e8c45fSAndroid Build Coastguard Worker statusToString(setupResult.status).c_str());
444*38e8c45fSAndroid Build Coastguard Worker }
445*38e8c45fSAndroid Build Coastguard Worker
446*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession::EventListener> listener;
447*38e8c45fSAndroid Build Coastguard Worker {
448*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(session->mMutex);
449*38e8c45fSAndroid Build Coastguard Worker auto it = session->mConnections.mThreads.find(rpc_this_thread::get_id());
450*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(it == session->mConnections.mThreads.end());
451*38e8c45fSAndroid Build Coastguard Worker it->second.detach();
452*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mThreads.erase(it);
453*38e8c45fSAndroid Build Coastguard Worker
454*38e8c45fSAndroid Build Coastguard Worker listener = session->mEventListener.promote();
455*38e8c45fSAndroid Build Coastguard Worker }
456*38e8c45fSAndroid Build Coastguard Worker
457*38e8c45fSAndroid Build Coastguard Worker // done after all cleanup, since session shutdown progresses via callbacks here
458*38e8c45fSAndroid Build Coastguard Worker if (connection != nullptr) {
459*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!session->removeIncomingConnection(connection),
460*38e8c45fSAndroid Build Coastguard Worker "bad state: connection object guaranteed to be in list");
461*38e8c45fSAndroid Build Coastguard Worker }
462*38e8c45fSAndroid Build Coastguard Worker
463*38e8c45fSAndroid Build Coastguard Worker session = nullptr;
464*38e8c45fSAndroid Build Coastguard Worker
465*38e8c45fSAndroid Build Coastguard Worker if (listener != nullptr) {
466*38e8c45fSAndroid Build Coastguard Worker listener->onSessionIncomingThreadEnded();
467*38e8c45fSAndroid Build Coastguard Worker }
468*38e8c45fSAndroid Build Coastguard Worker }
469*38e8c45fSAndroid Build Coastguard Worker
server()470*38e8c45fSAndroid Build Coastguard Worker sp<RpcServer> RpcSession::server() {
471*38e8c45fSAndroid Build Coastguard Worker RpcServer* unsafeServer = mForServer.unsafe_get();
472*38e8c45fSAndroid Build Coastguard Worker sp<RpcServer> server = mForServer.promote();
473*38e8c45fSAndroid Build Coastguard Worker
474*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF((unsafeServer == nullptr) != (server == nullptr),
475*38e8c45fSAndroid Build Coastguard Worker "wp<> is to avoid strong cycle only");
476*38e8c45fSAndroid Build Coastguard Worker return server;
477*38e8c45fSAndroid Build Coastguard Worker }
478*38e8c45fSAndroid Build Coastguard Worker
setupClient(const std::function<status_t (const std::vector<uint8_t> & sessionId,bool incoming)> & connectAndInit)479*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupClient(const std::function<status_t(const std::vector<uint8_t>& sessionId,
480*38e8c45fSAndroid Build Coastguard Worker bool incoming)>& connectAndInit) {
481*38e8c45fSAndroid Build Coastguard Worker {
482*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
483*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once");
484*38e8c45fSAndroid Build Coastguard Worker mStartedSetup = true;
485*38e8c45fSAndroid Build Coastguard Worker
486*38e8c45fSAndroid Build Coastguard Worker if constexpr (!kEnableRpcThreads) {
487*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mMaxIncomingThreads > 0,
488*38e8c45fSAndroid Build Coastguard Worker "Incoming threads are not supported on single-threaded libbinder");
489*38e8c45fSAndroid Build Coastguard Worker // mMaxIncomingThreads should not change from here to its use below,
490*38e8c45fSAndroid Build Coastguard Worker // since we set mStartedSetup==true and setMaxIncomingThreads checks
491*38e8c45fSAndroid Build Coastguard Worker // for that
492*38e8c45fSAndroid Build Coastguard Worker }
493*38e8c45fSAndroid Build Coastguard Worker }
494*38e8c45fSAndroid Build Coastguard Worker
495*38e8c45fSAndroid Build Coastguard Worker if (auto status = initShutdownTrigger(); status != OK) return status;
496*38e8c45fSAndroid Build Coastguard Worker
497*38e8c45fSAndroid Build Coastguard Worker auto oldProtocolVersion = mProtocolVersion;
498*38e8c45fSAndroid Build Coastguard Worker auto cleanup = make_scope_guard([&] {
499*38e8c45fSAndroid Build Coastguard Worker // if any threads are started, shut them down
500*38e8c45fSAndroid Build Coastguard Worker (void)shutdownAndWait(true);
501*38e8c45fSAndroid Build Coastguard Worker
502*38e8c45fSAndroid Build Coastguard Worker mShutdownListener = nullptr;
503*38e8c45fSAndroid Build Coastguard Worker mEventListener.clear();
504*38e8c45fSAndroid Build Coastguard Worker
505*38e8c45fSAndroid Build Coastguard Worker mId.clear();
506*38e8c45fSAndroid Build Coastguard Worker
507*38e8c45fSAndroid Build Coastguard Worker mShutdownTrigger = nullptr;
508*38e8c45fSAndroid Build Coastguard Worker mRpcBinderState = std::make_unique<RpcState>();
509*38e8c45fSAndroid Build Coastguard Worker
510*38e8c45fSAndroid Build Coastguard Worker // protocol version may have been downgraded - if we reuse this object
511*38e8c45fSAndroid Build Coastguard Worker // to connect to another server, force that server to request a
512*38e8c45fSAndroid Build Coastguard Worker // downgrade again
513*38e8c45fSAndroid Build Coastguard Worker mProtocolVersion = oldProtocolVersion;
514*38e8c45fSAndroid Build Coastguard Worker
515*38e8c45fSAndroid Build Coastguard Worker mConnections = {};
516*38e8c45fSAndroid Build Coastguard Worker
517*38e8c45fSAndroid Build Coastguard Worker // clear mStartedSetup so that we can reuse this RpcSession
518*38e8c45fSAndroid Build Coastguard Worker mStartedSetup = false;
519*38e8c45fSAndroid Build Coastguard Worker });
520*38e8c45fSAndroid Build Coastguard Worker
521*38e8c45fSAndroid Build Coastguard Worker if (status_t status = connectAndInit({}, false /*incoming*/); status != OK) return status;
522*38e8c45fSAndroid Build Coastguard Worker
523*38e8c45fSAndroid Build Coastguard Worker {
524*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection connection;
525*38e8c45fSAndroid Build Coastguard Worker if (status_t status = ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
526*38e8c45fSAndroid Build Coastguard Worker ConnectionUse::CLIENT, &connection);
527*38e8c45fSAndroid Build Coastguard Worker status != OK)
528*38e8c45fSAndroid Build Coastguard Worker return status;
529*38e8c45fSAndroid Build Coastguard Worker
530*38e8c45fSAndroid Build Coastguard Worker uint32_t version;
531*38e8c45fSAndroid Build Coastguard Worker if (status_t status =
532*38e8c45fSAndroid Build Coastguard Worker state()->readNewSessionResponse(connection.get(),
533*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession>::fromExisting(this), &version);
534*38e8c45fSAndroid Build Coastguard Worker status != OK)
535*38e8c45fSAndroid Build Coastguard Worker return status;
536*38e8c45fSAndroid Build Coastguard Worker if (!setProtocolVersionInternal(version, false)) return BAD_VALUE;
537*38e8c45fSAndroid Build Coastguard Worker }
538*38e8c45fSAndroid Build Coastguard Worker
539*38e8c45fSAndroid Build Coastguard Worker // TODO(b/189955605): we should add additional sessions dynamically
540*38e8c45fSAndroid Build Coastguard Worker // instead of all at once.
541*38e8c45fSAndroid Build Coastguard Worker size_t numThreadsAvailable;
542*38e8c45fSAndroid Build Coastguard Worker if (status_t status = getRemoteMaxThreads(&numThreadsAvailable); status != OK) {
543*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not get max threads after initial session setup: %s",
544*38e8c45fSAndroid Build Coastguard Worker statusToString(status).c_str());
545*38e8c45fSAndroid Build Coastguard Worker return status;
546*38e8c45fSAndroid Build Coastguard Worker }
547*38e8c45fSAndroid Build Coastguard Worker
548*38e8c45fSAndroid Build Coastguard Worker if (status_t status = readId(); status != OK) {
549*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not get session id after initial session setup: %s",
550*38e8c45fSAndroid Build Coastguard Worker statusToString(status).c_str());
551*38e8c45fSAndroid Build Coastguard Worker return status;
552*38e8c45fSAndroid Build Coastguard Worker }
553*38e8c45fSAndroid Build Coastguard Worker
554*38e8c45fSAndroid Build Coastguard Worker size_t outgoingConnections = std::min(numThreadsAvailable, mMaxOutgoingConnections);
555*38e8c45fSAndroid Build Coastguard Worker ALOGI_IF(outgoingConnections != numThreadsAvailable,
556*38e8c45fSAndroid Build Coastguard Worker "Server hints client to start %zu outgoing threads, but client will only start %zu "
557*38e8c45fSAndroid Build Coastguard Worker "because it is preconfigured to start at most %zu outgoing threads.",
558*38e8c45fSAndroid Build Coastguard Worker numThreadsAvailable, outgoingConnections, mMaxOutgoingConnections);
559*38e8c45fSAndroid Build Coastguard Worker
560*38e8c45fSAndroid Build Coastguard Worker // TODO(b/189955605): we should add additional sessions dynamically
561*38e8c45fSAndroid Build Coastguard Worker // instead of all at once - the other side should be responsible for setting
562*38e8c45fSAndroid Build Coastguard Worker // up additional connections. We need to create at least one (unless 0 are
563*38e8c45fSAndroid Build Coastguard Worker // requested to be set) in order to allow the other side to reliably make
564*38e8c45fSAndroid Build Coastguard Worker // any requests at all.
565*38e8c45fSAndroid Build Coastguard Worker
566*38e8c45fSAndroid Build Coastguard Worker // we've already setup one client
567*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("RpcSession::setupClient() instantiating %zu outgoing connections (server max: "
568*38e8c45fSAndroid Build Coastguard Worker "%zu) and %zu incoming threads",
569*38e8c45fSAndroid Build Coastguard Worker outgoingConnections, numThreadsAvailable, mMaxIncomingThreads);
570*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i + 1 < outgoingConnections; i++) {
571*38e8c45fSAndroid Build Coastguard Worker if (status_t status = connectAndInit(mId, false /*incoming*/); status != OK) return status;
572*38e8c45fSAndroid Build Coastguard Worker }
573*38e8c45fSAndroid Build Coastguard Worker
574*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < mMaxIncomingThreads; i++) {
575*38e8c45fSAndroid Build Coastguard Worker if (status_t status = connectAndInit(mId, true /*incoming*/); status != OK) return status;
576*38e8c45fSAndroid Build Coastguard Worker }
577*38e8c45fSAndroid Build Coastguard Worker
578*38e8c45fSAndroid Build Coastguard Worker cleanup.release();
579*38e8c45fSAndroid Build Coastguard Worker
580*38e8c45fSAndroid Build Coastguard Worker return OK;
581*38e8c45fSAndroid Build Coastguard Worker }
582*38e8c45fSAndroid Build Coastguard Worker
setupSocketClient(const RpcSocketAddress & addr)583*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupSocketClient(const RpcSocketAddress& addr) {
584*38e8c45fSAndroid Build Coastguard Worker return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) {
585*38e8c45fSAndroid Build Coastguard Worker return setupOneSocketConnection(addr, sessionId, incoming);
586*38e8c45fSAndroid Build Coastguard Worker });
587*38e8c45fSAndroid Build Coastguard Worker }
588*38e8c45fSAndroid Build Coastguard Worker
setupOneSocketConnection(const RpcSocketAddress & addr,const std::vector<uint8_t> & sessionId,bool incoming)589*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::setupOneSocketConnection(const RpcSocketAddress& addr,
590*38e8c45fSAndroid Build Coastguard Worker const std::vector<uint8_t>& sessionId,
591*38e8c45fSAndroid Build Coastguard Worker bool incoming) {
592*38e8c45fSAndroid Build Coastguard Worker RpcTransportFd transportFd;
593*38e8c45fSAndroid Build Coastguard Worker status_t status = singleSocketConnection(addr, mShutdownTrigger, &transportFd);
594*38e8c45fSAndroid Build Coastguard Worker if (status != OK) return status;
595*38e8c45fSAndroid Build Coastguard Worker
596*38e8c45fSAndroid Build Coastguard Worker return initAndAddConnection(std::move(transportFd), sessionId, incoming);
597*38e8c45fSAndroid Build Coastguard Worker }
598*38e8c45fSAndroid Build Coastguard Worker
singleSocketConnection(const RpcSocketAddress & addr,const std::unique_ptr<FdTrigger> & shutdownTrigger,RpcTransportFd * outFd)599*38e8c45fSAndroid Build Coastguard Worker status_t singleSocketConnection(const RpcSocketAddress& addr,
600*38e8c45fSAndroid Build Coastguard Worker const std::unique_ptr<FdTrigger>& shutdownTrigger,
601*38e8c45fSAndroid Build Coastguard Worker RpcTransportFd* outFd) {
602*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(outFd == nullptr,
603*38e8c45fSAndroid Build Coastguard Worker "There is no reason to call this function without an outFd");
604*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(shutdownTrigger == nullptr,
605*38e8c45fSAndroid Build Coastguard Worker "FdTrigger argument is required so we don't get stuck in the connect call "
606*38e8c45fSAndroid Build Coastguard Worker "if the server process shuts down.");
607*38e8c45fSAndroid Build Coastguard Worker for (size_t tries = 0; tries < 5; tries++) {
608*38e8c45fSAndroid Build Coastguard Worker if (tries > 0) usleep(10000);
609*38e8c45fSAndroid Build Coastguard Worker
610*38e8c45fSAndroid Build Coastguard Worker unique_fd serverFd(TEMP_FAILURE_RETRY(
611*38e8c45fSAndroid Build Coastguard Worker socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
612*38e8c45fSAndroid Build Coastguard Worker if (!serverFd.ok()) {
613*38e8c45fSAndroid Build Coastguard Worker int savedErrno = errno;
614*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not create socket at %s: %s", addr.toString().c_str(),
615*38e8c45fSAndroid Build Coastguard Worker strerror(savedErrno));
616*38e8c45fSAndroid Build Coastguard Worker return -savedErrno;
617*38e8c45fSAndroid Build Coastguard Worker }
618*38e8c45fSAndroid Build Coastguard Worker
619*38e8c45fSAndroid Build Coastguard Worker if (addr.addr()->sa_family == AF_INET || addr.addr()->sa_family == AF_INET6) {
620*38e8c45fSAndroid Build Coastguard Worker int noDelay = 1;
621*38e8c45fSAndroid Build Coastguard Worker int result =
622*38e8c45fSAndroid Build Coastguard Worker setsockopt(serverFd.get(), IPPROTO_TCP, TCP_NODELAY, &noDelay, sizeof(noDelay));
623*38e8c45fSAndroid Build Coastguard Worker if (result < 0) {
624*38e8c45fSAndroid Build Coastguard Worker int savedErrno = errno;
625*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not set TCP_NODELAY on %s: %s", addr.toString().c_str(),
626*38e8c45fSAndroid Build Coastguard Worker strerror(savedErrno));
627*38e8c45fSAndroid Build Coastguard Worker return -savedErrno;
628*38e8c45fSAndroid Build Coastguard Worker }
629*38e8c45fSAndroid Build Coastguard Worker }
630*38e8c45fSAndroid Build Coastguard Worker
631*38e8c45fSAndroid Build Coastguard Worker RpcTransportFd transportFd(std::move(serverFd));
632*38e8c45fSAndroid Build Coastguard Worker
633*38e8c45fSAndroid Build Coastguard Worker if (0 != TEMP_FAILURE_RETRY(connect(transportFd.fd.get(), addr.addr(), addr.addrSize()))) {
634*38e8c45fSAndroid Build Coastguard Worker int connErrno = errno;
635*38e8c45fSAndroid Build Coastguard Worker if (connErrno == EAGAIN || connErrno == EINPROGRESS) {
636*38e8c45fSAndroid Build Coastguard Worker // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
637*38e8c45fSAndroid Build Coastguard Worker // EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
638*38e8c45fSAndroid Build Coastguard Worker status_t pollStatus = shutdownTrigger->triggerablePoll(transportFd, POLLOUT);
639*38e8c45fSAndroid Build Coastguard Worker if (pollStatus != OK) {
640*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
641*38e8c45fSAndroid Build Coastguard Worker statusToString(pollStatus).c_str());
642*38e8c45fSAndroid Build Coastguard Worker return pollStatus;
643*38e8c45fSAndroid Build Coastguard Worker }
644*38e8c45fSAndroid Build Coastguard Worker // Set connErrno to the errno that connect() would have set if the fd were blocking.
645*38e8c45fSAndroid Build Coastguard Worker socklen_t connErrnoLen = sizeof(connErrno);
646*38e8c45fSAndroid Build Coastguard Worker int ret = getsockopt(transportFd.fd.get(), SOL_SOCKET, SO_ERROR, &connErrno,
647*38e8c45fSAndroid Build Coastguard Worker &connErrnoLen);
648*38e8c45fSAndroid Build Coastguard Worker if (ret == -1) {
649*38e8c45fSAndroid Build Coastguard Worker int savedErrno = errno;
650*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s. "
651*38e8c45fSAndroid Build Coastguard Worker "(Original error from connect() is: %s)",
652*38e8c45fSAndroid Build Coastguard Worker strerror(savedErrno), strerror(connErrno));
653*38e8c45fSAndroid Build Coastguard Worker return -savedErrno;
654*38e8c45fSAndroid Build Coastguard Worker }
655*38e8c45fSAndroid Build Coastguard Worker // Retrieved the real connErrno as if connect() was called with a blocking socket
656*38e8c45fSAndroid Build Coastguard Worker // fd. Continue checking connErrno.
657*38e8c45fSAndroid Build Coastguard Worker }
658*38e8c45fSAndroid Build Coastguard Worker if (connErrno == ECONNRESET) {
659*38e8c45fSAndroid Build Coastguard Worker ALOGW("Connection reset on %s", addr.toString().c_str());
660*38e8c45fSAndroid Build Coastguard Worker continue;
661*38e8c45fSAndroid Build Coastguard Worker }
662*38e8c45fSAndroid Build Coastguard Worker // connErrno could be zero if getsockopt determines so. Hence zero-check again.
663*38e8c45fSAndroid Build Coastguard Worker if (connErrno != 0) {
664*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
665*38e8c45fSAndroid Build Coastguard Worker strerror(connErrno));
666*38e8c45fSAndroid Build Coastguard Worker return -connErrno;
667*38e8c45fSAndroid Build Coastguard Worker }
668*38e8c45fSAndroid Build Coastguard Worker }
669*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(),
670*38e8c45fSAndroid Build Coastguard Worker transportFd.fd.get());
671*38e8c45fSAndroid Build Coastguard Worker
672*38e8c45fSAndroid Build Coastguard Worker *outFd = std::move(transportFd);
673*38e8c45fSAndroid Build Coastguard Worker return OK;
674*38e8c45fSAndroid Build Coastguard Worker }
675*38e8c45fSAndroid Build Coastguard Worker
676*38e8c45fSAndroid Build Coastguard Worker ALOGE("Ran out of retries to connect to %s", addr.toString().c_str());
677*38e8c45fSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
678*38e8c45fSAndroid Build Coastguard Worker }
679*38e8c45fSAndroid Build Coastguard Worker
initAndAddConnection(RpcTransportFd fd,const std::vector<uint8_t> & sessionId,bool incoming)680*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::initAndAddConnection(RpcTransportFd fd, const std::vector<uint8_t>& sessionId,
681*38e8c45fSAndroid Build Coastguard Worker bool incoming) {
682*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
683*38e8c45fSAndroid Build Coastguard Worker auto server = mCtx->newTransport(std::move(fd), mShutdownTrigger.get());
684*38e8c45fSAndroid Build Coastguard Worker if (server == nullptr) {
685*38e8c45fSAndroid Build Coastguard Worker ALOGE("%s: Unable to set up RpcTransport", __PRETTY_FUNCTION__);
686*38e8c45fSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
687*38e8c45fSAndroid Build Coastguard Worker }
688*38e8c45fSAndroid Build Coastguard Worker
689*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("Socket at client with RpcTransport %p", server.get());
690*38e8c45fSAndroid Build Coastguard Worker
691*38e8c45fSAndroid Build Coastguard Worker if (sessionId.size() > std::numeric_limits<uint16_t>::max()) {
692*38e8c45fSAndroid Build Coastguard Worker ALOGE("Session ID too big %zu", sessionId.size());
693*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
694*38e8c45fSAndroid Build Coastguard Worker }
695*38e8c45fSAndroid Build Coastguard Worker
696*38e8c45fSAndroid Build Coastguard Worker RpcConnectionHeader header{
697*38e8c45fSAndroid Build Coastguard Worker .version = mProtocolVersion.value_or(RPC_WIRE_PROTOCOL_VERSION),
698*38e8c45fSAndroid Build Coastguard Worker .options = 0,
699*38e8c45fSAndroid Build Coastguard Worker .fileDescriptorTransportMode = static_cast<uint8_t>(mFileDescriptorTransportMode),
700*38e8c45fSAndroid Build Coastguard Worker .sessionIdSize = static_cast<uint16_t>(sessionId.size()),
701*38e8c45fSAndroid Build Coastguard Worker };
702*38e8c45fSAndroid Build Coastguard Worker
703*38e8c45fSAndroid Build Coastguard Worker if (incoming) {
704*38e8c45fSAndroid Build Coastguard Worker header.options |= RPC_CONNECTION_OPTION_INCOMING;
705*38e8c45fSAndroid Build Coastguard Worker }
706*38e8c45fSAndroid Build Coastguard Worker
707*38e8c45fSAndroid Build Coastguard Worker iovec headerIov{&header, sizeof(header)};
708*38e8c45fSAndroid Build Coastguard Worker auto sendHeaderStatus = server->interruptableWriteFully(mShutdownTrigger.get(), &headerIov, 1,
709*38e8c45fSAndroid Build Coastguard Worker std::nullopt, nullptr);
710*38e8c45fSAndroid Build Coastguard Worker if (sendHeaderStatus != OK) {
711*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not write connection header to socket: %s",
712*38e8c45fSAndroid Build Coastguard Worker statusToString(sendHeaderStatus).c_str());
713*38e8c45fSAndroid Build Coastguard Worker return sendHeaderStatus;
714*38e8c45fSAndroid Build Coastguard Worker }
715*38e8c45fSAndroid Build Coastguard Worker
716*38e8c45fSAndroid Build Coastguard Worker if (sessionId.size() > 0) {
717*38e8c45fSAndroid Build Coastguard Worker iovec sessionIov{const_cast<void*>(static_cast<const void*>(sessionId.data())),
718*38e8c45fSAndroid Build Coastguard Worker sessionId.size()};
719*38e8c45fSAndroid Build Coastguard Worker auto sendSessionIdStatus =
720*38e8c45fSAndroid Build Coastguard Worker server->interruptableWriteFully(mShutdownTrigger.get(), &sessionIov, 1,
721*38e8c45fSAndroid Build Coastguard Worker std::nullopt, nullptr);
722*38e8c45fSAndroid Build Coastguard Worker if (sendSessionIdStatus != OK) {
723*38e8c45fSAndroid Build Coastguard Worker ALOGE("Could not write session ID ('%s') to socket: %s",
724*38e8c45fSAndroid Build Coastguard Worker HexString(sessionId.data(), sessionId.size()).c_str(),
725*38e8c45fSAndroid Build Coastguard Worker statusToString(sendSessionIdStatus).c_str());
726*38e8c45fSAndroid Build Coastguard Worker return sendSessionIdStatus;
727*38e8c45fSAndroid Build Coastguard Worker }
728*38e8c45fSAndroid Build Coastguard Worker }
729*38e8c45fSAndroid Build Coastguard Worker
730*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("Socket at client: header sent");
731*38e8c45fSAndroid Build Coastguard Worker
732*38e8c45fSAndroid Build Coastguard Worker if (incoming) {
733*38e8c45fSAndroid Build Coastguard Worker return addIncomingConnection(std::move(server));
734*38e8c45fSAndroid Build Coastguard Worker } else {
735*38e8c45fSAndroid Build Coastguard Worker return addOutgoingConnection(std::move(server), true /*init*/);
736*38e8c45fSAndroid Build Coastguard Worker }
737*38e8c45fSAndroid Build Coastguard Worker }
738*38e8c45fSAndroid Build Coastguard Worker
addIncomingConnection(std::unique_ptr<RpcTransport> rpcTransport)739*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::addIncomingConnection(std::unique_ptr<RpcTransport> rpcTransport) {
740*38e8c45fSAndroid Build Coastguard Worker RpcMutex mutex;
741*38e8c45fSAndroid Build Coastguard Worker RpcConditionVariable joinCv;
742*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock lock(mutex);
743*38e8c45fSAndroid Build Coastguard Worker RpcMaybeThread thread;
744*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession> thiz = sp<RpcSession>::fromExisting(this);
745*38e8c45fSAndroid Build Coastguard Worker bool ownershipTransferred = false;
746*38e8c45fSAndroid Build Coastguard Worker thread = RpcMaybeThread([&]() {
747*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock threadLock(mutex);
748*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<RpcTransport> movedRpcTransport = std::move(rpcTransport);
749*38e8c45fSAndroid Build Coastguard Worker // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
750*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession> session = thiz;
751*38e8c45fSAndroid Build Coastguard Worker session->preJoinThreadOwnership(std::move(thread));
752*38e8c45fSAndroid Build Coastguard Worker
753*38e8c45fSAndroid Build Coastguard Worker // only continue once we have a response or the connection fails
754*38e8c45fSAndroid Build Coastguard Worker auto setupResult = session->preJoinSetup(std::move(movedRpcTransport));
755*38e8c45fSAndroid Build Coastguard Worker
756*38e8c45fSAndroid Build Coastguard Worker ownershipTransferred = true;
757*38e8c45fSAndroid Build Coastguard Worker threadLock.unlock();
758*38e8c45fSAndroid Build Coastguard Worker joinCv.notify_one();
759*38e8c45fSAndroid Build Coastguard Worker // do not use & vars below
760*38e8c45fSAndroid Build Coastguard Worker
761*38e8c45fSAndroid Build Coastguard Worker RpcSession::join(std::move(session), std::move(setupResult));
762*38e8c45fSAndroid Build Coastguard Worker });
763*38e8c45fSAndroid Build Coastguard Worker rpcJoinIfSingleThreaded(thread);
764*38e8c45fSAndroid Build Coastguard Worker joinCv.wait(lock, [&] { return ownershipTransferred; });
765*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!ownershipTransferred);
766*38e8c45fSAndroid Build Coastguard Worker return OK;
767*38e8c45fSAndroid Build Coastguard Worker }
768*38e8c45fSAndroid Build Coastguard Worker
initShutdownTrigger()769*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::initShutdownTrigger() {
770*38e8c45fSAndroid Build Coastguard Worker // first client connection added, but setForServer not called, so
771*38e8c45fSAndroid Build Coastguard Worker // initializaing for a client.
772*38e8c45fSAndroid Build Coastguard Worker if (mShutdownTrigger == nullptr) {
773*38e8c45fSAndroid Build Coastguard Worker mShutdownTrigger = FdTrigger::make();
774*38e8c45fSAndroid Build Coastguard Worker mEventListener = mShutdownListener = sp<WaitForShutdownListener>::make();
775*38e8c45fSAndroid Build Coastguard Worker if (mShutdownTrigger == nullptr) return INVALID_OPERATION;
776*38e8c45fSAndroid Build Coastguard Worker }
777*38e8c45fSAndroid Build Coastguard Worker return OK;
778*38e8c45fSAndroid Build Coastguard Worker }
779*38e8c45fSAndroid Build Coastguard Worker
addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTransport,bool init)780*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTransport, bool init) {
781*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection> connection = sp<RpcConnection>::make();
782*38e8c45fSAndroid Build Coastguard Worker {
783*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
784*38e8c45fSAndroid Build Coastguard Worker connection->rpcTransport = std::move(rpcTransport);
785*38e8c45fSAndroid Build Coastguard Worker connection->exclusiveTid = binder::os::GetThreadId();
786*38e8c45fSAndroid Build Coastguard Worker mConnections.mOutgoing.push_back(connection);
787*38e8c45fSAndroid Build Coastguard Worker }
788*38e8c45fSAndroid Build Coastguard Worker
789*38e8c45fSAndroid Build Coastguard Worker status_t status = OK;
790*38e8c45fSAndroid Build Coastguard Worker if (init) {
791*38e8c45fSAndroid Build Coastguard Worker status =
792*38e8c45fSAndroid Build Coastguard Worker mRpcBinderState->sendConnectionInit(connection, sp<RpcSession>::fromExisting(this));
793*38e8c45fSAndroid Build Coastguard Worker }
794*38e8c45fSAndroid Build Coastguard Worker
795*38e8c45fSAndroid Build Coastguard Worker clearConnectionTid(connection);
796*38e8c45fSAndroid Build Coastguard Worker
797*38e8c45fSAndroid Build Coastguard Worker return status;
798*38e8c45fSAndroid Build Coastguard Worker }
799*38e8c45fSAndroid Build Coastguard Worker
setForServer(const wp<RpcServer> & server,const wp<EventListener> & eventListener,const std::vector<uint8_t> & sessionId,const sp<IBinder> & sessionSpecificRoot)800*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListener>& eventListener,
801*38e8c45fSAndroid Build Coastguard Worker const std::vector<uint8_t>& sessionId,
802*38e8c45fSAndroid Build Coastguard Worker const sp<IBinder>& sessionSpecificRoot) {
803*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mForServer != nullptr);
804*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(server == nullptr);
805*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mEventListener != nullptr);
806*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(eventListener == nullptr);
807*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr);
808*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mCtx != nullptr);
809*38e8c45fSAndroid Build Coastguard Worker
810*38e8c45fSAndroid Build Coastguard Worker mShutdownTrigger = FdTrigger::make();
811*38e8c45fSAndroid Build Coastguard Worker if (mShutdownTrigger == nullptr) return false;
812*38e8c45fSAndroid Build Coastguard Worker
813*38e8c45fSAndroid Build Coastguard Worker mId = sessionId;
814*38e8c45fSAndroid Build Coastguard Worker mForServer = server;
815*38e8c45fSAndroid Build Coastguard Worker mEventListener = eventListener;
816*38e8c45fSAndroid Build Coastguard Worker mSessionSpecificRootObject = sessionSpecificRoot;
817*38e8c45fSAndroid Build Coastguard Worker return true;
818*38e8c45fSAndroid Build Coastguard Worker }
819*38e8c45fSAndroid Build Coastguard Worker
setSessionSpecificRoot(const sp<IBinder> & sessionSpecificRoot)820*38e8c45fSAndroid Build Coastguard Worker void RpcSession::setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot) {
821*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mSessionSpecificRootObject != nullptr,
822*38e8c45fSAndroid Build Coastguard Worker "Session specific root object already set");
823*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mForServer != nullptr,
824*38e8c45fSAndroid Build Coastguard Worker "Session specific root object cannot be set for a server");
825*38e8c45fSAndroid Build Coastguard Worker mSessionSpecificRootObject = sessionSpecificRoot;
826*38e8c45fSAndroid Build Coastguard Worker }
827*38e8c45fSAndroid Build Coastguard Worker
assignIncomingConnectionToThisThread(std::unique_ptr<RpcTransport> rpcTransport)828*38e8c45fSAndroid Build Coastguard Worker sp<RpcSession::RpcConnection> RpcSession::assignIncomingConnectionToThisThread(
829*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<RpcTransport> rpcTransport) {
830*38e8c45fSAndroid Build Coastguard Worker RpcMutexLockGuard _l(mMutex);
831*38e8c45fSAndroid Build Coastguard Worker
832*38e8c45fSAndroid Build Coastguard Worker if (mConnections.mIncoming.size() >= mMaxIncomingThreads) {
833*38e8c45fSAndroid Build Coastguard Worker ALOGE("Cannot add thread to session with %zu threads (max is set to %zu)",
834*38e8c45fSAndroid Build Coastguard Worker mConnections.mIncoming.size(), mMaxIncomingThreads);
835*38e8c45fSAndroid Build Coastguard Worker return nullptr;
836*38e8c45fSAndroid Build Coastguard Worker }
837*38e8c45fSAndroid Build Coastguard Worker
838*38e8c45fSAndroid Build Coastguard Worker // Don't accept any more connections, some have shutdown. Usually this
839*38e8c45fSAndroid Build Coastguard Worker // happens when new connections are still being established as part of a
840*38e8c45fSAndroid Build Coastguard Worker // very short-lived session which shuts down after it already started
841*38e8c45fSAndroid Build Coastguard Worker // accepting new connections.
842*38e8c45fSAndroid Build Coastguard Worker if (mConnections.mIncoming.size() < mConnections.mMaxIncoming) {
843*38e8c45fSAndroid Build Coastguard Worker return nullptr;
844*38e8c45fSAndroid Build Coastguard Worker }
845*38e8c45fSAndroid Build Coastguard Worker
846*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection> session = sp<RpcConnection>::make();
847*38e8c45fSAndroid Build Coastguard Worker session->rpcTransport = std::move(rpcTransport);
848*38e8c45fSAndroid Build Coastguard Worker session->exclusiveTid = binder::os::GetThreadId();
849*38e8c45fSAndroid Build Coastguard Worker
850*38e8c45fSAndroid Build Coastguard Worker mConnections.mIncoming.push_back(session);
851*38e8c45fSAndroid Build Coastguard Worker mConnections.mMaxIncoming = mConnections.mIncoming.size();
852*38e8c45fSAndroid Build Coastguard Worker
853*38e8c45fSAndroid Build Coastguard Worker return session;
854*38e8c45fSAndroid Build Coastguard Worker }
855*38e8c45fSAndroid Build Coastguard Worker
removeIncomingConnection(const sp<RpcConnection> & connection)856*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::removeIncomingConnection(const sp<RpcConnection>& connection) {
857*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock _l(mMutex);
858*38e8c45fSAndroid Build Coastguard Worker if (auto it =
859*38e8c45fSAndroid Build Coastguard Worker std::find(mConnections.mIncoming.begin(), mConnections.mIncoming.end(), connection);
860*38e8c45fSAndroid Build Coastguard Worker it != mConnections.mIncoming.end()) {
861*38e8c45fSAndroid Build Coastguard Worker mConnections.mIncoming.erase(it);
862*38e8c45fSAndroid Build Coastguard Worker if (mConnections.mIncoming.size() == 0) {
863*38e8c45fSAndroid Build Coastguard Worker sp<EventListener> listener = mEventListener.promote();
864*38e8c45fSAndroid Build Coastguard Worker if (listener) {
865*38e8c45fSAndroid Build Coastguard Worker _l.unlock();
866*38e8c45fSAndroid Build Coastguard Worker listener->onSessionAllIncomingThreadsEnded(sp<RpcSession>::fromExisting(this));
867*38e8c45fSAndroid Build Coastguard Worker }
868*38e8c45fSAndroid Build Coastguard Worker }
869*38e8c45fSAndroid Build Coastguard Worker return true;
870*38e8c45fSAndroid Build Coastguard Worker }
871*38e8c45fSAndroid Build Coastguard Worker return false;
872*38e8c45fSAndroid Build Coastguard Worker }
873*38e8c45fSAndroid Build Coastguard Worker
clearConnectionTid(const sp<RpcConnection> & connection)874*38e8c45fSAndroid Build Coastguard Worker void RpcSession::clearConnectionTid(const sp<RpcConnection>& connection) {
875*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock _l(mMutex);
876*38e8c45fSAndroid Build Coastguard Worker connection->exclusiveTid = std::nullopt;
877*38e8c45fSAndroid Build Coastguard Worker if (mConnections.mWaitingThreads > 0) {
878*38e8c45fSAndroid Build Coastguard Worker _l.unlock();
879*38e8c45fSAndroid Build Coastguard Worker mAvailableConnectionCv.notify_one();
880*38e8c45fSAndroid Build Coastguard Worker }
881*38e8c45fSAndroid Build Coastguard Worker }
882*38e8c45fSAndroid Build Coastguard Worker
getCertificate(RpcCertificateFormat format)883*38e8c45fSAndroid Build Coastguard Worker std::vector<uint8_t> RpcSession::getCertificate(RpcCertificateFormat format) {
884*38e8c45fSAndroid Build Coastguard Worker return mCtx->getCertificate(format);
885*38e8c45fSAndroid Build Coastguard Worker }
886*38e8c45fSAndroid Build Coastguard Worker
find(const sp<RpcSession> & session,ConnectionUse use,ExclusiveConnection * connection)887*38e8c45fSAndroid Build Coastguard Worker status_t RpcSession::ExclusiveConnection::find(const sp<RpcSession>& session, ConnectionUse use,
888*38e8c45fSAndroid Build Coastguard Worker ExclusiveConnection* connection) {
889*38e8c45fSAndroid Build Coastguard Worker connection->mSession = session;
890*38e8c45fSAndroid Build Coastguard Worker connection->mConnection = nullptr;
891*38e8c45fSAndroid Build Coastguard Worker connection->mReentrant = false;
892*38e8c45fSAndroid Build Coastguard Worker
893*38e8c45fSAndroid Build Coastguard Worker uint64_t tid = binder::os::GetThreadId();
894*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock _l(session->mMutex);
895*38e8c45fSAndroid Build Coastguard Worker
896*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mWaitingThreads++;
897*38e8c45fSAndroid Build Coastguard Worker while (true) {
898*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection> exclusive;
899*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection> available;
900*38e8c45fSAndroid Build Coastguard Worker
901*38e8c45fSAndroid Build Coastguard Worker // CHECK FOR DEDICATED CLIENT SOCKET
902*38e8c45fSAndroid Build Coastguard Worker //
903*38e8c45fSAndroid Build Coastguard Worker // A server/looper should always use a dedicated connection if available
904*38e8c45fSAndroid Build Coastguard Worker findConnection(tid, &exclusive, &available, session->mConnections.mOutgoing,
905*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mOutgoingOffset);
906*38e8c45fSAndroid Build Coastguard Worker
907*38e8c45fSAndroid Build Coastguard Worker // WARNING: this assumes a server cannot request its client to send
908*38e8c45fSAndroid Build Coastguard Worker // a transaction, as mIncoming is excluded below.
909*38e8c45fSAndroid Build Coastguard Worker //
910*38e8c45fSAndroid Build Coastguard Worker // Imagine we have more than one thread in play, and a single thread
911*38e8c45fSAndroid Build Coastguard Worker // sends a synchronous, then an asynchronous command. Imagine the
912*38e8c45fSAndroid Build Coastguard Worker // asynchronous command is sent on the first client connection. Then, if
913*38e8c45fSAndroid Build Coastguard Worker // we naively send a synchronous command to that same connection, the
914*38e8c45fSAndroid Build Coastguard Worker // thread on the far side might be busy processing the asynchronous
915*38e8c45fSAndroid Build Coastguard Worker // command. So, we move to considering the second available thread
916*38e8c45fSAndroid Build Coastguard Worker // for subsequent calls.
917*38e8c45fSAndroid Build Coastguard Worker if (use == ConnectionUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
918*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mOutgoingOffset = (session->mConnections.mOutgoingOffset + 1) %
919*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mOutgoing.size();
920*38e8c45fSAndroid Build Coastguard Worker }
921*38e8c45fSAndroid Build Coastguard Worker
922*38e8c45fSAndroid Build Coastguard Worker // USE SERVING SOCKET (e.g. nested transaction)
923*38e8c45fSAndroid Build Coastguard Worker if (use != ConnectionUse::CLIENT_ASYNC) {
924*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection> exclusiveIncoming;
925*38e8c45fSAndroid Build Coastguard Worker // server connections are always assigned to a thread
926*38e8c45fSAndroid Build Coastguard Worker findConnection(tid, &exclusiveIncoming, nullptr /*available*/,
927*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mIncoming, 0 /* index hint */);
928*38e8c45fSAndroid Build Coastguard Worker
929*38e8c45fSAndroid Build Coastguard Worker // asynchronous calls cannot be nested, we currently allow ref count
930*38e8c45fSAndroid Build Coastguard Worker // calls to be nested (so that you can use this without having extra
931*38e8c45fSAndroid Build Coastguard Worker // threads). Note 'drainCommands' is used so that these ref counts can't
932*38e8c45fSAndroid Build Coastguard Worker // build up.
933*38e8c45fSAndroid Build Coastguard Worker if (exclusiveIncoming != nullptr) {
934*38e8c45fSAndroid Build Coastguard Worker if (exclusiveIncoming->allowNested) {
935*38e8c45fSAndroid Build Coastguard Worker // guaranteed to be processed as nested command
936*38e8c45fSAndroid Build Coastguard Worker exclusive = exclusiveIncoming;
937*38e8c45fSAndroid Build Coastguard Worker } else if (use == ConnectionUse::CLIENT_REFCOUNT && available == nullptr) {
938*38e8c45fSAndroid Build Coastguard Worker // prefer available socket, but if we don't have one, don't
939*38e8c45fSAndroid Build Coastguard Worker // wait for one
940*38e8c45fSAndroid Build Coastguard Worker exclusive = exclusiveIncoming;
941*38e8c45fSAndroid Build Coastguard Worker }
942*38e8c45fSAndroid Build Coastguard Worker }
943*38e8c45fSAndroid Build Coastguard Worker }
944*38e8c45fSAndroid Build Coastguard Worker
945*38e8c45fSAndroid Build Coastguard Worker // if our thread is already using a connection, prioritize using that
946*38e8c45fSAndroid Build Coastguard Worker if (exclusive != nullptr) {
947*38e8c45fSAndroid Build Coastguard Worker connection->mConnection = exclusive;
948*38e8c45fSAndroid Build Coastguard Worker connection->mReentrant = true;
949*38e8c45fSAndroid Build Coastguard Worker break;
950*38e8c45fSAndroid Build Coastguard Worker } else if (available != nullptr) {
951*38e8c45fSAndroid Build Coastguard Worker connection->mConnection = available;
952*38e8c45fSAndroid Build Coastguard Worker connection->mConnection->exclusiveTid = tid;
953*38e8c45fSAndroid Build Coastguard Worker break;
954*38e8c45fSAndroid Build Coastguard Worker }
955*38e8c45fSAndroid Build Coastguard Worker
956*38e8c45fSAndroid Build Coastguard Worker if (session->mConnections.mOutgoing.size() == 0) {
957*38e8c45fSAndroid Build Coastguard Worker ALOGE("Session has no outgoing connections. This is required for an RPC server to make "
958*38e8c45fSAndroid Build Coastguard Worker "any non-nested (e.g. oneway or on another thread) calls. Use code request "
959*38e8c45fSAndroid Build Coastguard Worker "reason: %d. Incoming connections: %zu. %s.",
960*38e8c45fSAndroid Build Coastguard Worker static_cast<int>(use), session->mConnections.mIncoming.size(),
961*38e8c45fSAndroid Build Coastguard Worker (session->server()
962*38e8c45fSAndroid Build Coastguard Worker ? "This is a server session, so see RpcSession::setMaxIncomingThreads "
963*38e8c45fSAndroid Build Coastguard Worker "for the corresponding client"
964*38e8c45fSAndroid Build Coastguard Worker : "This is a client session, so see "
965*38e8c45fSAndroid Build Coastguard Worker "RpcSession::setMaxOutgoingConnections "
966*38e8c45fSAndroid Build Coastguard Worker "for this client or RpcServer::setMaxThreads for the corresponding "
967*38e8c45fSAndroid Build Coastguard Worker "server"));
968*38e8c45fSAndroid Build Coastguard Worker return WOULD_BLOCK;
969*38e8c45fSAndroid Build Coastguard Worker }
970*38e8c45fSAndroid Build Coastguard Worker
971*38e8c45fSAndroid Build Coastguard Worker LOG_RPC_DETAIL("No available connections (have %zu clients and %zu servers). Waiting...",
972*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mOutgoing.size(),
973*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mIncoming.size());
974*38e8c45fSAndroid Build Coastguard Worker session->mAvailableConnectionCv.wait(_l);
975*38e8c45fSAndroid Build Coastguard Worker }
976*38e8c45fSAndroid Build Coastguard Worker session->mConnections.mWaitingThreads--;
977*38e8c45fSAndroid Build Coastguard Worker
978*38e8c45fSAndroid Build Coastguard Worker return OK;
979*38e8c45fSAndroid Build Coastguard Worker }
980*38e8c45fSAndroid Build Coastguard Worker
findConnection(uint64_t tid,sp<RpcConnection> * exclusive,sp<RpcConnection> * available,std::vector<sp<RpcConnection>> & sockets,size_t socketsIndexHint)981*38e8c45fSAndroid Build Coastguard Worker void RpcSession::ExclusiveConnection::findConnection(uint64_t tid, sp<RpcConnection>* exclusive,
982*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection>* available,
983*38e8c45fSAndroid Build Coastguard Worker std::vector<sp<RpcConnection>>& sockets,
984*38e8c45fSAndroid Build Coastguard Worker size_t socketsIndexHint) {
985*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(sockets.size() > 0 && socketsIndexHint >= sockets.size(),
986*38e8c45fSAndroid Build Coastguard Worker "Bad index %zu >= %zu", socketsIndexHint, sockets.size());
987*38e8c45fSAndroid Build Coastguard Worker
988*38e8c45fSAndroid Build Coastguard Worker if (*exclusive != nullptr) return; // consistent with break below
989*38e8c45fSAndroid Build Coastguard Worker
990*38e8c45fSAndroid Build Coastguard Worker for (size_t i = 0; i < sockets.size(); i++) {
991*38e8c45fSAndroid Build Coastguard Worker sp<RpcConnection>& socket = sockets[(i + socketsIndexHint) % sockets.size()];
992*38e8c45fSAndroid Build Coastguard Worker
993*38e8c45fSAndroid Build Coastguard Worker // take first available connection (intuition = caching)
994*38e8c45fSAndroid Build Coastguard Worker if (available && *available == nullptr && socket->exclusiveTid == std::nullopt) {
995*38e8c45fSAndroid Build Coastguard Worker *available = socket;
996*38e8c45fSAndroid Build Coastguard Worker continue;
997*38e8c45fSAndroid Build Coastguard Worker }
998*38e8c45fSAndroid Build Coastguard Worker
999*38e8c45fSAndroid Build Coastguard Worker // though, prefer to take connection which is already inuse by this thread
1000*38e8c45fSAndroid Build Coastguard Worker // (nested transactions)
1001*38e8c45fSAndroid Build Coastguard Worker if (exclusive && socket->exclusiveTid == tid) {
1002*38e8c45fSAndroid Build Coastguard Worker *exclusive = socket;
1003*38e8c45fSAndroid Build Coastguard Worker break; // consistent with return above
1004*38e8c45fSAndroid Build Coastguard Worker }
1005*38e8c45fSAndroid Build Coastguard Worker }
1006*38e8c45fSAndroid Build Coastguard Worker }
1007*38e8c45fSAndroid Build Coastguard Worker
~ExclusiveConnection()1008*38e8c45fSAndroid Build Coastguard Worker RpcSession::ExclusiveConnection::~ExclusiveConnection() {
1009*38e8c45fSAndroid Build Coastguard Worker // reentrant use of a connection means something less deep in the call stack
1010*38e8c45fSAndroid Build Coastguard Worker // is using this fd, and it retains the right to it. So, we don't give up
1011*38e8c45fSAndroid Build Coastguard Worker // exclusive ownership, and no thread is freed.
1012*38e8c45fSAndroid Build Coastguard Worker if (!mReentrant && mConnection != nullptr) {
1013*38e8c45fSAndroid Build Coastguard Worker mSession->clearConnectionTid(mConnection);
1014*38e8c45fSAndroid Build Coastguard Worker }
1015*38e8c45fSAndroid Build Coastguard Worker }
1016*38e8c45fSAndroid Build Coastguard Worker
hasActiveConnection(const std::vector<sp<RpcConnection>> & connections)1017*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::hasActiveConnection(const std::vector<sp<RpcConnection>>& connections) {
1018*38e8c45fSAndroid Build Coastguard Worker for (const auto& connection : connections) {
1019*38e8c45fSAndroid Build Coastguard Worker if (connection->exclusiveTid != std::nullopt && !connection->rpcTransport->isWaiting()) {
1020*38e8c45fSAndroid Build Coastguard Worker return true;
1021*38e8c45fSAndroid Build Coastguard Worker }
1022*38e8c45fSAndroid Build Coastguard Worker }
1023*38e8c45fSAndroid Build Coastguard Worker return false;
1024*38e8c45fSAndroid Build Coastguard Worker }
1025*38e8c45fSAndroid Build Coastguard Worker
hasActiveRequests()1026*38e8c45fSAndroid Build Coastguard Worker bool RpcSession::hasActiveRequests() {
1027*38e8c45fSAndroid Build Coastguard Worker RpcMutexUniqueLock _l(mMutex);
1028*38e8c45fSAndroid Build Coastguard Worker if (hasActiveConnection(mConnections.mIncoming)) {
1029*38e8c45fSAndroid Build Coastguard Worker return true;
1030*38e8c45fSAndroid Build Coastguard Worker }
1031*38e8c45fSAndroid Build Coastguard Worker if (hasActiveConnection(mConnections.mOutgoing)) {
1032*38e8c45fSAndroid Build Coastguard Worker return true;
1033*38e8c45fSAndroid Build Coastguard Worker }
1034*38e8c45fSAndroid Build Coastguard Worker return mConnections.mWaitingThreads != 0;
1035*38e8c45fSAndroid Build Coastguard Worker }
1036*38e8c45fSAndroid Build Coastguard Worker
1037*38e8c45fSAndroid Build Coastguard Worker } // namespace android
1038