xref: /aosp_15_r20/frameworks/native/libs/binder/RpcSession.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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