mediaextractor: load extractor plug-ins from apex
Note: media apex is not added in the default build.
The new code path will be no-op for now.
Test: boot & adb shell dumpsys media.extractor
Bug: 112766843
Change-Id: I1bdf2c41cc5f88c80c2fd20677dce1d58420e947
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 1f8ccb3..81fc4ae 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "MediaExtractorFactory"
#include <utils/Log.h>
+#include <android/dlext.h>
#include <binder/IPCThreadState.h>
#include <binder/PermissionCache.h>
#include <binder/IServiceManager.h>
@@ -36,6 +37,23 @@
#include <dirent.h>
#include <dlfcn.h>
+// Copied from GraphicsEnv.cpp
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+ 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,
+ };
+}
+
namespace android {
// static
@@ -145,6 +163,13 @@
std::shared_ptr<std::list<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins;
bool MediaExtractorFactory::gPluginsRegistered = false;
bool MediaExtractorFactory::gIgnoreVersion = false;
+std::string MediaExtractorFactory::gLinkedLibraries;
+
+// static
+void MediaExtractorFactory::SetLinkedLibraries(const std::string& linkedLibraries) {
+ Mutex::Autolock autoLock(gPluginMutex);
+ gLinkedLibraries = linkedLibraries;
+}
// static
void *MediaExtractorFactory::sniff(
@@ -328,6 +353,62 @@
}
}
+//static
+void MediaExtractorFactory::RegisterExtractorsInApex(
+ const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList) {
+ ALOGV("search for plugins at %s", libDirPath);
+ ALOGV("linked libs %s", gLinkedLibraries.c_str());
+
+ android_namespace_t *extractorNs = android_create_namespace("extractor",
+ nullptr, // ld_library_path
+ libDirPath,
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr); // parent
+ if (!android_link_namespaces(extractorNs, nullptr, gLinkedLibraries.c_str())) {
+ ALOGE("Failed to link namespace. Failed to load extractor plug-ins in apex.");
+ return;
+ }
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = extractorNs,
+ };
+
+ DIR *libDir = opendir(libDirPath);
+ if (libDir) {
+ struct dirent* libEntry;
+ while ((libEntry = readdir(libDir))) {
+ if (libEntry->d_name[0] == '.') {
+ continue;
+ }
+ String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
+ if (!libPath.contains("extractor.so")) {
+ continue;
+ }
+ void *libHandle = android_dlopen_ext(
+ libPath.string(),
+ RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+ if (libHandle) {
+ GetExtractorDef getDef =
+ (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+ if (getDef) {
+ ALOGV("registering sniffer for %s", libPath.string());
+ RegisterExtractor(
+ new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+ } else {
+ ALOGW("%s does not contain sniffer", libPath.string());
+ dlclose(libHandle);
+ }
+ } else {
+ ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
+ }
+ }
+ closedir(libDir);
+ } else {
+ ALOGE("couldn't opendir(%s)", libDirPath);
+ }
+}
+
static bool compareFunc(const sp<ExtractorPlugin>& first, const sp<ExtractorPlugin>& second) {
return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
}
@@ -346,6 +427,12 @@
std::shared_ptr<std::list<sp<ExtractorPlugin>>> newList(new std::list<sp<ExtractorPlugin>>());
+ RegisterExtractorsInApex("/apex/com.android.media/lib"
+#ifdef __LP64__
+ "64"
+#endif
+ , *newList);
+
RegisterExtractorsInSystem("/system/lib"
#ifdef __LP64__
"64"
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index ef9f7ed..84e01f3 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -35,17 +35,21 @@
const sp<DataSource> &source, const char *mime = NULL);
static void LoadPlugins(const ::std::string& apkPath);
static status_t dump(int fd, const Vector<String16>& args);
+ static void SetLinkedLibraries(const std::string& linkedLibraries);
private:
static Mutex gPluginMutex;
static std::shared_ptr<std::list<sp<ExtractorPlugin>>> gPlugins;
static bool gPluginsRegistered;
static bool gIgnoreVersion;
+ static std::string gLinkedLibraries;
static void RegisterExtractorsInApk(
const char *apkPath, std::list<sp<ExtractorPlugin>> &pluginList);
static void RegisterExtractorsInSystem(
const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList);
+ static void RegisterExtractorsInApex(
+ const char *libDirPath, std::list<sp<ExtractorPlugin>> &pluginList);
static void RegisterExtractor(
const sp<ExtractorPlugin> &plugin, std::list<sp<ExtractorPlugin>> &pluginList);
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 73c9535..19ce7e9 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -9,6 +9,24 @@
LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
LOCAL_MODULE:= libmediaextractorservice
+
+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/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index f4d8b43..8b26178 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -29,6 +29,11 @@
namespace android {
+MediaExtractorService::MediaExtractorService()
+ : BnMediaExtractorService() {
+ MediaExtractorFactory::SetLinkedLibraries(std::string(LINKED_LIBRARIES));
+}
+
sp<IMediaExtractor> MediaExtractorService::makeExtractor(
const sp<IDataSource> &remoteSource, const char *mime) {
ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime);
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 9df3ecd..6007004 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -27,7 +27,7 @@
{
friend class BinderService<MediaExtractorService>; // for MediaExtractorService()
public:
- MediaExtractorService() : BnMediaExtractorService() { }
+ MediaExtractorService();
virtual ~MediaExtractorService() { }
virtual void onFirstRef() { }