codec2: list c2.* components in MediaCodecList

- Set proper media type for component interface and read them in
  CCodec instead of current hack.
- Define debug.stagefright.omx_default_rank to override default OMX.*
  rank value (currently set to be preferred over c2.*)
- Move MediaCodec::CreateByType logic from ACodec to MediaCodec.

Test: am instrument -e size small -w 'android.media.cts/android.support.test.runner.AndroidJUnitRunner'
Test: setprop debug.stagefright.ccodec yes
Test: killall mediaserver
Test: cts-tradefed run cts -m CtsMediaTestCases -t android.media.cts.MediaCodecListTest
Change-Id: I55bd10d2d8c65867eae654e5bd64ef545689e699
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index a570ffe..5308e1c 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -141,6 +141,10 @@
     return mIsEncoder;
 }
 
+uint32_t MediaCodecInfo::rank() const {
+    return mRank;
+}
+
 void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
     mimes->clear();
     for (size_t ix = 0; ix < mCaps.size(); ix++) {
@@ -170,10 +174,12 @@
     AString name = AString::FromParcel(parcel);
     AString owner = AString::FromParcel(parcel);
     bool isEncoder = static_cast<bool>(parcel.readInt32());
+    uint32_t rank = parcel.readUint32();
     sp<MediaCodecInfo> info = new MediaCodecInfo;
     info->mName = name;
     info->mOwner = owner;
     info->mIsEncoder = isEncoder;
+    info->mRank = rank;
     size_t size = static_cast<size_t>(parcel.readInt32());
     for (size_t i = 0; i < size; i++) {
         AString mime = AString::FromParcel(parcel);
@@ -191,6 +197,7 @@
     mName.writeToParcel(parcel);
     mOwner.writeToParcel(parcel);
     parcel->writeInt32(mIsEncoder);
+    parcel->writeUint32(mRank);
     parcel->writeInt32(mCaps.size());
     for (size_t i = 0; i < mCaps.size(); i++) {
         mCaps.keyAt(i).writeToParcel(parcel);
@@ -210,7 +217,7 @@
     return -1;
 }
 
-MediaCodecInfo::MediaCodecInfo() {
+MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
 }
 
 void MediaCodecInfoWriter::setName(const char* name) {
@@ -225,6 +232,10 @@
     mInfo->mIsEncoder = isEncoder;
 }
 
+void MediaCodecInfoWriter::setRank(uint32_t rank) {
+    mInfo->mRank = rank;
+}
+
 std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
         MediaCodecInfoWriter::addMime(const char *mime) {
     ssize_t ix = mInfo->getCapabilityIndex(mime);
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index ab2cd24..b3777d3 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -170,6 +170,7 @@
      * Currently, this is the "instance name" of the IOmx service.
      */
     const char *getOwnerName() const;
+    uint32_t rank() const;
 
     /**
      * Serialization over Binder
@@ -182,6 +183,7 @@
     AString mOwner;
     bool mIsEncoder;
     KeyedVector<AString, sp<Capabilities> > mCaps;
+    uint32_t mRank;
 
     ssize_t getCapabilityIndex(const char *mime) const;
 
@@ -252,6 +254,13 @@
      * @return `true` if `mime` is removed; `false` if `mime` is not found.
      */
     bool removeMime(const char* mime);
+    /**
+     * Set rank of the codec. MediaCodecList will stable-sort the list according
+     * to rank in non-descending order.
+     *
+     * @param rank The rank of the component.
+     */
+    void setRank(uint32_t rank);
 private:
     /**
      * The associated `MediaCodecInfo`.
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6da6c13..b296622 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -6349,90 +6349,54 @@
     Vector<AString> matchingCodecs;
     Vector<AString> owners;
 
-    AString mime;
-
     AString componentName;
-    int32_t encoder = false;
-    if (msg->findString("componentName", &componentName)) {
-        sp<IMediaCodecList> list = MediaCodecList::getInstance();
-        if (list == nullptr) {
-            ALOGE("Unable to obtain MediaCodecList while "
-                    "attempting to create codec \"%s\"",
-                    componentName.c_str());
-            mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
-            return false;
-        }
-        ssize_t index = list->findCodecByName(componentName.c_str());
-        if (index < 0) {
-            ALOGE("Unable to find codec \"%s\"",
-                    componentName.c_str());
-            mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
-            return false;
-        }
-        sp<MediaCodecInfo> info = list->getCodecInfo(index);
-        if (info == nullptr) {
-            ALOGE("Unexpected error (index out-of-bound) while "
-                    "retrieving information for codec \"%s\"",
-                    componentName.c_str());
-            mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
-            return false;
-        }
-        matchingCodecs.add(info->getCodecName());
-        owners.add(info->getOwnerName() == nullptr ?
-                "default" : info->getOwnerName());
-    } else {
-        CHECK(msg->findString("mime", &mime));
+    CHECK(msg->findString("componentName", &componentName));
 
-        if (!msg->findInt32("encoder", &encoder)) {
-            encoder = false;
-        }
-
-        MediaCodecList::findMatchingCodecs(
-                mime.c_str(),
-                encoder, // createEncoder
-                0,       // flags
-                &matchingCodecs,
-                &owners);
+    sp<IMediaCodecList> list = MediaCodecList::getInstance();
+    if (list == nullptr) {
+        ALOGE("Unable to obtain MediaCodecList while "
+                "attempting to create codec \"%s\"",
+                componentName.c_str());
+        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+        return false;
     }
+    ssize_t index = list->findCodecByName(componentName.c_str());
+    if (index < 0) {
+        ALOGE("Unable to find codec \"%s\"",
+                componentName.c_str());
+        mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
+        return false;
+    }
+    sp<MediaCodecInfo> info = list->getCodecInfo(index);
+    if (info == nullptr) {
+        ALOGE("Unexpected error (index out-of-bound) while "
+                "retrieving information for codec \"%s\"",
+                componentName.c_str());
+        mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
+        return false;
+    }
+    AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName();
 
     sp<CodecObserver> observer = new CodecObserver;
     sp<IOMX> omx;
     sp<IOMXNode> omxNode;
 
     status_t err = NAME_NOT_FOUND;
-    for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
-            ++matchIndex) {
-        componentName = matchingCodecs[matchIndex];
-
-        OMXClient client;
-        if (client.connect(owners[matchIndex].c_str()) != OK) {
-            mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
-            return false;
-        }
-        omx = client.interface();
-
-        pid_t tid = gettid();
-        int prevPriority = androidGetThreadPriority(tid);
-        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
-        err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
-        androidSetThreadPriority(tid, prevPriority);
-
-        if (err == OK) {
-            break;
-        } else {
-            ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
-        }
-
-        omxNode = NULL;
+    OMXClient client;
+    if (client.connect(owner.c_str()) != OK) {
+        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+        return false;
     }
+    omx = client.interface();
 
-    if (omxNode == NULL) {
-        if (!mime.empty()) {
-            ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
-                    encoder ? "en" : "de", mime.c_str(), err);
-        } else {
-            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
-        }
+    pid_t tid = gettid();
+    int prevPriority = androidGetThreadPriority(tid);
+    androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+    err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
+    androidSetThreadPriority(tid, prevPriority);
+
+    if (err != OK) {
+        ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
 
         mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
         return false;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 8a15a50..f598062 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -63,6 +63,7 @@
         "C2OMXNode.cpp",
         "CCodec.cpp",
         "CCodecBufferChannel.cpp",
+        "Codec2InfoBuilder.cpp",
         "CodecBase.cpp",
         "CallbackDataSource.cpp",
         "CallbackMediaSource.cpp",
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
index bb70458..f62ee41 100644
--- a/media/libstagefright/CCodec.cpp
+++ b/media/libstagefright/CCodec.cpp
@@ -313,6 +313,19 @@
 }
 
 void CCodec::configure(const sp<AMessage> &msg) {
+    std::shared_ptr<C2ComponentInterface> intf;
+    {
+        Mutexed<State>::Locked state(mState);
+        if (state->get() != ALLOCATED) {
+            state->set(RELEASED);
+            state.unlock();
+            mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+            state.lock();
+            return;
+        }
+        intf = state->comp->intf();
+    }
+
     sp<AMessage> inputFormat(new AMessage);
     sp<AMessage> outputFormat(new AMessage);
     if (status_t err = [=] {
@@ -332,11 +345,34 @@
             setSurface(surface);
         }
 
+        std::vector<std::unique_ptr<C2Param>> params;
+        std::initializer_list<C2Param::Index> indices {
+            C2PortMimeConfig::input::PARAM_TYPE,
+            C2PortMimeConfig::output::PARAM_TYPE,
+        };
+        c2_status_t c2err = intf->query_vb(
+                {},
+                indices,
+                C2_DONT_BLOCK,
+                &params);
+        if (c2err != C2_OK) {
+            ALOGE("Failed to query component interface: %d", c2err);
+            return UNKNOWN_ERROR;
+        }
+        if (params.size() != indices.size()) {
+            ALOGE("Component returns wrong number of params");
+            return UNKNOWN_ERROR;
+        }
+        if (!params[0] || !params[1]) {
+            ALOGE("Component returns null params");
+            return UNKNOWN_ERROR;
+        }
+        inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
+        outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
+
         // XXX: hack
         bool audio = mime.startsWithIgnoreCase("audio/");
         if (encoder) {
-            outputFormat->setString("mime", mime);
-            inputFormat->setString("mime", AStringPrintf("%s/raw", audio ? "audio" : "video"));
             if (audio) {
                 inputFormat->setInt32("channel-count", 1);
                 inputFormat->setInt32("sample-rate", 44100);
@@ -347,8 +383,6 @@
                 outputFormat->setInt32("height", 1920);
             }
         } else {
-            inputFormat->setString("mime", mime);
-            outputFormat->setString("mime", AStringPrintf("%s/raw", audio ? "audio" : "video"));
             if (audio) {
                 outputFormat->setInt32("channel-count", 2);
                 outputFormat->setInt32("sample-rate", 44100);
@@ -712,7 +746,7 @@
     switch (msg->what()) {
         case kWhatAllocate: {
             // C2ComponentStore::createComponent() should return within 100ms.
-            setDeadline(now + 150ms);
+            setDeadline(now + 150ms, "allocate");
             AString componentName;
             CHECK(msg->findString("componentName", &componentName));
             allocate(componentName);
@@ -720,7 +754,7 @@
         }
         case kWhatConfigure: {
             // C2Component::commit_sm() should return within 5ms.
-            setDeadline(now + 50ms);
+            setDeadline(now + 50ms, "configure");
             sp<AMessage> format;
             CHECK(msg->findMessage("format", &format));
             configure(format);
@@ -728,31 +762,31 @@
         }
         case kWhatStart: {
             // C2Component::start() should return within 500ms.
-            setDeadline(now + 550ms);
+            setDeadline(now + 550ms, "start");
             start();
             break;
         }
         case kWhatStop: {
             // C2Component::stop() should return within 500ms.
-            setDeadline(now + 550ms);
+            setDeadline(now + 550ms, "stop");
             stop();
             break;
         }
         case kWhatFlush: {
             // C2Component::flush_sm() should return within 5ms.
-            setDeadline(now + 50ms);
+            setDeadline(now + 50ms, "flush");
             flush();
             break;
         }
         case kWhatCreateInputSurface: {
             // Surface operations may be briefly blocking.
-            setDeadline(now + 100ms);
+            setDeadline(now + 100ms, "createInputSurface");
             createInputSurface();
             break;
         }
         case kWhatSetInputSurface: {
             // Surface operations may be briefly blocking.
-            setDeadline(now + 100ms);
+            setDeadline(now + 100ms, "setInputSurface");
             sp<RefBase> obj;
             CHECK(msg->findObject("surface", &obj));
             sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
@@ -780,25 +814,28 @@
             break;
         }
     }
-    setDeadline(TimePoint::max());
+    setDeadline(TimePoint::max(), "none");
 }
 
-void CCodec::setDeadline(const TimePoint &newDeadline) {
-    Mutexed<TimePoint>::Locked deadline(mDeadline);
-    *deadline = newDeadline;
+void CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
+    Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+    deadline->set(newDeadline, name);
 }
 
 void CCodec::initiateReleaseIfStuck() {
+    std::string name;
     {
-        Mutexed<TimePoint>::Locked deadline(mDeadline);
-        if (*deadline >= std::chrono::steady_clock::now()) {
+        Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+        if (deadline->get() >= std::chrono::steady_clock::now()) {
             // We're not stuck.
             return;
         }
+        name = deadline->getName();
     }
 
+    ALOGW("previous call to %s exceeded timeout", name.c_str());
     mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
-    initiateRelease();
+    initiateRelease(false);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/Codec2InfoBuilder.cpp b/media/libstagefright/Codec2InfoBuilder.cpp
new file mode 100644
index 0000000..ee7258d
--- /dev/null
+++ b/media/libstagefright/Codec2InfoBuilder.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 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 "Codec2InfoBuilder"
+#include <log/log.h>
+
+#include <C2Component.h>
+#include <C2PlatformSupport.h>
+#include <C2V4l2Support.h>
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/Codec2InfoBuilder.h>
+
+namespace android {
+
+using ConstTraitsPtr = std::shared_ptr<const C2Component::Traits>;
+
+status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
+    // Obtain C2ComponentStore
+    std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore();
+    if (store == nullptr) {
+        ALOGE("Cannot find a component store.");
+        return NO_INIT;
+    }
+
+    std::vector<ConstTraitsPtr> traits = store->listComponents();
+
+    if (property_get_bool("debug.stagefright.ccodec_v4l2", false)) {
+        std::shared_ptr<C2ComponentStore> v4l2Store = GetCodec2VDAComponentStore();
+        if (v4l2Store == nullptr) {
+            ALOGD("Cannot find a V4L2 component store.");
+            // non-fatal.
+        } else {
+            std::vector<ConstTraitsPtr> v4l2Traits = v4l2Store->listComponents();
+            traits.insert(traits.end(), v4l2Traits.begin(), v4l2Traits.end());
+        }
+    }
+
+    for (const ConstTraitsPtr &trait : traits) {
+        std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
+        codecInfo->setName(trait->name.c_str());
+        codecInfo->setOwner("dummy");
+        // TODO: get this from trait->kind
+        codecInfo->setEncoder(trait->name.find("encoder") != std::string::npos);
+        codecInfo->setRank(trait->rank);
+        (void)codecInfo->addMime(trait->mediaType.c_str());
+    }
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 2b33708..7d5c63a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -421,13 +421,33 @@
 sp<MediaCodec> MediaCodec::CreateByType(
         const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
         uid_t uid) {
-    sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
+    Vector<AString> matchingCodecs;
+    Vector<AString> owners;
 
-    const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
+    MediaCodecList::findMatchingCodecs(
+            mime.c_str(),
+            encoder,
+            0,
+            &matchingCodecs,
+            &owners);
+
     if (err != NULL) {
-        *err = ret;
+        *err = NAME_NOT_FOUND;
     }
-    return ret == OK ? codec : NULL; // NULL deallocates codec.
+    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+        sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
+        AString componentName = matchingCodecs[i];
+        status_t ret = codec->init(componentName);
+        if (err != NULL) {
+            *err = ret;
+        }
+        if (ret == OK) {
+            return codec;
+        }
+        ALOGD("Allocating component '%s' failed (%d), try next one.",
+                componentName.c_str(), ret);
+    }
+    return NULL;
 }
 
 // static
@@ -435,7 +455,7 @@
         const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
     sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
 
-    const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
+    const status_t ret = codec->init(name);
     if (err != NULL) {
         *err = ret;
     }
@@ -553,11 +573,11 @@
 }
 
 //static
-sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
+sp<CodecBase> MediaCodec::GetCodecBase(const AString &name) {
     static bool ccodecEnabled = property_get_bool("debug.stagefright.ccodec", false);
-    if (ccodecEnabled && !nameIsType && name.startsWithIgnoreCase("c2.")) {
+    if (ccodecEnabled && name.startsWithIgnoreCase("c2.")) {
         return new CCodec;
-    } else if (nameIsType || name.startsWithIgnoreCase("omx.")) {
+    } else if (name.startsWithIgnoreCase("omx.")) {
         // at this time only ACodec specifies a mime type.
         return new ACodec;
     } else if (name.startsWithIgnoreCase("android.filter.")) {
@@ -567,48 +587,42 @@
     }
 }
 
-status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
+status_t MediaCodec::init(const AString &name) {
     mResourceManagerService->init();
 
     // save init parameters for reset
     mInitName = name;
-    mInitNameIsType = nameIsType;
-    mInitIsEncoder = encoder;
 
     // Current video decoders do not return from OMX_FillThisBuffer
     // quickly, violating the OpenMAX specs, until that is remedied
     // we need to invest in an extra looper to free the main event
     // queue.
 
-    mCodec = GetCodecBase(name, nameIsType);
+    mCodec = GetCodecBase(name);
     if (mCodec == NULL) {
         return NAME_NOT_FOUND;
     }
 
     bool secureCodec = false;
-    if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
-        mIsVideo = true;
-    } else {
-        AString tmp = name;
-        if (tmp.endsWith(".secure")) {
-            secureCodec = true;
-            tmp.erase(tmp.size() - 7, 7);
-        }
-        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
-        if (mcl == NULL) {
-            mCodec = NULL;  // remove the codec.
-            return NO_INIT; // if called from Java should raise IOException
-        }
-        ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
-        if (codecIdx >= 0) {
-            const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
-            Vector<AString> mimes;
-            info->getSupportedMimes(&mimes);
-            for (size_t i = 0; i < mimes.size(); i++) {
-                if (mimes[i].startsWith("video/")) {
-                    mIsVideo = true;
-                    break;
-                }
+    AString tmp = name;
+    if (tmp.endsWith(".secure")) {
+        secureCodec = true;
+        tmp.erase(tmp.size() - 7, 7);
+    }
+    const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+    if (mcl == NULL) {
+        mCodec = NULL;  // remove the codec.
+        return NO_INIT; // if called from Java should raise IOException
+    }
+    ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
+    if (codecIdx >= 0) {
+        const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
+        Vector<AString> mimes;
+        info->getSupportedMimes(&mimes);
+        for (size_t i = 0; i < mimes.size(); i++) {
+            if (mimes[i].startsWith("video/")) {
+                mIsVideo = true;
+                break;
             }
         }
     }
@@ -638,22 +652,10 @@
 
     sp<AMessage> msg = new AMessage(kWhatInit, this);
     msg->setString("name", name);
-    msg->setInt32("nameIsType", nameIsType);
-
-    if (nameIsType) {
-        msg->setInt32("encoder", encoder);
-    }
 
     if (mAnalyticsItem != NULL) {
-        if (nameIsType) {
-            // name is the mime type
-            mAnalyticsItem->setCString(kCodecMime, name.c_str());
-        } else {
-            mAnalyticsItem->setCString(kCodecCodec, name.c_str());
-        }
+        mAnalyticsItem->setCString(kCodecCodec, name.c_str());
         mAnalyticsItem->setCString(kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio);
-        if (nameIsType)
-            mAnalyticsItem->setInt32(kCodecEncoder, encoder);
     }
 
     status_t err;
@@ -719,6 +721,7 @@
         if (format->findInt32("level", &level)) {
             mAnalyticsItem->setInt32(kCodecLevel, level);
         }
+        mAnalyticsItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
     }
 
     if (mIsVideo) {
@@ -743,8 +746,7 @@
         }
 
         // Prevent possible integer overflow in downstream code.
-        if (mInitIsEncoder
-                && (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
+        if ((uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
             ALOGE("buffer size is too big, width=%d, height=%d", mVideoWidth, mVideoHeight);
             return BAD_VALUE;
         }
@@ -1023,7 +1025,7 @@
     mHaveInputSurface = false;
 
     if (err == OK) {
-        err = init(mInitName, mInitNameIsType, mInitIsEncoder);
+        err = init(mInitName);
     }
     return err;
 }
@@ -1973,21 +1975,8 @@
             AString name;
             CHECK(msg->findString("name", &name));
 
-            int32_t nameIsType;
-            int32_t encoder = false;
-            CHECK(msg->findInt32("nameIsType", &nameIsType));
-            if (nameIsType) {
-                CHECK(msg->findInt32("encoder", &encoder));
-            }
-
             sp<AMessage> format = new AMessage;
-
-            if (nameIsType) {
-                format->setString("mime", name.c_str());
-                format->setInt32("encoder", encoder);
-            } else {
-                format->setString("componentName", name.c_str());
-            }
+            format->setString("componentName", name.c_str());
 
             mCodec->initiateAllocateComponent(format);
             break;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 54265a4..f595646 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -29,6 +29,7 @@
 #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>
@@ -77,6 +78,15 @@
 }
 
 OmxInfoBuilder sOmxInfoBuilder;
+Codec2InfoBuilder sCodec2InfoBuilder;
+
+std::initializer_list<MediaCodecListBuilderBase *> GetBuilders() {
+    if (property_get_bool("debug.stagefright.ccodec", false)) {
+        return {&sOmxInfoBuilder, &sCodec2InfoBuilder};
+    } else {
+        return {&sOmxInfoBuilder};
+    }
+}
 
 }  // unnamed namespace
 
@@ -88,7 +98,7 @@
     ALOGV("Enter profilerThreadWrapper.");
     remove(kProfilingResults);  // remove previous result so that it won't be loaded to
                                 // the new MediaCodecList
-    sp<MediaCodecList> codecList(new MediaCodecList(&sOmxInfoBuilder));
+    sp<MediaCodecList> codecList(new MediaCodecList(GetBuilders()));
     if (codecList->initCheck() != OK) {
         ALOGW("Failed to create a new MediaCodecList, skipping codec profiling.");
         return nullptr;
@@ -98,7 +108,7 @@
     ALOGV("Codec profiling started.");
     profileCodecs(infos, kProfilingResults);
     ALOGV("Codec profiling completed.");
-    codecList = new MediaCodecList(&sOmxInfoBuilder);
+    codecList = new MediaCodecList(GetBuilders());
     if (codecList->initCheck() != OK) {
         ALOGW("Failed to parse profiling results.");
         return nullptr;
@@ -116,7 +126,7 @@
     Mutex::Autolock autoLock(sInitMutex);
 
     if (sCodecList == nullptr) {
-        MediaCodecList *codecList = new MediaCodecList(&sOmxInfoBuilder);
+        MediaCodecList *codecList = new MediaCodecList(GetBuilders());
         if (codecList->initCheck() == OK) {
             sCodecList = codecList;
 
@@ -169,11 +179,28 @@
     return sRemoteList;
 }
 
-MediaCodecList::MediaCodecList(MediaCodecListBuilderBase* builder) {
+MediaCodecList::MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders) {
     mGlobalSettings = new AMessage();
     mCodecInfos.clear();
     MediaCodecListWriter writer(this);
-    mInitCheck = builder->buildMediaCodecList(&writer);
+    for (MediaCodecListBuilderBase *builder : builders) {
+        mInitCheck = builder->buildMediaCodecList(&writer);
+        if (mInitCheck != OK) {
+            break;
+        }
+    }
+    std::stable_sort(
+            mCodecInfos.begin(),
+            mCodecInfos.end(),
+            [](const sp<MediaCodecInfo> &info1, const sp<MediaCodecInfo> &info2) {
+                if (info2 == nullptr) {
+                    return false;
+                } else if (info1 == nullptr) {
+                    return true;
+                } else {
+                    return info1->rank() < info2->rank();
+                }
+            });
 }
 
 MediaCodecList::~MediaCodecList() {
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index a6ebadd..fe141ab 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -154,22 +154,22 @@
     // codec name -> index into swCodecs/hwCodecs
     std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
             swCodecName2Info, hwCodecName2Info;
-    // owner name -> MediaCodecInfo
-    // This map will be used to obtain the correct IOmx service(s) needed for
-    // creating IOmxNode instances and querying capabilities.
-    std::map<std::string, std::vector<sp<MediaCodecInfo> > >
-            owner2CodecInfo;
 
-    for (const auto& role : roles) {
-        const auto& typeName = role.type;
+    char rank[PROPERTY_VALUE_MAX];
+    uint32_t defaultRank = 0x100;
+    if (property_get("debug.stagefright.omx_default_rank", rank, nullptr)) {
+        defaultRank = std::strtoul(rank, nullptr, 10);
+    }
+    for (const IOmxStore::RoleInfo& role : roles) {
+        const hidl_string& typeName = role.type;
         bool isEncoder = role.isEncoder;
         bool preferPlatformNodes = role.preferPlatformNodes;
         // If preferPlatformNodes is true, hardware nodes must be added after
         // platform (software) nodes. hwCodecs is used to hold hardware nodes
         // that need to be added after software nodes for the same role.
         std::vector<const IOmxStore::NodeInfo*> hwCodecs;
-        for (const auto& node : role.nodes) {
-            const auto& nodeName = node.name;
+        for (const IOmxStore::NodeInfo& node : role.nodes) {
+            const hidl_string& nodeName = node.name;
             bool isSoftware = hasPrefix(nodeName, "OMX.google");
             MediaCodecInfoWriter* info;
             if (isSoftware) {
@@ -182,6 +182,7 @@
                     info->setName(nodeName.c_str());
                     info->setOwner(node.owner.c_str());
                     info->setEncoder(isEncoder);
+                    info->setRank(defaultRank);
                 } else {
                     // The node has been seen before. Simply retrieve the
                     // existing MediaCodecInfoWriter.
@@ -198,6 +199,7 @@
                         info->setName(nodeName.c_str());
                         info->setOwner(node.owner.c_str());
                         info->setEncoder(isEncoder);
+                        info->setRank(defaultRank);
                     } else {
                         // If preferPlatformNodes is true, this node must be
                         // added after all software nodes.
@@ -224,9 +226,9 @@
         // added in the loop above, but rather saved in hwCodecs. They are
         // going to be added here.
         if (preferPlatformNodes) {
-            for (const auto& node : hwCodecs) {
+            for (const IOmxStore::NodeInfo *node : hwCodecs) {
                 MediaCodecInfoWriter* info;
-                const auto& nodeName = node->name;
+                const hidl_string& nodeName = node->name;
                 auto c2i = hwCodecName2Info.find(nodeName);
                 if (c2i == hwCodecName2Info.end()) {
                     // Create a new MediaCodecInfo for a new node.
@@ -236,6 +238,7 @@
                     info->setName(nodeName.c_str());
                     info->setOwner(node->owner.c_str());
                     info->setEncoder(isEncoder);
+                    info->setRank(defaultRank);
                 } else {
                     // The node has been seen before. Simply retrieve the
                     // existing MediaCodecInfoWriter.
diff --git a/media/libstagefright/codec2/SimpleC2Component.cpp b/media/libstagefright/codec2/SimpleC2Component.cpp
index c345783..333cfeb 100644
--- a/media/libstagefright/codec2/SimpleC2Component.cpp
+++ b/media/libstagefright/codec2/SimpleC2Component.cpp
@@ -226,7 +226,9 @@
         releasing = std::move(state->mThread);
     }
     mExitRequested = true;
-    releasing.join();
+    if (releasing.joinable()) {
+        releasing.join();
+    }
     onRelease();
     return C2_OK;
 }
diff --git a/media/libstagefright/codec2/SimpleC2Interface.cpp b/media/libstagefright/codec2/SimpleC2Interface.cpp
index f082243..d159426 100644
--- a/media/libstagefright/codec2/SimpleC2Interface.cpp
+++ b/media/libstagefright/codec2/SimpleC2Interface.cpp
@@ -45,15 +45,38 @@
     if (heapParams) {
         heapParams->clear();
         for (const auto &index : heapParamIndices) {
-            if (index.coreIndex() != C2StreamFormatConfig::CORE_INDEX
-                    || !index.forStream()
-                    || index.stream() != 0u) {
-                heapParams->push_back(nullptr);
-            }
-            if (index.forInput()) {
-                heapParams->push_back(C2Param::Copy(mInputFormat));
-            } else {
-                heapParams->push_back(C2Param::Copy(mOutputFormat));
+            switch (index.type()) {
+                case C2StreamFormatConfig::input::PARAM_TYPE:
+                    if (index.stream() == 0u) {
+                        heapParams->push_back(C2Param::Copy(mInputFormat));
+                    } else {
+                        heapParams->push_back(nullptr);
+                    }
+                    break;
+                case C2StreamFormatConfig::output::PARAM_TYPE:
+                    if (index.stream() == 0u) {
+                        heapParams->push_back(C2Param::Copy(mOutputFormat));
+                    } else {
+                        heapParams->push_back(nullptr);
+                    }
+                    break;
+                case C2PortMimeConfig::input::PARAM_TYPE:
+                    if (mInputMediaType) {
+                        heapParams->push_back(C2Param::Copy(*mInputMediaType));
+                    } else {
+                        heapParams->push_back(nullptr);
+                    }
+                    break;
+                case C2PortMimeConfig::output::PARAM_TYPE:
+                    if (mOutputMediaType) {
+                        heapParams->push_back(C2Param::Copy(*mOutputMediaType));
+                    } else {
+                        heapParams->push_back(nullptr);
+                    }
+                    break;
+                default:
+                    heapParams->push_back(nullptr);
+                    break;
             }
         }
     }
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index 61fcfc0..dbcd82d 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -398,7 +398,7 @@
         domain_t domain; ///< component domain (e.g. audio or video)
         kind_t kind; ///< component kind (e.g. encoder, decoder or filter)
         rank_t rank; ///< rank used to determine component ordering (the lower the sooner)
-        C2StringLiteral mediaType; ///< media type supported by the component
+        C2String mediaType; ///< media type supported by the component
 
         /**
          * name alias(es) for backward compatibility.
diff --git a/media/libstagefright/codec2/include/SimpleC2Interface.h b/media/libstagefright/codec2/include/SimpleC2Interface.h
index b934f12..310096f 100644
--- a/media/libstagefright/codec2/include/SimpleC2Interface.h
+++ b/media/libstagefright/codec2/include/SimpleC2Interface.h
@@ -27,13 +27,9 @@
     public:
         inline Builder(
                 const char *name,
-                c2_node_id_t id)
-            : mIntf(new SimpleC2Interface(name, id)) {}
-
-        inline Builder(
-                const char *name,
                 c2_node_id_t id,
-                std::function<void(::android::SimpleC2Interface*)> deleter)
+                std::function<void(C2ComponentInterface*)> deleter =
+                    std::default_delete<C2ComponentInterface>())
             : mIntf(new SimpleC2Interface(name, id), deleter) {}
 
         inline Builder &inputFormat(C2FormatKind input) {
@@ -46,6 +42,28 @@
             return *this;
         }
 
+        inline Builder &inputMediaType(const char *mediaType, size_t maxLen = 128) {
+            mIntf->mInputMediaType = C2PortMimeConfig::input::AllocShared(maxLen);
+            std::strncpy(mIntf->mInputMediaType->m.value, mediaType, maxLen);
+            return *this;
+        }
+
+        inline Builder &outputMediaType(const char *mediaType, size_t maxLen = 128) {
+            mIntf->mOutputMediaType = C2PortMimeConfig::output::AllocShared(maxLen);
+            std::strncpy(mIntf->mOutputMediaType->m.value, mediaType, maxLen);
+            return *this;
+        }
+
+        template<size_t N>
+        inline Builder &inputMediaType(const char mediaType[N]) {
+            return inputMediaType(mediaType, N);
+        }
+
+        template<size_t N>
+        inline Builder &outputMediaType(const char mediaType[N]) {
+            return outputMediaType(mediaType, N);
+        }
+
         inline std::shared_ptr<SimpleC2Interface> build() {
             return mIntf;
         }
@@ -89,6 +107,8 @@
     const c2_node_id_t mId;
     C2StreamFormatConfig::input mInputFormat;
     C2StreamFormatConfig::output mOutputFormat;
+    std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
+    std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
 
     SimpleC2Interface() = delete;
 };
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index c4ed2f4..f612b4f 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -203,9 +203,17 @@
         /**
          * Creates an uninitialized component module.
          *
+         * \param name[in]  component name.
+         *
          * \note Only used by ComponentLoader.
          */
-        ComponentModule() : mInit(C2_NO_INIT) {}
+        ComponentModule()
+            : mInit(C2_NO_INIT),
+              mLibHandle(nullptr),
+              createFactory(nullptr),
+              destroyFactory(nullptr),
+              mComponentFactory(nullptr) {
+        }
 
         /**
          * Initializes a component module with a given library path. Must be called exactly once.
@@ -383,12 +391,35 @@
         std::shared_ptr<C2ComponentInterface> intf;
         c2_status_t res = createInterface(0, &intf);
         if (res != C2_OK) {
+            ALOGD("failed to create interface: %d", res);
             return nullptr;
         }
 
         std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
         if (traits) {
-            // traits->name = intf->getName();
+            traits->name = intf->getName();
+            // TODO: get this from interface properly.
+            bool encoder = (traits->name.find("encoder") != std::string::npos);
+            uint32_t mediaTypeIndex = encoder ? C2PortMimeConfig::output::PARAM_TYPE
+                    : C2PortMimeConfig::input::PARAM_TYPE;
+            std::vector<std::unique_ptr<C2Param>> params;
+            res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, &params);
+            if (res != C2_OK) {
+                ALOGD("failed to query interface: %d", res);
+                return nullptr;
+            }
+            if (params.size() != 1u) {
+                ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
+                return nullptr;
+            }
+            C2PortMimeConfig *mediaTypeConfig = (C2PortMimeConfig *)(params[0].get());
+            if (mediaTypeConfig == nullptr) {
+                ALOGD("failed to query media type");
+                return nullptr;
+            }
+            traits->mediaType = mediaTypeConfig->m.value;
+            // TODO: get this properly.
+            traits->rank = 0x200;
         }
 
         mTraits = traits;
diff --git a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
index 3f09e0a..c82ea45 100644
--- a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
+++ b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
@@ -25,6 +25,7 @@
 
 #include <cutils/properties.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/misc.h>
@@ -50,12 +51,22 @@
 
 namespace android {
 
-C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
-    : SimpleC2Component(
-            SimpleC2Interface::Builder(name, id)
+constexpr char kComponentName[] = "c2.google.aac.decoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+        const char *name, c2_node_id_t id,
+        std::function<void(C2ComponentInterface*)> deleter =
+            std::default_delete<C2ComponentInterface>()) {
+    return SimpleC2Interface::Builder(name, id, deleter)
             .inputFormat(C2FormatCompressed)
             .outputFormat(C2FormatAudio)
-            .build()),
+            .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
+            .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+            .build();
+}
+
+C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
+    : SimpleC2Component(BuildIntf(name, id)),
       mAACDecoder(NULL),
       mStreamInfo(NULL),
       mIsADTS(false),
@@ -333,6 +344,7 @@
         const std::unique_ptr<C2Work> &work,
         const std::shared_ptr<C2BlockPool> &pool) {
     work->workletsProcessed = 0u;
+    work->result = C2_OK;
     if (mSignalledError) {
         return;
     }
@@ -675,20 +687,18 @@
 class C2SoftAacDecFactory : public C2ComponentFactory {
 public:
     virtual c2_status_t createComponent(
-            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
-            std::function<void(::C2Component*)> deleter) override {
-        *component = std::shared_ptr<C2Component>(new C2SoftAac("aac", id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2Component>* const component,
+            std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftAac(kComponentName, id), deleter);
         return C2_OK;
     }
 
     virtual c2_status_t createInterface(
-            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
-            std::function<void(::C2ComponentInterface*)> deleter) override {
-        *interface =
-                SimpleC2Interface::Builder("aac", id, deleter)
-                .inputFormat(C2FormatCompressed)
-                .outputFormat(C2FormatVideo)
-                .build();
+            c2_node_id_t id,
+            std::shared_ptr<C2ComponentInterface>* const interface,
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = BuildIntf(kComponentName, id, deleter);
         return C2_OK;
     }
 
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
index 74f5a7a..70f6817 100644
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
@@ -22,20 +22,31 @@
 
 #include <C2PlatformSupport.h>
 #include <SimpleC2Interface.h>
+#include <media/stagefright/foundation/MediaDefs.h>
 #include <media/stagefright/foundation/hexdump.h>
 
 #include "C2SoftAacEnc.h"
 
 namespace android {
 
+constexpr char kComponentName[] = "c2.google.aac.encoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+        const char *name, c2_node_id_t id,
+        std::function<void(C2ComponentInterface*)> deleter =
+            std::default_delete<C2ComponentInterface>()) {
+    return SimpleC2Interface::Builder(name, id, deleter)
+            .inputFormat(C2FormatAudio)
+            .outputFormat(C2FormatCompressed)
+            .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
+            .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+            .build();
+}
+
 C2SoftAacEnc::C2SoftAacEnc(
         const char *name,
         c2_node_id_t id)
-    : SimpleC2Component(
-            SimpleC2Interface::Builder(name, id)
-            .inputFormat(C2FormatAudio)
-            .outputFormat(C2FormatCompressed)
-            .build()),
+    : SimpleC2Component(BuildIntf(name, id)),
       mAACEncoder(NULL),
       mNumChannels(1),
       mSampleRate(44100),
@@ -176,6 +187,7 @@
 void C2SoftAacEnc::process(
         const std::unique_ptr<C2Work> &work,
         const std::shared_ptr<C2BlockPool> &pool) {
+    work->result = C2_OK;
     work->workletsProcessed = 0u;
 
     if (mSignalledError) {
@@ -381,20 +393,17 @@
 class C2SoftAacEncFactory : public C2ComponentFactory {
 public:
     virtual c2_status_t createComponent(
-            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
-            std::function<void(::C2Component*)> deleter) override {
-        *component = std::shared_ptr<C2Component>(new C2SoftAacEnc("aacenc", id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2Component>* const component,
+            std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftAacEnc(kComponentName, id), deleter);
         return C2_OK;
     }
 
     virtual c2_status_t createInterface(
             c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
-            std::function<void(::C2ComponentInterface*)> deleter) override {
-        *interface =
-                SimpleC2Interface::Builder("aacenc", id, deleter)
-                .inputFormat(C2FormatAudio)
-                .outputFormat(C2FormatCompressed)
-                .build();
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = BuildIntf(kComponentName, id, deleter);
         return C2_OK;
     }
 
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 3c09e37..b9ba251 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -54,7 +54,7 @@
 
 #define PRINT_TIME  ALOGV
 
-#define componentName                   "video_decoder.avc"
+constexpr char kComponentName[] = "c2.google.avc.decoder";
 // #define codingType                      OMX_VIDEO_CodingAVC
 #define CODEC_MIME_TYPE                 MEDIA_MIMETYPE_VIDEO_AVC
 
@@ -71,6 +71,18 @@
         (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
 namespace {
 
+std::shared_ptr<C2ComponentInterface> BuildIntf(
+        const char *name, c2_node_id_t id,
+        std::function<void(C2ComponentInterface*)> deleter =
+            std::default_delete<C2ComponentInterface>()) {
+    return SimpleC2Interface::Builder(name, id, deleter)
+            .inputFormat(C2FormatCompressed)
+            .outputFormat(C2FormatVideo)
+            .inputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
+            .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
+            .build();
+}
+
 #if 0
 using SupportedValuesWithFields = C2SoftAvcDecIntf::SupportedValuesWithFields;
 
@@ -614,11 +626,7 @@
 C2SoftAvcDec::C2SoftAvcDec(
         const char *name,
         c2_node_id_t id)
-    : SimpleC2Component(
-          SimpleC2Interface::Builder(name, id)
-          .inputFormat(C2FormatCompressed)
-          .outputFormat(C2FormatVideo)
-          .build()),
+    : SimpleC2Component(BuildIntf(name, id)),
       mCodecCtx(NULL),
       mFlushOutBuffer(NULL),
       mIvColorFormat(IV_YUV_420P),
@@ -1327,21 +1335,18 @@
 class C2SoftAvcDecFactory : public C2ComponentFactory {
 public:
     virtual c2_status_t createComponent(
-            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
-            std::function<void(::C2Component*)> deleter) override {
-        *component = std::shared_ptr<C2Component>(new C2SoftAvcDec("avc", id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2Component>* const component,
+            std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftAvcDec(kComponentName, id), deleter);
         return C2_OK;
     }
 
     virtual c2_status_t createInterface(
-            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
-            std::function<void(::C2ComponentInterface*)> deleter) override {
-        *interface =
-              SimpleC2Interface::Builder("avc", id, deleter)
-              .inputFormat(C2FormatCompressed)
-              .outputFormat(C2FormatVideo)
-              .build();
-//            std::shared_ptr<C2ComponentInterface>(new C2SoftAvcDecIntf("avc", id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2ComponentInterface>* const interface,
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = BuildIntf(kComponentName, id, deleter);
         return C2_OK;
     }
 
diff --git a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
index e105460..8fb8122 100644
--- a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
@@ -35,7 +35,9 @@
 
 namespace android {
 
-#define ive_api_function ih264e_api_function
+#define ive_api_function  ih264e_api_function
+
+constexpr char kComponentName[] = "c2.google.avc.encoder";
 
 namespace {
 
@@ -55,6 +57,18 @@
     return (size_t)cpuCoreCount;
 }
 
+std::shared_ptr<C2ComponentInterface> BuildIntf(
+        const char *name, c2_node_id_t id,
+        std::function<void(C2ComponentInterface*)> deleter =
+            std::default_delete<C2ComponentInterface>()) {
+    return SimpleC2Interface::Builder(name, id, deleter)
+            .inputFormat(C2FormatVideo)
+            .outputFormat(C2FormatCompressed)
+            .inputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
+            .outputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
+            .build();
+}
+
 void ConvertRGBToPlanarYUV(
         uint8_t *dstY, size_t dstStride, size_t dstVStride,
         const C2GraphicView &src) {
@@ -115,11 +129,7 @@
 }  // namespace
 
 C2SoftAvcEnc::C2SoftAvcEnc(const char *name, c2_node_id_t id)
-    : SimpleC2Component(
-          SimpleC2Interface::Builder(name, id)
-          .inputFormat(C2FormatVideo)
-          .outputFormat(C2FormatCompressed)
-          .build()),
+    : SimpleC2Component(BuildIntf(name, id)),
       mUpdateFlag(0),
       mIvVideoColorFormat(IV_YUV_420P),
       mAVCEncProfile(IV_PROFILE_BASE),
@@ -1209,20 +1219,18 @@
 class C2SoftAvcEncFactory : public C2ComponentFactory {
 public:
     virtual c2_status_t createComponent(
-            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
-            std::function<void(::C2Component*)> deleter) override {
-        *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc("avcenc", id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2Component>* const component,
+            std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc(kComponentName, id), deleter);
         return C2_OK;
     }
 
     virtual c2_status_t createInterface(
-            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
-            std::function<void(::C2ComponentInterface*)> deleter) override {
-        *interface =
-              SimpleC2Interface::Builder("avcenc", id, deleter)
-              .inputFormat(C2FormatVideo)
-              .outputFormat(C2FormatCompressed)
-              .build();
+            c2_node_id_t id,
+            std::shared_ptr<C2ComponentInterface>* const interface,
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = BuildIntf(kComponentName, id, deleter);
         return C2_OK;
     }
 
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
index e830324..d296a3d 100644
--- a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
@@ -24,21 +24,37 @@
 #include <SimpleC2Interface.h>
 
 #include <media/stagefright/foundation/ADebug.h>
-
-#ifdef ALAW
-#define COMPONENT_NAME "g711a"
-#else
-#define COMPONENT_NAME "g711m"
-#endif
+#include <media/stagefright/foundation/MediaDefs.h>
 
 namespace android {
 
-C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
-    : SimpleC2Component(
-            SimpleC2Interface::Builder(name, id)
+#ifdef ALAW
+constexpr char kComponentName[] = "c2.google.g711.alaw.decoder";
+#else
+constexpr char kComponentName[] = "c2.google.g711.mlaw.decoder";
+#endif
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+        const char *name, c2_node_id_t id,
+        std::function<void(C2ComponentInterface*)> deleter =
+            std::default_delete<C2ComponentInterface>()) {
+    return SimpleC2Interface::Builder(name, id, deleter)
             .inputFormat(C2FormatCompressed)
             .outputFormat(C2FormatAudio)
-            .build()) {
+            .inputMediaType(
+#ifdef ALAW
+                    MEDIA_MIMETYPE_AUDIO_G711_ALAW
+#else
+                    MEDIA_MIMETYPE_AUDIO_G711_MLAW
+#endif
+            )
+            .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+            .build();
+}
+
+
+C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
+    : SimpleC2Component(BuildIntf(name, id)) {
 }
 
 C2SoftG711::~C2SoftG711() {
@@ -206,20 +222,17 @@
 class C2SoftG711DecFactory : public C2ComponentFactory {
 public:
     virtual c2_status_t createComponent(
-            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
-            std::function<void(::C2Component*)> deleter) override {
-        *component = std::shared_ptr<C2Component>(new C2SoftG711(COMPONENT_NAME, id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2Component>* const component,
+            std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftG711(kComponentName, id), deleter);
         return C2_OK;
     }
 
     virtual c2_status_t createInterface(
             c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
-            std::function<void(::C2ComponentInterface*)> deleter) override {
-        *interface =
-                SimpleC2Interface::Builder(COMPONENT_NAME, id, deleter)
-                .inputFormat(C2FormatCompressed)
-                .outputFormat(C2FormatAudio)
-                .build();
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = BuildIntf(kComponentName, id, deleter);
         return C2_OK;
     }
 
diff --git a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
index 9e8b527..9cac87e 100644
--- a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
@@ -26,17 +26,28 @@
 #include <SimpleC2Interface.h>
 
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
 
 #include <numeric>
 
 namespace android {
 
-C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
-    : SimpleC2Component(
-            SimpleC2Interface::Builder(name, id)
+constexpr char kComponentName[] = "c2.google.aac.encoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+        const char *name, c2_node_id_t id,
+        std::function<void(C2ComponentInterface*)> deleter =
+            std::default_delete<C2ComponentInterface>()) {
+    return SimpleC2Interface::Builder(name, id, deleter)
             .inputFormat(C2FormatCompressed)
             .outputFormat(C2FormatAudio)
-            .build()),
+            .inputMediaType(MEDIA_MIMETYPE_AUDIO_MPEG)
+            .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+            .build();
+}
+
+C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
+    : SimpleC2Component(BuildIntf(name, id)),
       mConfig(nullptr),
       mDecoderBuf(nullptr) {
 }
@@ -397,20 +408,18 @@
 class C2SoftMp3DecFactory : public C2ComponentFactory {
 public:
     virtual c2_status_t createComponent(
-            c2_node_id_t id, std::shared_ptr<C2Component>* const component,
-            std::function<void(::C2Component*)> deleter) override {
-        *component = std::shared_ptr<C2Component>(new C2SoftMP3("mp3", id), deleter);
+            c2_node_id_t id,
+            std::shared_ptr<C2Component>* const component,
+            std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(new C2SoftMP3(kComponentName, id), deleter);
         return C2_OK;
     }
 
     virtual c2_status_t createInterface(
-            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
-            std::function<void(::C2ComponentInterface*)> deleter) override {
-        *interface =
-                SimpleC2Interface::Builder("mp3", id, deleter)
-                .inputFormat(C2FormatCompressed)
-                .outputFormat(C2FormatAudio)
-                .build();
+            c2_node_id_t id,
+            std::shared_ptr<C2ComponentInterface>* const interface,
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = BuildIntf(kComponentName, id, deleter);
         return C2_OK;
     }
 
diff --git a/media/libstagefright/include/media/stagefright/CCodec.h b/media/libstagefright/include/media/stagefright/CCodec.h
index 24ee0a3..3a2670d 100644
--- a/media/libstagefright/include/media/stagefright/CCodec.h
+++ b/media/libstagefright/include/media/stagefright/CCodec.h
@@ -83,7 +83,7 @@
     void setInputSurface(const sp<PersistentSurface> &surface);
     status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
 
-    void setDeadline(const TimePoint &deadline);
+    void setDeadline(const TimePoint &deadline, const char *name);
 
     enum {
         kWhatAllocate,
@@ -126,10 +126,25 @@
         sp<AMessage> outputFormat;
     };
 
+    struct NamedTimePoint {
+        inline void set(
+                const TimePoint &timePoint,
+                const char *name) {
+            mTimePoint = timePoint;
+            mName = name;
+        }
+
+        inline TimePoint get() const { return mTimePoint; }
+        inline const char *getName() const { return mName; }
+    private:
+        TimePoint mTimePoint;
+        const char *mName;
+    };
+
     Mutexed<State> mState;
     std::shared_ptr<CCodecBufferChannel> mChannel;
     std::shared_ptr<C2Component::Listener> mListener;
-    Mutexed<TimePoint> mDeadline;
+    Mutexed<NamedTimePoint> mDeadline;
     Mutexed<Formats> mFormats;
     Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
 
diff --git a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
new file mode 100644
index 0000000..ea0b5c4
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 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 CODEC2_INFO_BUILDER_H_
+#define CODEC2_INFO_BUILDER_H_
+
+#include <media/stagefright/MediaCodecList.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Codec2InfoBuilder : public MediaCodecListBuilderBase {
+public:
+    Codec2InfoBuilder() = default;
+    status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
+};
+
+}  // namespace android
+
+#endif  // CODEC2_INFO_BUILDER_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 0bc02af..e7faea5 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -334,8 +334,6 @@
 
     // initial create parameters
     AString mInitName;
-    bool mInitNameIsType;
-    bool mInitIsEncoder;
 
     // configure parameter
     sp<AMessage> mConfigureMsg;
@@ -370,14 +368,14 @@
 
     MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
 
-    static sp<CodecBase> GetCodecBase(const AString &name, bool nameIsType = false);
+    static sp<CodecBase> GetCodecBase(const AString &name);
 
     static status_t PostAndAwaitResponse(
             const sp<AMessage> &msg, sp<AMessage> *response);
 
     void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
 
-    status_t init(const AString &name, bool nameIsType, bool encoder);
+    status_t init(const AString &name);
 
     void setState(State newState);
     void returnBuffersToCodec(bool isReclaim = false);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index f2bd496..d46fe85 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -18,6 +18,8 @@
 
 #define MEDIA_CODEC_LIST_H_
 
+#include <initializer_list>
+
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AString.h>
 #include <media/IMediaCodecList.h>
@@ -94,9 +96,9 @@
 
     /**
      * This constructor will call `buildMediaCodecList()` from the given
-     * `MediaCodecListBuilderBase` object.
+     * `MediaCodecListBuilderBase` objects.
      */
-    MediaCodecList(MediaCodecListBuilderBase* builder);
+    MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders);
 
     ~MediaCodecList();