diff options
| -rw-r--r-- | libs/binder/ndk/Android.bp | 7 | ||||
| -rw-r--r-- | libs/binder/ndk/ibinder_jni.cpp | 68 |
2 files changed, 69 insertions, 6 deletions
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp index 05655c18c5..0826544d89 100644 --- a/libs/binder/ndk/Android.bp +++ b/libs/binder/ndk/Android.bp @@ -39,12 +39,17 @@ cc_library { ], shared_libs: [ - "libandroid_runtime", "libbase", "libbinder", "libutils", ], + required: [ + // libbinder_ndk may be used by Java and non-Java things. When lower-level things use it, + // they shouldn't have to take on the cost of loading libandroid_runtime. + "libandroid_runtime", + ], + version_script: "libbinder_ndk.map.txt", stubs: { symbol_file: "libbinder_ndk.map.txt", diff --git a/libs/binder/ndk/ibinder_jni.cpp b/libs/binder/ndk/ibinder_jni.cpp index baea2e87d3..4a31080824 100644 --- a/libs/binder/ndk/ibinder_jni.cpp +++ b/libs/binder/ndk/ibinder_jni.cpp @@ -17,15 +17,68 @@ #include <android/binder_ibinder_jni.h> #include "ibinder_internal.h" -#include <android_util_Binder.h> +#include <android-base/logging.h> +#include <binder/IBinder.h> + +#include <mutex> + +#include <dlfcn.h> using ::android::IBinder; -using ::android::ibinderForJavaObject; -using ::android::javaObjectForIBinder; using ::android::sp; +struct LazyAndroidRuntime { + typedef sp<IBinder> (*FromJava)(JNIEnv* env, jobject obj); + typedef jobject (*ToJava)(JNIEnv* env, const sp<IBinder>& val); + + static FromJava ibinderForJavaObject; + static ToJava javaObjectForIBinder; + + static void load() { + std::call_once(mLoadFlag, []() { + void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY); + if (handle == nullptr) { + LOG(WARNING) << "Could not open libandroid_runtime."; + return; + } + + ibinderForJavaObject = reinterpret_cast<FromJava>( + dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject")); + if (ibinderForJavaObject == nullptr) { + LOG(WARNING) << "Could not find ibinderForJavaObject."; + // no return + } + + javaObjectForIBinder = reinterpret_cast<ToJava>(dlsym( + handle, "_ZN7android20javaObjectForIBinderEP7_JNIEnvRKNS_2spINS_7IBinderEEE")); + if (javaObjectForIBinder == nullptr) { + LOG(WARNING) << "Could not find javaObjectForIBinder."; + // no return + } + }); + } + + private: + static std::once_flag mLoadFlag; + + LazyAndroidRuntime(){}; +}; + +LazyAndroidRuntime::FromJava LazyAndroidRuntime::ibinderForJavaObject = nullptr; +LazyAndroidRuntime::ToJava LazyAndroidRuntime::javaObjectForIBinder = nullptr; +std::once_flag LazyAndroidRuntime::mLoadFlag; + AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) { - sp<IBinder> ibinder = ibinderForJavaObject(env, binder); + if (binder == nullptr) { + return nullptr; + } + + LazyAndroidRuntime::load(); + if (LazyAndroidRuntime::ibinderForJavaObject == nullptr) { + return nullptr; + } + + sp<IBinder> ibinder = (LazyAndroidRuntime::ibinderForJavaObject)(env, binder); sp<AIBinder> cbinder = ABpBinder::lookupOrCreateFromBinder(ibinder); AIBinder_incStrong(cbinder.get()); @@ -38,5 +91,10 @@ jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) { return nullptr; } - return javaObjectForIBinder(env, binder->getBinder()); + LazyAndroidRuntime::load(); + if (LazyAndroidRuntime::javaObjectForIBinder == nullptr) { + return nullptr; + } + + return (LazyAndroidRuntime::javaObjectForIBinder)(env, binder->getBinder()); } |