RpcSession attaches/detaches JVM for Java thread
If javaAttachThread / javaDetachThread exists, run them before
and after the while loop in join. This ensures the
Java thread is attached / detached appropriately for
binder threads that handles RPC calls.
Test: run aservice on Java services
Bug: 190450693
Change-Id: I23f171dd1e08dfacfbbb46ecc9564cbf42d6f353
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index ee5e8bb..bdf1bbe 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -18,13 +18,16 @@
#include <binder/RpcSession.h>
+#include <dlfcn.h>
#include <inttypes.h>
#include <poll.h>
+#include <pthread.h>
#include <unistd.h>
#include <string_view>
#include <android-base/macros.h>
+#include <android_runtime/threads.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
#include <binder/Stability.h>
@@ -274,10 +277,53 @@
};
}
+namespace {
+// RAII object for attaching / detaching current thread to JVM if Android Runtime exists. If
+// Android Runtime doesn't exist, no-op.
+class JavaThreadAttacher {
+public:
+ JavaThreadAttacher() {
+ // Use dlsym to find androidJavaAttachThread because libandroid_runtime is loaded after
+ // libbinder.
+ static auto attachFn = reinterpret_cast<decltype(&androidJavaAttachThread)>(
+ dlsym(RTLD_DEFAULT, "androidJavaAttachThread"));
+ if (attachFn == nullptr) return;
+
+ char buf[16];
+ const char* threadName = "UnknownRpcSessionThread"; // default thread name
+ if (0 == pthread_getname_np(pthread_self(), buf, sizeof(buf))) {
+ threadName = buf;
+ }
+ LOG_RPC_DETAIL("Attaching current thread %s to JVM", threadName);
+ LOG_ALWAYS_FATAL_IF(!attachFn(threadName), "Cannot attach thread %s to JVM", threadName);
+ mAttached = true;
+ }
+ ~JavaThreadAttacher() {
+ if (!mAttached) return;
+ static auto detachFn = reinterpret_cast<decltype(&androidJavaDetachThread)>(
+ dlsym(RTLD_DEFAULT, "androidJavaDetachThread"));
+ LOG_ALWAYS_FATAL_IF(detachFn == nullptr,
+ "androidJavaAttachThread exists but androidJavaDetachThread doesn't");
+
+ LOG_RPC_DETAIL("Detaching current thread from JVM");
+ if (detachFn()) {
+ mAttached = false;
+ } else {
+ ALOGW("Unable to detach current thread from JVM");
+ }
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(JavaThreadAttacher);
+ bool mAttached = false;
+};
+} // namespace
+
void RpcSession::join(sp<RpcSession>&& session, PreJoinSetupResult&& setupResult) {
sp<RpcConnection>& connection = setupResult.connection;
if (setupResult.status == OK) {
+ JavaThreadAttacher javaThreadAttacher;
while (true) {
status_t status = session->state()->getAndExecuteCommand(connection, session,
RpcState::CommandType::ANY);