Decouple libstagefright from Codec 2.0

And load CCodec as a plugin.

Bug: 74403547
Test: adb shell am instrument -e size small -w 'android.media.cts/android.support.test.runner.AndroidJUnitRunner'
Test: adb shell setprop debug.stagefright.ccodec yes
Test: adb shell stagefright -S -N c2.google.avc.decoder /sdcard/a.mp4
Change-Id: I42f4a3d8dde0e1ae9fc2dbeab11be3dc3a8576fb
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 71bff84..e2d5d0d 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -56,6 +56,7 @@
     srcs: [
         "CodecBase.cpp",
         "FrameRenderTracker.cpp",
+        "MediaCodecListWriter.cpp",
     ],
 
     cflags: [
@@ -66,7 +67,7 @@
     shared_libs: [
         "libgui",
         "liblog",
-        "libmedia",
+        "libmedia_omx",
         "libstagefright_foundation",
         "libui",
         "libutils",
@@ -95,6 +96,7 @@
         "CCodec.cpp",
         "CCodecBufferChannel.cpp",
         "Codec2Buffer.cpp",
+        "Codec2InfoBuilder.cpp",
     ],
 
     cflags: [
@@ -120,8 +122,10 @@
         "libstagefright_codecbase",
         "libstagefright_foundation",
         "libstagefright_omx_utils",
+        "libstagefright_xmlparser",
         "libui",
         "libutils",
+        // TODO: Remove libv4l2_c2_componentstore.
         "libv4l2_c2componentstore",
         "android.hardware.cas.native@1.0",
 
@@ -154,7 +158,6 @@
         "AudioPresentationInfo.cpp",
         "AudioSource.cpp",
         "BufferImpl.cpp",
-        "Codec2InfoBuilder.cpp",
         "CallbackDataSource.cpp",
         "CallbackMediaSource.cpp",
         "CameraSource.cpp",
@@ -190,6 +193,7 @@
         "SkipCutBuffer.cpp",
         "StagefrightMediaScanner.cpp",
         "StagefrightMetadataRetriever.cpp",
+        "StagefrightPluginLoader.cpp",
         "SurfaceUtils.cpp",
         "Utils.cpp",
         "ThrottledSource.cpp",
@@ -217,8 +221,6 @@
         "libutils",
         "libmedia_helper",
         "libstagefright_ccodec",
-        "libstagefright_codec2",
-        "libstagefright_codec2_vndk",
         "libstagefright_codecbase",
         "libstagefright_foundation",
         "libstagefright_omx",
@@ -228,8 +230,6 @@
         "libhidlallocatorutils",
         "libhidlbase",
         "libhidlmemory",
-        // TODO: Remove libv4l2_c2_componentstore.
-        "libv4l2_c2componentstore",
         "libziparchive",
         "android.hidl.allocator@1.0",
         "android.hardware.cas.native@1.0",
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
index 0a20d34..322f9fd 100644
--- a/media/libstagefright/CCodec.cpp
+++ b/media/libstagefright/CCodec.cpp
@@ -910,3 +910,7 @@
 }
 
 }  // namespace android
+
+extern "C" android::CodecBase *CreateCodec() {
+    return new android::CCodec;
+}
diff --git a/media/libstagefright/Codec2InfoBuilder.cpp b/media/libstagefright/Codec2InfoBuilder.cpp
index 78c4e38..bd749c4 100644
--- a/media/libstagefright/Codec2InfoBuilder.cpp
+++ b/media/libstagefright/Codec2InfoBuilder.cpp
@@ -159,3 +159,7 @@
 }
 
 }  // namespace android
+
+extern "C" android::MediaCodecListBuilderBase *CreateBuilder() {
+    return new android::Codec2InfoBuilder;
+}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index edcb8c7..5ad4c01 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -16,11 +16,14 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaCodec"
+#include <utils/Log.h>
+
 #include <inttypes.h>
 
 #include "include/SecureBuffer.h"
 #include "include/SharedMemoryBuffer.h"
 #include "include/SoftwareRenderer.h"
+#include "StagefrightPluginLoader.h"
 
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 
@@ -45,7 +48,6 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/ACodec.h>
 #include <media/stagefright/BufferProducerWrapper.h>
