Load MediaPlayer2 implementation with a linker namespace.
MediaPlayer2 calls System.loadLibrary(media2_jni) and
libmedia2_jni loads the MediaPlayer2 native implementation
in libmediaplayer2_jni with an isolated linker namespace.
Test: build & boot & atest MediaPlayer2Test
Bug: 112766913
Change-Id: I07c542da5ccb305f839cda488c9e83b43c98c9e1
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index d6b6339..ec20ca8 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -85,7 +85,7 @@
}
cc_library_shared {
- name: "libmedia2_jni",
+ name: "libmediaplayer2_jni",
srcs: [
"android_media_DataSourceCallback.cpp",
@@ -117,7 +117,10 @@
"libz",
],
- header_libs: ["libhardware_headers"],
+ header_libs: [
+ "libhardware_headers",
+ "libnativewindow_headers",
+ ],
static_libs: [
"libbase",
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
new file mode 100644
index 0000000..1d7d6de
--- /dev/null
+++ b/media/jni/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SRC_FILES := \
+ Media2Jni.cpp \
+
+# TODO: Move libmedia2_jni from system to media apex. Currently, libraries defined in
+# Android.mk is not visible in apex build.
+LOCAL_MODULE:= libmedia2_jni
+LOCAL_SHARED_LIBRARIES := libdl liblog
+
+sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
+ $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+ $(UBSAN_RUNTIME_LIBRARY) \
+ $(TSAN_RUNTIME_LIBRARY)))
+
+# $(info Sanitizer: $(sanitizer_runtime_libraries))
+
+ndk_libraries := $(call normalize-path-list,$(addprefix lib,$(addsuffix .so,\
+ $(NDK_PREBUILT_SHARED_LIBRARIES))))
+
+# $(info NDK: $(ndk_libraries))
+
+LOCAL_CFLAGS += -DLINKED_LIBRARIES='"$(sanitizer_runtime_libraries):$(ndk_libraries)"'
+
+sanitizer_runtime_libraries :=
+ndk_libraries :=
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/jni/Media2Jni.cpp b/media/jni/Media2Jni.cpp
new file mode 100644
index 0000000..6c0a65c
--- /dev/null
+++ b/media/jni/Media2Jni.cpp
@@ -0,0 +1,89 @@
+/*
+**
+** Copyright 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_NDEBUG 0
+#define LOG_TAG "MediaPlayer2-JNI"
+#include "utils/Log.h"
+
+#include "jni.h"
+#include <android/dlext.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+extern "C" {
+ // Copied from GraphicsEnv.cpp
+ // TODO(b/37049319) Get this from a header once one exists
+ android_namespace_t* android_create_namespace(const char* name,
+ const char* ld_library_path,
+ const char* default_library_path,
+ uint64_t type,
+ const char* permitted_when_isolated_path,
+ android_namespace_t* parent);
+ bool android_link_namespaces(android_namespace_t* from,
+ android_namespace_t* to,
+ const char* shared_libs_sonames);
+ enum {
+ ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+ };
+
+} // extern "C"
+
+static const char kApexLibPath[] = "/apex/com.android.media/lib"
+#ifdef __LP64__
+ "64"
+#endif
+ "/";
+static const char kMediaPlayer2LibPath[] = "/apex/com.android.media/lib"
+#ifdef __LP64__
+ "64"
+#endif
+ "/libmediaplayer2_jni.so";
+
+typedef jint (*Media2JniOnLoad)(JavaVM*, void*);
+
+JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+ android_namespace_t *media2Ns = android_create_namespace("media2",
+ nullptr, // ld_library_path
+ kApexLibPath,
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr); // parent
+ if (!android_link_namespaces(media2Ns, nullptr, LINKED_LIBRARIES)) {
+ ALOGE("Failed to link namespace. Failed to load extractor plug-ins in apex.");
+ return -1;
+ }
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = media2Ns,
+ };
+ // load libmediaplayer2_jni and call JNI_OnLoad.
+ void *libHandle = android_dlopen_ext(kMediaPlayer2LibPath, RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+ if (libHandle == NULL) {
+ ALOGW("couldn't dlopen(%s) %s", kMediaPlayer2LibPath, strerror(errno));
+ return -1;
+ }
+ Media2JniOnLoad media2JniOnLoad = (Media2JniOnLoad) dlsym(libHandle, "JNI_OnLoad");
+ if (!media2JniOnLoad) {
+ ALOGW("%s does not contain JNI_OnLoad()", kMediaPlayer2LibPath);
+ dlclose(libHandle);
+ return -1;
+ }
+ return media2JniOnLoad(vm, reserved);
+}