Use libandroid_runtime lazily
This is a part of cutting dependency from libmediandk to
libandroid_runtime.
By making a libandroid_runtime to be loaded lazily,
libmediandk won't load libandroid_runtime when it is used as a LL-NDK.
Bug: 124268753
Test: m -j
Change-Id: Ib040856c58d38e11a5f32cd5dd5519910573334b
Merged-In: Ib040856c58d38e11a5f32cd5dd5519910573334b
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index ac837a3..4be71ac 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -33,13 +33,70 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/NuMediaExtractor.h>
#include <media/IMediaHTTPService.h>
-#include <android_runtime/AndroidRuntime.h>
-#include <android_util_Binder.h>
#include <jni.h>
+#include <mutex> // std::call_once,once_flag
+#include <dlfcn.h> // dlopen
+
using namespace android;
+// load libandroid_runtime.so lazily.
+// A vendor process may use libmediandk but should not depend on libandroid_runtime.
+// TODO(jooyung): remove duplicate (b/125550121)
+// frameworks/native/libs/binder/ndk/ibinder_jni.cpp
+namespace {
+
+typedef JNIEnv* (*getJNIEnv_t)();
+typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj);
+
+getJNIEnv_t getJNIEnv_;
+ibinderForJavaObject_t ibinderForJavaObject_;
+
+std::once_flag mLoadFlag;
+
+void load() {
+ std::call_once(mLoadFlag, []() {
+ void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY);
+ if (handle == nullptr) {
+ ALOGE("Could not open libandroid_runtime.");
+ return;
+ }
+
+ getJNIEnv_ = reinterpret_cast<getJNIEnv_t>(
+ dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv"));
+ if (getJNIEnv_ == nullptr) {
+ ALOGE("Could not find AndroidRuntime::getJNIEnv.");
+ // no return
+ }
+
+ ibinderForJavaObject_ = reinterpret_cast<ibinderForJavaObject_t>(
+ dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
+ if (ibinderForJavaObject_ == nullptr) {
+ ALOGE("Could not find ibinderForJavaObject.");
+ // no return
+ }
+ });
+}
+
+JNIEnv* getJNIEnv() {
+ load();
+ if (getJNIEnv_ == nullptr) {
+ return nullptr;
+ }
+ return (getJNIEnv_)();
+}
+
+sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) {
+ load();
+ if (ibinderForJavaObject_ == nullptr) {
+ return nullptr;
+ }
+ return (ibinderForJavaObject_)(env, obj);
+}
+
+} // namespace
+
static media_status_t translate_error(status_t err) {
if (err == OK) {
return AMEDIA_OK;
@@ -87,7 +144,7 @@
ALOGV("setDataSource(%s)", location);
// TODO: add header support
- JNIEnv *env = AndroidRuntime::getJNIEnv();
+ JNIEnv *env = getJNIEnv();
jobject service = NULL;
if (env == NULL) {
ALOGE("setDataSource(path) must be called from Java thread");