Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e6d245e authored by Dongwon Kang's avatar Dongwon Kang
Browse files

Load extractor libs directly from update APK

Test: play MP4 file. install and uninstall media update apk.
Bug: 67908547
Change-Id: I80c7772e25ba010be468834ce238f0fb86bc8d14
parent 5e1897bb
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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",
@@ -179,6 +187,11 @@ cc_library_shared {
        "StringArray.cpp",
    ],

    aidl: {
        local_include_dirs: ["aidl"],
        export_aidl_headers: true,
    },

    shared_libs: [
        "liblog",
        "libcutils",
+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);
}
+2 −0
Original line number Diff line number Diff line
@@ -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",
@@ -215,6 +216,7 @@ cc_library_shared {
        "libmedia_helper",
        "libstagefright_foundation",
        "libdl",
        "libziparchive",
    ],

    static_libs: [
+48 −40
Original line number Diff line number Diff line
@@ -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 @@ sp<IMediaExtractor> MediaExtractorFactory::CreateFromService(
        const sp<DataSource> &source, const char *mime) {

    ALOGV("MediaExtractorFactory::CreateFromService %s", mime);

    UpdateExtractors(nullptr);

    // initialize source decryption if needed
@@ -132,9 +136,10 @@ sp<IMediaExtractor> MediaExtractorFactory::CreateFromService(
}

//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,13 +242,23 @@ void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,

//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;
        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 =
@@ -260,17 +275,20 @@ void MediaExtractorFactory::RegisterExtractors(
                    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);
    }
}

// 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 @@ void MediaExtractorFactory::UpdateExtractors(const char *newlyInstalledLibPath)

    std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>());

    RegisterExtractors("/system/lib"
#ifdef __LP64__
            "64"
#endif
            "/extractors", *newList);

    RegisterExtractors("/vendor/lib"
#ifdef __LP64__
            "64"
#endif
            "/extractors", *newList);
    RegisterExtractors(kUpdateApkPath, *newList);

    if (newlyInstalledLibPath != nullptr) {
        RegisterExtractors(newlyInstalledLibPath, *newList);
    if (newUpdateApkPath != nullptr) {
        RegisterExtractors(newUpdateApkPath, *newList);
    }

    gPlugins = newList;
+3 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ public:
            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 @@ private:
    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 @@ private:
            String8 *mimeType, float *confidence, sp<AMessage> *meta,
            sp<ExtractorPlugin> &plugin);

    static void UpdateExtractors(const char *newlyInstalledLibPath);
    static void UpdateExtractors(const char *newUpdateApkPath);
};

}  // namespace android
Loading