Add libandroid_runtime_lazy
Extract lazy loading of libandroid_runtime from libbinder_ndk
into its own library.
This lib loads libandroid_runtime on demand, so the clients
which don't use this can benefit.
Do not over-use this lib to mock the build system and pretend not
depending on libandroid_runtime.
Bug: 125550121
Test: m -j
Test: readelf -d $OUT/system/lib64/libbinder_ndk.so | grep NEED
# see if there is not libandroid_runtime
Test: atest android.binder.cts
Change-Id: I4b120686ba34f45e060594641ffc74bc1496c8c9
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
new file mode 100644
index 0000000..b200314
--- /dev/null
+++ b/libs/android_runtime_lazy/Android.bp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// libandroid_runtime_lazy is a shim library.
+// This provides very limited small set of APIs from libandroid_runtime.
+//
+// By depending on this instead of libandroid_runtime,
+// a library can be loaded without paying the cost of libandroid_runtime
+// which is quite huge. The cost will be paid when libandroid_runtime is actually used.
+//
+// For Partial-source PDK build, there is a constraint that
+// frameworks/native modules should not depend on frameworks/base.
+// This library can be used to cut down the dependency between them.
+// (e.g. libbinder_ndk)
+//
+// Some libraries which serve as LL-NDK and NDK as well may depend on this
+// instead of libandroid_runtime. When they are used by a vendor process,
+// depending on libandroid_runtime is meaningless. In this case,
+// they can depend on libandroid_runtime_lazy.
+cc_library {
+ name: "libandroid_runtime_lazy",
+ vendor_available: true,
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wunused",
+ "-Wunreachable-code",
+ ],
+
+ srcs: [
+ "android_runtime_lazy.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libutils",
+ ],
+
+ required: [
+ "libandroid_runtime",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ header_libs: [
+ "jni_headers",
+ "libbinder_headers",
+ ],
+}
diff --git a/libs/android_runtime_lazy/android_runtime_lazy.cpp b/libs/android_runtime_lazy/android_runtime_lazy.cpp
new file mode 100644
index 0000000..98d8e8a
--- /dev/null
+++ b/libs/android_runtime_lazy/android_runtime_lazy.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "ANDROID_RUNTIME_LAZY"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_util_Binder.h"
+
+#include <dlfcn.h>
+#include <mutex>
+
+#include <log/log.h>
+
+namespace android {
+namespace {
+
+std::once_flag loadFlag;
+
+typedef JNIEnv* (*getJNIEnv_t)();
+typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj);
+typedef jobject (*javaObjectForIBinder_t)(JNIEnv* env, const sp<IBinder>& val);
+
+getJNIEnv_t _getJNIEnv;
+ibinderForJavaObject_t _ibinderForJavaObject;
+javaObjectForIBinder_t _javaObjectForIBinder;
+
+void load() {
+ std::call_once(loadFlag, []() {
+ 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) {
+ ALOGW("Could not find getJNIEnv.");
+ // no return
+ }
+
+ _ibinderForJavaObject = reinterpret_cast<ibinderForJavaObject_t>(
+ dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
+ if (_ibinderForJavaObject == nullptr) {
+ ALOGW("Could not find ibinderForJavaObject.");
+ // no return
+ }
+
+ _javaObjectForIBinder = reinterpret_cast<javaObjectForIBinder_t>(
+ dlsym(handle,
+ "_ZN7android20javaObjectForIBinderEP7_JNIEnvRKNS_2spINS_7IBinderEEE"));
+ if (_javaObjectForIBinder == nullptr) {
+ ALOGW("Could not find javaObjectForIBinder.");
+ // no return
+ }
+ });
+}
+
+} // namespace
+
+// exports delegate functions
+
+JNIEnv* AndroidRuntime::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);
+}
+
+jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) {
+ load();
+ if (_javaObjectForIBinder == nullptr) {
+ return nullptr;
+ }
+ return _javaObjectForIBinder(env, val);
+}
+
+} // namespace android
diff --git a/libs/android_runtime_lazy/include/android_runtime/AndroidRuntime.h b/libs/android_runtime_lazy/include/android_runtime/AndroidRuntime.h
new file mode 100644
index 0000000..85231fa
--- /dev/null
+++ b/libs/android_runtime_lazy/include/android_runtime/AndroidRuntime.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "jni.h"
+
+namespace android {
+
+// Intentionally use the same name with AndroidRuntime in frameworks/base/core/jni/
+// to make the client use this in the same way with the original class.
+class AndroidRuntime {
+public:
+ static JNIEnv* getJNIEnv();
+};
+
+} // namespace android
diff --git a/libs/android_runtime_lazy/include/android_util_Binder.h b/libs/android_runtime_lazy/include/android_util_Binder.h
new file mode 100644
index 0000000..e47390e
--- /dev/null
+++ b/libs/android_runtime_lazy/include/android_util_Binder.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/IBinder.h>
+#include "jni.h"
+
+namespace android {
+
+// The name of this file is same with the file in frameworks/base/core/jni/
+// This is intentional to make the client use these exported functions
+// in the same way with the original.
+
+jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);
+sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj);
+
+} // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index a96c9a0..21bef2e 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -39,17 +39,12 @@
],
shared_libs: [
+ "libandroid_runtime_lazy",
"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",
- ],
-
header_libs: [
"jni_headers",
],
diff --git a/libs/binder/ndk/ibinder_jni.cpp b/libs/binder/ndk/ibinder_jni.cpp
index 4a31080..d931785 100644
--- a/libs/binder/ndk/ibinder_jni.cpp
+++ b/libs/binder/ndk/ibinder_jni.cpp
@@ -17,69 +17,19 @@
#include <android/binder_ibinder_jni.h>
#include "ibinder_internal.h"
-#include <android-base/logging.h>
-#include <binder/IBinder.h>
-
-#include <mutex>
-
-#include <dlfcn.h>
+#include <android_util_Binder.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) {
if (binder == nullptr) {
return nullptr;
}
- LazyAndroidRuntime::load();
- if (LazyAndroidRuntime::ibinderForJavaObject == nullptr) {
- return nullptr;
- }
-
- sp<IBinder> ibinder = (LazyAndroidRuntime::ibinderForJavaObject)(env, binder);
-
+ sp<IBinder> ibinder = ibinderForJavaObject(env, binder);
sp<AIBinder> cbinder = ABpBinder::lookupOrCreateFromBinder(ibinder);
AIBinder_incStrong(cbinder.get());
@@ -91,10 +41,5 @@
return nullptr;
}
- LazyAndroidRuntime::load();
- if (LazyAndroidRuntime::javaObjectForIBinder == nullptr) {
- return nullptr;
- }
-
- return (LazyAndroidRuntime::javaObjectForIBinder)(env, binder->getBinder());
+ return javaObjectForIBinder(env, binder->getBinder());
}
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index b29b6e7..8cd4e03 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -41,7 +41,7 @@
name: "test_libbinder_ndk_test_defaults",
defaults: ["test_libbinder_ndk_defaults"],
shared_libs: [
- "libandroid_runtime",
+ "libandroid_runtime_lazy",
"libbase",
"libbinder",
"libutils",