Loading media/libmedia/Android.bp +13 −0 Original line number Diff line number Diff line Loading @@ -139,10 +139,18 @@ cc_library_static { }, } filegroup { name: "mediaupdateservice_aidl", srcs: [ "aidl/android/media/IMediaExtractorUpdateService.aidl", ], } cc_library_shared { name: "libmedia", srcs: [ ":mediaupdateservice_aidl", "IDataSource.cpp", "BufferingSettings.cpp", "mediaplayer.cpp", Loading Loading @@ -179,6 +187,11 @@ cc_library_shared { "StringArray.cpp", ], aidl: { local_include_dirs: ["aidl"], export_aidl_headers: true, }, shared_libs: [ "liblog", "libcutils", Loading media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl 0 → 100644 +25 −0 Original line number Diff line number Diff line /* * 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); } media/libstagefright/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,7 @@ cc_library_shared { "libRScpp", "libhidlbase", "libhidlmemory", "libziparchive", "android.hidl.allocator@1.0", "android.hardware.cas.native@1.0", "android.hardware.media.omx@1.0", Loading Loading @@ -211,6 +212,7 @@ cc_library_shared { "libmedia_helper", "libstagefright_foundation", "libdl", "libziparchive", ], static_libs: [ Loading media/libstagefright/InterfaceUtils.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -38,11 +38,12 @@ sp<IDataSource> CreateIDataSourceFromDataSource(const sp<DataSource> &source) { return RemoteDataSource::wrap(source); } sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(const sp<MediaExtractor> &extractor) { sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor( const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin) { if (extractor == nullptr) { return nullptr; } return RemoteMediaExtractor::wrap(extractor); return RemoteMediaExtractor::wrap(extractor, plugin); } sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source) { Loading @@ -52,11 +53,12 @@ sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source return new CallbackMediaSource(source); } sp<IMediaSource> CreateIMediaSourceFromMediaSource(const sp<MediaSource> &source) { sp<IMediaSource> CreateIMediaSourceFromMediaSource( const sp<MediaSource> &source, const sp<RefBase> &plugin) { if (source == nullptr) { return nullptr; } return RemoteMediaSource::wrap(source); return RemoteMediaSource::wrap(source, plugin); } } // namespace android media/libstagefright/MediaExtractorFactory.cpp +115 −69 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ */ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaExtractor" #define LOG_TAG "MediaExtractorFactory" #include <utils/Log.h> #include <binder/IServiceManager.h> Loading @@ -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) { Loading @@ -45,8 +48,7 @@ sp<IMediaExtractor> MediaExtractorFactory::Create( if (!property_get_bool("media.stagefright.extractremote", true)) { // local extractor ALOGW("creating media extractor in calling process"); sp<MediaExtractor> extractor = CreateFromService(source, mime); return CreateIMediaExtractorFromMediaExtractor(extractor); return CreateFromService(source, mime); } else { // remote extractor ALOGV("get service manager"); Loading Loading @@ -103,11 +105,12 @@ sp<IMediaExtractor> MediaExtractorFactory::CreateFromFd( return Create(*out, mime); } sp<MediaExtractor> MediaExtractorFactory::CreateFromService( sp<IMediaExtractor> MediaExtractorFactory::CreateFromService( const sp<DataSource> &source, const char *mime) { ALOGV("MediaExtractorFactory::%s %s", __func__, mime); RegisterDefaultSniffers(); ALOGV("MediaExtractorFactory::CreateFromService %s", mime); UpdateExtractors(nullptr); // initialize source decryption if needed source->DrmInitialization(nullptr /* mime */); Loading @@ -117,7 +120,8 @@ sp<MediaExtractor> MediaExtractorFactory::CreateFromService( MediaExtractor::CreatorFunc creator = NULL; String8 tmp; float confidence; creator = sniff(source, &tmp, &confidence, &meta); sp<ExtractorPlugin> plugin; creator = sniff(source, &tmp, &confidence, &meta, plugin); if (!creator) { ALOGV("FAILED to autodetect media content."); return NULL; Loading @@ -128,39 +132,64 @@ sp<MediaExtractor> MediaExtractorFactory::CreateFromService( mime, confidence); MediaExtractor *ret = creator(source, meta); return ret; return CreateIMediaExtractorFromMediaExtractor(ret, plugin); } Mutex MediaExtractorFactory::gSnifferMutex; List<MediaExtractor::ExtractorDef> MediaExtractorFactory::gSniffers; bool MediaExtractorFactory::gSniffersRegistered = false; //static 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 { MediaExtractor::ExtractorDef def; void *libHandle; String8 libPath; ExtractorPlugin(MediaExtractor::ExtractorDef definition, void *handle, String8 &path) : def(definition), libHandle(handle), libPath(path) { } ~ExtractorPlugin() { if (libHandle != nullptr) { ALOGV("closing handle for %s %d", libPath.c_str(), def.extractor_version); dlclose(libHandle); } } }; Mutex MediaExtractorFactory::gPluginMutex; std::shared_ptr<List<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins; bool MediaExtractorFactory::gPluginsRegistered = false; // static MediaExtractor::CreatorFunc MediaExtractorFactory::sniff( const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta) { const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta, sp<ExtractorPlugin> &plugin) { *mimeType = ""; *confidence = 0.0f; meta->clear(); std::shared_ptr<List<sp<ExtractorPlugin>>> plugins; { Mutex::Autolock autoLock(gSnifferMutex); if (!gSniffersRegistered) { Mutex::Autolock autoLock(gPluginMutex); if (!gPluginsRegistered) { return NULL; } plugins = gPlugins; } MediaExtractor::CreatorFunc curCreator = NULL; MediaExtractor::CreatorFunc bestCreator = NULL; for (List<MediaExtractor::ExtractorDef>::iterator it = gSniffers.begin(); it != gSniffers.end(); ++it) { for (auto it = plugins->begin(); it != plugins->end(); ++it) { String8 newMimeType; float newConfidence; sp<AMessage> newMeta; if ((curCreator = (*it).sniff(source, &newMimeType, &newConfidence, &newMeta))) { if ((curCreator = (*it)->def.sniff(source, &newMimeType, &newConfidence, &newMeta))) { if (newConfidence > *confidence) { *mimeType = newMimeType; *confidence = newConfidence; *meta = newMeta; plugin = *it; bestCreator = curCreator; } } Loading @@ -170,95 +199,112 @@ MediaExtractor::CreatorFunc MediaExtractorFactory::sniff( } // static void MediaExtractorFactory::RegisterSniffer_l(const MediaExtractor::ExtractorDef &def) { void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList) { // sanity check check struct version, uuid, name if (def.def_version == 0 || def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) { ALOGE("don't understand extractor format %u, ignoring.", def.def_version); if (plugin->def.def_version == 0 || plugin->def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) { ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version); return; } if (memcmp(&def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) { if (memcmp(&plugin->def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) { ALOGE("invalid UUID, ignoring"); return; } if (def.extractor_name == NULL || strlen(def.extractor_name) == 0) { if (plugin->def.extractor_name == NULL || strlen(plugin->def.extractor_name) == 0) { ALOGE("extractors should have a name, ignoring"); return; } for (List<MediaExtractor::ExtractorDef>::iterator it = gSniffers.begin(); it != gSniffers.end(); ++it) { if (memcmp(&((*it).extractor_uuid), &def.extractor_uuid, 16) == 0) { for (auto it = pluginList.begin(); it != pluginList.end(); ++it) { if (memcmp(&((*it)->def.extractor_uuid), &plugin->def.extractor_uuid, 16) == 0) { // there's already an extractor with the same uuid if ((*it).extractor_version < def.extractor_version) { if ((*it)->def.extractor_version < plugin->def.extractor_version) { // this one is newer, replace the old one ALOGW("replacing extractor '%s' version %u with version %u", def.extractor_name, (*it).extractor_version, def.extractor_version); gSniffers.erase(it); plugin->def.extractor_name, (*it)->def.extractor_version, plugin->def.extractor_version); pluginList.erase(it); break; } else { ALOGW("ignoring extractor '%s' version %u in favor of version %u", def.extractor_name, def.extractor_version, (*it).extractor_version); plugin->def.extractor_name, plugin->def.extractor_version, (*it)->def.extractor_version); return; } } } ALOGV("registering extractor for %s", def.extractor_name); gSniffers.push_back(def); ALOGV("registering extractor for %s", plugin->def.extractor_name); pluginList.push_back(plugin); } //static void MediaExtractorFactory::RegisterDefaultSniffers() { Mutex::Autolock autoLock(gSnifferMutex); if (gSniffersRegistered) { return; } auto registerExtractors = [](const char *libDirPath) -> void { DIR *libDir = opendir(libDirPath); if (libDir) { struct dirent* libEntry; while ((libEntry = readdir(libDir))) { String8 libPath = String8(libDirPath) + libEntry->d_name; void MediaExtractorFactory::RegisterExtractors( 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 getsniffer = MediaExtractor::GetExtractorDef getDef = (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF"); if (getsniffer) { if (getDef) { ALOGV("registering sniffer for %s", libPath.string()); RegisterSniffer_l(getsniffer()); RegisterExtractor( new ExtractorPlugin(getDef(), libHandle, libPath), pluginList); } else { ALOGW("%s does not contain sniffer", libPath.string()); dlclose(libHandle); } } else { ALOGW("couldn't dlopen(%s)", libPath.string()); ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno)); } } closedir(libDir); EndIteration(cookie); } else { ALOGE("couldn't opendir(%s)", libDirPath); ALOGW("couldn't find plugins from %s, %d", apkPath, ret); } CloseArchive(zipHandle); } else { ALOGW("couldn't open(%s) %d", apkPath, ret); } } }; registerExtractors("/system/lib" #ifdef __LP64__ "64" #endif "/extractors/"); // static void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) { Mutex::Autolock autoLock(gPluginMutex); if (newUpdateApkPath != nullptr) { gPluginsRegistered = false; } if (gPluginsRegistered) { return; } std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>()); registerExtractors("/vendor/lib" #ifdef __LP64__ "64" #endif "/extractors/"); RegisterExtractors(kUpdateApkPath, *newList); gSniffersRegistered = true; if (newUpdateApkPath != nullptr) { RegisterExtractors(newUpdateApkPath, *newList); } gPlugins = newList; gPluginsRegistered = true; } } // namespace android Loading
media/libmedia/Android.bp +13 −0 Original line number Diff line number Diff line Loading @@ -139,10 +139,18 @@ cc_library_static { }, } filegroup { name: "mediaupdateservice_aidl", srcs: [ "aidl/android/media/IMediaExtractorUpdateService.aidl", ], } cc_library_shared { name: "libmedia", srcs: [ ":mediaupdateservice_aidl", "IDataSource.cpp", "BufferingSettings.cpp", "mediaplayer.cpp", Loading Loading @@ -179,6 +187,11 @@ cc_library_shared { "StringArray.cpp", ], aidl: { local_include_dirs: ["aidl"], export_aidl_headers: true, }, shared_libs: [ "liblog", "libcutils", Loading
media/libmedia/aidl/android/media/IMediaExtractorUpdateService.aidl 0 → 100644 +25 −0 Original line number Diff line number Diff line /* * 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); }
media/libstagefright/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,7 @@ cc_library_shared { "libRScpp", "libhidlbase", "libhidlmemory", "libziparchive", "android.hidl.allocator@1.0", "android.hardware.cas.native@1.0", "android.hardware.media.omx@1.0", Loading Loading @@ -211,6 +212,7 @@ cc_library_shared { "libmedia_helper", "libstagefright_foundation", "libdl", "libziparchive", ], static_libs: [ Loading
media/libstagefright/InterfaceUtils.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -38,11 +38,12 @@ sp<IDataSource> CreateIDataSourceFromDataSource(const sp<DataSource> &source) { return RemoteDataSource::wrap(source); } sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(const sp<MediaExtractor> &extractor) { sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor( const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin) { if (extractor == nullptr) { return nullptr; } return RemoteMediaExtractor::wrap(extractor); return RemoteMediaExtractor::wrap(extractor, plugin); } sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source) { Loading @@ -52,11 +53,12 @@ sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source return new CallbackMediaSource(source); } sp<IMediaSource> CreateIMediaSourceFromMediaSource(const sp<MediaSource> &source) { sp<IMediaSource> CreateIMediaSourceFromMediaSource( const sp<MediaSource> &source, const sp<RefBase> &plugin) { if (source == nullptr) { return nullptr; } return RemoteMediaSource::wrap(source); return RemoteMediaSource::wrap(source, plugin); } } // namespace android
media/libstagefright/MediaExtractorFactory.cpp +115 −69 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ */ //#define LOG_NDEBUG 0 #define LOG_TAG "MediaExtractor" #define LOG_TAG "MediaExtractorFactory" #include <utils/Log.h> #include <binder/IServiceManager.h> Loading @@ -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) { Loading @@ -45,8 +48,7 @@ sp<IMediaExtractor> MediaExtractorFactory::Create( if (!property_get_bool("media.stagefright.extractremote", true)) { // local extractor ALOGW("creating media extractor in calling process"); sp<MediaExtractor> extractor = CreateFromService(source, mime); return CreateIMediaExtractorFromMediaExtractor(extractor); return CreateFromService(source, mime); } else { // remote extractor ALOGV("get service manager"); Loading Loading @@ -103,11 +105,12 @@ sp<IMediaExtractor> MediaExtractorFactory::CreateFromFd( return Create(*out, mime); } sp<MediaExtractor> MediaExtractorFactory::CreateFromService( sp<IMediaExtractor> MediaExtractorFactory::CreateFromService( const sp<DataSource> &source, const char *mime) { ALOGV("MediaExtractorFactory::%s %s", __func__, mime); RegisterDefaultSniffers(); ALOGV("MediaExtractorFactory::CreateFromService %s", mime); UpdateExtractors(nullptr); // initialize source decryption if needed source->DrmInitialization(nullptr /* mime */); Loading @@ -117,7 +120,8 @@ sp<MediaExtractor> MediaExtractorFactory::CreateFromService( MediaExtractor::CreatorFunc creator = NULL; String8 tmp; float confidence; creator = sniff(source, &tmp, &confidence, &meta); sp<ExtractorPlugin> plugin; creator = sniff(source, &tmp, &confidence, &meta, plugin); if (!creator) { ALOGV("FAILED to autodetect media content."); return NULL; Loading @@ -128,39 +132,64 @@ sp<MediaExtractor> MediaExtractorFactory::CreateFromService( mime, confidence); MediaExtractor *ret = creator(source, meta); return ret; return CreateIMediaExtractorFromMediaExtractor(ret, plugin); } Mutex MediaExtractorFactory::gSnifferMutex; List<MediaExtractor::ExtractorDef> MediaExtractorFactory::gSniffers; bool MediaExtractorFactory::gSniffersRegistered = false; //static 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 { MediaExtractor::ExtractorDef def; void *libHandle; String8 libPath; ExtractorPlugin(MediaExtractor::ExtractorDef definition, void *handle, String8 &path) : def(definition), libHandle(handle), libPath(path) { } ~ExtractorPlugin() { if (libHandle != nullptr) { ALOGV("closing handle for %s %d", libPath.c_str(), def.extractor_version); dlclose(libHandle); } } }; Mutex MediaExtractorFactory::gPluginMutex; std::shared_ptr<List<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins; bool MediaExtractorFactory::gPluginsRegistered = false; // static MediaExtractor::CreatorFunc MediaExtractorFactory::sniff( const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta) { const sp<DataSource> &source, String8 *mimeType, float *confidence, sp<AMessage> *meta, sp<ExtractorPlugin> &plugin) { *mimeType = ""; *confidence = 0.0f; meta->clear(); std::shared_ptr<List<sp<ExtractorPlugin>>> plugins; { Mutex::Autolock autoLock(gSnifferMutex); if (!gSniffersRegistered) { Mutex::Autolock autoLock(gPluginMutex); if (!gPluginsRegistered) { return NULL; } plugins = gPlugins; } MediaExtractor::CreatorFunc curCreator = NULL; MediaExtractor::CreatorFunc bestCreator = NULL; for (List<MediaExtractor::ExtractorDef>::iterator it = gSniffers.begin(); it != gSniffers.end(); ++it) { for (auto it = plugins->begin(); it != plugins->end(); ++it) { String8 newMimeType; float newConfidence; sp<AMessage> newMeta; if ((curCreator = (*it).sniff(source, &newMimeType, &newConfidence, &newMeta))) { if ((curCreator = (*it)->def.sniff(source, &newMimeType, &newConfidence, &newMeta))) { if (newConfidence > *confidence) { *mimeType = newMimeType; *confidence = newConfidence; *meta = newMeta; plugin = *it; bestCreator = curCreator; } } Loading @@ -170,95 +199,112 @@ MediaExtractor::CreatorFunc MediaExtractorFactory::sniff( } // static void MediaExtractorFactory::RegisterSniffer_l(const MediaExtractor::ExtractorDef &def) { void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin, List<sp<ExtractorPlugin>> &pluginList) { // sanity check check struct version, uuid, name if (def.def_version == 0 || def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) { ALOGE("don't understand extractor format %u, ignoring.", def.def_version); if (plugin->def.def_version == 0 || plugin->def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) { ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version); return; } if (memcmp(&def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) { if (memcmp(&plugin->def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) { ALOGE("invalid UUID, ignoring"); return; } if (def.extractor_name == NULL || strlen(def.extractor_name) == 0) { if (plugin->def.extractor_name == NULL || strlen(plugin->def.extractor_name) == 0) { ALOGE("extractors should have a name, ignoring"); return; } for (List<MediaExtractor::ExtractorDef>::iterator it = gSniffers.begin(); it != gSniffers.end(); ++it) { if (memcmp(&((*it).extractor_uuid), &def.extractor_uuid, 16) == 0) { for (auto it = pluginList.begin(); it != pluginList.end(); ++it) { if (memcmp(&((*it)->def.extractor_uuid), &plugin->def.extractor_uuid, 16) == 0) { // there's already an extractor with the same uuid if ((*it).extractor_version < def.extractor_version) { if ((*it)->def.extractor_version < plugin->def.extractor_version) { // this one is newer, replace the old one ALOGW("replacing extractor '%s' version %u with version %u", def.extractor_name, (*it).extractor_version, def.extractor_version); gSniffers.erase(it); plugin->def.extractor_name, (*it)->def.extractor_version, plugin->def.extractor_version); pluginList.erase(it); break; } else { ALOGW("ignoring extractor '%s' version %u in favor of version %u", def.extractor_name, def.extractor_version, (*it).extractor_version); plugin->def.extractor_name, plugin->def.extractor_version, (*it)->def.extractor_version); return; } } } ALOGV("registering extractor for %s", def.extractor_name); gSniffers.push_back(def); ALOGV("registering extractor for %s", plugin->def.extractor_name); pluginList.push_back(plugin); } //static void MediaExtractorFactory::RegisterDefaultSniffers() { Mutex::Autolock autoLock(gSnifferMutex); if (gSniffersRegistered) { return; } auto registerExtractors = [](const char *libDirPath) -> void { DIR *libDir = opendir(libDirPath); if (libDir) { struct dirent* libEntry; while ((libEntry = readdir(libDir))) { String8 libPath = String8(libDirPath) + libEntry->d_name; void MediaExtractorFactory::RegisterExtractors( 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 getsniffer = MediaExtractor::GetExtractorDef getDef = (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF"); if (getsniffer) { if (getDef) { ALOGV("registering sniffer for %s", libPath.string()); RegisterSniffer_l(getsniffer()); RegisterExtractor( new ExtractorPlugin(getDef(), libHandle, libPath), pluginList); } else { ALOGW("%s does not contain sniffer", libPath.string()); dlclose(libHandle); } } else { ALOGW("couldn't dlopen(%s)", libPath.string()); ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno)); } } closedir(libDir); EndIteration(cookie); } else { ALOGE("couldn't opendir(%s)", libDirPath); ALOGW("couldn't find plugins from %s, %d", apkPath, ret); } CloseArchive(zipHandle); } else { ALOGW("couldn't open(%s) %d", apkPath, ret); } } }; registerExtractors("/system/lib" #ifdef __LP64__ "64" #endif "/extractors/"); // static void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) { Mutex::Autolock autoLock(gPluginMutex); if (newUpdateApkPath != nullptr) { gPluginsRegistered = false; } if (gPluginsRegistered) { return; } std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>()); registerExtractors("/vendor/lib" #ifdef __LP64__ "64" #endif "/extractors/"); RegisterExtractors(kUpdateApkPath, *newList); gSniffersRegistered = true; if (newUpdateApkPath != nullptr) { RegisterExtractors(newUpdateApkPath, *newList); } gPlugins = newList; gPluginsRegistered = true; } } // namespace android