Load extractor libs directly from update APK
Test: play MP4 file. install and uninstall media update apk.
Bug: 67908547
Change-Id: I80c7772e25ba010be468834ce238f0fb86bc8d14
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 0b4fd25..3c9bfdd 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -139,10 +139,18 @@
},
}
+filegroup {
+ name: "mediaupdateservice_aidl",
+ srcs: [
+ "aidl/android/media/IMediaExtractorUpdateService.aidl",
+ ],
+}
+
cc_library_shared {
name: "libmedia",
srcs: [
+ ":mediaupdateservice_aidl",
"IDataSource.cpp",
"BufferingSettings.cpp",
"mediaplayer.cpp",
@@ -179,6 +187,11 @@
"StringArray.cpp",
],
+ aidl: {
+ local_include_dirs: ["aidl"],
+ export_aidl_headers: true,
+ },
+
shared_libs: [
"liblog",
"libcutils",
diff --git a/media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl b/media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl
new file mode 100644
index 0000000..57b1bc9
--- /dev/null
+++ b/media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 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.
+ */
+
+package android.media;
+
+/**
+ * Service to reload extractor plugins when update package is installed/uninstalled.
+ * @hide
+ */
+interface IMediaExtractorUpdateService {
+ void loadPlugins(@utf8InCpp String apkPath);
+}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 26de4ca..95e3721 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -112,6 +112,7 @@
"libRScpp",
"libhidlbase",
"libhidlmemory",
+ "libziparchive",
"android.hidl.allocator@1.0",
"android.hardware.cas.native@1.0",
"android.hardware.media.omx@1.0",
@@ -215,6 +216,7 @@
"libmedia_helper",
"libstagefright_foundation",
"libdl",
+ "libziparchive",
],
static_libs: [
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 4ca2d0d..2ade598 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -31,12 +31,15 @@
#include <media/IMediaExtractorService.h>
#include <cutils/properties.h>
#include <utils/String8.h>
+#include <ziparchive/zip_archive.h>
#include <dirent.h>
#include <dlfcn.h>
namespace android {
+static const char *kUpdateApkPath = "/system/priv-app/MediaUpdate/MediaUpdate.apk";
+
// static
sp<IMediaExtractor> MediaExtractorFactory::Create(
const sp<DataSource> &source, const char *mime) {
@@ -106,6 +109,7 @@
const sp<DataSource> &source, const char *mime) {
ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
+
UpdateExtractors(nullptr);
// initialize source decryption if needed
@@ -132,9 +136,10 @@
}
//static
-void MediaExtractorFactory::LoadPlugins(const ::std::string& libraryPath) {
- ALOGV("Load plugins from: %s", libraryPath.c_str());
- UpdateExtractors(libraryPath.c_str());
+void MediaExtractorFactory::LoadPlugins(const ::std::string& apkPath) {
+ // TODO: Verify apk path with package manager in extractor process.
+ ALOGV("Load plugins from: %s", apkPath.c_str());
+ UpdateExtractors(apkPath.empty() ? nullptr : apkPath.c_str());
}
struct ExtractorPlugin : public RefBase {
@@ -237,40 +242,53 @@
//static
void MediaExtractorFactory::RegisterExtractors(
- const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList) {
- ALOGV("search for plugins at %s", libDirPath);
- DIR *libDir = opendir(libDirPath);
- if (libDir) {
- struct dirent* libEntry;
- while ((libEntry = readdir(libDir))) {
- String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
- void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
- if (libHandle) {
- MediaExtractor::GetExtractorDef getDef =
- (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
- if (getDef) {
- ALOGV("registering sniffer for %s", libPath.string());
- RegisterExtractor(
- new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+ const char *apkPath, List<sp<ExtractorPlugin>> &pluginList) {
+ ALOGV("search for plugins at %s", apkPath);
+ ZipArchiveHandle zipHandle;
+ int32_t ret = OpenArchive(apkPath, &zipHandle);
+ if (ret == 0) {
+ char abi[PROPERTY_VALUE_MAX];
+ property_get("ro.product.cpu.abi", abi, "arm64-v8a");
+ ZipString prefix(String8::format("lib/%s/", abi).c_str());
+ ZipString suffix("extractor.so");
+ void* cookie;
+ ret = StartIteration(zipHandle, &cookie, &prefix, &suffix);
+ if (ret == 0) {
+ ZipEntry entry;
+ ZipString name;
+ while (Next(cookie, &entry, &name) == 0) {
+ String8 libPath = String8(apkPath) + "!/" +
+ String8(reinterpret_cast<const char*>(name.name), name.name_length);
+ void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
+ if (libHandle) {
+ MediaExtractor::GetExtractorDef getDef =
+ (MediaExtractor::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("%s does not contain sniffer", libPath.string());
- dlclose(libHandle);
+ ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
}
- } else {
- ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
}
+ EndIteration(cookie);
+ } else {
+ ALOGW("couldn't find plugins from %s, %d", apkPath, ret);
}
-
- closedir(libDir);
+ CloseArchive(zipHandle);
} else {
- ALOGE("couldn't opendir(%s)", libDirPath);
+ ALOGW("couldn't open(%s) %d", apkPath, ret);
}
}
// static
-void MediaExtractorFactory::UpdateExtractors(const char *newlyInstalledLibPath) {
+void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
Mutex::Autolock autoLock(gPluginMutex);
- if (newlyInstalledLibPath != nullptr) {
+ if (newUpdateApkPath != nullptr) {
gPluginsRegistered = false;
}
if (gPluginsRegistered) {
@@ -279,20 +297,10 @@
std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>());
- RegisterExtractors("/system/lib"
-#ifdef __LP64__
- "64"
-#endif
- "/extractors", *newList);
+ RegisterExtractors(kUpdateApkPath, *newList);
- RegisterExtractors("/vendor/lib"
-#ifdef __LP64__
- "64"
-#endif
- "/extractors", *newList);
-
- if (newlyInstalledLibPath != nullptr) {
- RegisterExtractors(newlyInstalledLibPath, *newList);
+ if (newUpdateApkPath != nullptr) {
+ RegisterExtractors(newUpdateApkPath, *newList);
}
gPlugins = newList;
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 0a9514a..7fddf80 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -40,6 +40,7 @@
int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out);
static sp<IMediaExtractor> CreateFromService(
const sp<DataSource> &source, const char *mime = NULL);
+ static void LoadPlugins(const ::std::string& apkPath);
private:
static Mutex gPluginMutex;
@@ -47,7 +48,7 @@
static bool gPluginsRegistered;
static void RegisterExtractors(
- const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList);
+ const char *apkPath, List<sp<ExtractorPlugin>> &pluginList);
static void RegisterExtractor(
const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList);
@@ -55,7 +56,7 @@
String8 *mimeType, float *confidence, sp<AMessage> *meta,
sp<ExtractorPlugin> &plugin);
- static void UpdateExtractors(const char *newlyInstalledLibPath);
+ static void UpdateExtractors(const char *newUpdateApkPath);
};
} // namespace android