-#include <media/stagefright/CCodec.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaDefs.h>
@@ -56,7 +58,6 @@
 #include <media/stagefright/SurfaceUtils.h>
 #include <mediautils/BatteryNotifier.h>
 #include <private/android_filesystem_config.h>
-#include <utils/Log.h>
 #include <utils/Singleton.h>
 
 namespace android {
@@ -570,11 +571,15 @@
     response->postReply(replyID);
 }
 
+static CodecBase *CreateCCodec() {
+    return StagefrightPluginLoader::GetCCodecInstance()->createCodec();
+}
+
 //static
 sp<CodecBase> MediaCodec::GetCodecBase(const AString &name) {
     static bool ccodecEnabled = property_get_bool("debug.stagefright.ccodec", false);
     if (ccodecEnabled && name.startsWithIgnoreCase("c2.")) {
-        return new CCodec;
+        return CreateCCodec();
     } else if (name.startsWithIgnoreCase("omx.")) {
         // at this time only ACodec specifies a mime type.
         return new ACodec;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 9244886..cd091a6 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include "MediaCodecListOverrides.h"
+#include "StagefrightPluginLoader.h"
 
 #include <binder/IServiceManager.h>
 
@@ -29,7 +30,6 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/MediaDefs.h>
-#include <media/stagefright/Codec2InfoBuilder.h>
 #include <media/stagefright/MediaCodecList.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/OmxInfoBuilder.h>
@@ -78,14 +78,25 @@
 }
 
 OmxInfoBuilder sOmxInfoBuilder;
-Codec2InfoBuilder sCodec2InfoBuilder;
 
-std::initializer_list<MediaCodecListBuilderBase *> GetBuilders() {
-    if (property_get_bool("debug.stagefright.ccodec", false)) {
-        return {&sOmxInfoBuilder, &sCodec2InfoBuilder};
-    } else {
-        return {&sOmxInfoBuilder};
+Mutex sCodec2InfoBuilderMutex;
+std::unique_ptr<MediaCodecListBuilderBase> sCodec2InfoBuilder;
+
+MediaCodecListBuilderBase *GetCodec2InfoBuilder() {
+    Mutex::Autolock _l(sCodec2InfoBuilderMutex);
+    if (!sCodec2InfoBuilder) {
+        sCodec2InfoBuilder.reset(
+                StagefrightPluginLoader::GetCCodecInstance()->createBuilder());
     }
+    return sCodec2InfoBuilder.get();
+}
+
+std::vector<MediaCodecListBuilderBase *> GetBuilders() {
+    std::vector<MediaCodecListBuilderBase *> builders {&sOmxInfoBuilder};
+    if (property_get_bool("debug.stagefright.ccodec", false)) {
+        builders.push_back(GetCodec2InfoBuilder());
+    }
+    return builders;
 }
 
 }  // unnamed namespace
@@ -179,16 +190,22 @@
     return sRemoteList;
 }
 
-MediaCodecList::MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders) {
+MediaCodecList::MediaCodecList(std::vector<MediaCodecListBuilderBase*> builders) {
     mGlobalSettings = new AMessage();
     mCodecInfos.clear();
-    MediaCodecListWriter writer(this);
+    MediaCodecListWriter writer;
     for (MediaCodecListBuilderBase *builder : builders) {
+        if (builder == nullptr) {
+            ALOGD("ignored a null builder");
+            continue;
+        }
         mInitCheck = builder->buildMediaCodecList(&writer);
         if (mInitCheck != OK) {
             break;
         }
     }
+    writer.writeGlobalSettings(mGlobalSettings);
+    writer.writeCodecInfos(&mCodecInfos);
     std::stable_sort(
             mCodecInfos.begin(),
             mCodecInfos.end(),
@@ -210,23 +227,6 @@
     return mInitCheck;
 }
 
-MediaCodecListWriter::MediaCodecListWriter(MediaCodecList* list) :
-    mList(list) {
-}
-
-void MediaCodecListWriter::addGlobalSetting(
-        const char* key, const char* value) {
-    mList->mGlobalSettings->setString(key, value);
-}
-
-std::unique_ptr<MediaCodecInfoWriter>
-        MediaCodecListWriter::addMediaCodecInfo() {
-    sp<MediaCodecInfo> info = new MediaCodecInfo();
-    mList->mCodecInfos.push_back(info);
-    return std::unique_ptr<MediaCodecInfoWriter>(
-            new MediaCodecInfoWriter(info.get()));
-}
-
 // legacy method for non-advanced codecs
 ssize_t MediaCodecList::findCodecByType(
         const char *type, bool encoder, size_t startIndex) const {
@@ -344,7 +344,4 @@
     }
 }
 
-MediaCodecListBuilderBase::~MediaCodecListBuilderBase() {
-}
-
 }  // namespace android
