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
diff --git a/packages/MediaUpdate/Android.mk b/packages/MediaUpdate/Android.mk
index 4a71401..ec614f6 100644
--- a/packages/MediaUpdate/Android.mk
+++ b/packages/MediaUpdate/Android.mk
@@ -31,4 +31,22 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
+LOCAL_MULTILIB := first
+
+# Embed native libraries in package, rather than installing to /system/lib*.
+LOCAL_MODULE_TAGS := samples
+
+# To embed native libraries in package, uncomment the lines below.
+LOCAL_JNI_SHARED_LIBRARIES := \
+ libaacextractor \
+ libamrextractor \
+ libflacextractor \
+ libmidiextractor \
+ libmkvextractor \
+ libmp3extractor \
+ libmp4extractor \
+ libmpeg2extractor \
+ liboggextractor \
+ libwavextractor \
+
include $(BUILD_PACKAGE)
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index cd086f9..b6de7e3 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -2,8 +2,11 @@
# service library
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := MediaExtractorService.cpp
LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SRC_FILES := \
+ MediaExtractorService.cpp \
+ MediaExtractorUpdateService.cpp \
+
LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog
LOCAL_MODULE:= libmediaextractorservice
include $(BUILD_SHARED_LIBRARY)
@@ -18,16 +21,7 @@
# extractor libraries
LOCAL_REQUIRED_MODULES := \
- libaacextractor \
- libamrextractor \
- libflacextractor \
- libmidiextractor \
- libmkvextractor \
- libmp3extractor \
- libmp4extractor \
- libmpeg2extractor \
- liboggextractor \
- libwavextractor \
+ MediaUpdate \
LOCAL_SRC_FILES := main_extractorservice.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
diff --git a/services/mediaextractor/MediaExtractorUpdateService.cpp b/services/mediaextractor/MediaExtractorUpdateService.cpp
new file mode 100644
index 0000000..473a698
--- /dev/null
+++ b/services/mediaextractor/MediaExtractorUpdateService.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "MediaExtractorUpdateService"
+#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaExtractorFactory.h>
+
+#include "MediaExtractorUpdateService.h"
+
+namespace android {
+namespace media {
+
+binder::Status MediaExtractorUpdateService::loadPlugins(const ::std::string& apkPath) {
+ ALOGV("loadPlugins %s", apkPath.c_str());
+ MediaExtractorFactory::LoadPlugins(apkPath);
+ return binder::Status::ok();
+}
+
+} // namespace media
+} // namespace android
diff --git a/services/mediaextractor/MediaExtractorUpdateService.h b/services/mediaextractor/MediaExtractorUpdateService.h
new file mode 100644
index 0000000..4115f6d
--- /dev/null
+++ b/services/mediaextractor/MediaExtractorUpdateService.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_EXTRACTOR_UPDATE_SERVICE_H
+#define ANDROID_MEDIA_EXTRACTOR_UPDATE_SERVICE_H
+
+#include <binder/BinderService.h>
+#include <android/media/BnMediaExtractorUpdateService.h>
+
+namespace android {
+namespace media {
+
+class MediaExtractorUpdateService
+ : public BinderService<MediaExtractorUpdateService>, public BnMediaExtractorUpdateService
+{
+ friend class BinderService<MediaExtractorUpdateService>;
+public:
+ MediaExtractorUpdateService() : BnMediaExtractorUpdateService() { }
+ virtual ~MediaExtractorUpdateService() { }
+ static const char* getServiceName() { return "media.extractor.update"; }
+ binder::Status loadPlugins(const ::std::string& apkPath);
+};
+
+} // namespace media
+} // namespace android
+
+#endif // ANDROID_MEDIA_EXTRACTOR_UPDATE_SERVICE_H
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index 6a5320d..1069b09 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -30,6 +30,7 @@
// from LOCAL_C_INCLUDES
#include "IcuUtils.h"
#include "MediaExtractorService.h"
+#include "MediaExtractorUpdateService.h"
#include "MediaUtils.h"
#include "minijail.h"
@@ -63,6 +64,7 @@
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
MediaExtractorService::instantiate();
+ media::MediaExtractorUpdateService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}