1d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang/*
2d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * Copyright (C) 2017 The Android Open Source Project
3d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *
4d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * Licensed under the Apache License, Version 2.0 (the "License");
5d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * you may not use this file except in compliance with the License.
6d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * You may obtain a copy of the License at
7d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *
8d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *      http://www.apache.org/licenses/LICENSE-2.0
9d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang *
10d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * Unless required by applicable law or agreed to in writing, software
11d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * distributed under the License is distributed on an "AS IS" BASIS,
12d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * See the License for the specific language governing permissions and
14d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang * limitations under the License.
15d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang */
16d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
17d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang//#define LOG_NDEBUG 0
185e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang#define LOG_TAG "MediaExtractorFactory"
19d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <utils/Log.h>
20d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
21d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <binder/IServiceManager.h>
22d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/DataSource.h>
23d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaAnalyticsItem.h>
24d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaExtractor.h>
25d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/foundation/AMessage.h>
26d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/InterfaceUtils.h>
27d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/MediaExtractorFactory.h>
28d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/IMediaExtractor.h>
29d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/IMediaExtractorService.h>
30d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <cutils/properties.h>
31d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <utils/String8.h>
323e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang#include <ziparchive/zip_archive.h>
33d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
34d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <dirent.h>
35d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <dlfcn.h>
36d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
37d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kangnamespace android {
38d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
39d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang// static
40d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kangsp<IMediaExtractor> MediaExtractorFactory::Create(
41d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        const sp<DataSource> &source, const char *mime) {
426969da62b068aff2aee650d57590532f8fc8de69Dongwon Kang    ALOGV("MediaExtractorFactory::Create %s", mime);
43d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
44d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    if (!property_get_bool("media.stagefright.extractremote", true)) {
45d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        // local extractor
46d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        ALOGW("creating media extractor in calling process");
475e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        return CreateFromService(source, mime);
48d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    } else {
49d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        // remote extractor
50d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        ALOGV("get service manager");
51d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
52d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
53d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        if (binder != 0) {
54d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
55d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            sp<IMediaExtractor> ex = mediaExService->makeExtractor(
56d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                    CreateIDataSourceFromDataSource(source), mime);
57d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            return ex;
58d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        } else {
59d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            ALOGE("extractor service not running");
60d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            return NULL;
61d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        }
62d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
63d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    return NULL;
64d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang}
65d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
665e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangsp<IMediaExtractor> MediaExtractorFactory::CreateFromService(
67d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        const sp<DataSource> &source, const char *mime) {
68d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
695e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
703e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang
715e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    UpdateExtractors(nullptr);
72d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
73d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    // initialize source decryption if needed
74d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    source->DrmInitialization(nullptr /* mime */);
75d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
7617e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    void *meta = nullptr;
77d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    MediaExtractor::CreatorFunc creator = NULL;
7817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    MediaExtractor::FreeMetaFunc freeMeta = nullptr;
79d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    float confidence;
805e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    sp<ExtractorPlugin> plugin;
8117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    creator = sniff(source.get(), &confidence, &meta, &freeMeta, plugin);
82d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    if (!creator) {
83d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        ALOGV("FAILED to autodetect media content.");
84d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        return NULL;
85d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
86d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
872a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    MediaExtractor *ret = creator(source.get(), meta);
8817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    if (meta != nullptr && freeMeta != nullptr) {
8917e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        freeMeta(meta);
9017e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    }
9117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang
9217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    ALOGV("Created an extractor '%s' with confidence %.2f",
9317e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang         ret != nullptr ? ret->name() : "<null>", confidence);
9417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang
952a243f08193fe9ff1afe018e9953f01c44ced9deMarco Nelissen    return CreateIMediaExtractorFromMediaExtractor(ret, source, plugin);
96d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang}
97d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
985e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang//static
993e6d245e154f8a382fd88529c2572d1117685511Dongwon Kangvoid MediaExtractorFactory::LoadPlugins(const ::std::string& apkPath) {
1003e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    // TODO: Verify apk path with package manager in extractor process.
1013e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    ALOGV("Load plugins from: %s", apkPath.c_str());
1023e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    UpdateExtractors(apkPath.empty() ? nullptr : apkPath.c_str());
1035e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang}
1045e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang
1055e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangstruct ExtractorPlugin : public RefBase {
1065e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    MediaExtractor::ExtractorDef def;
1075e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    void *libHandle;
1085e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    String8 libPath;
109c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    String8 uuidString;
1105e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang
1115e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    ExtractorPlugin(MediaExtractor::ExtractorDef definition, void *handle, String8 &path)
112c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen        : def(definition), libHandle(handle), libPath(path) {
113c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen        for (size_t i = 0; i < sizeof MediaExtractor::ExtractorDef::extractor_uuid; i++) {
114c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen            uuidString.appendFormat("%02x", def.extractor_uuid.b[i]);
115c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen        }
116c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    }
1175e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    ~ExtractorPlugin() {
1185e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        if (libHandle != nullptr) {
1195e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang            ALOGV("closing handle for %s %d", libPath.c_str(), def.extractor_version);
1205e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang            dlclose(libHandle);
1215e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        }
1225e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    }
1235e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang};
1245e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang
1255e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon KangMutex MediaExtractorFactory::gPluginMutex;
1265e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangstd::shared_ptr<List<sp<ExtractorPlugin>>> MediaExtractorFactory::gPlugins;
1275e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangbool MediaExtractorFactory::gPluginsRegistered = false;
128d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
129d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang// static
130d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon KangMediaExtractor::CreatorFunc MediaExtractorFactory::sniff(
13117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        DataSourceBase *source, float *confidence, void **meta,
13217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        MediaExtractor::FreeMetaFunc *freeMeta, sp<ExtractorPlugin> &plugin) {
133d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    *confidence = 0.0f;
13417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang    *meta = nullptr;
135d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
1365e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    std::shared_ptr<List<sp<ExtractorPlugin>>> plugins;
137d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    {
1385e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        Mutex::Autolock autoLock(gPluginMutex);
1395e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        if (!gPluginsRegistered) {
140d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            return NULL;
141d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        }
1425e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        plugins = gPlugins;
143d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
144d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
145d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    MediaExtractor::CreatorFunc curCreator = NULL;
146d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    MediaExtractor::CreatorFunc bestCreator = NULL;
1475e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    for (auto it = plugins->begin(); it != plugins->end(); ++it) {
148d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        float newConfidence;
14917e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        void *newMeta = nullptr;
15017e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        MediaExtractor::FreeMetaFunc newFreeMeta = nullptr;
15117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang        if ((curCreator = (*it)->def.sniff(source, &newConfidence, &newMeta, &newFreeMeta))) {
152d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            if (newConfidence > *confidence) {
153d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                *confidence = newConfidence;
15417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                if (*meta != nullptr && *freeMeta != nullptr) {
15517e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                    (*freeMeta)(*meta);
15617e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                }
157d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                *meta = newMeta;
15817e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                *freeMeta = newFreeMeta;
1595e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                plugin = *it;
160d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                bestCreator = curCreator;
16117e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang            } else {
16217e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                if (newMeta != nullptr && newFreeMeta != nullptr) {
16317e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                    newFreeMeta(newMeta);
16417e172b4c3c87ecaa7c87eecc42b4dc47e3e9734Dongwon Kang                }
165d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            }
166d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        }
167d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
168d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
169d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    return bestCreator;
170d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang}
171d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
172d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang// static
1735e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kangvoid MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,
1745e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        List<sp<ExtractorPlugin>> &pluginList) {
175d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    // sanity check check struct version, uuid, name
1765e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    if (plugin->def.def_version == 0
1775e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang            || plugin->def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) {
1785e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
179d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        return;
180d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
1815e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    if (memcmp(&plugin->def.extractor_uuid, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) {
182d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        ALOGE("invalid UUID, ignoring");
183d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        return;
184d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
1855e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    if (plugin->def.extractor_name == NULL || strlen(plugin->def.extractor_name) == 0) {
186d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        ALOGE("extractors should have a name, ignoring");
187d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        return;
188d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
189d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
1905e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    for (auto it = pluginList.begin(); it != pluginList.end(); ++it) {
1915e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        if (memcmp(&((*it)->def.extractor_uuid), &plugin->def.extractor_uuid, 16) == 0) {
192d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            // there's already an extractor with the same uuid
1935e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang            if ((*it)->def.extractor_version < plugin->def.extractor_version) {
194d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                // this one is newer, replace the old one
195d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                ALOGW("replacing extractor '%s' version %u with version %u",
1965e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                        plugin->def.extractor_name,
1975e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                        (*it)->def.extractor_version,
1985e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                        plugin->def.extractor_version);
1995e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                pluginList.erase(it);
200d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                break;
201d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            } else {
202d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                ALOGW("ignoring extractor '%s' version %u in favor of version %u",
2035e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                        plugin->def.extractor_name,
2045e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                        plugin->def.extractor_version,
2055e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang                        (*it)->def.extractor_version);
206d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                return;
207d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            }
208d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        }
209d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang    }
2105e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    ALOGV("registering extractor for %s", plugin->def.extractor_name);
2115e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    pluginList.push_back(plugin);
212d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang}
213d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
2145e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang//static
215767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kangvoid MediaExtractorFactory::RegisterExtractorsInApk(
2163e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        const char *apkPath, List<sp<ExtractorPlugin>> &pluginList) {
2173e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    ALOGV("search for plugins at %s", apkPath);
2183e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    ZipArchiveHandle zipHandle;
2193e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    int32_t ret = OpenArchive(apkPath, &zipHandle);
2203e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    if (ret == 0) {
2213e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        char abi[PROPERTY_VALUE_MAX];
2223e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        property_get("ro.product.cpu.abi", abi, "arm64-v8a");
2232b22e7083877778100b7e25b375842b23d14e701Andreas Gampe        String8 prefix8 = String8::format("lib/%s/", abi);
2242b22e7083877778100b7e25b375842b23d14e701Andreas Gampe        ZipString prefix(prefix8.c_str());
2253e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        ZipString suffix("extractor.so");
2263e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        void* cookie;
2273e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        ret = StartIteration(zipHandle, &cookie, &prefix, &suffix);
2283e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        if (ret == 0) {
2293e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang            ZipEntry entry;
2303e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang            ZipString name;
2313e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang            while (Next(cookie, &entry, &name) == 0) {
2323e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                String8 libPath = String8(apkPath) + "!/" +
2333e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                    String8(reinterpret_cast<const char*>(name.name), name.name_length);
234767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                // TODO: Open with a linker namespace so that it can be linked with sub-libraries
235767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                // within the apk instead of system libraries already loaded.
2363e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
2373e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                if (libHandle) {
2383e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                    MediaExtractor::GetExtractorDef getDef =
2393e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                        (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
2403e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                    if (getDef) {
2413e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                        ALOGV("registering sniffer for %s", libPath.string());
2423e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                        RegisterExtractor(
2433e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                                new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
2443e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                    } else {
2453e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                        ALOGW("%s does not contain sniffer", libPath.string());
2463e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                        dlclose(libHandle);
2473e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                    }
248d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                } else {
2493e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang                    ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
250d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang                }
251d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang            }
2523e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang            EndIteration(cookie);
2533e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        } else {
2543e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang            ALOGW("couldn't find plugins from %s, %d", apkPath, ret);
255d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang        }
2563e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        CloseArchive(zipHandle);
2575e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    } else {
2583e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang        ALOGW("couldn't open(%s) %d", apkPath, ret);
2595e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    }
2605e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang}
2615e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang
262767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang//static
263767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kangvoid MediaExtractorFactory::RegisterExtractorsInSystem(
264767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        const char *libDirPath, List<sp<ExtractorPlugin>> &pluginList) {
265767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    ALOGV("search for plugins at %s", libDirPath);
266767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    DIR *libDir = opendir(libDirPath);
267767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    if (libDir) {
268767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        struct dirent* libEntry;
269767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        while ((libEntry = readdir(libDir))) {
270767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
271767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
272767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            if (libHandle) {
273767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                MediaExtractor::GetExtractorDef getDef =
274767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                    (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
275767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                if (getDef) {
276767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                    ALOGV("registering sniffer for %s", libPath.string());
277767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                    RegisterExtractor(
278767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                            new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
279767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                } else {
280767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                    ALOGW("%s does not contain sniffer", libPath.string());
281767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                    dlclose(libHandle);
282767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                }
283767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            } else {
284767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang                ALOGW("couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
285767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            }
286767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        }
287767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang
288767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        closedir(libDir);
289767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    } else {
290767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        ALOGE("couldn't opendir(%s)", libDirPath);
291767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    }
292767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang}
293767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang
2945e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang// static
2953e6d245e154f8a382fd88529c2572d1117685511Dongwon Kangvoid MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
2965e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    Mutex::Autolock autoLock(gPluginMutex);
2973e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    if (newUpdateApkPath != nullptr) {
2985e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        gPluginsRegistered = false;
2995e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    }
3005e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    if (gPluginsRegistered) {
3015e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang        return;
3025e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    }
3035e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang
3045e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    std::shared_ptr<List<sp<ExtractorPlugin>>> newList(new List<sp<ExtractorPlugin>>());
3055e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang
306767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    RegisterExtractorsInSystem("/system/lib"
307767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#ifdef __LP64__
308767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            "64"
309767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#endif
310767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            "/extractors", *newList);
311767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang
312767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang    RegisterExtractorsInSystem("/vendor/lib"
313767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#ifdef __LP64__
314767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            "64"
315767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang#endif
316767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang            "/extractors", *newList);
317d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
3183e6d245e154f8a382fd88529c2572d1117685511Dongwon Kang    if (newUpdateApkPath != nullptr) {
319767456dfce275fbe2d0bea227c271fcbd4c5be19Dongwon Kang        RegisterExtractorsInApk(newUpdateApkPath, *newList);
3205e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    }
321d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
3225e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    gPlugins = newList;
3235e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang    gPluginsRegistered = true;
3245e1897bbd25d8353d9567b746ce50d4b80d30564Dongwon Kang}
325d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang
326c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissenstatus_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
327c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    Mutex::Autolock autoLock(gPluginMutex);
328c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    String8 out;
329c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    out.append("Available extractors:\n");
330f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen    if (gPluginsRegistered) {
331f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen        for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
332f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen            out.appendFormat("  %25s: uuid(%s), version(%u), path(%s)\n",
333f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen                    (*it)->def.extractor_name,
334f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen                    (*it)->uuidString.c_str(),
335f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen                    (*it)->def.extractor_version,
336f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen                    (*it)->libPath.c_str());
337f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen        }
338f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen    } else {
339f3b8a779fae3ce135ef066a9ddddba77c07a8caeMarco Nelissen        out.append("  (no plugins registered)\n");
340c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    }
341c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    write(fd, out.string(), out.size());
342c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen    return OK;
343c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen}
344c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen
345c96ca4397cca129afd6b111f61f98dcfc2c1e3a7Marco Nelissen
346d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang}  // namespace android
347