diff --git a/media/libstagefright/MediaCodecListWriter.cpp b/media/libstagefright/MediaCodecListWriter.cpp
new file mode 100644
index 0000000..b32e470
--- /dev/null
+++ b/media/libstagefright/MediaCodecListWriter.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012, 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_NDEBUG 0
+#define LOG_TAG "MediaCodecListWriter"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <media/MediaCodecInfo.h>
+
+namespace android {
+
+void MediaCodecListWriter::addGlobalSetting(
+        const char* key, const char* value) {
+    mGlobalSettings.emplace_back(key, value);
+}
+
+std::unique_ptr<MediaCodecInfoWriter>
+        MediaCodecListWriter::addMediaCodecInfo() {
+    sp<MediaCodecInfo> info = new MediaCodecInfo();
+    mCodecInfos.push_back(info);
+    return std::unique_ptr<MediaCodecInfoWriter>(
+            new MediaCodecInfoWriter(info.get()));
+}
+
+void MediaCodecListWriter::writeGlobalSettings(
+        const sp<AMessage> &globalSettings) const {
+    for (const std::pair<std::string, std::string> &kv : mGlobalSettings) {
+        globalSettings->setString(kv.first.c_str(), kv.second.c_str());
+    }
+}
+
+void MediaCodecListWriter::writeCodecInfos(
+        std::vector<sp<MediaCodecInfo>> *codecInfos) const {
+    for (const sp<MediaCodecInfo> &info : mCodecInfos) {
+        codecInfos->push_back(info);
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.cpp b/media/libstagefright/StagefrightPluginLoader.cpp
new file mode 100644
index 0000000..7f13f87
--- /dev/null
+++ b/media/libstagefright/StagefrightPluginLoader.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "StagefrightPluginLoader"
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+
+#include "StagefrightPluginLoader.h"
+
+namespace android {
+
+/* static */ Mutex StagefrightPluginLoader::sMutex;
+/* static */ std::unique_ptr<StagefrightPluginLoader> StagefrightPluginLoader::sInstance;
+
+StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath)
+    : mCreateCodec(nullptr),
+      mCreateBuilder(nullptr) {
+    mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
+    if (mLibHandle == nullptr) {
+        ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
+        return;
+    }
+    mCreateCodec = (CodecBase::CreateCodecFunc)dlsym(mLibHandle, "CreateCodec");
+    if (mCreateCodec == nullptr) {
+        ALOGD("Failed to find symbol: CreateCodec (%s)", dlerror());
+    }
+    mCreateBuilder = (MediaCodecListBuilderBase::CreateBuilderFunc)dlsym(
+            mLibHandle, "CreateBuilder");
+    if (mCreateBuilder == nullptr) {
+        ALOGD("Failed to find symbol: CreateBuilder (%s)", dlerror());
+    }
+}
+
+StagefrightPluginLoader::~StagefrightPluginLoader() {
+    if (mLibHandle != nullptr) {
+        ALOGV("Closing handle");
+        dlclose(mLibHandle);
+    }
+}
+
+CodecBase *StagefrightPluginLoader::createCodec() {
+    if (mLibHandle == nullptr || mCreateCodec == nullptr) {
+        ALOGD("Handle or CreateCodec symbol is null");
+        return nullptr;
+    }
+    return mCreateCodec();
+}
+
+MediaCodecListBuilderBase *StagefrightPluginLoader::createBuilder() {
+    if (mLibHandle == nullptr || mCreateBuilder == nullptr) {
+        ALOGD("Handle or CreateBuilder symbol is null");
+        return nullptr;
+    }
+    return mCreateBuilder();
+}
+
+//static
+const std::unique_ptr<StagefrightPluginLoader> &StagefrightPluginLoader::GetCCodecInstance() {
+    Mutex::Autolock _l(sMutex);
+    if (!sInstance) {
+        ALOGV("Loading library");
+        sInstance.reset(new StagefrightPluginLoader("libstagefright_ccodec.so"));
+    }
+    return sInstance;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.h b/media/libstagefright/StagefrightPluginLoader.h
new file mode 100644
index 0000000..2746756
--- /dev/null
+++ b/media/libstagefright/StagefrightPluginLoader.h
@@ -0,0 +1,47 @@
+/*
+ * 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 STAGEFRIGHT_PLUGIN_LOADER_H_
+
+#define STAGEFRIGHT_PLUGIN_LOADER_H_
+
+#include <media/stagefright/CodecBase.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <utils/Mutex.h>
+
+namespace android {
+
+class StagefrightPluginLoader {
+public:
+    static const std::unique_ptr<StagefrightPluginLoader> &GetCCodecInstance();
+    ~StagefrightPluginLoader();
+
+    CodecBase *createCodec();
+    MediaCodecListBuilderBase *createBuilder();
+private:
+    explicit StagefrightPluginLoader(const char *libPath);
+
+    static Mutex sMutex;
+    static std::unique_ptr<StagefrightPluginLoader> sInstance;
+
+    void *mLibHandle;
+    CodecBase::CreateCodecFunc mCreateCodec;
+    MediaCodecListBuilderBase::CreateBuilderFunc mCreateBuilder;
+};
+
+}  // namespace android
+
+#endif  // STAGEFRIGHT_PLUGIN_LOADER_H_
diff --git a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
index ea0b5c4..30c189e 100644
--- a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
+++ b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
@@ -25,6 +25,7 @@
 class Codec2InfoBuilder : public MediaCodecListBuilderBase {
 public:
     Codec2InfoBuilder() = default;
+    ~Codec2InfoBuilder() override = default;
     status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
 };
 
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 268662f..1cbf865 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -222,9 +222,7 @@
     virtual void signalSetParameters(const sp<AMessage> &msg) = 0;
     virtual void signalEndOfInputStream() = 0;
 
-    /*
-     * Codec-related defines
-     */
+    typedef CodecBase *(*CreateCodecFunc)(void);
 
 protected:
     CodecBase() = default;
@@ -324,4 +322,3 @@
 }  // namespace android
 
 #endif  // CODEC_BASE_H_
-
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index bb4da09..e44b0a4 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -18,10 +18,11 @@
 
 #define MEDIA_CODEC_LIST_H_
 
-#include <initializer_list>
+#include <vector>
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/MediaCodecListWriter.h>
 #include <media/IMediaCodecList.h>
 #include <media/MediaCodecInfo.h>
 
@@ -37,8 +38,6 @@
 
 struct AMessage;
 
-struct MediaCodecListBuilderBase;
-
 struct MediaCodecList : public BnMediaCodecList {
     static sp<IMediaCodecList> getInstance();
 
@@ -97,7 +96,7 @@
      * This constructor will call `buildMediaCodecList()` from the given
      * `MediaCodecListBuilderBase` objects.
      */
-    MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders);
+    MediaCodecList(std::vector<MediaCodecListBuilderBase*> builders);
 
     ~MediaCodecList();
 
@@ -105,66 +104,6 @@
 
     MediaCodecList(const MediaCodecList&) = delete;
     MediaCodecList& operator=(const MediaCodecList&) = delete;
-
-    friend MediaCodecListWriter;
-};
-
-/**
- * This class is to be used by a `MediaCodecListBuilderBase` instance to add
- * information to the associated `MediaCodecList` object.
- */
-struct MediaCodecListWriter {
-    /**
-     * Add a key-value pair to a `MediaCodecList`'s global settings.
-     *
-     * @param key Key.
-     * @param value Value.
-     */
-    void addGlobalSetting(const char* key, const char* value);
-    /**
-     * Create an add a new `MediaCodecInfo` object to a `MediaCodecList`, and
-     * return a `MediaCodecInfoWriter` object associated with the newly added
-     * `MediaCodecInfo`.
-     *
-     * @return The `MediaCodecInfoWriter` object associated with the newly
-     * added `MediaCodecInfo` object.
-     */
-    std::unique_ptr<MediaCodecInfoWriter> addMediaCodecInfo();
-private:
-    /**
-     * The associated `MediaCodecList` object.
-     */
-    MediaCodecList* mList;
-
-    /**
-     * Construct this writer object associated with the given `MediaCodecList`
-     * object.
-     *
-     * @param list The "base" `MediaCodecList` object.
-     */
-    MediaCodecListWriter(MediaCodecList* list);
-
-    friend MediaCodecList;
-};
-
-/**
- * This interface is to be used by `MediaCodecList` to fill its members with
- * appropriate information. `buildMediaCodecList()` will be called from a
- * `MediaCodecList` object during its construction.
- */
-struct MediaCodecListBuilderBase {
-    /**
-     * Build the `MediaCodecList` via the given `MediaCodecListWriter` interface.
-     *
-     * @param writer The writer interface.
-     * @return The status of the construction. `NO_ERROR` means success.
-     */
-    virtual status_t buildMediaCodecList(MediaCodecListWriter* writer) = 0;
-
-    /**
-     * The default destructor does nothing.
-     */
-    virtual ~MediaCodecListBuilderBase();
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h b/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
new file mode 100644
index 0000000..59f57c7
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012, 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 MEDIA_CODEC_LIST_WRITER_H_
+
+#define MEDIA_CODEC_LIST_WRITER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <media/MediaCodecInfo.h>
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+/**
+ * This class is to be used by a `MediaCodecListBuilderBase` instance to add
+ * information to the destination `MediaCodecList` object.
+ */
+struct MediaCodecListWriter {
+    /**
+     * Add a key-value pair to a `MediaCodecList`'s global settings.
+     *
+     * @param key Key.
+     * @param value Value.
+     */
+    void addGlobalSetting(const char* key, const char* value);
+    /**
+     * Create an add a new `MediaCodecInfo` object for a `MediaCodecList`, and
+     * return a `MediaCodecInfoWriter` object associated with the newly added
+     * `MediaCodecInfo`.
+     *
+     * @return The `MediaCodecInfoWriter` object associated with the newly
+     * added `MediaCodecInfo` object.
+     */
+    std::unique_ptr<MediaCodecInfoWriter> addMediaCodecInfo();
+private:
+    MediaCodecListWriter() = default;
+
+    void writeGlobalSettings(const sp<AMessage> &globalSettings) const;
+    void writeCodecInfos(std::vector<sp<MediaCodecInfo>> *codecInfos) const;
+
+    std::vector<std::pair<std::string, std::string>> mGlobalSettings;
+    std::vector<sp<MediaCodecInfo>> mCodecInfos;
+
+    friend struct MediaCodecList;
+};
+
+/**
+ * This interface is to be used by `MediaCodecList` to fill its members with
+ * appropriate information. `buildMediaCodecList()` will be called from a
+ * `MediaCodecList` object during its construction.
+ */
+struct MediaCodecListBuilderBase {
+    /**
+     * Build the `MediaCodecList` via the given `MediaCodecListWriter` interface.
+     *
+     * @param writer The writer interface.
+     * @return The status of the construction. `NO_ERROR` means success.
+     */
+    virtual status_t buildMediaCodecList(MediaCodecListWriter* writer) = 0;
+
+    /**
+     * The default destructor does nothing.
+     */
+    virtual ~MediaCodecListBuilderBase() = default;
+
+    typedef MediaCodecListBuilderBase *(*CreateBuilderFunc)(void);
+};
+
+}  // namespace android
+
+#endif  // MEDIA_CODEC_LIST_WRITER_H_
+
diff --git a/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h b/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
index 1b4d873..28f6094 100644
--- a/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
+++ b/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
@@ -25,6 +25,7 @@
 class OmxInfoBuilder : public MediaCodecListBuilderBase {
 public:
     OmxInfoBuilder();
+    ~OmxInfoBuilder() override = default;
     status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
 };