Loading include/android/surface_control.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -358,6 +358,11 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction, * enum. * enum. * * * Available since API level 29. * Available since API level 29. * * @deprecated Use setCrop, setPosition, setBufferTransform, and setScale instead. Those functions * provide well defined behavior and allows for more control by the apps. It also allows the caller * to set different properties at different times, instead of having to specify all the desired * properties at once. */ */ void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction, void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, const ARect& source, ASurfaceControl* surface_control, const ARect& source, Loading libs/binder/LazyServiceRegistrar.cpp +13 −9 Original line number Original line Diff line number Diff line Loading @@ -123,16 +123,20 @@ bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, cons std::string regStr = (reRegister) ? "Re-registering" : "Registering"; std::string regStr = (reRegister) ? "Re-registering" : "Registering"; ALOGI("%s service %s", regStr.c_str(), name.c_str()); ALOGI("%s service %s", regStr.c_str(), name.c_str()); if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) { if (Status status = manager->addService(name.c_str(), service, allowIsolated, dumpFlags); ALOGE("Failed to register service %s", name.c_str()); !status.isOk()) { ALOGE("Failed to register service %s (%s)", name.c_str(), status.toString8().c_str()); return false; return false; } } if (!reRegister) { if (!reRegister) { if (!manager->registerClientCallback(name, service, if (Status status = sp<android::os::IClientCallback>::fromExisting(this)) manager->registerClientCallback(name, service, .isOk()) { sp<android::os::IClientCallback>::fromExisting( ALOGE("Failed to add client callback for service %s", name.c_str()); this)); !status.isOk()) { ALOGE("Failed to add client callback for service %s (%s)", name.c_str(), status.toString8().c_str()); return false; return false; } } Loading Loading @@ -171,10 +175,10 @@ bool ClientCounterCallbackImpl::tryUnregister() { auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); for (auto& [name, entry] : mRegisteredServices) { for (auto& [name, entry] : mRegisteredServices) { bool success = manager->tryUnregisterService(name, entry.service).isOk(); Status status = manager->tryUnregisterService(name, entry.service); if (!success) { if (!status.isOk()) { ALOGI("Failed to unregister service %s", name.c_str()); ALOGI("Failed to unregister service %s (%s)", name.c_str(), status.toString8().c_str()); return false; return false; } } entry.registered = false; entry.registered = false; Loading libs/binder/RpcServer.cpp +16 −9 Original line number Original line Diff line number Diff line Loading @@ -49,8 +49,6 @@ bool RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); return setupSocketServer(UnixSocketAddress(path)); } } #ifdef __BIONIC__ bool RpcServer::setupVsockServer(unsigned int port) { bool RpcServer::setupVsockServer(unsigned int port) { // realizing value w/ this type at compile time to avoid ubsan abort // realizing value w/ this type at compile time to avoid ubsan abort constexpr unsigned int kAnyCid = VMADDR_CID_ANY; constexpr unsigned int kAnyCid = VMADDR_CID_ANY; Loading @@ -58,8 +56,6 @@ bool RpcServer::setupVsockServer(unsigned int port) { return setupSocketServer(VsockSocketAddress(kAnyCid, port)); return setupSocketServer(VsockSocketAddress(kAnyCid, port)); } } #endif // __BIONIC__ bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) { bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) { const char* kAddr = "127.0.0.1"; const char* kAddr = "127.0.0.1"; Loading Loading @@ -121,16 +117,14 @@ sp<IBinder> RpcServer::getRootObject() { void RpcServer::join() { void RpcServer::join() { LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::vector<std::thread> pool; { { std::lock_guard<std::mutex> _l(mLock); std::lock_guard<std::mutex> _l(mLock); LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join."); LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join."); } } while (true) { while (true) { unique_fd clientFd( unique_fd clientFd(TEMP_FAILURE_RETRY( TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC))); accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC))); if (clientFd < 0) { if (clientFd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); ALOGE("Could not accept4 socket: %s", strerror(errno)); Loading @@ -138,7 +132,8 @@ void RpcServer::join() { } } LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); // TODO(b/183988761): cannot trust this simple ID // TODO(b/183988761): cannot trust this simple ID, should not block this // thread LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); int32_t id; int32_t id; if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) { if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) { Loading Loading @@ -216,4 +211,16 @@ bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) { return true; return true; } } void RpcServer::onSessionTerminating(const sp<RpcSession>& session) { auto id = session->mId; LOG_ALWAYS_FATAL_IF(id == std::nullopt, "Server sessions must be initialized with ID"); LOG_RPC_DETAIL("Dropping session %d", *id); std::lock_guard<std::mutex> _l(mLock); auto it = mSessions.find(*id); LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %d", *id); LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %d", *id); (void)mSessions.erase(it); } } // namespace android } // namespace android libs/binder/RpcSession.cpp +76 −45 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <string_view> #include <string_view> #include <binder/Parcel.h> #include <binder/Parcel.h> #include <binder/RpcServer.h> #include <binder/Stability.h> #include <binder/Stability.h> #include <utils/String8.h> #include <utils/String8.h> Loading @@ -48,7 +49,7 @@ RpcSession::~RpcSession() { LOG_RPC_DETAIL("RpcSession destroyed %p", this); LOG_RPC_DETAIL("RpcSession destroyed %p", this); std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); LOG_ALWAYS_FATAL_IF(mServers.size() != 0, LOG_ALWAYS_FATAL_IF(mServerConnections.size() != 0, "Should not be able to destroy a session with servers in use."); "Should not be able to destroy a session with servers in use."); } } Loading @@ -60,14 +61,10 @@ bool RpcSession::setupUnixDomainClient(const char* path) { return setupSocketClient(UnixSocketAddress(path)); return setupSocketClient(UnixSocketAddress(path)); } } #ifdef __BIONIC__ bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) { bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) { return setupSocketClient(VsockSocketAddress(cid, port)); return setupSocketClient(VsockSocketAddress(cid, port)); } } #endif // __BIONIC__ bool RpcSession::setupInetClient(const char* addr, unsigned int port) { bool RpcSession::setupInetClient(const char* addr, unsigned int port) { auto aiStart = InetSocketAddress::getAddrInfo(addr, port); auto aiStart = InetSocketAddress::getAddrInfo(addr, port); if (aiStart == nullptr) return false; if (aiStart == nullptr) return false; Loading Loading @@ -142,8 +139,10 @@ void RpcSession::startThread(unique_fd client) { holdThis->join(unique_fd(fd)); holdThis->join(unique_fd(fd)); { { std::lock_guard<std::mutex> _l(holdThis->mMutex); std::lock_guard<std::mutex> _l(holdThis->mMutex); size_t erased = mThreads.erase(std::this_thread::get_id()); auto it = mThreads.find(std::this_thread::get_id()); LOG_ALWAYS_FATAL_IF(erased != 0, "Could not erase thread."); LOG_ALWAYS_FATAL_IF(it == mThreads.end()); it->second.detach(); mThreads.erase(it); } } }); }); mThreads[thread.get_id()] = std::move(thread); mThreads[thread.get_id()] = std::move(thread); Loading @@ -168,6 +167,22 @@ void RpcSession::join(unique_fd client) { "bad state: connection object guaranteed to be in list"); "bad state: connection object guaranteed to be in list"); } } void RpcSession::terminateLocked() { // TODO(b/185167543): // - kindly notify other side of the connection of termination (can't be // locked) // - prevent new client/servers from being added // - stop all threads which are currently reading/writing // - terminate RpcState? if (mTerminated) return; sp<RpcServer> server = mForServer.promote(); if (server) { server->onSessionTerminating(sp<RpcSession>::fromExisting(this)); } } wp<RpcServer> RpcSession::server() { wp<RpcServer> RpcSession::server() { return mForServer; return mForServer; } } Loading @@ -175,9 +190,9 @@ wp<RpcServer> RpcSession::server() { bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { { { std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); LOG_ALWAYS_FATAL_IF(mClients.size() != 0, LOG_ALWAYS_FATAL_IF(mClientConnections.size() != 0, "Must only setup session once, but already has %zu clients", "Must only setup session once, but already has %zu clients", mClients.size()); mClientConnections.size()); } } if (!setupOneSocketClient(addr, RPC_SESSION_ID_NEW)) return false; if (!setupOneSocketClient(addr, RPC_SESSION_ID_NEW)) return false; Loading @@ -200,28 +215,34 @@ bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { // we've already setup one client // we've already setup one client for (size_t i = 0; i + 1 < numThreadsAvailable; i++) { for (size_t i = 0; i + 1 < numThreadsAvailable; i++) { // TODO(b/185167543): avoid race w/ accept4 not being called on server // TODO(b/185167543): shutdown existing connections? for (size_t tries = 0; tries < 5; tries++) { if (!setupOneSocketClient(addr, mId.value())) return false; if (setupOneSocketClient(addr, mId.value())) break; usleep(10000); } } } return true; return true; } } bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) { bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) { for (size_t tries = 0; tries < 5; tries++) { if (tries > 0) usleep(10000); unique_fd serverFd( unique_fd serverFd( TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); if (serverFd == -1) { if (serverFd == -1) { int savedErrno = errno; int savedErrno = errno; ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; return false; } } if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { if (errno == ECONNRESET) { ALOGW("Connection reset on %s", addr.toString().c_str()); continue; } int savedErrno = errno; int savedErrno = errno; ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; return false; } } Loading @@ -238,11 +259,15 @@ bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) return true; return true; } } ALOGE("Ran out of retries to connect to %s", addr.toString().c_str()); return false; } void RpcSession::addClient(unique_fd fd) { void RpcSession::addClient(unique_fd fd) { std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); sp<RpcConnection> session = sp<RpcConnection>::make(); sp<RpcConnection> session = sp<RpcConnection>::make(); session->fd = std::move(fd); session->fd = std::move(fd); mClients.push_back(session); mClientConnections.push_back(session); } } void RpcSession::setForServer(const wp<RpcServer>& server, int32_t sessionId) { void RpcSession::setForServer(const wp<RpcServer>& server, int32_t sessionId) { Loading @@ -255,15 +280,19 @@ sp<RpcSession::RpcConnection> RpcSession::assignServerToThisThread(unique_fd fd) sp<RpcConnection> session = sp<RpcConnection>::make(); sp<RpcConnection> session = sp<RpcConnection>::make(); session->fd = std::move(fd); session->fd = std::move(fd); session->exclusiveTid = gettid(); session->exclusiveTid = gettid(); mServers.push_back(session); mServerConnections.push_back(session); return session; return session; } } bool RpcSession::removeServerConnection(const sp<RpcConnection>& connection) { bool RpcSession::removeServerConnection(const sp<RpcConnection>& connection) { std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); if (auto it = std::find(mServers.begin(), mServers.end(), connection); it != mServers.end()) { if (auto it = std::find(mServerConnections.begin(), mServerConnections.end(), connection); mServers.erase(it); it != mServerConnections.end()) { mServerConnections.erase(it); if (mServerConnections.size() == 0) { terminateLocked(); } return true; return true; } } return false; return false; Loading @@ -283,10 +312,11 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi // CHECK FOR DEDICATED CLIENT SOCKET // CHECK FOR DEDICATED CLIENT SOCKET // // // A server/looper should always use a dedicated session if available // A server/looper should always use a dedicated session if available findConnection(tid, &exclusive, &available, mSession->mClients, mSession->mClientsOffset); findConnection(tid, &exclusive, &available, mSession->mClientConnections, mSession->mClientConnectionsOffset); // WARNING: this assumes a server cannot request its client to send // WARNING: this assumes a server cannot request its client to send // a transaction, as mServers is excluded below. // a transaction, as mServerConnections is excluded below. // // // Imagine we have more than one thread in play, and a single thread // Imagine we have more than one thread in play, and a single thread // sends a synchronous, then an asynchronous command. Imagine the // sends a synchronous, then an asynchronous command. Imagine the Loading @@ -296,7 +326,8 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi // command. So, we move to considering the second available thread // command. So, we move to considering the second available thread // for subsequent calls. // for subsequent calls. if (use == ConnectionUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) { if (use == ConnectionUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) { mSession->mClientsOffset = (mSession->mClientsOffset + 1) % mSession->mClients.size(); mSession->mClientConnectionsOffset = (mSession->mClientConnectionsOffset + 1) % mSession->mClientConnections.size(); } } // USE SERVING SOCKET (for nested transaction) // USE SERVING SOCKET (for nested transaction) Loading @@ -304,7 +335,7 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi // asynchronous calls cannot be nested // asynchronous calls cannot be nested if (use != ConnectionUse::CLIENT_ASYNC) { if (use != ConnectionUse::CLIENT_ASYNC) { // server connections are always assigned to a thread // server connections are always assigned to a thread findConnection(tid, &exclusive, nullptr /*available*/, mSession->mServers, findConnection(tid, &exclusive, nullptr /*available*/, mSession->mServerConnections, 0 /* index hint */); 0 /* index hint */); } } Loading @@ -320,13 +351,13 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi } } // in regular binder, this would usually be a deadlock :) // in regular binder, this would usually be a deadlock :) LOG_ALWAYS_FATAL_IF(mSession->mClients.size() == 0, LOG_ALWAYS_FATAL_IF(mSession->mClientConnections.size() == 0, "Not a client of any session. You must create a session to an " "Not a client of any session. You must create a session to an " "RPC server to make any non-nested (e.g. oneway or on another thread) " "RPC server to make any non-nested (e.g. oneway or on another thread) " "calls."); "calls."); LOG_RPC_DETAIL("No available session (have %zu clients and %zu servers). Waiting...", LOG_RPC_DETAIL("No available session (have %zu clients and %zu servers). Waiting...", mSession->mClients.size(), mSession->mServers.size()); mSession->mClientConnections.size(), mSession->mServerConnections.size()); mSession->mAvailableConnectionCv.wait(_l); mSession->mAvailableConnectionCv.wait(_l); } } mSession->mWaitingThreads--; mSession->mWaitingThreads--; Loading libs/binder/RpcSocketAddress.h +1 −7 Original line number Original line Diff line number Diff line Loading @@ -24,9 +24,7 @@ #include <sys/types.h> #include <sys/types.h> #include <sys/un.h> #include <sys/un.h> #ifdef __BIONIC__ #include "vm_sockets.h" #include <linux/vm_sockets.h> #endif namespace android { namespace android { Loading Loading @@ -59,8 +57,6 @@ private: sockaddr_un mAddr; sockaddr_un mAddr; }; }; #ifdef __BIONIC__ class VsockSocketAddress : public RpcSocketAddress { class VsockSocketAddress : public RpcSocketAddress { public: public: VsockSocketAddress(unsigned int cid, unsigned int port) VsockSocketAddress(unsigned int cid, unsigned int port) Loading @@ -80,8 +76,6 @@ private: sockaddr_vm mAddr; sockaddr_vm mAddr; }; }; #endif // __BIONIC__ class InetSocketAddress : public RpcSocketAddress { class InetSocketAddress : public RpcSocketAddress { public: public: InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port) InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port) Loading Loading
include/android/surface_control.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -358,6 +358,11 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction, * enum. * enum. * * * Available since API level 29. * Available since API level 29. * * @deprecated Use setCrop, setPosition, setBufferTransform, and setScale instead. Those functions * provide well defined behavior and allows for more control by the apps. It also allows the caller * to set different properties at different times, instead of having to specify all the desired * properties at once. */ */ void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction, void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, const ARect& source, ASurfaceControl* surface_control, const ARect& source, Loading
libs/binder/LazyServiceRegistrar.cpp +13 −9 Original line number Original line Diff line number Diff line Loading @@ -123,16 +123,20 @@ bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, cons std::string regStr = (reRegister) ? "Re-registering" : "Registering"; std::string regStr = (reRegister) ? "Re-registering" : "Registering"; ALOGI("%s service %s", regStr.c_str(), name.c_str()); ALOGI("%s service %s", regStr.c_str(), name.c_str()); if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) { if (Status status = manager->addService(name.c_str(), service, allowIsolated, dumpFlags); ALOGE("Failed to register service %s", name.c_str()); !status.isOk()) { ALOGE("Failed to register service %s (%s)", name.c_str(), status.toString8().c_str()); return false; return false; } } if (!reRegister) { if (!reRegister) { if (!manager->registerClientCallback(name, service, if (Status status = sp<android::os::IClientCallback>::fromExisting(this)) manager->registerClientCallback(name, service, .isOk()) { sp<android::os::IClientCallback>::fromExisting( ALOGE("Failed to add client callback for service %s", name.c_str()); this)); !status.isOk()) { ALOGE("Failed to add client callback for service %s (%s)", name.c_str(), status.toString8().c_str()); return false; return false; } } Loading Loading @@ -171,10 +175,10 @@ bool ClientCounterCallbackImpl::tryUnregister() { auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); for (auto& [name, entry] : mRegisteredServices) { for (auto& [name, entry] : mRegisteredServices) { bool success = manager->tryUnregisterService(name, entry.service).isOk(); Status status = manager->tryUnregisterService(name, entry.service); if (!success) { if (!status.isOk()) { ALOGI("Failed to unregister service %s", name.c_str()); ALOGI("Failed to unregister service %s (%s)", name.c_str(), status.toString8().c_str()); return false; return false; } } entry.registered = false; entry.registered = false; Loading
libs/binder/RpcServer.cpp +16 −9 Original line number Original line Diff line number Diff line Loading @@ -49,8 +49,6 @@ bool RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); return setupSocketServer(UnixSocketAddress(path)); } } #ifdef __BIONIC__ bool RpcServer::setupVsockServer(unsigned int port) { bool RpcServer::setupVsockServer(unsigned int port) { // realizing value w/ this type at compile time to avoid ubsan abort // realizing value w/ this type at compile time to avoid ubsan abort constexpr unsigned int kAnyCid = VMADDR_CID_ANY; constexpr unsigned int kAnyCid = VMADDR_CID_ANY; Loading @@ -58,8 +56,6 @@ bool RpcServer::setupVsockServer(unsigned int port) { return setupSocketServer(VsockSocketAddress(kAnyCid, port)); return setupSocketServer(VsockSocketAddress(kAnyCid, port)); } } #endif // __BIONIC__ bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) { bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) { const char* kAddr = "127.0.0.1"; const char* kAddr = "127.0.0.1"; Loading Loading @@ -121,16 +117,14 @@ sp<IBinder> RpcServer::getRootObject() { void RpcServer::join() { void RpcServer::join() { LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::vector<std::thread> pool; { { std::lock_guard<std::mutex> _l(mLock); std::lock_guard<std::mutex> _l(mLock); LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join."); LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join."); } } while (true) { while (true) { unique_fd clientFd( unique_fd clientFd(TEMP_FAILURE_RETRY( TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC))); accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC))); if (clientFd < 0) { if (clientFd < 0) { ALOGE("Could not accept4 socket: %s", strerror(errno)); ALOGE("Could not accept4 socket: %s", strerror(errno)); Loading @@ -138,7 +132,8 @@ void RpcServer::join() { } } LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); // TODO(b/183988761): cannot trust this simple ID // TODO(b/183988761): cannot trust this simple ID, should not block this // thread LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); int32_t id; int32_t id; if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) { if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) { Loading Loading @@ -216,4 +211,16 @@ bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) { return true; return true; } } void RpcServer::onSessionTerminating(const sp<RpcSession>& session) { auto id = session->mId; LOG_ALWAYS_FATAL_IF(id == std::nullopt, "Server sessions must be initialized with ID"); LOG_RPC_DETAIL("Dropping session %d", *id); std::lock_guard<std::mutex> _l(mLock); auto it = mSessions.find(*id); LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %d", *id); LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %d", *id); (void)mSessions.erase(it); } } // namespace android } // namespace android
libs/binder/RpcSession.cpp +76 −45 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <string_view> #include <string_view> #include <binder/Parcel.h> #include <binder/Parcel.h> #include <binder/RpcServer.h> #include <binder/Stability.h> #include <binder/Stability.h> #include <utils/String8.h> #include <utils/String8.h> Loading @@ -48,7 +49,7 @@ RpcSession::~RpcSession() { LOG_RPC_DETAIL("RpcSession destroyed %p", this); LOG_RPC_DETAIL("RpcSession destroyed %p", this); std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); LOG_ALWAYS_FATAL_IF(mServers.size() != 0, LOG_ALWAYS_FATAL_IF(mServerConnections.size() != 0, "Should not be able to destroy a session with servers in use."); "Should not be able to destroy a session with servers in use."); } } Loading @@ -60,14 +61,10 @@ bool RpcSession::setupUnixDomainClient(const char* path) { return setupSocketClient(UnixSocketAddress(path)); return setupSocketClient(UnixSocketAddress(path)); } } #ifdef __BIONIC__ bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) { bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) { return setupSocketClient(VsockSocketAddress(cid, port)); return setupSocketClient(VsockSocketAddress(cid, port)); } } #endif // __BIONIC__ bool RpcSession::setupInetClient(const char* addr, unsigned int port) { bool RpcSession::setupInetClient(const char* addr, unsigned int port) { auto aiStart = InetSocketAddress::getAddrInfo(addr, port); auto aiStart = InetSocketAddress::getAddrInfo(addr, port); if (aiStart == nullptr) return false; if (aiStart == nullptr) return false; Loading Loading @@ -142,8 +139,10 @@ void RpcSession::startThread(unique_fd client) { holdThis->join(unique_fd(fd)); holdThis->join(unique_fd(fd)); { { std::lock_guard<std::mutex> _l(holdThis->mMutex); std::lock_guard<std::mutex> _l(holdThis->mMutex); size_t erased = mThreads.erase(std::this_thread::get_id()); auto it = mThreads.find(std::this_thread::get_id()); LOG_ALWAYS_FATAL_IF(erased != 0, "Could not erase thread."); LOG_ALWAYS_FATAL_IF(it == mThreads.end()); it->second.detach(); mThreads.erase(it); } } }); }); mThreads[thread.get_id()] = std::move(thread); mThreads[thread.get_id()] = std::move(thread); Loading @@ -168,6 +167,22 @@ void RpcSession::join(unique_fd client) { "bad state: connection object guaranteed to be in list"); "bad state: connection object guaranteed to be in list"); } } void RpcSession::terminateLocked() { // TODO(b/185167543): // - kindly notify other side of the connection of termination (can't be // locked) // - prevent new client/servers from being added // - stop all threads which are currently reading/writing // - terminate RpcState? if (mTerminated) return; sp<RpcServer> server = mForServer.promote(); if (server) { server->onSessionTerminating(sp<RpcSession>::fromExisting(this)); } } wp<RpcServer> RpcSession::server() { wp<RpcServer> RpcSession::server() { return mForServer; return mForServer; } } Loading @@ -175,9 +190,9 @@ wp<RpcServer> RpcSession::server() { bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { { { std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); LOG_ALWAYS_FATAL_IF(mClients.size() != 0, LOG_ALWAYS_FATAL_IF(mClientConnections.size() != 0, "Must only setup session once, but already has %zu clients", "Must only setup session once, but already has %zu clients", mClients.size()); mClientConnections.size()); } } if (!setupOneSocketClient(addr, RPC_SESSION_ID_NEW)) return false; if (!setupOneSocketClient(addr, RPC_SESSION_ID_NEW)) return false; Loading @@ -200,28 +215,34 @@ bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) { // we've already setup one client // we've already setup one client for (size_t i = 0; i + 1 < numThreadsAvailable; i++) { for (size_t i = 0; i + 1 < numThreadsAvailable; i++) { // TODO(b/185167543): avoid race w/ accept4 not being called on server // TODO(b/185167543): shutdown existing connections? for (size_t tries = 0; tries < 5; tries++) { if (!setupOneSocketClient(addr, mId.value())) return false; if (setupOneSocketClient(addr, mId.value())) break; usleep(10000); } } } return true; return true; } } bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) { bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) { for (size_t tries = 0; tries < 5; tries++) { if (tries > 0) usleep(10000); unique_fd serverFd( unique_fd serverFd( TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); if (serverFd == -1) { if (serverFd == -1) { int savedErrno = errno; int savedErrno = errno; ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; return false; } } if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { if (errno == ECONNRESET) { ALOGW("Connection reset on %s", addr.toString().c_str()); continue; } int savedErrno = errno; int savedErrno = errno; ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; return false; } } Loading @@ -238,11 +259,15 @@ bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) return true; return true; } } ALOGE("Ran out of retries to connect to %s", addr.toString().c_str()); return false; } void RpcSession::addClient(unique_fd fd) { void RpcSession::addClient(unique_fd fd) { std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); sp<RpcConnection> session = sp<RpcConnection>::make(); sp<RpcConnection> session = sp<RpcConnection>::make(); session->fd = std::move(fd); session->fd = std::move(fd); mClients.push_back(session); mClientConnections.push_back(session); } } void RpcSession::setForServer(const wp<RpcServer>& server, int32_t sessionId) { void RpcSession::setForServer(const wp<RpcServer>& server, int32_t sessionId) { Loading @@ -255,15 +280,19 @@ sp<RpcSession::RpcConnection> RpcSession::assignServerToThisThread(unique_fd fd) sp<RpcConnection> session = sp<RpcConnection>::make(); sp<RpcConnection> session = sp<RpcConnection>::make(); session->fd = std::move(fd); session->fd = std::move(fd); session->exclusiveTid = gettid(); session->exclusiveTid = gettid(); mServers.push_back(session); mServerConnections.push_back(session); return session; return session; } } bool RpcSession::removeServerConnection(const sp<RpcConnection>& connection) { bool RpcSession::removeServerConnection(const sp<RpcConnection>& connection) { std::lock_guard<std::mutex> _l(mMutex); std::lock_guard<std::mutex> _l(mMutex); if (auto it = std::find(mServers.begin(), mServers.end(), connection); it != mServers.end()) { if (auto it = std::find(mServerConnections.begin(), mServerConnections.end(), connection); mServers.erase(it); it != mServerConnections.end()) { mServerConnections.erase(it); if (mServerConnections.size() == 0) { terminateLocked(); } return true; return true; } } return false; return false; Loading @@ -283,10 +312,11 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi // CHECK FOR DEDICATED CLIENT SOCKET // CHECK FOR DEDICATED CLIENT SOCKET // // // A server/looper should always use a dedicated session if available // A server/looper should always use a dedicated session if available findConnection(tid, &exclusive, &available, mSession->mClients, mSession->mClientsOffset); findConnection(tid, &exclusive, &available, mSession->mClientConnections, mSession->mClientConnectionsOffset); // WARNING: this assumes a server cannot request its client to send // WARNING: this assumes a server cannot request its client to send // a transaction, as mServers is excluded below. // a transaction, as mServerConnections is excluded below. // // // Imagine we have more than one thread in play, and a single thread // Imagine we have more than one thread in play, and a single thread // sends a synchronous, then an asynchronous command. Imagine the // sends a synchronous, then an asynchronous command. Imagine the Loading @@ -296,7 +326,8 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi // command. So, we move to considering the second available thread // command. So, we move to considering the second available thread // for subsequent calls. // for subsequent calls. if (use == ConnectionUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) { if (use == ConnectionUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) { mSession->mClientsOffset = (mSession->mClientsOffset + 1) % mSession->mClients.size(); mSession->mClientConnectionsOffset = (mSession->mClientConnectionsOffset + 1) % mSession->mClientConnections.size(); } } // USE SERVING SOCKET (for nested transaction) // USE SERVING SOCKET (for nested transaction) Loading @@ -304,7 +335,7 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi // asynchronous calls cannot be nested // asynchronous calls cannot be nested if (use != ConnectionUse::CLIENT_ASYNC) { if (use != ConnectionUse::CLIENT_ASYNC) { // server connections are always assigned to a thread // server connections are always assigned to a thread findConnection(tid, &exclusive, nullptr /*available*/, mSession->mServers, findConnection(tid, &exclusive, nullptr /*available*/, mSession->mServerConnections, 0 /* index hint */); 0 /* index hint */); } } Loading @@ -320,13 +351,13 @@ RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& sessi } } // in regular binder, this would usually be a deadlock :) // in regular binder, this would usually be a deadlock :) LOG_ALWAYS_FATAL_IF(mSession->mClients.size() == 0, LOG_ALWAYS_FATAL_IF(mSession->mClientConnections.size() == 0, "Not a client of any session. You must create a session to an " "Not a client of any session. You must create a session to an " "RPC server to make any non-nested (e.g. oneway or on another thread) " "RPC server to make any non-nested (e.g. oneway or on another thread) " "calls."); "calls."); LOG_RPC_DETAIL("No available session (have %zu clients and %zu servers). Waiting...", LOG_RPC_DETAIL("No available session (have %zu clients and %zu servers). Waiting...", mSession->mClients.size(), mSession->mServers.size()); mSession->mClientConnections.size(), mSession->mServerConnections.size()); mSession->mAvailableConnectionCv.wait(_l); mSession->mAvailableConnectionCv.wait(_l); } } mSession->mWaitingThreads--; mSession->mWaitingThreads--; Loading
libs/binder/RpcSocketAddress.h +1 −7 Original line number Original line Diff line number Diff line Loading @@ -24,9 +24,7 @@ #include <sys/types.h> #include <sys/types.h> #include <sys/un.h> #include <sys/un.h> #ifdef __BIONIC__ #include "vm_sockets.h" #include <linux/vm_sockets.h> #endif namespace android { namespace android { Loading Loading @@ -59,8 +57,6 @@ private: sockaddr_un mAddr; sockaddr_un mAddr; }; }; #ifdef __BIONIC__ class VsockSocketAddress : public RpcSocketAddress { class VsockSocketAddress : public RpcSocketAddress { public: public: VsockSocketAddress(unsigned int cid, unsigned int port) VsockSocketAddress(unsigned int cid, unsigned int port) Loading @@ -80,8 +76,6 @@ private: sockaddr_vm mAddr; sockaddr_vm mAddr; }; }; #endif // __BIONIC__ class InetSocketAddress : public RpcSocketAddress { class InetSocketAddress : public RpcSocketAddress { public: public: InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port) InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port) Loading